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