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