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