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