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