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