libdwarf_rw.c revision 1.1.1.2 1 /* $NetBSD: libdwarf_rw.c,v 1.1.1.2 2016/02/20 02:42:00 christos Exp $ */
2 /*-
3 * Copyright (c) 2007 John Birrell (jb (at) freebsd.org)
4 * Copyright (c) 2010 Kai Wang
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include "_libdwarf.h"
30
31 __RCSID("$NetBSD: libdwarf_rw.c,v 1.1.1.2 2016/02/20 02:42:00 christos Exp $");
32 ELFTC_VCSID("Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste ");
33
34 uint64_t
35 _dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
36 {
37 uint64_t ret;
38 uint8_t *src;
39
40 src = data + *offsetp;
41
42 ret = 0;
43 switch (bytes_to_read) {
44 case 8:
45 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
46 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
47 /* FALLTHROUGH */
48 case 4:
49 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
50 /* FALLTHROUGH */
51 case 2:
52 ret |= ((uint64_t) src[1]) << 8;
53 /* FALLTHROUGH */
54 case 1:
55 ret |= src[0];
56 break;
57 default:
58 return (0);
59 }
60
61 *offsetp += bytes_to_read;
62
63 return (ret);
64 }
65
66 uint64_t
67 _dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
68 {
69 uint64_t ret;
70 uint8_t *src;
71
72 src = *data;
73
74 ret = 0;
75 switch (bytes_to_read) {
76 case 8:
77 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
78 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
79 /* FALLTHROUGH */
80 case 4:
81 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
82 /* FALLTHROUGH */
83 case 2:
84 ret |= ((uint64_t) src[1]) << 8;
85 /* FALLTHROUGH */
86 case 1:
87 ret |= src[0];
88 break;
89 default:
90 return (0);
91 }
92
93 *data += bytes_to_read;
94
95 return (ret);
96 }
97
98 uint64_t
99 _dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
100 {
101 uint64_t ret;
102 uint8_t *src;
103
104 src = data + *offsetp;
105
106 switch (bytes_to_read) {
107 case 1:
108 ret = src[0];
109 break;
110 case 2:
111 ret = src[1] | ((uint64_t) src[0]) << 8;
112 break;
113 case 4:
114 ret = src[3] | ((uint64_t) src[2]) << 8;
115 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
116 break;
117 case 8:
118 ret = src[7] | ((uint64_t) src[6]) << 8;
119 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
120 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
121 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
122 break;
123 default:
124 return (0);
125 }
126
127 *offsetp += bytes_to_read;
128
129 return (ret);
130 }
131
132 uint64_t
133 _dwarf_decode_msb(uint8_t **data, int bytes_to_read)
134 {
135 uint64_t ret;
136 uint8_t *src;
137
138 src = *data;
139
140 ret = 0;
141 switch (bytes_to_read) {
142 case 1:
143 ret = src[0];
144 break;
145 case 2:
146 ret = src[1] | ((uint64_t) src[0]) << 8;
147 break;
148 case 4:
149 ret = src[3] | ((uint64_t) src[2]) << 8;
150 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
151 break;
152 case 8:
153 ret = src[7] | ((uint64_t) src[6]) << 8;
154 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
155 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
156 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
157 break;
158 default:
159 return (0);
160 break;
161 }
162
163 *data += bytes_to_read;
164
165 return (ret);
166 }
167
168 void
169 _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
170 int bytes_to_write)
171 {
172 uint8_t *dst;
173
174 dst = data + *offsetp;
175
176 switch (bytes_to_write) {
177 case 8:
178 dst[7] = (value >> 56) & 0xff;
179 dst[6] = (value >> 48) & 0xff;
180 dst[5] = (value >> 40) & 0xff;
181 dst[4] = (value >> 32) & 0xff;
182 /* FALLTHROUGH */
183 case 4:
184 dst[3] = (value >> 24) & 0xff;
185 dst[2] = (value >> 16) & 0xff;
186 /* FALLTHROUGH */
187 case 2:
188 dst[1] = (value >> 8) & 0xff;
189 /* FALLTHROUGH */
190 case 1:
191 dst[0] = value & 0xff;
192 break;
193 default:
194 return;
195 }
196
197 *offsetp += bytes_to_write;
198 }
199
200 int
201 _dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
202 uint64_t value, int bytes_to_write, Dwarf_Error *error)
203 {
204
205 assert(*size > 0);
206
207 while (*offsetp + bytes_to_write > *size) {
208 *size *= 2;
209 *block = realloc(*block, (size_t) *size);
210 if (*block == NULL) {
211 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
212 return (DW_DLE_MEMORY);
213 }
214 }
215
216 _dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
217
218 return (DW_DLE_NONE);
219 }
220
221 void
222 _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
223 int bytes_to_write)
224 {
225 uint8_t *dst;
226
227 dst = data + *offsetp;
228
229 switch (bytes_to_write) {
230 case 8:
231 dst[7] = value & 0xff;
232 dst[6] = (value >> 8) & 0xff;
233 dst[5] = (value >> 16) & 0xff;
234 dst[4] = (value >> 24) & 0xff;
235 value >>= 32;
236 /* FALLTHROUGH */
237 case 4:
238 dst[3] = value & 0xff;
239 dst[2] = (value >> 8) & 0xff;
240 value >>= 16;
241 /* FALLTHROUGH */
242 case 2:
243 dst[1] = value & 0xff;
244 value >>= 8;
245 /* FALLTHROUGH */
246 case 1:
247 dst[0] = value & 0xff;
248 break;
249 default:
250 return;
251 }
252
253 *offsetp += bytes_to_write;
254 }
255
256 int
257 _dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
258 uint64_t value, int bytes_to_write, Dwarf_Error *error)
259 {
260
261 assert(*size > 0);
262
263 while (*offsetp + bytes_to_write > *size) {
264 *size *= 2;
265 *block = realloc(*block, (size_t) *size);
266 if (*block == NULL) {
267 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
268 return (DW_DLE_MEMORY);
269 }
270 }
271
272 _dwarf_write_msb(*block, offsetp, value, bytes_to_write);
273
274 return (DW_DLE_NONE);
275 }
276
277 int64_t
278 _dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
279 {
280 int64_t ret = 0;
281 uint8_t b;
282 int shift = 0;
283 uint8_t *src;
284
285 src = data + *offsetp;
286
287 do {
288 b = *src++;
289 ret |= ((b & 0x7f) << shift);
290 (*offsetp)++;
291 shift += 7;
292 } while ((b & 0x80) != 0);
293
294 if (shift < 64 && (b & 0x40) != 0)
295 ret |= (-1 << shift);
296
297 return (ret);
298 }
299
300 int
301 _dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
302 {
303 uint8_t *p;
304
305 p = data;
306
307 for (;;) {
308 if (p >= end)
309 return (-1);
310 *p = val & 0x7f;
311 val >>= 7;
312 if ((val == 0 && (*p & 0x40) == 0) ||
313 (val == -1 && (*p & 0x40) != 0)) {
314 p++;
315 break;
316 }
317 *p++ |= 0x80;
318 }
319
320 return (p - data);
321 }
322
323 int
324 _dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
325 int64_t val, Dwarf_Error *error)
326 {
327 int len;
328
329 assert(*size > 0);
330
331 while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
332 val)) < 0) {
333 *size *= 2;
334 *block = realloc(*block, (size_t) *size);
335 if (*block == NULL) {
336 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
337 return (DW_DLE_MEMORY);
338 }
339 }
340
341 *offsetp += len;
342
343 return (DW_DLE_NONE);
344 }
345
346 uint64_t
347 _dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
348 {
349 uint64_t ret = 0;
350 uint8_t b;
351 int shift = 0;
352 uint8_t *src;
353
354 src = data + *offsetp;
355
356 do {
357 b = *src++;
358 ret |= ((b & 0x7f) << shift);
359 (*offsetp)++;
360 shift += 7;
361 } while ((b & 0x80) != 0);
362
363 return (ret);
364 }
365
366 int
367 _dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
368 {
369 uint8_t *p;
370
371 p = data;
372
373 do {
374 if (p >= end)
375 return (-1);
376 *p = val & 0x7f;
377 val >>= 7;
378 if (val > 0)
379 *p |= 0x80;
380 p++;
381 } while (val > 0);
382
383 return (p - data);
384 }
385
386 int
387 _dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
388 uint64_t val, Dwarf_Error *error)
389 {
390 int len;
391
392 assert(*size > 0);
393
394 while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
395 val)) < 0) {
396 *size *= 2;
397 *block = realloc(*block, (size_t) *size);
398 if (*block == NULL) {
399 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
400 return (DW_DLE_MEMORY);
401 }
402 }
403
404 *offsetp += len;
405
406 return (DW_DLE_NONE);
407 }
408
409 int64_t
410 _dwarf_decode_sleb128(uint8_t **dp)
411 {
412 int64_t ret = 0;
413 uint8_t b;
414 int shift = 0;
415
416 uint8_t *src = *dp;
417
418 do {
419 b = *src++;
420 ret |= ((b & 0x7f) << shift);
421 shift += 7;
422 } while ((b & 0x80) != 0);
423
424 if (shift < 64 && (b & 0x40) != 0)
425 ret |= (-1 << shift);
426
427 *dp = src;
428
429 return (ret);
430 }
431
432 uint64_t
433 _dwarf_decode_uleb128(uint8_t **dp)
434 {
435 uint64_t ret = 0;
436 uint8_t b;
437 int shift = 0;
438
439 uint8_t *src = *dp;
440
441 do {
442 b = *src++;
443 ret |= ((b & 0x7f) << shift);
444 shift += 7;
445 } while ((b & 0x80) != 0);
446
447 *dp = src;
448
449 return (ret);
450 }
451
452 char *
453 _dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
454 {
455 char *ret, *src;
456
457 ret = src = (char *) data + *offsetp;
458
459 while (*src != '\0' && *offsetp < size) {
460 src++;
461 (*offsetp)++;
462 }
463
464 if (*src == '\0' && *offsetp < size)
465 (*offsetp)++;
466
467 return (ret);
468 }
469
470 void
471 _dwarf_write_string(void *data, uint64_t *offsetp, char *string)
472 {
473 char *dst;
474
475 dst = (char *) data + *offsetp;
476 strcpy(dst, string);
477 (*offsetp) += strlen(string) + 1;
478 }
479
480 int
481 _dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
482 char *string, Dwarf_Error *error)
483 {
484 size_t len;
485
486 assert(*size > 0);
487
488 len = strlen(string) + 1;
489 while (*offsetp + len > *size) {
490 *size *= 2;
491 *block = realloc(*block, (size_t) *size);
492 if (*block == NULL) {
493 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
494 return (DW_DLE_MEMORY);
495 }
496 }
497
498 _dwarf_write_string(*block, offsetp, string);
499
500 return (DW_DLE_NONE);
501 }
502
503 uint8_t *
504 _dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
505 {
506 uint8_t *ret, *src;
507
508 ret = src = (uint8_t *) data + *offsetp;
509
510 (*offsetp) += length;
511
512 return (ret);
513 }
514
515 void
516 _dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
517 uint64_t length)
518 {
519 uint8_t *dst;
520
521 dst = (uint8_t *) data + *offsetp;
522 memcpy(dst, blk, length);
523 (*offsetp) += length;
524 }
525
526 int
527 _dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
528 uint8_t *blk, uint64_t length, Dwarf_Error *error)
529 {
530
531 assert(*size > 0);
532
533 while (*offsetp + length > *size) {
534 *size *= 2;
535 *block = realloc(*block, (size_t) *size);
536 if (*block == NULL) {
537 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
538 return (DW_DLE_MEMORY);
539 }
540 }
541
542 _dwarf_write_block(*block, offsetp, blk, length);
543
544 return (DW_DLE_NONE);
545 }
546
547 void
548 _dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
549 uint64_t length)
550 {
551 uint8_t *dst;
552
553 dst = (uint8_t *) data + *offsetp;
554 memset(dst, byte, length);
555 (*offsetp) += length;
556 }
557
558 int
559 _dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
560 uint8_t byte, uint64_t cnt, Dwarf_Error *error)
561 {
562 assert(*size > 0);
563
564 while (*offsetp + cnt > *size) {
565 *size *= 2;
566 *block = realloc(*block, (size_t) *size);
567 if (*block == NULL) {
568 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
569 return (DW_DLE_MEMORY);
570 }
571 }
572
573 _dwarf_write_padding(*block, offsetp, byte, cnt);
574
575 return (DW_DLE_NONE);
576 }
577