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