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