1 /* $NetBSD: libdwarf_rw.c,v 1.5 2024/03/03 17:37:32 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2007 John Birrell (jb@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.5 2024/03/03 17:37:32 christos Exp $");
33 ELFTC_VCSID("Id: libdwarf_rw.c 4007 2023-10-12 18:17:02Z kaiwang27");
34
35 uint64_t
_dwarf_read_lsb(uint8_t * data,uint64_t * offsetp,int bytes_to_read)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[3]) << 24;
51 /* FALLTHROUGH */
52 case 3:
53 ret |= ((uint64_t) src[2]) << 16;
54 /* FALLTHROUGH */
55 case 2:
56 ret |= ((uint64_t) src[1]) << 8;
57 /* FALLTHROUGH */
58 case 1:
59 ret |= src[0];
60 break;
61 default:
62 return (0);
63 }
64
65 *offsetp += bytes_to_read;
66
67 return (ret);
68 }
69
70 uint64_t
_dwarf_decode_lsb(uint8_t ** data,int bytes_to_read)71 _dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
72 {
73 uint64_t ret;
74 uint8_t *src;
75
76 src = *data;
77
78 ret = 0;
79 switch (bytes_to_read) {
80 case 8:
81 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
82 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
83 /* FALLTHROUGH */
84 case 4:
85 ret |= ((uint64_t) src[3]) << 24;
86 /* FALLTHROUGH */
87 case 3:
88 ret |= ((uint64_t) src[2]) << 16;
89 /* FALLTHROUGH */
90 case 2:
91 ret |= ((uint64_t) src[1]) << 8;
92 /* FALLTHROUGH */
93 case 1:
94 ret |= src[0];
95 break;
96 default:
97 return (0);
98 }
99
100 *data += bytes_to_read;
101
102 return (ret);
103 }
104
105 uint64_t
_dwarf_read_msb(uint8_t * data,uint64_t * offsetp,int bytes_to_read)106 _dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
107 {
108 uint64_t ret;
109 uint8_t *src;
110
111 src = data + *offsetp;
112
113 switch (bytes_to_read) {
114 case 1:
115 ret = src[0];
116 break;
117 case 2:
118 ret = src[1] | ((uint64_t) src[0]) << 8;
119 break;
120 case 3:
121 ret = src[2] | ((uint64_t) src[1]) << 8;
122 ret |= ((uint64_t) src[0]) << 16;
123 break;
124 case 4:
125 ret = src[3] | ((uint64_t) src[2]) << 8;
126 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
127 break;
128 case 8:
129 ret = src[7] | ((uint64_t) src[6]) << 8;
130 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
131 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
132 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
133 break;
134 default:
135 return (0);
136 }
137
138 *offsetp += bytes_to_read;
139
140 return (ret);
141 }
142
143 uint64_t
_dwarf_decode_msb(uint8_t ** data,int bytes_to_read)144 _dwarf_decode_msb(uint8_t **data, int bytes_to_read)
145 {
146 uint64_t ret;
147 uint8_t *src;
148
149 src = *data;
150
151 ret = 0;
152 switch (bytes_to_read) {
153 case 1:
154 ret = src[0];
155 break;
156 case 2:
157 ret = src[1] | ((uint64_t) src[0]) << 8;
158 break;
159 case 3:
160 ret = src[2] | ((uint64_t) src[1]) << 8;
161 ret |= ((uint64_t) src[0]) << 16;
162 break;
163 case 4:
164 ret = src[3] | ((uint64_t) src[2]) << 8;
165 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
166 break;
167 case 8:
168 ret = src[7] | ((uint64_t) src[6]) << 8;
169 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
170 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
171 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
172 break;
173 default:
174 return (0);
175 }
176
177 *data += bytes_to_read;
178
179 return (ret);
180 }
181
182 void
_dwarf_write_lsb(uint8_t * data,uint64_t * offsetp,uint64_t value,int bytes_to_write)183 _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
184 int bytes_to_write)
185 {
186 uint8_t *dst;
187
188 dst = data + *offsetp;
189
190 switch (bytes_to_write) {
191 case 8:
192 dst[7] = (value >> 56) & 0xff;
193 dst[6] = (value >> 48) & 0xff;
194 dst[5] = (value >> 40) & 0xff;
195 dst[4] = (value >> 32) & 0xff;
196 /* FALLTHROUGH */
197 case 4:
198 dst[3] = (value >> 24) & 0xff;
199 dst[2] = (value >> 16) & 0xff;
200 /* FALLTHROUGH */
201 case 2:
202 dst[1] = (value >> 8) & 0xff;
203 /* FALLTHROUGH */
204 case 1:
205 dst[0] = value & 0xff;
206 break;
207 default:
208 return;
209 }
210
211 *offsetp += bytes_to_write;
212 }
213
214 int
_dwarf_write_lsb_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t value,int bytes_to_write,Dwarf_Error * error)215 _dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
216 uint64_t value, int bytes_to_write, Dwarf_Error *error)
217 {
218
219 assert(*size > 0);
220
221 while (*offsetp + bytes_to_write > *size) {
222 *size *= 2;
223 *block = realloc(*block, (size_t) *size);
224 if (*block == NULL) {
225 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
226 return (DW_DLE_MEMORY);
227 }
228 }
229
230 _dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
231
232 return (DW_DLE_NONE);
233 }
234
235 void
_dwarf_write_msb(uint8_t * data,uint64_t * offsetp,uint64_t value,int bytes_to_write)236 _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
237 int bytes_to_write)
238 {
239 uint8_t *dst;
240
241 dst = data + *offsetp;
242
243 switch (bytes_to_write) {
244 case 8:
245 dst[7] = value & 0xff;
246 dst[6] = (value >> 8) & 0xff;
247 dst[5] = (value >> 16) & 0xff;
248 dst[4] = (value >> 24) & 0xff;
249 value >>= 32;
250 /* FALLTHROUGH */
251 case 4:
252 dst[3] = value & 0xff;
253 dst[2] = (value >> 8) & 0xff;
254 value >>= 16;
255 /* FALLTHROUGH */
256 case 2:
257 dst[1] = value & 0xff;
258 value >>= 8;
259 /* FALLTHROUGH */
260 case 1:
261 dst[0] = value & 0xff;
262 break;
263 default:
264 return;
265 }
266
267 *offsetp += bytes_to_write;
268 }
269
270 int
_dwarf_write_msb_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t value,int bytes_to_write,Dwarf_Error * error)271 _dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
272 uint64_t value, int bytes_to_write, Dwarf_Error *error)
273 {
274
275 assert(*size > 0);
276
277 while (*offsetp + bytes_to_write > *size) {
278 *size *= 2;
279 *block = realloc(*block, (size_t) *size);
280 if (*block == NULL) {
281 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
282 return (DW_DLE_MEMORY);
283 }
284 }
285
286 _dwarf_write_msb(*block, offsetp, value, bytes_to_write);
287
288 return (DW_DLE_NONE);
289 }
290
291 int64_t
_dwarf_read_sleb128(uint8_t * data,uint64_t * offsetp)292 _dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
293 {
294 int64_t ret = 0;
295 uint8_t b;
296 int shift = 0;
297 uint8_t *src;
298
299 src = data + *offsetp;
300
301 do {
302 b = *src++;
303 ret |= ((b & 0x7f) << shift);
304 (*offsetp)++;
305 shift += 7;
306 } while ((b & 0x80) != 0);
307
308 if (shift < 64 && (b & 0x40) != 0)
309 ret |= (~0UL << shift);
310
311 return (ret);
312 }
313
314 int
_dwarf_write_sleb128(uint8_t * data,uint8_t * end,int64_t val)315 _dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
316 {
317 uint8_t *p;
318
319 p = data;
320
321 for (;;) {
322 if (p >= end)
323 return (-1);
324 *p = val & 0x7f;
325 val >>= 7;
326 if ((val == 0 && (*p & 0x40) == 0) ||
327 (val == -1 && (*p & 0x40) != 0)) {
328 p++;
329 break;
330 }
331 *p++ |= 0x80;
332 }
333
334 return (p - data);
335 }
336
337 int
_dwarf_write_sleb128_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,int64_t val,Dwarf_Error * error)338 _dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
339 int64_t val, Dwarf_Error *error)
340 {
341 int len;
342
343 assert(*size > 0);
344
345 while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
346 val)) < 0) {
347 *size *= 2;
348 *block = realloc(*block, (size_t) *size);
349 if (*block == NULL) {
350 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
351 return (DW_DLE_MEMORY);
352 }
353 }
354
355 *offsetp += len;
356
357 return (DW_DLE_NONE);
358 }
359
360 uint64_t
_dwarf_read_uleb128(uint8_t * data,uint64_t * offsetp)361 _dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
362 {
363 uint64_t ret = 0;
364 uint8_t b;
365 int shift = 0;
366 uint8_t *src;
367
368 src = data + *offsetp;
369
370 do {
371 b = *src++;
372 ret |= ((b & 0x7f) << shift);
373 (*offsetp)++;
374 shift += 7;
375 } while ((b & 0x80) != 0);
376
377 return (ret);
378 }
379
380 int
_dwarf_write_uleb128(uint8_t * data,uint8_t * end,uint64_t val)381 _dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
382 {
383 uint8_t *p;
384
385 p = data;
386
387 do {
388 if (p >= end)
389 return (-1);
390 *p = val & 0x7f;
391 val >>= 7;
392 if (val > 0)
393 *p |= 0x80;
394 p++;
395 } while (val > 0);
396
397 return (p - data);
398 }
399
400 int
_dwarf_write_uleb128_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t val,Dwarf_Error * error)401 _dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
402 uint64_t val, Dwarf_Error *error)
403 {
404 int len;
405
406 assert(*size > 0);
407
408 while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
409 val)) < 0) {
410 *size *= 2;
411 *block = realloc(*block, (size_t) *size);
412 if (*block == NULL) {
413 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
414 return (DW_DLE_MEMORY);
415 }
416 }
417
418 *offsetp += len;
419
420 return (DW_DLE_NONE);
421 }
422
423 int64_t
_dwarf_decode_sleb128(uint8_t ** dp)424 _dwarf_decode_sleb128(uint8_t **dp)
425 {
426 int64_t ret = 0;
427 uint8_t b;
428 int shift = 0;
429
430 uint8_t *src = *dp;
431
432 do {
433 b = *src++;
434 ret |= ((b & 0x7f) << shift);
435 shift += 7;
436 } while ((b & 0x80) != 0);
437
438 if (shift < 64 && (b & 0x40) != 0)
439 ret |= (~0UL << shift);
440
441 *dp = src;
442
443 return (ret);
444 }
445
446 uint64_t
_dwarf_decode_uleb128(uint8_t ** dp)447 _dwarf_decode_uleb128(uint8_t **dp)
448 {
449 uint64_t ret = 0;
450 uint8_t b;
451 int shift = 0;
452
453 uint8_t *src = *dp;
454
455 do {
456 b = *src++;
457 ret |= ((b & 0x7f) << shift);
458 shift += 7;
459 } while ((b & 0x80) != 0);
460
461 *dp = src;
462
463 return (ret);
464 }
465
466 char *
_dwarf_read_string(void * data,Dwarf_Unsigned size,uint64_t * offsetp)467 _dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
468 {
469 char *ret, *src;
470
471 ret = src = (char *) data + *offsetp;
472
473 while (*src != '\0' && *offsetp < size) {
474 src++;
475 (*offsetp)++;
476 }
477
478 if (*src == '\0' && *offsetp < size)
479 (*offsetp)++;
480
481 return (ret);
482 }
483
484 void
_dwarf_write_string(void * data,uint64_t * offsetp,char * string)485 _dwarf_write_string(void *data, uint64_t *offsetp, char *string)
486 {
487 char *dst;
488
489 dst = (char *) data + *offsetp;
490 strcpy(dst, string);
491 (*offsetp) += strlen(string) + 1;
492 }
493
494 int
_dwarf_write_string_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,char * string,Dwarf_Error * error)495 _dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
496 char *string, Dwarf_Error *error)
497 {
498 size_t len;
499
500 assert(*size > 0);
501
502 len = strlen(string) + 1;
503 while (*offsetp + len > *size) {
504 *size *= 2;
505 *block = realloc(*block, (size_t) *size);
506 if (*block == NULL) {
507 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
508 return (DW_DLE_MEMORY);
509 }
510 }
511
512 _dwarf_write_string(*block, offsetp, string);
513
514 return (DW_DLE_NONE);
515 }
516
517 uint8_t *
_dwarf_read_block(void * data,uint64_t * offsetp,uint64_t length)518 _dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
519 {
520 uint8_t *ret, *src;
521
522 ret = src = (uint8_t *) data + *offsetp;
523
524 (*offsetp) += length;
525
526 return (ret);
527 }
528
529 void
_dwarf_write_block(void * data,uint64_t * offsetp,uint8_t * blk,uint64_t length)530 _dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
531 uint64_t length)
532 {
533 uint8_t *dst;
534
535 dst = (uint8_t *) data + *offsetp;
536 memcpy(dst, blk, length);
537 (*offsetp) += length;
538 }
539
540 int
_dwarf_write_block_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint8_t * blk,uint64_t length,Dwarf_Error * error)541 _dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
542 uint8_t *blk, uint64_t length, Dwarf_Error *error)
543 {
544
545 assert(*size > 0);
546
547 while (*offsetp + length > *size) {
548 *size *= 2;
549 *block = realloc(*block, (size_t) *size);
550 if (*block == NULL) {
551 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
552 return (DW_DLE_MEMORY);
553 }
554 }
555
556 _dwarf_write_block(*block, offsetp, blk, length);
557
558 return (DW_DLE_NONE);
559 }
560
561 void
_dwarf_write_padding(void * data,uint64_t * offsetp,uint8_t byte,uint64_t length)562 _dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
563 uint64_t length)
564 {
565 uint8_t *dst;
566
567 dst = (uint8_t *) data + *offsetp;
568 memset(dst, byte, length);
569 (*offsetp) += length;
570 }
571
572 int
_dwarf_write_padding_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint8_t byte,uint64_t cnt,Dwarf_Error * error)573 _dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
574 uint8_t byte, uint64_t cnt, Dwarf_Error *error)
575 {
576 assert(*size > 0);
577
578 while (*offsetp + cnt > *size) {
579 *size *= 2;
580 *block = realloc(*block, (size_t) *size);
581 if (*block == NULL) {
582 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
583 return (DW_DLE_MEMORY);
584 }
585 }
586
587 _dwarf_write_padding(*block, offsetp, byte, cnt);
588
589 return (DW_DLE_NONE);
590 }
591