Home | History | Annotate | Line # | Download | only in libdwarf
libdwarf_rw.c revision 1.3
      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 (at) 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