2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3 * Copyright (c) 2010 Kai Wang
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include "_libdwarf.h"
30 ELFTC_VCSID("$Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste $");
33 _dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
38 src = data + *offsetp;
41 switch (bytes_to_read) {
43 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
44 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
47 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
50 ret |= ((uint64_t) src[1]) << 8;
59 *offsetp += bytes_to_read;
65 _dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
73 switch (bytes_to_read) {
75 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
76 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
79 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
82 ret |= ((uint64_t) src[1]) << 8;
91 *data += bytes_to_read;
97 _dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
102 src = data + *offsetp;
104 switch (bytes_to_read) {
109 ret = src[1] | ((uint64_t) src[0]) << 8;
112 ret = src[3] | ((uint64_t) src[2]) << 8;
113 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
116 ret = src[7] | ((uint64_t) src[6]) << 8;
117 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
118 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
119 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
125 *offsetp += bytes_to_read;
131 _dwarf_decode_msb(uint8_t **data, int bytes_to_read)
139 switch (bytes_to_read) {
144 ret = src[1] | ((uint64_t) src[0]) << 8;
147 ret = src[3] | ((uint64_t) src[2]) << 8;
148 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
151 ret = src[7] | ((uint64_t) src[6]) << 8;
152 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
153 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
154 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
161 *data += bytes_to_read;
167 _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
172 dst = data + *offsetp;
174 switch (bytes_to_write) {
176 dst[7] = (value >> 56) & 0xff;
177 dst[6] = (value >> 48) & 0xff;
178 dst[5] = (value >> 40) & 0xff;
179 dst[4] = (value >> 32) & 0xff;
182 dst[3] = (value >> 24) & 0xff;
183 dst[2] = (value >> 16) & 0xff;
186 dst[1] = (value >> 8) & 0xff;
189 dst[0] = value & 0xff;
195 *offsetp += bytes_to_write;
199 _dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
200 uint64_t value, int bytes_to_write, Dwarf_Error *error)
205 while (*offsetp + bytes_to_write > *size) {
207 *block = realloc(*block, (size_t) *size);
208 if (*block == NULL) {
209 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
210 return (DW_DLE_MEMORY);
214 _dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
216 return (DW_DLE_NONE);
220 _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
225 dst = data + *offsetp;
227 switch (bytes_to_write) {
229 dst[7] = value & 0xff;
230 dst[6] = (value >> 8) & 0xff;
231 dst[5] = (value >> 16) & 0xff;
232 dst[4] = (value >> 24) & 0xff;
236 dst[3] = value & 0xff;
237 dst[2] = (value >> 8) & 0xff;
241 dst[1] = value & 0xff;
245 dst[0] = value & 0xff;
251 *offsetp += bytes_to_write;
255 _dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
256 uint64_t value, int bytes_to_write, Dwarf_Error *error)
261 while (*offsetp + bytes_to_write > *size) {
263 *block = realloc(*block, (size_t) *size);
264 if (*block == NULL) {
265 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
266 return (DW_DLE_MEMORY);
270 _dwarf_write_msb(*block, offsetp, value, bytes_to_write);
272 return (DW_DLE_NONE);
276 _dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
283 src = data + *offsetp;
287 ret |= ((b & 0x7f) << shift);
290 } while ((b & 0x80) != 0);
292 if (shift < 64 && (b & 0x40) != 0)
293 ret |= (-1 << shift);
299 _dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
310 if ((val == 0 && (*p & 0x40) == 0) ||
311 (val == -1 && (*p & 0x40) != 0)) {
322 _dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
323 int64_t val, Dwarf_Error *error)
329 while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
332 *block = realloc(*block, (size_t) *size);
333 if (*block == NULL) {
334 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
335 return (DW_DLE_MEMORY);
341 return (DW_DLE_NONE);
345 _dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
352 src = data + *offsetp;
356 ret |= ((b & 0x7f) << shift);
359 } while ((b & 0x80) != 0);
365 _dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
385 _dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
386 uint64_t val, Dwarf_Error *error)
392 while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
395 *block = realloc(*block, (size_t) *size);
396 if (*block == NULL) {
397 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
398 return (DW_DLE_MEMORY);
404 return (DW_DLE_NONE);
408 _dwarf_decode_sleb128(uint8_t **dp)
418 ret |= ((b & 0x7f) << shift);
420 } while ((b & 0x80) != 0);
422 if (shift < 64 && (b & 0x40) != 0)
423 ret |= (-1 << shift);
431 _dwarf_decode_uleb128(uint8_t **dp)
441 ret |= ((b & 0x7f) << shift);
443 } while ((b & 0x80) != 0);
451 _dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
455 ret = src = (char *) data + *offsetp;
457 while (*src != '\0' && *offsetp < size) {
462 if (*src == '\0' && *offsetp < size)
469 _dwarf_write_string(void *data, uint64_t *offsetp, char *string)
473 dst = (char *) data + *offsetp;
475 (*offsetp) += strlen(string) + 1;
479 _dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
480 char *string, Dwarf_Error *error)
486 len = strlen(string) + 1;
487 while (*offsetp + len > *size) {
489 *block = realloc(*block, (size_t) *size);
490 if (*block == NULL) {
491 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
492 return (DW_DLE_MEMORY);
496 _dwarf_write_string(*block, offsetp, string);
498 return (DW_DLE_NONE);
502 _dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
506 ret = src = (uint8_t *) data + *offsetp;
508 (*offsetp) += length;
514 _dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
519 dst = (uint8_t *) data + *offsetp;
520 memcpy(dst, blk, length);
521 (*offsetp) += length;
525 _dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
526 uint8_t *blk, uint64_t length, Dwarf_Error *error)
531 while (*offsetp + length > *size) {
533 *block = realloc(*block, (size_t) *size);
534 if (*block == NULL) {
535 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
536 return (DW_DLE_MEMORY);
540 _dwarf_write_block(*block, offsetp, blk, length);
542 return (DW_DLE_NONE);
546 _dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
551 dst = (uint8_t *) data + *offsetp;
552 memset(dst, byte, length);
553 (*offsetp) += length;
557 _dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
558 uint8_t byte, uint64_t cnt, Dwarf_Error *error)
562 while (*offsetp + cnt > *size) {
564 *block = realloc(*block, (size_t) *size);
565 if (*block == NULL) {
566 DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
567 return (DW_DLE_MEMORY);
571 _dwarf_write_padding(*block, offsetp, byte, cnt);
573 return (DW_DLE_NONE);