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