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