xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/libdwarf_rw.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
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