libdwarf_rw.c revision 295577
1273806Snp/*- 2319255Snp * Copyright (c) 2007 John Birrell (jb@freebsd.org) 3319255Snp * Copyright (c) 2010 Kai Wang 4319255Snp * All rights reserved. 5319255Snp * 6273806Snp * Redistribution and use in source and binary forms, with or without 7273806Snp * modification, are permitted provided that the following conditions 8273806Snp * are met: 9273806Snp * 1. Redistributions of source code must retain the above copyright 10273806Snp * notice, this list of conditions and the following disclaimer. 11273806Snp * 2. Redistributions in binary form must reproduce the above copyright 12273806Snp * notice, this list of conditions and the following disclaimer in the 13273806Snp * documentation and/or other materials provided with the distribution. 14273806Snp * 15273806Snp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16273806Snp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17273806Snp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18273806Snp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19273806Snp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20273806Snp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21273806Snp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22273806Snp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23273806Snp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24273806Snp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25273806Snp * SUCH DAMAGE. 26273806Snp */ 27273806Snp 28273806Snp#include "_libdwarf.h" 29273806Snp 30273806SnpELFTC_VCSID("$Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste $"); 31273806Snp 32273806Snpuint64_t 33273806Snp_dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read) 34273806Snp{ 35273806Snp uint64_t ret; 36273806Snp uint8_t *src; 37273806Snp 38273806Snp src = data + *offsetp; 39273806Snp 40273806Snp ret = 0; 41273806Snp switch (bytes_to_read) { 42273806Snp case 8: 43273806Snp ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; 44273806Snp ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; 45273806Snp /* FALLTHROUGH */ 46273806Snp case 4: 47273806Snp ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; 48273806Snp /* FALLTHROUGH */ 49273806Snp case 2: 50273806Snp ret |= ((uint64_t) src[1]) << 8; 51273806Snp /* FALLTHROUGH */ 52273806Snp case 1: 53273806Snp ret |= src[0]; 54273806Snp break; 55273806Snp default: 56273806Snp return (0); 57273806Snp } 58273806Snp 59273806Snp *offsetp += bytes_to_read; 60273806Snp 61273806Snp return (ret); 62273806Snp} 63273806Snp 64273806Snpuint64_t 65273806Snp_dwarf_decode_lsb(uint8_t **data, int bytes_to_read) 66273806Snp{ 67273806Snp uint64_t ret; 68273806Snp uint8_t *src; 69273806Snp 70273806Snp src = *data; 71273806Snp 72273806Snp ret = 0; 73273806Snp switch (bytes_to_read) { 74273806Snp case 8: 75273806Snp ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; 76273806Snp ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; 77273806Snp /* FALLTHROUGH */ 78273806Snp case 4: 79273806Snp ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; 80273806Snp /* FALLTHROUGH */ 81273806Snp case 2: 82273806Snp ret |= ((uint64_t) src[1]) << 8; 83273806Snp /* FALLTHROUGH */ 84273806Snp case 1: 85273806Snp ret |= src[0]; 86273806Snp break; 87273806Snp default: 88273806Snp return (0); 89273806Snp } 90273806Snp 91273806Snp *data += bytes_to_read; 92273806Snp 93273806Snp return (ret); 94273806Snp} 95273806Snp 96273806Snpuint64_t 97273806Snp_dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read) 98273806Snp{ 99273806Snp uint64_t ret; 100273806Snp uint8_t *src; 101273806Snp 102273806Snp src = data + *offsetp; 103273806Snp 104273806Snp switch (bytes_to_read) { 105273806Snp case 1: 106273806Snp ret = src[0]; 107273806Snp break; 108273806Snp case 2: 109273806Snp ret = src[1] | ((uint64_t) src[0]) << 8; 110273806Snp break; 111273806Snp case 4: 112273806Snp ret = src[3] | ((uint64_t) src[2]) << 8; 113273806Snp ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24; 114273806Snp break; 115273806Snp case 8: 116273806Snp ret = src[7] | ((uint64_t) src[6]) << 8; 117273806Snp ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24; 118273806Snp ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40; 119273806Snp ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56; 120273806Snp break; 121273806Snp default: 122273806Snp return (0); 123273806Snp } 124273806Snp 125273806Snp *offsetp += bytes_to_read; 126273806Snp 127273806Snp return (ret); 128273806Snp} 129273806Snp 130273806Snpuint64_t 131273806Snp_dwarf_decode_msb(uint8_t **data, int bytes_to_read) 132273806Snp{ 133273806Snp uint64_t ret; 134273806Snp uint8_t *src; 135273806Snp 136273806Snp src = *data; 137273806Snp 138273806Snp ret = 0; 139273806Snp switch (bytes_to_read) { 140273806Snp case 1: 141273806Snp ret = src[0]; 142273806Snp break; 143273806Snp case 2: 144273806Snp ret = src[1] | ((uint64_t) src[0]) << 8; 145273806Snp break; 146273806Snp case 4: 147273806Snp ret = src[3] | ((uint64_t) src[2]) << 8; 148273806Snp ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24; 149273806Snp break; 150273806Snp case 8: 151273806Snp ret = src[7] | ((uint64_t) src[6]) << 8; 152273806Snp ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24; 153273806Snp ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40; 154273806Snp ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56; 155273806Snp break; 156273806Snp default: 157273806Snp return (0); 158273806Snp break; 159273806Snp } 160273806Snp 161273806Snp *data += bytes_to_read; 162273806Snp 163273806Snp return (ret); 164273806Snp} 165273806Snp 166273806Snpvoid 167273806Snp_dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value, 168273806Snp int bytes_to_write) 169273806Snp{ 170273806Snp uint8_t *dst; 171273806Snp 172273806Snp dst = data + *offsetp; 173273806Snp 174273806Snp switch (bytes_to_write) { 175273806Snp case 8: 176273806Snp dst[7] = (value >> 56) & 0xff; 177273806Snp dst[6] = (value >> 48) & 0xff; 178273806Snp dst[5] = (value >> 40) & 0xff; 179273806Snp dst[4] = (value >> 32) & 0xff; 180273806Snp /* FALLTHROUGH */ 181273806Snp case 4: 182273806Snp dst[3] = (value >> 24) & 0xff; 183273806Snp dst[2] = (value >> 16) & 0xff; 184273806Snp /* FALLTHROUGH */ 185273806Snp case 2: 186273806Snp dst[1] = (value >> 8) & 0xff; 187273806Snp /* FALLTHROUGH */ 188273806Snp case 1: 189273806Snp dst[0] = value & 0xff; 190273806Snp break; 191273806Snp default: 192273806Snp return; 193273806Snp } 194273806Snp 195273806Snp *offsetp += bytes_to_write; 196273806Snp} 197273806Snp 198273806Snpint 199273806Snp_dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp, 200273806Snp uint64_t value, int bytes_to_write, Dwarf_Error *error) 201273806Snp{ 202273806Snp 203273806Snp assert(*size > 0); 204273806Snp 205273806Snp while (*offsetp + bytes_to_write > *size) { 206273806Snp *size *= 2; 207273806Snp *block = realloc(*block, (size_t) *size); 208273806Snp if (*block == NULL) { 209273806Snp DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 210273806Snp return (DW_DLE_MEMORY); 211273806Snp } 212273806Snp } 213273806Snp 214273806Snp _dwarf_write_lsb(*block, offsetp, value, bytes_to_write); 215273806Snp 216273806Snp return (DW_DLE_NONE); 217273806Snp} 218273806Snp 219273806Snpvoid 220273806Snp_dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value, 221273806Snp int bytes_to_write) 222273806Snp{ 223273806Snp uint8_t *dst; 224273806Snp 225273806Snp dst = data + *offsetp; 226273806Snp 227273806Snp switch (bytes_to_write) { 228273806Snp case 8: 229273806Snp dst[7] = value & 0xff; 230273806Snp dst[6] = (value >> 8) & 0xff; 231273806Snp dst[5] = (value >> 16) & 0xff; 232273806Snp dst[4] = (value >> 24) & 0xff; 233273806Snp value >>= 32; 234273806Snp /* FALLTHROUGH */ 235273806Snp case 4: 236273806Snp dst[3] = value & 0xff; 237273806Snp dst[2] = (value >> 8) & 0xff; 238273806Snp value >>= 16; 239273806Snp /* FALLTHROUGH */ 240273806Snp case 2: 241273806Snp dst[1] = value & 0xff; 242273806Snp value >>= 8; 243273806Snp /* FALLTHROUGH */ 244273806Snp case 1: 245273806Snp dst[0] = value & 0xff; 246273806Snp break; 247273806Snp default: 248273806Snp return; 249273806Snp } 250273806Snp 251273806Snp *offsetp += bytes_to_write; 252273806Snp} 253273806Snp 254273806Snpint 255273806Snp_dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp, 256273806Snp uint64_t value, int bytes_to_write, Dwarf_Error *error) 257273806Snp{ 258273806Snp 259273806Snp assert(*size > 0); 260273806Snp 261273806Snp while (*offsetp + bytes_to_write > *size) { 262273806Snp *size *= 2; 263273806Snp *block = realloc(*block, (size_t) *size); 264273806Snp if (*block == NULL) { 265273806Snp DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 266273806Snp return (DW_DLE_MEMORY); 267273806Snp } 268273806Snp } 269273806Snp 270273806Snp _dwarf_write_msb(*block, offsetp, value, bytes_to_write); 271273806Snp 272273806Snp return (DW_DLE_NONE); 273273806Snp} 274273806Snp 275273806Snpint64_t 276273806Snp_dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp) 277273806Snp{ 278273806Snp int64_t ret = 0; 279273806Snp uint8_t b; 280273806Snp int shift = 0; 281273806Snp uint8_t *src; 282273806Snp 283273806Snp src = data + *offsetp; 284273806Snp 285273806Snp do { 286273806Snp b = *src++; 287273806Snp ret |= ((b & 0x7f) << shift); 288273806Snp (*offsetp)++; 289273806Snp shift += 7; 290273806Snp } while ((b & 0x80) != 0); 291273806Snp 292273806Snp if (shift < 64 && (b & 0x40) != 0) 293273806Snp ret |= (-1 << shift); 294273806Snp 295273806Snp return (ret); 296273806Snp} 297273806Snp 298273806Snpint 299273806Snp_dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val) 300273806Snp{ 301273806Snp uint8_t *p; 302273806Snp 303273806Snp p = data; 304273806Snp 305273806Snp for (;;) { 306273806Snp if (p >= end) 307273806Snp return (-1); 308273806Snp *p = val & 0x7f; 309273806Snp val >>= 7; 310273806Snp if ((val == 0 && (*p & 0x40) == 0) || 311273806Snp (val == -1 && (*p & 0x40) != 0)) { 312273806Snp p++; 313273806Snp break; 314273806Snp } 315273806Snp *p++ |= 0x80; 316273806Snp } 317273806Snp 318273806Snp return (p - data); 319273806Snp} 320273806Snp 321273806Snpint 322273806Snp_dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp, 323273806Snp int64_t val, Dwarf_Error *error) 324273806Snp{ 325273806Snp int len; 326273806Snp 327273806Snp assert(*size > 0); 328273806Snp 329273806Snp while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size, 330273806Snp val)) < 0) { 331273806Snp *size *= 2; 332273806Snp *block = realloc(*block, (size_t) *size); 333273806Snp if (*block == NULL) { 334273806Snp DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 335273806Snp return (DW_DLE_MEMORY); 336273806Snp } 337273806Snp } 338273806Snp 339273806Snp *offsetp += len; 340273806Snp 341273806Snp return (DW_DLE_NONE); 342273806Snp} 343273806Snp 344273806Snpuint64_t 345273806Snp_dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp) 346319255Snp{ 347319255Snp uint64_t ret = 0; 348319255Snp uint8_t b; 349319255Snp int shift = 0; 350319255Snp uint8_t *src; 351319255Snp 352319255Snp src = data + *offsetp; 353319255Snp 354319255Snp do { 355319255Snp b = *src++; 356319255Snp ret |= ((b & 0x7f) << shift); 357319255Snp (*offsetp)++; 358319255Snp shift += 7; 359319255Snp } while ((b & 0x80) != 0); 360319255Snp 361319255Snp return (ret); 362319255Snp} 363319255Snp 364319255Snpint 365319255Snp_dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val) 366319255Snp{ 367319255Snp uint8_t *p; 368319255Snp 369319255Snp p = data; 370319255Snp 371319255Snp do { 372319255Snp if (p >= end) 373319255Snp return (-1); 374319255Snp *p = val & 0x7f; 375319255Snp val >>= 7; 376319255Snp if (val > 0) 377319255Snp *p |= 0x80; 378319255Snp p++; 379319255Snp } while (val > 0); 380319255Snp 381319255Snp return (p - data); 382319255Snp} 383319255Snp 384319255Snpint 385319255Snp_dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp, 386319255Snp uint64_t val, Dwarf_Error *error) 387319255Snp{ 388319255Snp int len; 389319255Snp 390319255Snp assert(*size > 0); 391319255Snp 392319255Snp while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size, 393319255Snp val)) < 0) { 394319255Snp *size *= 2; 395319255Snp *block = realloc(*block, (size_t) *size); 396319255Snp if (*block == NULL) { 397319255Snp DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 398319255Snp return (DW_DLE_MEMORY); 399319255Snp } 400319255Snp } 401319255Snp 402319255Snp *offsetp += len; 403319255Snp 404319255Snp return (DW_DLE_NONE); 405319255Snp} 406319255Snp 407319255Snpint64_t 408319255Snp_dwarf_decode_sleb128(uint8_t **dp) 409319255Snp{ 410319255Snp int64_t ret = 0; 411319255Snp uint8_t b; 412319255Snp int shift = 0; 413319255Snp 414319255Snp uint8_t *src = *dp; 415319255Snp 416319255Snp do { 417319255Snp b = *src++; 418319255Snp ret |= ((b & 0x7f) << shift); 419319255Snp shift += 7; 420319255Snp } while ((b & 0x80) != 0); 421319255Snp 422319255Snp if (shift < 64 && (b & 0x40) != 0) 423319255Snp ret |= (-1 << shift); 424319255Snp 425319255Snp *dp = src; 426319255Snp 427319255Snp return (ret); 428319255Snp} 429319255Snp 430319255Snpuint64_t 431319255Snp_dwarf_decode_uleb128(uint8_t **dp) 432319255Snp{ 433319255Snp uint64_t ret = 0; 434319255Snp uint8_t b; 435319255Snp int shift = 0; 436319255Snp 437319255Snp uint8_t *src = *dp; 438319255Snp 439319255Snp do { 440319255Snp b = *src++; 441319255Snp ret |= ((b & 0x7f) << shift); 442319255Snp shift += 7; 443319255Snp } while ((b & 0x80) != 0); 444319255Snp 445319255Snp *dp = src; 446319255Snp 447319255Snp return (ret); 448319255Snp} 449319255Snp 450319255Snpchar * 451319255Snp_dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp) 452319255Snp{ 453319255Snp char *ret, *src; 454319255Snp 455319255Snp ret = src = (char *) data + *offsetp; 456319255Snp 457319255Snp while (*src != '\0' && *offsetp < size) { 458319255Snp src++; 459319255Snp (*offsetp)++; 460319255Snp } 461319255Snp 462319255Snp if (*src == '\0' && *offsetp < size) 463319255Snp (*offsetp)++; 464319255Snp 465319255Snp return (ret); 466319255Snp} 467319255Snp 468319255Snpvoid 469319255Snp_dwarf_write_string(void *data, uint64_t *offsetp, char *string) 470319255Snp{ 471319255Snp char *dst; 472319255Snp 473319255Snp dst = (char *) data + *offsetp; 474319255Snp strcpy(dst, string); 475273806Snp (*offsetp) += strlen(string) + 1; 476273806Snp} 477273806Snp 478319255Snpint 479319255Snp_dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp, 480319255Snp char *string, Dwarf_Error *error) 481273806Snp{ 482273806Snp size_t len; 483273806Snp 484273806Snp assert(*size > 0); 485273806Snp 486273806Snp len = strlen(string) + 1; 487273806Snp while (*offsetp + len > *size) { 488273806Snp *size *= 2; 489273806Snp *block = realloc(*block, (size_t) *size); 490273806Snp if (*block == NULL) { 491273806Snp DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 492273806Snp return (DW_DLE_MEMORY); 493273806Snp } 494273806Snp } 495273806Snp 496273806Snp _dwarf_write_string(*block, offsetp, string); 497273806Snp 498273806Snp return (DW_DLE_NONE); 499273806Snp} 500273806Snp 501273806Snpuint8_t * 502273806Snp_dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length) 503273806Snp{ 504273806Snp uint8_t *ret, *src; 505273806Snp 506273806Snp ret = src = (uint8_t *) data + *offsetp; 507273806Snp 508273806Snp (*offsetp) += length; 509273806Snp 510273806Snp return (ret); 511319255Snp} 512319255Snp 513319255Snpvoid 514319255Snp_dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk, 515273806Snp uint64_t length) 516273806Snp{ 517273806Snp uint8_t *dst; 518273806Snp 519273806Snp dst = (uint8_t *) data + *offsetp; 520273806Snp memcpy(dst, blk, length); 521273806Snp (*offsetp) += length; 522273806Snp} 523273806Snp 524273806Snpint 525273806Snp_dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp, 526273806Snp uint8_t *blk, uint64_t length, Dwarf_Error *error) 527273806Snp{ 528273806Snp 529273806Snp assert(*size > 0); 530273806Snp 531273806Snp while (*offsetp + length > *size) { 532273806Snp *size *= 2; 533273806Snp *block = realloc(*block, (size_t) *size); 534273806Snp if (*block == NULL) { 535273806Snp DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 536273806Snp return (DW_DLE_MEMORY); 537273806Snp } 538273806Snp } 539273806Snp 540273806Snp _dwarf_write_block(*block, offsetp, blk, length); 541273806Snp 542273806Snp return (DW_DLE_NONE); 543273806Snp} 544273806Snp 545273806Snpvoid 546273806Snp_dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte, 547273806Snp uint64_t length) 548273806Snp{ 549273806Snp uint8_t *dst; 550273806Snp 551273806Snp dst = (uint8_t *) data + *offsetp; 552273806Snp memset(dst, byte, length); 553273806Snp (*offsetp) += length; 554273806Snp} 555273806Snp 556273806Snpint 557273806Snp_dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp, 558273806Snp uint8_t byte, uint64_t cnt, Dwarf_Error *error) 559273806Snp{ 560273806Snp assert(*size > 0); 561273806Snp 562273806Snp while (*offsetp + cnt > *size) { 563273806Snp *size *= 2; 564273806Snp *block = realloc(*block, (size_t) *size); 565273806Snp if (*block == NULL) { 566273806Snp DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY); 567273806Snp return (DW_DLE_MEMORY); 568273806Snp } 569273806Snp } 570273806Snp 571273806Snp _dwarf_write_padding(*block, offsetp, byte, cnt); 572273806Snp 573273806Snp return (DW_DLE_NONE); 574273806Snp} 575273806Snp