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