12de3b87aSKai Wang /*-
22de3b87aSKai Wang  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
32de3b87aSKai Wang  * Copyright (c) 2010 Kai Wang
42de3b87aSKai Wang  * All rights reserved.
52de3b87aSKai Wang  *
62de3b87aSKai Wang  * Redistribution and use in source and binary forms, with or without
72de3b87aSKai Wang  * modification, are permitted provided that the following conditions
82de3b87aSKai Wang  * are met:
92de3b87aSKai Wang  * 1. Redistributions of source code must retain the above copyright
102de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer.
112de3b87aSKai Wang  * 2. Redistributions in binary form must reproduce the above copyright
122de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer in the
132de3b87aSKai Wang  *    documentation and/or other materials provided with the distribution.
142de3b87aSKai Wang  *
152de3b87aSKai Wang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162de3b87aSKai Wang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172de3b87aSKai Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182de3b87aSKai Wang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192de3b87aSKai Wang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202de3b87aSKai Wang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212de3b87aSKai Wang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222de3b87aSKai Wang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232de3b87aSKai Wang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242de3b87aSKai Wang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252de3b87aSKai Wang  * SUCH DAMAGE.
262de3b87aSKai Wang  */
272de3b87aSKai Wang 
282de3b87aSKai Wang #include "_libdwarf.h"
292de3b87aSKai Wang 
30*839529caSEd Maste ELFTC_VCSID("$Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste $");
312de3b87aSKai Wang 
322de3b87aSKai Wang uint64_t
_dwarf_read_lsb(uint8_t * data,uint64_t * offsetp,int bytes_to_read)332de3b87aSKai Wang _dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
342de3b87aSKai Wang {
352de3b87aSKai Wang 	uint64_t ret;
362de3b87aSKai Wang 	uint8_t *src;
372de3b87aSKai Wang 
382de3b87aSKai Wang 	src = data + *offsetp;
392de3b87aSKai Wang 
402de3b87aSKai Wang 	ret = 0;
412de3b87aSKai Wang 	switch (bytes_to_read) {
422de3b87aSKai Wang 	case 8:
432de3b87aSKai Wang 		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
442de3b87aSKai Wang 		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
45*839529caSEd Maste 		/* FALLTHROUGH */
462de3b87aSKai Wang 	case 4:
472de3b87aSKai Wang 		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
48*839529caSEd Maste 		/* FALLTHROUGH */
492de3b87aSKai Wang 	case 2:
502de3b87aSKai Wang 		ret |= ((uint64_t) src[1]) << 8;
51*839529caSEd Maste 		/* FALLTHROUGH */
522de3b87aSKai Wang 	case 1:
532de3b87aSKai Wang 		ret |= src[0];
542de3b87aSKai Wang 		break;
552de3b87aSKai Wang 	default:
562de3b87aSKai Wang 		return (0);
572de3b87aSKai Wang 	}
582de3b87aSKai Wang 
592de3b87aSKai Wang 	*offsetp += bytes_to_read;
602de3b87aSKai Wang 
612de3b87aSKai Wang 	return (ret);
622de3b87aSKai Wang }
632de3b87aSKai Wang 
642de3b87aSKai Wang uint64_t
_dwarf_decode_lsb(uint8_t ** data,int bytes_to_read)652de3b87aSKai Wang _dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
662de3b87aSKai Wang {
672de3b87aSKai Wang 	uint64_t ret;
682de3b87aSKai Wang 	uint8_t *src;
692de3b87aSKai Wang 
702de3b87aSKai Wang 	src = *data;
712de3b87aSKai Wang 
722de3b87aSKai Wang 	ret = 0;
732de3b87aSKai Wang 	switch (bytes_to_read) {
742de3b87aSKai Wang 	case 8:
752de3b87aSKai Wang 		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
762de3b87aSKai Wang 		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
77*839529caSEd Maste 		/* FALLTHROUGH */
782de3b87aSKai Wang 	case 4:
792de3b87aSKai Wang 		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
80*839529caSEd Maste 		/* FALLTHROUGH */
812de3b87aSKai Wang 	case 2:
822de3b87aSKai Wang 		ret |= ((uint64_t) src[1]) << 8;
83*839529caSEd Maste 		/* FALLTHROUGH */
842de3b87aSKai Wang 	case 1:
852de3b87aSKai Wang 		ret |= src[0];
862de3b87aSKai Wang 		break;
872de3b87aSKai Wang 	default:
882de3b87aSKai Wang 		return (0);
892de3b87aSKai Wang 	}
902de3b87aSKai Wang 
912de3b87aSKai Wang 	*data += bytes_to_read;
922de3b87aSKai Wang 
932de3b87aSKai Wang 	return (ret);
942de3b87aSKai Wang }
952de3b87aSKai Wang 
962de3b87aSKai Wang uint64_t
_dwarf_read_msb(uint8_t * data,uint64_t * offsetp,int bytes_to_read)972de3b87aSKai Wang _dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
982de3b87aSKai Wang {
992de3b87aSKai Wang 	uint64_t ret;
1002de3b87aSKai Wang 	uint8_t *src;
1012de3b87aSKai Wang 
1022de3b87aSKai Wang 	src = data + *offsetp;
1032de3b87aSKai Wang 
1042de3b87aSKai Wang 	switch (bytes_to_read) {
1052de3b87aSKai Wang 	case 1:
1062de3b87aSKai Wang 		ret = src[0];
1072de3b87aSKai Wang 		break;
1082de3b87aSKai Wang 	case 2:
1092de3b87aSKai Wang 		ret = src[1] | ((uint64_t) src[0]) << 8;
1102de3b87aSKai Wang 		break;
1112de3b87aSKai Wang 	case 4:
1122de3b87aSKai Wang 		ret = src[3] | ((uint64_t) src[2]) << 8;
1132de3b87aSKai Wang 		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
1142de3b87aSKai Wang 		break;
1152de3b87aSKai Wang 	case 8:
1162de3b87aSKai Wang 		ret = src[7] | ((uint64_t) src[6]) << 8;
1172de3b87aSKai Wang 		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
1182de3b87aSKai Wang 		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
1192de3b87aSKai Wang 		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
1202de3b87aSKai Wang 		break;
1212de3b87aSKai Wang 	default:
1222de3b87aSKai Wang 		return (0);
1232de3b87aSKai Wang 	}
1242de3b87aSKai Wang 
1252de3b87aSKai Wang 	*offsetp += bytes_to_read;
1262de3b87aSKai Wang 
1272de3b87aSKai Wang 	return (ret);
1282de3b87aSKai Wang }
1292de3b87aSKai Wang 
1302de3b87aSKai Wang uint64_t
_dwarf_decode_msb(uint8_t ** data,int bytes_to_read)1312de3b87aSKai Wang _dwarf_decode_msb(uint8_t **data, int bytes_to_read)
1322de3b87aSKai Wang {
1332de3b87aSKai Wang 	uint64_t ret;
1342de3b87aSKai Wang 	uint8_t *src;
1352de3b87aSKai Wang 
1362de3b87aSKai Wang 	src = *data;
1372de3b87aSKai Wang 
1382de3b87aSKai Wang 	ret = 0;
1392de3b87aSKai Wang 	switch (bytes_to_read) {
1402de3b87aSKai Wang 	case 1:
1412de3b87aSKai Wang 		ret = src[0];
1422de3b87aSKai Wang 		break;
1432de3b87aSKai Wang 	case 2:
1442de3b87aSKai Wang 		ret = src[1] | ((uint64_t) src[0]) << 8;
1452de3b87aSKai Wang 		break;
1462de3b87aSKai Wang 	case 4:
1472de3b87aSKai Wang 		ret = src[3] | ((uint64_t) src[2]) << 8;
1482de3b87aSKai Wang 		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
1492de3b87aSKai Wang 		break;
1502de3b87aSKai Wang 	case 8:
1512de3b87aSKai Wang 		ret = src[7] | ((uint64_t) src[6]) << 8;
1522de3b87aSKai Wang 		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
1532de3b87aSKai Wang 		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
1542de3b87aSKai Wang 		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
1552de3b87aSKai Wang 		break;
1562de3b87aSKai Wang 	default:
1572de3b87aSKai Wang 		return (0);
1582de3b87aSKai Wang 		break;
1592de3b87aSKai Wang 	}
1602de3b87aSKai Wang 
1612de3b87aSKai Wang 	*data += bytes_to_read;
1622de3b87aSKai Wang 
1632de3b87aSKai Wang 	return (ret);
1642de3b87aSKai Wang }
1652de3b87aSKai Wang 
1662de3b87aSKai Wang void
_dwarf_write_lsb(uint8_t * data,uint64_t * offsetp,uint64_t value,int bytes_to_write)1672de3b87aSKai Wang _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
1682de3b87aSKai Wang     int bytes_to_write)
1692de3b87aSKai Wang {
1702de3b87aSKai Wang 	uint8_t *dst;
1712de3b87aSKai Wang 
1722de3b87aSKai Wang 	dst = data + *offsetp;
1732de3b87aSKai Wang 
1742de3b87aSKai Wang 	switch (bytes_to_write) {
1752de3b87aSKai Wang 	case 8:
1762de3b87aSKai Wang 		dst[7] = (value >> 56) & 0xff;
1772de3b87aSKai Wang 		dst[6] = (value >> 48) & 0xff;
1782de3b87aSKai Wang 		dst[5] = (value >> 40) & 0xff;
1792de3b87aSKai Wang 		dst[4] = (value >> 32) & 0xff;
180*839529caSEd Maste 		/* FALLTHROUGH */
1812de3b87aSKai Wang 	case 4:
1822de3b87aSKai Wang 		dst[3] = (value >> 24) & 0xff;
1832de3b87aSKai Wang 		dst[2] = (value >> 16) & 0xff;
184*839529caSEd Maste 		/* FALLTHROUGH */
1852de3b87aSKai Wang 	case 2:
1862de3b87aSKai Wang 		dst[1] = (value >> 8) & 0xff;
187*839529caSEd Maste 		/* FALLTHROUGH */
1882de3b87aSKai Wang 	case 1:
1892de3b87aSKai Wang 		dst[0] = value & 0xff;
1902de3b87aSKai Wang 		break;
1912de3b87aSKai Wang 	default:
1922de3b87aSKai Wang 		return;
1932de3b87aSKai Wang 	}
1942de3b87aSKai Wang 
1952de3b87aSKai Wang 	*offsetp += bytes_to_write;
1962de3b87aSKai Wang }
1972de3b87aSKai Wang 
1982de3b87aSKai Wang int
_dwarf_write_lsb_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t value,int bytes_to_write,Dwarf_Error * error)1992de3b87aSKai Wang _dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
2002de3b87aSKai Wang     uint64_t value, int bytes_to_write, Dwarf_Error *error)
2012de3b87aSKai Wang {
2022de3b87aSKai Wang 
2032de3b87aSKai Wang 	assert(*size > 0);
2042de3b87aSKai Wang 
2052de3b87aSKai Wang 	while (*offsetp + bytes_to_write > *size) {
2062de3b87aSKai Wang 		*size *= 2;
2072de3b87aSKai Wang 		*block = realloc(*block, (size_t) *size);
2082de3b87aSKai Wang 		if (*block == NULL) {
2092de3b87aSKai Wang 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
2102de3b87aSKai Wang 			return (DW_DLE_MEMORY);
2112de3b87aSKai Wang 		}
2122de3b87aSKai Wang 	}
2132de3b87aSKai Wang 
2142de3b87aSKai Wang 	_dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
2152de3b87aSKai Wang 
2162de3b87aSKai Wang 	return (DW_DLE_NONE);
2172de3b87aSKai Wang }
2182de3b87aSKai Wang 
2192de3b87aSKai Wang void
_dwarf_write_msb(uint8_t * data,uint64_t * offsetp,uint64_t value,int bytes_to_write)2202de3b87aSKai Wang _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
2212de3b87aSKai Wang     int bytes_to_write)
2222de3b87aSKai Wang {
2232de3b87aSKai Wang 	uint8_t *dst;
2242de3b87aSKai Wang 
2252de3b87aSKai Wang 	dst = data + *offsetp;
2262de3b87aSKai Wang 
2272de3b87aSKai Wang 	switch (bytes_to_write) {
2282de3b87aSKai Wang 	case 8:
2292de3b87aSKai Wang 		dst[7] = value & 0xff;
2302de3b87aSKai Wang 		dst[6] = (value >> 8) & 0xff;
2312de3b87aSKai Wang 		dst[5] = (value >> 16) & 0xff;
2322de3b87aSKai Wang 		dst[4] = (value >> 24) & 0xff;
2332de3b87aSKai Wang 		value >>= 32;
234*839529caSEd Maste 		/* FALLTHROUGH */
2352de3b87aSKai Wang 	case 4:
2362de3b87aSKai Wang 		dst[3] = value & 0xff;
2372de3b87aSKai Wang 		dst[2] = (value >> 8) & 0xff;
2382de3b87aSKai Wang 		value >>= 16;
239*839529caSEd Maste 		/* FALLTHROUGH */
2402de3b87aSKai Wang 	case 2:
2412de3b87aSKai Wang 		dst[1] = value & 0xff;
2422de3b87aSKai Wang 		value >>= 8;
243*839529caSEd Maste 		/* FALLTHROUGH */
2442de3b87aSKai Wang 	case 1:
2452de3b87aSKai Wang 		dst[0] = value & 0xff;
2462de3b87aSKai Wang 		break;
2472de3b87aSKai Wang 	default:
2482de3b87aSKai Wang 		return;
2492de3b87aSKai Wang 	}
2502de3b87aSKai Wang 
2512de3b87aSKai Wang 	*offsetp += bytes_to_write;
2522de3b87aSKai Wang }
2532de3b87aSKai Wang 
2542de3b87aSKai Wang int
_dwarf_write_msb_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t value,int bytes_to_write,Dwarf_Error * error)2552de3b87aSKai Wang _dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
2562de3b87aSKai Wang     uint64_t value, int bytes_to_write, Dwarf_Error *error)
2572de3b87aSKai Wang {
2582de3b87aSKai Wang 
2592de3b87aSKai Wang 	assert(*size > 0);
2602de3b87aSKai Wang 
2612de3b87aSKai Wang 	while (*offsetp + bytes_to_write > *size) {
2622de3b87aSKai Wang 		*size *= 2;
2632de3b87aSKai Wang 		*block = realloc(*block, (size_t) *size);
2642de3b87aSKai Wang 		if (*block == NULL) {
2652de3b87aSKai Wang 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
2662de3b87aSKai Wang 			return (DW_DLE_MEMORY);
2672de3b87aSKai Wang 		}
2682de3b87aSKai Wang 	}
2692de3b87aSKai Wang 
2702de3b87aSKai Wang 	_dwarf_write_msb(*block, offsetp, value, bytes_to_write);
2712de3b87aSKai Wang 
2722de3b87aSKai Wang 	return (DW_DLE_NONE);
2732de3b87aSKai Wang }
2742de3b87aSKai Wang 
2752de3b87aSKai Wang int64_t
_dwarf_read_sleb128(uint8_t * data,uint64_t * offsetp)2762de3b87aSKai Wang _dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
2772de3b87aSKai Wang {
2782de3b87aSKai Wang 	int64_t ret = 0;
2792de3b87aSKai Wang 	uint8_t b;
2802de3b87aSKai Wang 	int shift = 0;
2812de3b87aSKai Wang 	uint8_t *src;
2822de3b87aSKai Wang 
2832de3b87aSKai Wang 	src = data + *offsetp;
2842de3b87aSKai Wang 
2852de3b87aSKai Wang 	do {
2862de3b87aSKai Wang 		b = *src++;
2872de3b87aSKai Wang 		ret |= ((b & 0x7f) << shift);
2882de3b87aSKai Wang 		(*offsetp)++;
2892de3b87aSKai Wang 		shift += 7;
2902de3b87aSKai Wang 	} while ((b & 0x80) != 0);
2912de3b87aSKai Wang 
2922de3b87aSKai Wang 	if (shift < 64 && (b & 0x40) != 0)
2932de3b87aSKai Wang 		ret |= (-1 << shift);
2942de3b87aSKai Wang 
2952de3b87aSKai Wang 	return (ret);
2962de3b87aSKai Wang }
2972de3b87aSKai Wang 
2982de3b87aSKai Wang int
_dwarf_write_sleb128(uint8_t * data,uint8_t * end,int64_t val)2992de3b87aSKai Wang _dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
3002de3b87aSKai Wang {
3012de3b87aSKai Wang 	uint8_t *p;
3022de3b87aSKai Wang 
3032de3b87aSKai Wang 	p = data;
3042de3b87aSKai Wang 
3052de3b87aSKai Wang 	for (;;) {
3062de3b87aSKai Wang 		if (p >= end)
3072de3b87aSKai Wang 			return (-1);
3082de3b87aSKai Wang 		*p = val & 0x7f;
3092de3b87aSKai Wang 		val >>= 7;
3102de3b87aSKai Wang 		if ((val == 0 && (*p & 0x40) == 0) ||
3112de3b87aSKai Wang 		    (val == -1 && (*p & 0x40) != 0)) {
3122de3b87aSKai Wang 			p++;
3132de3b87aSKai Wang 			break;
3142de3b87aSKai Wang 		}
3152de3b87aSKai Wang 		*p++ |= 0x80;
3162de3b87aSKai Wang 	}
3172de3b87aSKai Wang 
3182de3b87aSKai Wang 	return (p - data);
3192de3b87aSKai Wang }
3202de3b87aSKai Wang 
3212de3b87aSKai Wang int
_dwarf_write_sleb128_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,int64_t val,Dwarf_Error * error)3222de3b87aSKai Wang _dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
3232de3b87aSKai Wang     int64_t val, Dwarf_Error *error)
3242de3b87aSKai Wang {
3252de3b87aSKai Wang 	int len;
3262de3b87aSKai Wang 
3272de3b87aSKai Wang 	assert(*size > 0);
3282de3b87aSKai Wang 
3292de3b87aSKai Wang 	while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
3302de3b87aSKai Wang 	    val)) < 0) {
3312de3b87aSKai Wang 		*size *= 2;
3322de3b87aSKai Wang 		*block = realloc(*block, (size_t) *size);
3332de3b87aSKai Wang 		if (*block == NULL) {
3342de3b87aSKai Wang 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
3352de3b87aSKai Wang 			return (DW_DLE_MEMORY);
3362de3b87aSKai Wang 		}
3372de3b87aSKai Wang 	}
3382de3b87aSKai Wang 
3392de3b87aSKai Wang 	*offsetp += len;
3402de3b87aSKai Wang 
3412de3b87aSKai Wang 	return (DW_DLE_NONE);
3422de3b87aSKai Wang }
3432de3b87aSKai Wang 
3442de3b87aSKai Wang uint64_t
_dwarf_read_uleb128(uint8_t * data,uint64_t * offsetp)3452de3b87aSKai Wang _dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
3462de3b87aSKai Wang {
3472de3b87aSKai Wang 	uint64_t ret = 0;
3482de3b87aSKai Wang 	uint8_t b;
3492de3b87aSKai Wang 	int shift = 0;
3502de3b87aSKai Wang 	uint8_t *src;
3512de3b87aSKai Wang 
3522de3b87aSKai Wang 	src = data + *offsetp;
3532de3b87aSKai Wang 
3542de3b87aSKai Wang 	do {
3552de3b87aSKai Wang 		b = *src++;
3562de3b87aSKai Wang 		ret |= ((b & 0x7f) << shift);
3572de3b87aSKai Wang 		(*offsetp)++;
3582de3b87aSKai Wang 		shift += 7;
3592de3b87aSKai Wang 	} while ((b & 0x80) != 0);
3602de3b87aSKai Wang 
3612de3b87aSKai Wang 	return (ret);
3622de3b87aSKai Wang }
3632de3b87aSKai Wang 
3642de3b87aSKai Wang int
_dwarf_write_uleb128(uint8_t * data,uint8_t * end,uint64_t val)3652de3b87aSKai Wang _dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
3662de3b87aSKai Wang {
3672de3b87aSKai Wang 	uint8_t *p;
3682de3b87aSKai Wang 
3692de3b87aSKai Wang 	p = data;
3702de3b87aSKai Wang 
3712de3b87aSKai Wang 	do {
3722de3b87aSKai Wang 		if (p >= end)
3732de3b87aSKai Wang 			return (-1);
3742de3b87aSKai Wang 		*p = val & 0x7f;
3752de3b87aSKai Wang 		val >>= 7;
3762de3b87aSKai Wang 		if (val > 0)
3772de3b87aSKai Wang 			*p |= 0x80;
3782de3b87aSKai Wang 		p++;
3792de3b87aSKai Wang 	} while (val > 0);
3802de3b87aSKai Wang 
3812de3b87aSKai Wang 	return (p - data);
3822de3b87aSKai Wang }
3832de3b87aSKai Wang 
3842de3b87aSKai Wang int
_dwarf_write_uleb128_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint64_t val,Dwarf_Error * error)3852de3b87aSKai Wang _dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
3862de3b87aSKai Wang     uint64_t val, Dwarf_Error *error)
3872de3b87aSKai Wang {
3882de3b87aSKai Wang 	int len;
3892de3b87aSKai Wang 
3902de3b87aSKai Wang 	assert(*size > 0);
3912de3b87aSKai Wang 
3922de3b87aSKai Wang 	while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
3932de3b87aSKai Wang 	    val)) < 0) {
3942de3b87aSKai Wang 		*size *= 2;
3952de3b87aSKai Wang 		*block = realloc(*block, (size_t) *size);
3962de3b87aSKai Wang 		if (*block == NULL) {
3972de3b87aSKai Wang 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
3982de3b87aSKai Wang 			return (DW_DLE_MEMORY);
3992de3b87aSKai Wang 		}
4002de3b87aSKai Wang 	}
4012de3b87aSKai Wang 
4022de3b87aSKai Wang 	*offsetp += len;
4032de3b87aSKai Wang 
4042de3b87aSKai Wang 	return (DW_DLE_NONE);
4052de3b87aSKai Wang }
4062de3b87aSKai Wang 
4072de3b87aSKai Wang int64_t
_dwarf_decode_sleb128(uint8_t ** dp)4082de3b87aSKai Wang _dwarf_decode_sleb128(uint8_t **dp)
4092de3b87aSKai Wang {
4102de3b87aSKai Wang 	int64_t ret = 0;
4112de3b87aSKai Wang 	uint8_t b;
4122de3b87aSKai Wang 	int shift = 0;
4132de3b87aSKai Wang 
4142de3b87aSKai Wang 	uint8_t *src = *dp;
4152de3b87aSKai Wang 
4162de3b87aSKai Wang 	do {
4172de3b87aSKai Wang 		b = *src++;
4182de3b87aSKai Wang 		ret |= ((b & 0x7f) << shift);
4192de3b87aSKai Wang 		shift += 7;
4202de3b87aSKai Wang 	} while ((b & 0x80) != 0);
4212de3b87aSKai Wang 
4222de3b87aSKai Wang 	if (shift < 64 && (b & 0x40) != 0)
4232de3b87aSKai Wang 		ret |= (-1 << shift);
4242de3b87aSKai Wang 
4252de3b87aSKai Wang 	*dp = src;
4262de3b87aSKai Wang 
4272de3b87aSKai Wang 	return (ret);
4282de3b87aSKai Wang }
4292de3b87aSKai Wang 
4302de3b87aSKai Wang uint64_t
_dwarf_decode_uleb128(uint8_t ** dp)4312de3b87aSKai Wang _dwarf_decode_uleb128(uint8_t **dp)
4322de3b87aSKai Wang {
4332de3b87aSKai Wang 	uint64_t ret = 0;
4342de3b87aSKai Wang 	uint8_t b;
4352de3b87aSKai Wang 	int shift = 0;
4362de3b87aSKai Wang 
4372de3b87aSKai Wang 	uint8_t *src = *dp;
4382de3b87aSKai Wang 
4392de3b87aSKai Wang 	do {
4402de3b87aSKai Wang 		b = *src++;
4412de3b87aSKai Wang 		ret |= ((b & 0x7f) << shift);
4422de3b87aSKai Wang 		shift += 7;
4432de3b87aSKai Wang 	} while ((b & 0x80) != 0);
4442de3b87aSKai Wang 
4452de3b87aSKai Wang 	*dp = src;
4462de3b87aSKai Wang 
4472de3b87aSKai Wang 	return (ret);
4482de3b87aSKai Wang }
4492de3b87aSKai Wang 
4502de3b87aSKai Wang char *
_dwarf_read_string(void * data,Dwarf_Unsigned size,uint64_t * offsetp)4512de3b87aSKai Wang _dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
4522de3b87aSKai Wang {
4532de3b87aSKai Wang 	char *ret, *src;
4542de3b87aSKai Wang 
4552de3b87aSKai Wang 	ret = src = (char *) data + *offsetp;
4562de3b87aSKai Wang 
4572de3b87aSKai Wang 	while (*src != '\0' && *offsetp < size) {
4582de3b87aSKai Wang 		src++;
4592de3b87aSKai Wang 		(*offsetp)++;
4602de3b87aSKai Wang 	}
4612de3b87aSKai Wang 
4622de3b87aSKai Wang 	if (*src == '\0' && *offsetp < size)
4632de3b87aSKai Wang 		(*offsetp)++;
4642de3b87aSKai Wang 
4652de3b87aSKai Wang 	return (ret);
4662de3b87aSKai Wang }
4672de3b87aSKai Wang 
4682de3b87aSKai Wang void
_dwarf_write_string(void * data,uint64_t * offsetp,char * string)4692de3b87aSKai Wang _dwarf_write_string(void *data, uint64_t *offsetp, char *string)
4702de3b87aSKai Wang {
4712de3b87aSKai Wang 	char *dst;
4722de3b87aSKai Wang 
4732de3b87aSKai Wang 	dst = (char *) data + *offsetp;
4742de3b87aSKai Wang 	strcpy(dst, string);
4752de3b87aSKai Wang 	(*offsetp) += strlen(string) + 1;
4762de3b87aSKai Wang }
4772de3b87aSKai Wang 
4782de3b87aSKai Wang int
_dwarf_write_string_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,char * string,Dwarf_Error * error)4792de3b87aSKai Wang _dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
4802de3b87aSKai Wang     char *string, Dwarf_Error *error)
4812de3b87aSKai Wang {
4822de3b87aSKai Wang 	size_t len;
4832de3b87aSKai Wang 
4842de3b87aSKai Wang 	assert(*size > 0);
4852de3b87aSKai Wang 
4862de3b87aSKai Wang 	len = strlen(string) + 1;
4872de3b87aSKai Wang 	while (*offsetp + len > *size) {
4882de3b87aSKai Wang 		*size *= 2;
4892de3b87aSKai Wang 		*block = realloc(*block, (size_t) *size);
4902de3b87aSKai Wang 		if (*block == NULL) {
4912de3b87aSKai Wang 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
4922de3b87aSKai Wang 			return (DW_DLE_MEMORY);
4932de3b87aSKai Wang 		}
4942de3b87aSKai Wang 	}
4952de3b87aSKai Wang 
4962de3b87aSKai Wang 	_dwarf_write_string(*block, offsetp, string);
4972de3b87aSKai Wang 
4982de3b87aSKai Wang 	return (DW_DLE_NONE);
4992de3b87aSKai Wang }
5002de3b87aSKai Wang 
5012de3b87aSKai Wang uint8_t *
_dwarf_read_block(void * data,uint64_t * offsetp,uint64_t length)5022de3b87aSKai Wang _dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
5032de3b87aSKai Wang {
5042de3b87aSKai Wang 	uint8_t *ret, *src;
5052de3b87aSKai Wang 
5062de3b87aSKai Wang 	ret = src = (uint8_t *) data + *offsetp;
5072de3b87aSKai Wang 
5082de3b87aSKai Wang 	(*offsetp) += length;
5092de3b87aSKai Wang 
5102de3b87aSKai Wang 	return (ret);
5112de3b87aSKai Wang }
5122de3b87aSKai Wang 
5132de3b87aSKai Wang void
_dwarf_write_block(void * data,uint64_t * offsetp,uint8_t * blk,uint64_t length)5142de3b87aSKai Wang _dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
5152de3b87aSKai Wang     uint64_t length)
5162de3b87aSKai Wang {
5172de3b87aSKai Wang 	uint8_t *dst;
5182de3b87aSKai Wang 
5192de3b87aSKai Wang 	dst = (uint8_t *) data + *offsetp;
5202de3b87aSKai Wang 	memcpy(dst, blk, length);
5212de3b87aSKai Wang 	(*offsetp) += length;
5222de3b87aSKai Wang }
5232de3b87aSKai Wang 
5242de3b87aSKai Wang int
_dwarf_write_block_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint8_t * blk,uint64_t length,Dwarf_Error * error)5252de3b87aSKai Wang _dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
5262de3b87aSKai Wang     uint8_t *blk, uint64_t length, Dwarf_Error *error)
5272de3b87aSKai Wang {
5282de3b87aSKai Wang 
5292de3b87aSKai Wang 	assert(*size > 0);
5302de3b87aSKai Wang 
5312de3b87aSKai Wang 	while (*offsetp + length > *size) {
5322de3b87aSKai Wang 		*size *= 2;
5332de3b87aSKai Wang 		*block = realloc(*block, (size_t) *size);
5342de3b87aSKai Wang 		if (*block == NULL) {
5352de3b87aSKai Wang 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
5362de3b87aSKai Wang 			return (DW_DLE_MEMORY);
5372de3b87aSKai Wang 		}
5382de3b87aSKai Wang 	}
5392de3b87aSKai Wang 
5402de3b87aSKai Wang 	_dwarf_write_block(*block, offsetp, blk, length);
5412de3b87aSKai Wang 
5422de3b87aSKai Wang 	return (DW_DLE_NONE);
5432de3b87aSKai Wang }
5442de3b87aSKai Wang 
5452de3b87aSKai Wang void
_dwarf_write_padding(void * data,uint64_t * offsetp,uint8_t byte,uint64_t length)5462de3b87aSKai Wang _dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
5472de3b87aSKai Wang     uint64_t length)
5482de3b87aSKai Wang {
5492de3b87aSKai Wang 	uint8_t *dst;
5502de3b87aSKai Wang 
5512de3b87aSKai Wang 	dst = (uint8_t *) data + *offsetp;
5522de3b87aSKai Wang 	memset(dst, byte, length);
5532de3b87aSKai Wang 	(*offsetp) += length;
5542de3b87aSKai Wang }
5552de3b87aSKai Wang 
5562de3b87aSKai Wang int
_dwarf_write_padding_alloc(uint8_t ** block,uint64_t * size,uint64_t * offsetp,uint8_t byte,uint64_t cnt,Dwarf_Error * error)5572de3b87aSKai Wang _dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
5582de3b87aSKai Wang     uint8_t byte, uint64_t cnt, Dwarf_Error *error)
5592de3b87aSKai Wang {
5602de3b87aSKai Wang 	assert(*size > 0);
5612de3b87aSKai Wang 
5622de3b87aSKai Wang 	while (*offsetp + cnt > *size) {
5632de3b87aSKai Wang 		*size *= 2;
5642de3b87aSKai Wang 		*block = realloc(*block, (size_t) *size);
5652de3b87aSKai Wang 		if (*block == NULL) {
5662de3b87aSKai Wang 			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
5672de3b87aSKai Wang 			return (DW_DLE_MEMORY);
5682de3b87aSKai Wang 		}
5692de3b87aSKai Wang 	}
5702de3b87aSKai Wang 
5712de3b87aSKai Wang 	_dwarf_write_padding(*block, offsetp, byte, cnt);
5722de3b87aSKai Wang 
5732de3b87aSKai Wang 	return (DW_DLE_NONE);
5742de3b87aSKai Wang }
575