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