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