1 /*- 2 * Copyright (c) 2009-2011,2014 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include "_libdwarf.h" 28 29 ELFTC_VCSID("$Id: libdwarf_frame.c 3589 2018-03-13 20:34:33Z kaiwang27 $"); 30 31 static int 32 _dwarf_frame_find_cie(Dwarf_FrameSec fs, Dwarf_Unsigned offset, 33 Dwarf_Cie *ret_cie) 34 { 35 Dwarf_Cie cie; 36 37 STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) { 38 if (cie->cie_offset == offset) 39 break; 40 } 41 42 if (cie == NULL) 43 return (DW_DLE_NO_ENTRY); 44 45 if (ret_cie != NULL) 46 *ret_cie = cie; 47 48 return (DW_DLE_NONE); 49 } 50 51 static int 52 _dwarf_frame_read_lsb_encoded(Dwarf_Debug dbg, Dwarf_Cie cie, uint64_t *val, 53 uint8_t *data, uint64_t *offsetp, uint8_t encode, Dwarf_Addr pc, 54 Dwarf_Error *error) 55 { 56 uint8_t application; 57 58 if (encode == DW_EH_PE_omit) 59 return (DW_DLE_NONE); 60 61 application = encode & 0xf0; 62 encode &= 0x0f; 63 64 switch (encode) { 65 case DW_EH_PE_absptr: 66 *val = dbg->read(data, offsetp, cie->cie_addrsize); 67 break; 68 case DW_EH_PE_uleb128: 69 *val = _dwarf_read_uleb128(data, offsetp); 70 break; 71 case DW_EH_PE_udata2: 72 *val = dbg->read(data, offsetp, 2); 73 break; 74 case DW_EH_PE_udata4: 75 *val = dbg->read(data, offsetp, 4); 76 break; 77 case DW_EH_PE_udata8: 78 *val = dbg->read(data, offsetp, 8); 79 break; 80 case DW_EH_PE_sleb128: 81 *val = _dwarf_read_sleb128(data, offsetp); 82 break; 83 case DW_EH_PE_sdata2: 84 *val = (int16_t) dbg->read(data, offsetp, 2); 85 break; 86 case DW_EH_PE_sdata4: 87 *val = (int32_t) dbg->read(data, offsetp, 4); 88 break; 89 case DW_EH_PE_sdata8: 90 *val = dbg->read(data, offsetp, 8); 91 break; 92 default: 93 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN); 94 return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN); 95 } 96 97 if (application == DW_EH_PE_pcrel) { 98 /* 99 * Value is relative to .eh_frame section virtual addr. 100 */ 101 switch (encode) { 102 case DW_EH_PE_uleb128: 103 case DW_EH_PE_udata2: 104 case DW_EH_PE_udata4: 105 case DW_EH_PE_udata8: 106 *val += pc; 107 break; 108 case DW_EH_PE_sleb128: 109 case DW_EH_PE_sdata2: 110 case DW_EH_PE_sdata4: 111 case DW_EH_PE_sdata8: 112 *val = pc + (int64_t) *val; 113 break; 114 default: 115 /* DW_EH_PE_absptr is absolute value. */ 116 break; 117 } 118 } 119 120 /* XXX Applications other than DW_EH_PE_pcrel are not handled. */ 121 122 return (DW_DLE_NONE); 123 } 124 125 static int 126 _dwarf_frame_parse_lsb_cie_augment(Dwarf_Debug dbg, Dwarf_Cie cie, 127 Dwarf_Error *error) 128 { 129 uint8_t *aug_p, *augdata_p; 130 uint64_t val, offset; 131 uint8_t encode; 132 int ret; 133 134 assert(cie->cie_augment != NULL && *cie->cie_augment == 'z'); 135 136 /* 137 * Here we're only interested in the presence of augment 'R' 138 * and associated CIE augment data, which describes the 139 * encoding scheme of FDE PC begin and range. 140 */ 141 aug_p = &cie->cie_augment[1]; 142 augdata_p = cie->cie_augdata; 143 while (*aug_p != '\0') { 144 switch (*aug_p) { 145 case 'S': 146 break; 147 case 'L': 148 /* Skip one augment in augment data. */ 149 augdata_p++; 150 break; 151 case 'P': 152 /* Skip two augments in augment data. */ 153 encode = *augdata_p++; 154 offset = 0; 155 ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val, 156 augdata_p, &offset, encode, 0, error); 157 if (ret != DW_DLE_NONE) 158 return (ret); 159 augdata_p += offset; 160 break; 161 case 'R': 162 cie->cie_fde_encode = *augdata_p++; 163 break; 164 default: 165 DWARF_SET_ERROR(dbg, error, 166 DW_DLE_FRAME_AUGMENTATION_UNKNOWN); 167 return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN); 168 } 169 aug_p++; 170 } 171 172 return (DW_DLE_NONE); 173 } 174 175 static int 176 _dwarf_frame_add_cie(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds, 177 Dwarf_Unsigned *off, Dwarf_Cie *ret_cie, Dwarf_Error *error) 178 { 179 Dwarf_Cie cie; 180 uint64_t length; 181 int dwarf_size, ret; 182 char *p; 183 184 /* Check if we already added this CIE. */ 185 if (_dwarf_frame_find_cie(fs, *off, &cie) != DW_DLE_NO_ENTRY) { 186 *off += cie->cie_length + 4; 187 return (DW_DLE_NONE); 188 } 189 190 if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) { 191 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 192 return (DW_DLE_MEMORY); 193 } 194 STAILQ_INSERT_TAIL(&fs->fs_cielist, cie, cie_next); 195 196 cie->cie_dbg = dbg; 197 cie->cie_index = fs->fs_cielen; 198 cie->cie_offset = *off; 199 200 length = dbg->read(ds->ds_data, off, 4); 201 if (length == 0xffffffff) { 202 dwarf_size = 8; 203 length = dbg->read(ds->ds_data, off, 8); 204 } else 205 dwarf_size = 4; 206 207 if (length > ds->ds_size - *off) { 208 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD); 209 return (DW_DLE_DEBUG_FRAME_LENGTH_BAD); 210 } 211 212 (void) dbg->read(ds->ds_data, off, dwarf_size); /* Skip CIE id. */ 213 cie->cie_length = length; 214 215 cie->cie_version = dbg->read(ds->ds_data, off, 1); 216 if (cie->cie_version != 1 && cie->cie_version != 3 && 217 cie->cie_version != 4) { 218 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_VERSION_BAD); 219 return (DW_DLE_FRAME_VERSION_BAD); 220 } 221 222 cie->cie_augment = ds->ds_data + *off; 223 p = (char *) ds->ds_data; 224 while (p[(*off)++] != '\0') 225 ; 226 227 /* We only recognize normal .dwarf_frame and GNU .eh_frame sections. */ 228 if (*cie->cie_augment != 0 && *cie->cie_augment != 'z') { 229 *off = cie->cie_offset + ((dwarf_size == 4) ? 4 : 12) + 230 cie->cie_length; 231 return (DW_DLE_NONE); 232 } 233 234 /* Optional EH Data field for .eh_frame section. */ 235 if (strstr((char *)cie->cie_augment, "eh") != NULL) 236 cie->cie_ehdata = dbg->read(ds->ds_data, off, 237 dbg->dbg_pointer_size); 238 239 /* DWARF4 added "address_size" and "segment_size". */ 240 if (cie->cie_version == 4) { 241 cie->cie_addrsize = dbg->read(ds->ds_data, off, 1); 242 cie->cie_segmentsize = dbg->read(ds->ds_data, off, 1); 243 } else { 244 /* 245 * Otherwise (DWARF[23]) we just set CIE addrsize to the 246 * debug context pointer size. 247 */ 248 cie->cie_addrsize = dbg->dbg_pointer_size; 249 } 250 251 cie->cie_caf = _dwarf_read_uleb128(ds->ds_data, off); 252 cie->cie_daf = _dwarf_read_sleb128(ds->ds_data, off); 253 254 /* Return address register. */ 255 if (cie->cie_version == 1) 256 cie->cie_ra = dbg->read(ds->ds_data, off, 1); 257 else 258 cie->cie_ra = _dwarf_read_uleb128(ds->ds_data, off); 259 260 /* Optional CIE augmentation data for .eh_frame section. */ 261 if (*cie->cie_augment == 'z') { 262 cie->cie_auglen = _dwarf_read_uleb128(ds->ds_data, off); 263 cie->cie_augdata = ds->ds_data + *off; 264 *off += cie->cie_auglen; 265 /* 266 * XXX Use DW_EH_PE_absptr for default FDE PC start/range, 267 * in case _dwarf_frame_parse_lsb_cie_augment fails to 268 * find out the real encode. 269 */ 270 cie->cie_fde_encode = DW_EH_PE_absptr; 271 ret = _dwarf_frame_parse_lsb_cie_augment(dbg, cie, error); 272 if (ret != DW_DLE_NONE) 273 return (ret); 274 } 275 276 /* CIE Initial instructions. */ 277 cie->cie_initinst = ds->ds_data + *off; 278 if (dwarf_size == 4) 279 cie->cie_instlen = cie->cie_offset + 4 + length - *off; 280 else 281 cie->cie_instlen = cie->cie_offset + 12 + length - *off; 282 283 *off += cie->cie_instlen; 284 285 #ifdef FRAME_DEBUG 286 printf("cie:\n"); 287 printf("\tcie_version=%u cie_offset=%ju cie_length=%ju cie_augment=%s" 288 " cie_instlen=%ju cie->cie_caf=%ju cie->cie_daf=%jd off=%ju\n", 289 cie->cie_version, cie->cie_offset, cie->cie_length, 290 (char *)cie->cie_augment, cie->cie_instlen, cie->cie_caf, 291 cie->cie_daf, *off); 292 #endif 293 294 if (ret_cie != NULL) 295 *ret_cie = cie; 296 297 fs->fs_cielen++; 298 299 return (DW_DLE_NONE); 300 } 301 302 static int 303 _dwarf_frame_add_fde(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds, 304 Dwarf_Unsigned *off, int eh_frame, Dwarf_Error *error) 305 { 306 Dwarf_Cie cie; 307 Dwarf_Fde fde; 308 Dwarf_Unsigned cieoff; 309 uint64_t length, val; 310 int dwarf_size, ret; 311 312 if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) { 313 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 314 return (DW_DLE_MEMORY); 315 } 316 STAILQ_INSERT_TAIL(&fs->fs_fdelist, fde, fde_next); 317 318 fde->fde_dbg = dbg; 319 fde->fde_fs = fs; 320 fde->fde_addr = ds->ds_data + *off; 321 fde->fde_offset = *off; 322 323 length = dbg->read(ds->ds_data, off, 4); 324 if (length == 0xffffffff) { 325 dwarf_size = 8; 326 length = dbg->read(ds->ds_data, off, 8); 327 } else 328 dwarf_size = 4; 329 330 if (length > ds->ds_size - *off) { 331 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD); 332 return (DW_DLE_DEBUG_FRAME_LENGTH_BAD); 333 } 334 335 fde->fde_length = length; 336 337 if (eh_frame) { 338 fde->fde_cieoff = dbg->read(ds->ds_data, off, 4); 339 cieoff = *off - (4 + fde->fde_cieoff); 340 /* This delta should never be 0. */ 341 if (cieoff == fde->fde_offset) { 342 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_CIE_FOR_FDE); 343 return (DW_DLE_NO_CIE_FOR_FDE); 344 } 345 } else { 346 fde->fde_cieoff = dbg->read(ds->ds_data, off, dwarf_size); 347 cieoff = fde->fde_cieoff; 348 } 349 350 if (_dwarf_frame_find_cie(fs, cieoff, &cie) == 351 DW_DLE_NO_ENTRY) { 352 ret = _dwarf_frame_add_cie(dbg, fs, ds, &cieoff, &cie, 353 error); 354 if (ret != DW_DLE_NONE) 355 return (ret); 356 } 357 fde->fde_cie = cie; 358 if (eh_frame) { 359 /* 360 * The FDE PC start/range for .eh_frame is encoded according 361 * to the LSB spec's extension to DWARF2. 362 */ 363 ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val, 364 ds->ds_data, off, cie->cie_fde_encode, ds->ds_addr + *off, 365 error); 366 if (ret != DW_DLE_NONE) 367 return (ret); 368 fde->fde_initloc = val; 369 /* 370 * FDE PC range should not be relative value to anything. 371 * So pass 0 for pc value. 372 */ 373 ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val, 374 ds->ds_data, off, cie->cie_fde_encode, 0, error); 375 if (ret != DW_DLE_NONE) 376 return (ret); 377 fde->fde_adrange = val; 378 } else { 379 fde->fde_initloc = dbg->read(ds->ds_data, off, 380 cie->cie_addrsize); 381 fde->fde_adrange = dbg->read(ds->ds_data, off, 382 cie->cie_addrsize); 383 } 384 385 /* Optional FDE augmentation data for .eh_frame section. (ignored) */ 386 if (eh_frame && *cie->cie_augment == 'z') { 387 fde->fde_auglen = _dwarf_read_uleb128(ds->ds_data, off); 388 fde->fde_augdata = ds->ds_data + *off; 389 *off += fde->fde_auglen; 390 } 391 392 fde->fde_inst = ds->ds_data + *off; 393 if (dwarf_size == 4) 394 fde->fde_instlen = fde->fde_offset + 4 + length - *off; 395 else 396 fde->fde_instlen = fde->fde_offset + 12 + length - *off; 397 398 *off += fde->fde_instlen; 399 400 #ifdef FRAME_DEBUG 401 printf("fde:"); 402 if (eh_frame) 403 printf("(eh_frame)"); 404 putchar('\n'); 405 printf("\tfde_offset=%ju fde_length=%ju fde_cieoff=%ju" 406 " fde_instlen=%ju off=%ju\n", fde->fde_offset, fde->fde_length, 407 fde->fde_cieoff, fde->fde_instlen, *off); 408 #endif 409 410 fs->fs_fdelen++; 411 412 return (DW_DLE_NONE); 413 } 414 415 static void 416 _dwarf_frame_section_cleanup(Dwarf_FrameSec fs) 417 { 418 Dwarf_Cie cie, tcie; 419 Dwarf_Fde fde, tfde; 420 421 STAILQ_FOREACH_SAFE(cie, &fs->fs_cielist, cie_next, tcie) { 422 STAILQ_REMOVE(&fs->fs_cielist, cie, _Dwarf_Cie, cie_next); 423 free(cie); 424 } 425 426 STAILQ_FOREACH_SAFE(fde, &fs->fs_fdelist, fde_next, tfde) { 427 STAILQ_REMOVE(&fs->fs_fdelist, fde, _Dwarf_Fde, fde_next); 428 free(fde); 429 } 430 431 if (fs->fs_ciearray != NULL) 432 free(fs->fs_ciearray); 433 if (fs->fs_fdearray != NULL) 434 free(fs->fs_fdearray); 435 436 free(fs); 437 } 438 439 static int 440 _dwarf_frame_section_init(Dwarf_Debug dbg, Dwarf_FrameSec *frame_sec, 441 Dwarf_Section *ds, int eh_frame, Dwarf_Error *error) 442 { 443 Dwarf_FrameSec fs; 444 Dwarf_Cie cie; 445 Dwarf_Fde fde; 446 uint64_t length, offset, cie_id, entry_off; 447 int dwarf_size, i, ret; 448 449 assert(frame_sec != NULL); 450 assert(*frame_sec == NULL); 451 452 if ((fs = calloc(1, sizeof(struct _Dwarf_FrameSec))) == NULL) { 453 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 454 return (DW_DLE_MEMORY); 455 } 456 STAILQ_INIT(&fs->fs_cielist); 457 STAILQ_INIT(&fs->fs_fdelist); 458 459 offset = 0; 460 while (offset < ds->ds_size) { 461 entry_off = offset; 462 length = dbg->read(ds->ds_data, &offset, 4); 463 if (length == 0xffffffff) { 464 dwarf_size = 8; 465 length = dbg->read(ds->ds_data, &offset, 8); 466 } else 467 dwarf_size = 4; 468 469 if (length > ds->ds_size - offset || 470 (length == 0 && !eh_frame)) { 471 ret = DW_DLE_DEBUG_FRAME_LENGTH_BAD; 472 DWARF_SET_ERROR(dbg, error, ret); 473 goto fail_cleanup; 474 } 475 476 /* Check terminator for .eh_frame */ 477 if (eh_frame && length == 0) 478 break; 479 480 cie_id = dbg->read(ds->ds_data, &offset, dwarf_size); 481 482 if (eh_frame) { 483 /* GNU .eh_frame use CIE id 0. */ 484 if (cie_id == 0) 485 ret = _dwarf_frame_add_cie(dbg, fs, ds, 486 &entry_off, NULL, error); 487 else 488 ret = _dwarf_frame_add_fde(dbg, fs, ds, 489 &entry_off, 1, error); 490 } else { 491 /* .dwarf_frame use CIE id ~0 */ 492 if ((dwarf_size == 4 && cie_id == ~0U) || 493 (dwarf_size == 8 && cie_id == ~0ULL)) 494 ret = _dwarf_frame_add_cie(dbg, fs, ds, 495 &entry_off, NULL, error); 496 else 497 ret = _dwarf_frame_add_fde(dbg, fs, ds, 498 &entry_off, 0, error); 499 } 500 501 if (ret != DW_DLE_NONE) 502 goto fail_cleanup; 503 504 offset = entry_off; 505 } 506 507 /* Create CIE array. */ 508 if (fs->fs_cielen > 0) { 509 if ((fs->fs_ciearray = malloc(sizeof(Dwarf_Cie) * 510 fs->fs_cielen)) == NULL) { 511 ret = DW_DLE_MEMORY; 512 DWARF_SET_ERROR(dbg, error, ret); 513 goto fail_cleanup; 514 } 515 i = 0; 516 STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) { 517 fs->fs_ciearray[i++] = cie; 518 } 519 assert((Dwarf_Unsigned)i == fs->fs_cielen); 520 } 521 522 /* Create FDE array. */ 523 if (fs->fs_fdelen > 0) { 524 if ((fs->fs_fdearray = malloc(sizeof(Dwarf_Fde) * 525 fs->fs_fdelen)) == NULL) { 526 ret = DW_DLE_MEMORY; 527 DWARF_SET_ERROR(dbg, error, ret); 528 goto fail_cleanup; 529 } 530 i = 0; 531 STAILQ_FOREACH(fde, &fs->fs_fdelist, fde_next) { 532 fs->fs_fdearray[i++] = fde; 533 } 534 assert((Dwarf_Unsigned)i == fs->fs_fdelen); 535 } 536 537 *frame_sec = fs; 538 539 return (DW_DLE_NONE); 540 541 fail_cleanup: 542 543 _dwarf_frame_section_cleanup(fs); 544 545 return (ret); 546 } 547 548 static int 549 _dwarf_frame_run_inst(Dwarf_Debug dbg, Dwarf_Regtable3 *rt, uint8_t addr_size, 550 uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf, 551 Dwarf_Addr pc, Dwarf_Addr pc_req, Dwarf_Addr *row_pc, Dwarf_Error *error) 552 { 553 Dwarf_Regtable3 *init_rt, *saved_rt; 554 uint8_t *p, *pe; 555 uint8_t high2, low6; 556 uint64_t reg, reg2, uoff, soff; 557 int ret; 558 559 #define CFA rt->rt3_cfa_rule 560 #define INITCFA init_rt->rt3_cfa_rule 561 #define RL rt->rt3_rules 562 #define INITRL init_rt->rt3_rules 563 564 #define CHECK_TABLE_SIZE(x) \ 565 do { \ 566 if ((x) >= rt->rt3_reg_table_size) { \ 567 DWARF_SET_ERROR(dbg, error, \ 568 DW_DLE_DF_REG_NUM_TOO_HIGH); \ 569 ret = DW_DLE_DF_REG_NUM_TOO_HIGH; \ 570 goto program_done; \ 571 } \ 572 } while(0) 573 574 #ifdef FRAME_DEBUG 575 printf("frame_run_inst: (caf=%ju, daf=%jd)\n", caf, daf); 576 #endif 577 578 ret = DW_DLE_NONE; 579 init_rt = saved_rt = NULL; 580 *row_pc = pc; 581 582 /* Save a copy of the table as initial state. */ 583 _dwarf_frame_regtable_copy(dbg, &init_rt, rt, error); 584 585 p = insts; 586 pe = p + len; 587 588 while (p < pe) { 589 590 #ifdef FRAME_DEBUG 591 printf("p=%p pe=%p pc=%#jx pc_req=%#jx\n", p, pe, pc, pc_req); 592 #endif 593 594 if (*p == DW_CFA_nop) { 595 #ifdef FRAME_DEBUG 596 printf("DW_CFA_nop\n"); 597 #endif 598 p++; 599 continue; 600 } 601 602 high2 = *p & 0xc0; 603 low6 = *p & 0x3f; 604 p++; 605 606 if (high2 > 0) { 607 switch (high2) { 608 case DW_CFA_advance_loc: 609 pc += low6 * caf; 610 #ifdef FRAME_DEBUG 611 printf("DW_CFA_advance_loc(%#jx(%u))\n", pc, 612 low6); 613 #endif 614 if (pc_req < pc) 615 goto program_done; 616 break; 617 case DW_CFA_offset: 618 *row_pc = pc; 619 CHECK_TABLE_SIZE(low6); 620 RL[low6].dw_offset_relevant = 1; 621 RL[low6].dw_value_type = DW_EXPR_OFFSET; 622 RL[low6].dw_regnum = dbg->dbg_frame_cfa_value; 623 RL[low6].dw_offset_or_block_len = 624 _dwarf_decode_uleb128(&p) * daf; 625 #ifdef FRAME_DEBUG 626 printf("DW_CFA_offset(%jd)\n", 627 RL[low6].dw_offset_or_block_len); 628 #endif 629 break; 630 case DW_CFA_restore: 631 *row_pc = pc; 632 CHECK_TABLE_SIZE(low6); 633 memcpy(&RL[low6], &INITRL[low6], 634 sizeof(Dwarf_Regtable_Entry3)); 635 #ifdef FRAME_DEBUG 636 printf("DW_CFA_restore(%u)\n", low6); 637 #endif 638 break; 639 default: 640 DWARF_SET_ERROR(dbg, error, 641 DW_DLE_FRAME_INSTR_EXEC_ERROR); 642 ret = DW_DLE_FRAME_INSTR_EXEC_ERROR; 643 goto program_done; 644 } 645 646 continue; 647 } 648 649 switch (low6) { 650 case DW_CFA_set_loc: 651 pc = dbg->decode(&p, addr_size); 652 #ifdef FRAME_DEBUG 653 printf("DW_CFA_set_loc(pc=%#jx)\n", pc); 654 #endif 655 if (pc_req < pc) 656 goto program_done; 657 break; 658 case DW_CFA_advance_loc1: 659 pc += dbg->decode(&p, 1) * caf; 660 #ifdef FRAME_DEBUG 661 printf("DW_CFA_set_loc1(pc=%#jx)\n", pc); 662 #endif 663 if (pc_req < pc) 664 goto program_done; 665 break; 666 case DW_CFA_advance_loc2: 667 pc += dbg->decode(&p, 2) * caf; 668 #ifdef FRAME_DEBUG 669 printf("DW_CFA_set_loc2(pc=%#jx)\n", pc); 670 #endif 671 if (pc_req < pc) 672 goto program_done; 673 break; 674 case DW_CFA_advance_loc4: 675 pc += dbg->decode(&p, 4) * caf; 676 #ifdef FRAME_DEBUG 677 printf("DW_CFA_set_loc4(pc=%#jx)\n", pc); 678 #endif 679 if (pc_req < pc) 680 goto program_done; 681 break; 682 case DW_CFA_offset_extended: 683 *row_pc = pc; 684 reg = _dwarf_decode_uleb128(&p); 685 uoff = _dwarf_decode_uleb128(&p); 686 CHECK_TABLE_SIZE(reg); 687 RL[reg].dw_offset_relevant = 1; 688 RL[reg].dw_value_type = DW_EXPR_OFFSET; 689 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value; 690 RL[reg].dw_offset_or_block_len = uoff * daf; 691 #ifdef FRAME_DEBUG 692 printf("DW_CFA_offset_extended(reg=%ju,uoff=%ju)\n", 693 reg, uoff); 694 #endif 695 break; 696 case DW_CFA_restore_extended: 697 *row_pc = pc; 698 reg = _dwarf_decode_uleb128(&p); 699 CHECK_TABLE_SIZE(reg); 700 memcpy(&RL[reg], &INITRL[reg], 701 sizeof(Dwarf_Regtable_Entry3)); 702 #ifdef FRAME_DEBUG 703 printf("DW_CFA_restore_extended(%ju)\n", reg); 704 #endif 705 break; 706 case DW_CFA_undefined: 707 *row_pc = pc; 708 reg = _dwarf_decode_uleb128(&p); 709 CHECK_TABLE_SIZE(reg); 710 RL[reg].dw_offset_relevant = 0; 711 RL[reg].dw_regnum = dbg->dbg_frame_undefined_value; 712 #ifdef FRAME_DEBUG 713 printf("DW_CFA_undefined(%ju)\n", reg); 714 #endif 715 break; 716 case DW_CFA_same_value: 717 reg = _dwarf_decode_uleb128(&p); 718 CHECK_TABLE_SIZE(reg); 719 RL[reg].dw_offset_relevant = 0; 720 RL[reg].dw_regnum = dbg->dbg_frame_same_value; 721 #ifdef FRAME_DEBUG 722 printf("DW_CFA_same_value(%ju)\n", reg); 723 #endif 724 break; 725 case DW_CFA_register: 726 *row_pc = pc; 727 reg = _dwarf_decode_uleb128(&p); 728 reg2 = _dwarf_decode_uleb128(&p); 729 CHECK_TABLE_SIZE(reg); 730 RL[reg].dw_offset_relevant = 0; 731 RL[reg].dw_regnum = reg2; 732 #ifdef FRAME_DEBUG 733 printf("DW_CFA_register(reg=%ju,reg2=%ju)\n", reg, 734 reg2); 735 #endif 736 break; 737 case DW_CFA_remember_state: 738 _dwarf_frame_regtable_copy(dbg, &saved_rt, rt, error); 739 #ifdef FRAME_DEBUG 740 printf("DW_CFA_remember_state\n"); 741 #endif 742 break; 743 case DW_CFA_restore_state: 744 *row_pc = pc; 745 _dwarf_frame_regtable_copy(dbg, &rt, saved_rt, error); 746 #ifdef FRAME_DEBUG 747 printf("DW_CFA_restore_state\n"); 748 #endif 749 break; 750 case DW_CFA_def_cfa: 751 *row_pc = pc; 752 reg = _dwarf_decode_uleb128(&p); 753 uoff = _dwarf_decode_uleb128(&p); 754 CFA.dw_offset_relevant = 1; 755 CFA.dw_value_type = DW_EXPR_OFFSET; 756 CFA.dw_regnum = reg; 757 CFA.dw_offset_or_block_len = uoff; 758 #ifdef FRAME_DEBUG 759 printf("DW_CFA_def_cfa(reg=%ju,uoff=%ju)\n", reg, uoff); 760 #endif 761 break; 762 case DW_CFA_def_cfa_register: 763 *row_pc = pc; 764 reg = _dwarf_decode_uleb128(&p); 765 CFA.dw_regnum = reg; 766 /* 767 * Note that DW_CFA_def_cfa_register change the CFA 768 * rule register while keep the old offset. So we 769 * should not touch the CFA.dw_offset_relevant flag 770 * here. 771 */ 772 #ifdef FRAME_DEBUG 773 printf("DW_CFA_def_cfa_register(%ju)\n", reg); 774 #endif 775 break; 776 case DW_CFA_def_cfa_offset: 777 *row_pc = pc; 778 uoff = _dwarf_decode_uleb128(&p); 779 CFA.dw_offset_relevant = 1; 780 CFA.dw_value_type = DW_EXPR_OFFSET; 781 CFA.dw_offset_or_block_len = uoff; 782 #ifdef FRAME_DEBUG 783 printf("DW_CFA_def_cfa_offset(%ju)\n", uoff); 784 #endif 785 break; 786 case DW_CFA_def_cfa_expression: 787 *row_pc = pc; 788 CFA.dw_offset_relevant = 0; 789 CFA.dw_value_type = DW_EXPR_EXPRESSION; 790 CFA.dw_offset_or_block_len = _dwarf_decode_uleb128(&p); 791 CFA.dw_block_ptr = p; 792 p += CFA.dw_offset_or_block_len; 793 #ifdef FRAME_DEBUG 794 printf("DW_CFA_def_cfa_expression\n"); 795 #endif 796 break; 797 case DW_CFA_expression: 798 *row_pc = pc; 799 reg = _dwarf_decode_uleb128(&p); 800 CHECK_TABLE_SIZE(reg); 801 RL[reg].dw_offset_relevant = 0; 802 RL[reg].dw_value_type = DW_EXPR_EXPRESSION; 803 RL[reg].dw_offset_or_block_len = 804 _dwarf_decode_uleb128(&p); 805 RL[reg].dw_block_ptr = p; 806 p += RL[reg].dw_offset_or_block_len; 807 #ifdef FRAME_DEBUG 808 printf("DW_CFA_expression\n"); 809 #endif 810 break; 811 case DW_CFA_offset_extended_sf: 812 *row_pc = pc; 813 reg = _dwarf_decode_uleb128(&p); 814 soff = _dwarf_decode_sleb128(&p); 815 CHECK_TABLE_SIZE(reg); 816 RL[reg].dw_offset_relevant = 1; 817 RL[reg].dw_value_type = DW_EXPR_OFFSET; 818 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value; 819 RL[reg].dw_offset_or_block_len = soff * daf; 820 #ifdef FRAME_DEBUG 821 printf("DW_CFA_offset_extended_sf(reg=%ju,soff=%jd)\n", 822 reg, soff); 823 #endif 824 break; 825 case DW_CFA_def_cfa_sf: 826 *row_pc = pc; 827 reg = _dwarf_decode_uleb128(&p); 828 soff = _dwarf_decode_sleb128(&p); 829 CFA.dw_offset_relevant = 1; 830 CFA.dw_value_type = DW_EXPR_OFFSET; 831 CFA.dw_regnum = reg; 832 CFA.dw_offset_or_block_len = soff * daf; 833 #ifdef FRAME_DEBUG 834 printf("DW_CFA_def_cfa_sf(reg=%ju,soff=%jd)\n", reg, 835 soff); 836 #endif 837 break; 838 case DW_CFA_def_cfa_offset_sf: 839 *row_pc = pc; 840 soff = _dwarf_decode_sleb128(&p); 841 CFA.dw_offset_relevant = 1; 842 CFA.dw_value_type = DW_EXPR_OFFSET; 843 CFA.dw_offset_or_block_len = soff * daf; 844 #ifdef FRAME_DEBUG 845 printf("DW_CFA_def_cfa_offset_sf(soff=%jd)\n", soff); 846 #endif 847 break; 848 case DW_CFA_val_offset: 849 *row_pc = pc; 850 reg = _dwarf_decode_uleb128(&p); 851 uoff = _dwarf_decode_uleb128(&p); 852 CHECK_TABLE_SIZE(reg); 853 RL[reg].dw_offset_relevant = 1; 854 RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET; 855 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value; 856 RL[reg].dw_offset_or_block_len = uoff * daf; 857 #ifdef FRAME_DEBUG 858 printf("DW_CFA_val_offset(reg=%ju,uoff=%ju)\n", reg, 859 uoff); 860 #endif 861 break; 862 case DW_CFA_val_offset_sf: 863 *row_pc = pc; 864 reg = _dwarf_decode_uleb128(&p); 865 soff = _dwarf_decode_sleb128(&p); 866 CHECK_TABLE_SIZE(reg); 867 RL[reg].dw_offset_relevant = 1; 868 RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET; 869 RL[reg].dw_regnum = dbg->dbg_frame_cfa_value; 870 RL[reg].dw_offset_or_block_len = soff * daf; 871 #ifdef FRAME_DEBUG 872 printf("DW_CFA_val_offset_sf(reg=%ju,soff=%jd)\n", reg, 873 soff); 874 #endif 875 break; 876 case DW_CFA_val_expression: 877 *row_pc = pc; 878 reg = _dwarf_decode_uleb128(&p); 879 CHECK_TABLE_SIZE(reg); 880 RL[reg].dw_offset_relevant = 0; 881 RL[reg].dw_value_type = DW_EXPR_VAL_EXPRESSION; 882 RL[reg].dw_offset_or_block_len = 883 _dwarf_decode_uleb128(&p); 884 RL[reg].dw_block_ptr = p; 885 p += RL[reg].dw_offset_or_block_len; 886 #ifdef FRAME_DEBUG 887 printf("DW_CFA_val_expression\n"); 888 #endif 889 break; 890 default: 891 DWARF_SET_ERROR(dbg, error, 892 DW_DLE_FRAME_INSTR_EXEC_ERROR); 893 ret = DW_DLE_FRAME_INSTR_EXEC_ERROR; 894 goto program_done; 895 } 896 } 897 898 program_done: 899 900 free(init_rt->rt3_rules); 901 free(init_rt); 902 if (saved_rt) { 903 free(saved_rt->rt3_rules); 904 free(saved_rt); 905 } 906 907 return (ret); 908 909 #undef CFA 910 #undef INITCFA 911 #undef RL 912 #undef INITRL 913 #undef CHECK_TABLE_SIZE 914 } 915 916 static int 917 _dwarf_frame_convert_inst(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts, 918 Dwarf_Unsigned len, Dwarf_Unsigned *count, Dwarf_Frame_Op *fop, 919 Dwarf_Frame_Op3 *fop3, Dwarf_Error *error) 920 { 921 uint8_t *p, *pe; 922 uint8_t high2, low6; 923 uint64_t reg, reg2, uoff, soff, blen; 924 925 #define SET_BASE_OP(x) \ 926 do { \ 927 if (fop != NULL) \ 928 fop[*count].fp_base_op = (x) >> 6; \ 929 if (fop3 != NULL) \ 930 fop3[*count].fp_base_op = (x) >> 6; \ 931 } while(0) 932 933 #define SET_EXTENDED_OP(x) \ 934 do { \ 935 if (fop != NULL) \ 936 fop[*count].fp_extended_op = (x); \ 937 if (fop3 != NULL) \ 938 fop3[*count].fp_extended_op = (x); \ 939 } while(0) 940 941 #define SET_REGISTER(x) \ 942 do { \ 943 if (fop != NULL) \ 944 fop[*count].fp_register = (x); \ 945 if (fop3 != NULL) \ 946 fop3[*count].fp_register = (x); \ 947 } while(0) 948 949 #define SET_OFFSET(x) \ 950 do { \ 951 if (fop != NULL) \ 952 fop[*count].fp_offset = (x); \ 953 if (fop3 != NULL) \ 954 fop3[*count].fp_offset_or_block_len = \ 955 (x); \ 956 } while(0) 957 958 #define SET_INSTR_OFFSET(x) \ 959 do { \ 960 if (fop != NULL) \ 961 fop[*count].fp_instr_offset = (x); \ 962 if (fop3 != NULL) \ 963 fop3[*count].fp_instr_offset = (x); \ 964 } while(0) 965 966 #define SET_BLOCK_LEN(x) \ 967 do { \ 968 if (fop3 != NULL) \ 969 fop3[*count].fp_offset_or_block_len = \ 970 (x); \ 971 } while(0) 972 973 #define SET_EXPR_BLOCK(addr, len) \ 974 do { \ 975 if (fop3 != NULL) { \ 976 fop3[*count].fp_expr_block = \ 977 malloc((size_t) (len)); \ 978 if (fop3[*count].fp_expr_block == NULL) { \ 979 DWARF_SET_ERROR(dbg, error, \ 980 DW_DLE_MEMORY); \ 981 return (DW_DLE_MEMORY); \ 982 } \ 983 memcpy(&fop3[*count].fp_expr_block, \ 984 (addr), (len)); \ 985 } \ 986 } while(0) 987 988 *count = 0; 989 990 p = insts; 991 pe = p + len; 992 993 while (p < pe) { 994 995 SET_INSTR_OFFSET(p - insts); 996 997 if (*p == DW_CFA_nop) { 998 p++; 999 (*count)++; 1000 continue; 1001 } 1002 1003 high2 = *p & 0xc0; 1004 low6 = *p & 0x3f; 1005 p++; 1006 1007 if (high2 > 0) { 1008 switch (high2) { 1009 case DW_CFA_advance_loc: 1010 SET_BASE_OP(high2); 1011 SET_OFFSET(low6); 1012 break; 1013 case DW_CFA_offset: 1014 SET_BASE_OP(high2); 1015 SET_REGISTER(low6); 1016 uoff = _dwarf_decode_uleb128(&p); 1017 SET_OFFSET(uoff); 1018 break; 1019 case DW_CFA_restore: 1020 SET_BASE_OP(high2); 1021 SET_REGISTER(low6); 1022 break; 1023 default: 1024 DWARF_SET_ERROR(dbg, error, 1025 DW_DLE_FRAME_INSTR_EXEC_ERROR); 1026 return (DW_DLE_FRAME_INSTR_EXEC_ERROR); 1027 } 1028 1029 (*count)++; 1030 continue; 1031 } 1032 1033 SET_EXTENDED_OP(low6); 1034 1035 switch (low6) { 1036 case DW_CFA_set_loc: 1037 uoff = dbg->decode(&p, addr_size); 1038 SET_OFFSET(uoff); 1039 break; 1040 case DW_CFA_advance_loc1: 1041 uoff = dbg->decode(&p, 1); 1042 SET_OFFSET(uoff); 1043 break; 1044 case DW_CFA_advance_loc2: 1045 uoff = dbg->decode(&p, 2); 1046 SET_OFFSET(uoff); 1047 break; 1048 case DW_CFA_advance_loc4: 1049 uoff = dbg->decode(&p, 4); 1050 SET_OFFSET(uoff); 1051 break; 1052 case DW_CFA_offset_extended: 1053 case DW_CFA_def_cfa: 1054 case DW_CFA_val_offset: 1055 reg = _dwarf_decode_uleb128(&p); 1056 uoff = _dwarf_decode_uleb128(&p); 1057 SET_REGISTER(reg); 1058 SET_OFFSET(uoff); 1059 break; 1060 case DW_CFA_restore_extended: 1061 case DW_CFA_undefined: 1062 case DW_CFA_same_value: 1063 case DW_CFA_def_cfa_register: 1064 reg = _dwarf_decode_uleb128(&p); 1065 SET_REGISTER(reg); 1066 break; 1067 case DW_CFA_register: 1068 reg = _dwarf_decode_uleb128(&p); 1069 reg2 = _dwarf_decode_uleb128(&p); 1070 SET_REGISTER(reg); 1071 SET_OFFSET(reg2); 1072 break; 1073 case DW_CFA_remember_state: 1074 case DW_CFA_restore_state: 1075 break; 1076 case DW_CFA_def_cfa_offset: 1077 uoff = _dwarf_decode_uleb128(&p); 1078 SET_OFFSET(uoff); 1079 break; 1080 case DW_CFA_def_cfa_expression: 1081 blen = _dwarf_decode_uleb128(&p); 1082 SET_BLOCK_LEN(blen); 1083 SET_EXPR_BLOCK(p, blen); 1084 p += blen; 1085 break; 1086 case DW_CFA_expression: 1087 case DW_CFA_val_expression: 1088 reg = _dwarf_decode_uleb128(&p); 1089 blen = _dwarf_decode_uleb128(&p); 1090 SET_REGISTER(reg); 1091 SET_BLOCK_LEN(blen); 1092 SET_EXPR_BLOCK(p, blen); 1093 p += blen; 1094 break; 1095 case DW_CFA_offset_extended_sf: 1096 case DW_CFA_def_cfa_sf: 1097 case DW_CFA_val_offset_sf: 1098 reg = _dwarf_decode_uleb128(&p); 1099 soff = _dwarf_decode_sleb128(&p); 1100 SET_REGISTER(reg); 1101 SET_OFFSET(soff); 1102 break; 1103 case DW_CFA_def_cfa_offset_sf: 1104 soff = _dwarf_decode_sleb128(&p); 1105 SET_OFFSET(soff); 1106 break; 1107 default: 1108 DWARF_SET_ERROR(dbg, error, 1109 DW_DLE_FRAME_INSTR_EXEC_ERROR); 1110 return (DW_DLE_FRAME_INSTR_EXEC_ERROR); 1111 } 1112 1113 (*count)++; 1114 } 1115 1116 return (DW_DLE_NONE); 1117 } 1118 1119 int 1120 _dwarf_frame_get_fop(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts, 1121 Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt, 1122 Dwarf_Error *error) 1123 { 1124 Dwarf_Frame_Op *oplist; 1125 Dwarf_Unsigned count; 1126 int ret; 1127 1128 ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count, 1129 NULL, NULL, error); 1130 if (ret != DW_DLE_NONE) 1131 return (ret); 1132 1133 if ((oplist = calloc(count, sizeof(Dwarf_Frame_Op))) == NULL) { 1134 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 1135 return (DW_DLE_MEMORY); 1136 } 1137 1138 ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count, 1139 oplist, NULL, error); 1140 if (ret != DW_DLE_NONE) { 1141 free(oplist); 1142 return (ret); 1143 } 1144 1145 *ret_oplist = oplist; 1146 *ret_opcnt = count; 1147 1148 return (DW_DLE_NONE); 1149 } 1150 1151 int 1152 _dwarf_frame_regtable_copy(Dwarf_Debug dbg, Dwarf_Regtable3 **dest, 1153 Dwarf_Regtable3 *src, Dwarf_Error *error) 1154 { 1155 int i; 1156 1157 assert(dest != NULL); 1158 assert(src != NULL); 1159 1160 if (*dest == NULL) { 1161 if ((*dest = malloc(sizeof(Dwarf_Regtable3))) == NULL) { 1162 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 1163 return (DW_DLE_MEMORY); 1164 } 1165 (*dest)->rt3_reg_table_size = src->rt3_reg_table_size; 1166 (*dest)->rt3_rules = malloc(src->rt3_reg_table_size * 1167 sizeof(Dwarf_Regtable_Entry3)); 1168 if ((*dest)->rt3_rules == NULL) { 1169 free(*dest); 1170 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 1171 return (DW_DLE_MEMORY); 1172 } 1173 } 1174 1175 memcpy(&(*dest)->rt3_cfa_rule, &src->rt3_cfa_rule, 1176 sizeof(Dwarf_Regtable_Entry3)); 1177 1178 for (i = 0; i < (*dest)->rt3_reg_table_size && 1179 i < src->rt3_reg_table_size; i++) 1180 memcpy(&(*dest)->rt3_rules[i], &src->rt3_rules[i], 1181 sizeof(Dwarf_Regtable_Entry3)); 1182 1183 for (; i < (*dest)->rt3_reg_table_size; i++) 1184 (*dest)->rt3_rules[i].dw_regnum = 1185 dbg->dbg_frame_undefined_value; 1186 1187 return (DW_DLE_NONE); 1188 } 1189 1190 int 1191 _dwarf_frame_get_internal_table(Dwarf_Fde fde, Dwarf_Addr pc_req, 1192 Dwarf_Regtable3 **ret_rt, Dwarf_Addr *ret_row_pc, Dwarf_Error *error) 1193 { 1194 Dwarf_Debug dbg; 1195 Dwarf_Cie cie; 1196 Dwarf_Regtable3 *rt; 1197 Dwarf_Addr row_pc; 1198 int i, ret; 1199 1200 assert(ret_rt != NULL); 1201 1202 dbg = fde->fde_dbg; 1203 assert(dbg != NULL); 1204 1205 rt = dbg->dbg_internal_reg_table; 1206 1207 /* Clear the content of regtable from previous run. */ 1208 memset(&rt->rt3_cfa_rule, 0, sizeof(Dwarf_Regtable_Entry3)); 1209 memset(rt->rt3_rules, 0, rt->rt3_reg_table_size * 1210 sizeof(Dwarf_Regtable_Entry3)); 1211 1212 /* Set rules to initial values. */ 1213 for (i = 0; i < rt->rt3_reg_table_size; i++) 1214 rt->rt3_rules[i].dw_regnum = dbg->dbg_frame_rule_initial_value; 1215 1216 /* Run initial instructions in CIE. */ 1217 cie = fde->fde_cie; 1218 assert(cie != NULL); 1219 ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize, 1220 cie->cie_initinst, cie->cie_instlen, cie->cie_caf, cie->cie_daf, 0, 1221 ~0ULL, &row_pc, error); 1222 if (ret != DW_DLE_NONE) 1223 return (ret); 1224 1225 /* Run instructions in FDE. */ 1226 if (pc_req >= fde->fde_initloc) { 1227 ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize, 1228 fde->fde_inst, fde->fde_instlen, cie->cie_caf, 1229 cie->cie_daf, fde->fde_initloc, pc_req, &row_pc, error); 1230 if (ret != DW_DLE_NONE) 1231 return (ret); 1232 } 1233 1234 *ret_rt = rt; 1235 *ret_row_pc = row_pc; 1236 1237 return (DW_DLE_NONE); 1238 } 1239 1240 void 1241 _dwarf_frame_cleanup(Dwarf_Debug dbg) 1242 { 1243 Dwarf_Regtable3 *rt; 1244 1245 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ); 1246 1247 if (dbg->dbg_internal_reg_table) { 1248 rt = dbg->dbg_internal_reg_table; 1249 free(rt->rt3_rules); 1250 free(rt); 1251 dbg->dbg_internal_reg_table = NULL; 1252 } 1253 1254 if (dbg->dbg_frame) { 1255 _dwarf_frame_section_cleanup(dbg->dbg_frame); 1256 dbg->dbg_frame = NULL; 1257 } 1258 1259 if (dbg->dbg_eh_frame) { 1260 _dwarf_frame_section_cleanup(dbg->dbg_eh_frame); 1261 dbg->dbg_eh_frame = NULL; 1262 } 1263 } 1264 1265 int 1266 _dwarf_frame_section_load(Dwarf_Debug dbg, Dwarf_Error *error) 1267 { 1268 Dwarf_Section *ds; 1269 1270 if ((ds = _dwarf_find_section(dbg, ".debug_frame")) != NULL) { 1271 return (_dwarf_frame_section_init(dbg, &dbg->dbg_frame, 1272 ds, 0, error)); 1273 } 1274 1275 return (DW_DLE_NONE); 1276 } 1277 1278 int 1279 _dwarf_frame_section_load_eh(Dwarf_Debug dbg, Dwarf_Error *error) 1280 { 1281 Dwarf_Section *ds; 1282 1283 if ((ds = _dwarf_find_section(dbg, ".eh_frame")) != NULL) { 1284 return (_dwarf_frame_section_init(dbg, &dbg->dbg_eh_frame, 1285 ds, 1, error)); 1286 } 1287 1288 return (DW_DLE_NONE); 1289 } 1290 1291 void 1292 _dwarf_frame_params_init(Dwarf_Debug dbg) 1293 { 1294 1295 /* Initialise call frame related parameters. */ 1296 dbg->dbg_frame_rule_table_size = DW_FRAME_LAST_REG_NUM; 1297 dbg->dbg_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE; 1298 dbg->dbg_frame_cfa_value = DW_FRAME_CFA_COL3; 1299 dbg->dbg_frame_same_value = DW_FRAME_SAME_VAL; 1300 dbg->dbg_frame_undefined_value = DW_FRAME_UNDEFINED_VAL; 1301 } 1302 1303 int 1304 _dwarf_frame_interal_table_init(Dwarf_Debug dbg, Dwarf_Error *error) 1305 { 1306 Dwarf_Regtable3 *rt; 1307 1308 if (dbg->dbg_internal_reg_table != NULL) 1309 return (DW_DLE_NONE); 1310 1311 /* Initialise internal register table. */ 1312 if ((rt = calloc(1, sizeof(Dwarf_Regtable3))) == NULL) { 1313 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 1314 return (DW_DLE_MEMORY); 1315 } 1316 1317 rt->rt3_reg_table_size = dbg->dbg_frame_rule_table_size; 1318 if ((rt->rt3_rules = calloc(rt->rt3_reg_table_size, 1319 sizeof(Dwarf_Regtable_Entry3))) == NULL) { 1320 free(rt); 1321 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 1322 return (DW_DLE_MEMORY); 1323 } 1324 1325 dbg->dbg_internal_reg_table = rt; 1326 1327 return (DW_DLE_NONE); 1328 } 1329 1330 #define _FDE_INST_INIT_SIZE 128 1331 1332 int 1333 _dwarf_frame_fde_add_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1, 1334 Dwarf_Unsigned val2, Dwarf_Error *error) 1335 { 1336 Dwarf_P_Debug dbg; 1337 uint8_t high2, low6; 1338 int ret; 1339 1340 #define ds fde 1341 #define ds_data fde_inst 1342 #define ds_cap fde_instcap 1343 #define ds_size fde_instlen 1344 1345 assert(fde != NULL && fde->fde_dbg != NULL); 1346 dbg = fde->fde_dbg; 1347 1348 if (fde->fde_inst == NULL) { 1349 fde->fde_instcap = _FDE_INST_INIT_SIZE; 1350 fde->fde_instlen = 0; 1351 if ((fde->fde_inst = malloc((size_t) fde->fde_instcap)) == 1352 NULL) { 1353 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 1354 return (DW_DLE_MEMORY); 1355 } 1356 } 1357 assert(fde->fde_instcap != 0); 1358 1359 RCHECK(WRITE_VALUE(op, 1)); 1360 if (op == DW_CFA_nop) 1361 return (DW_DLE_NONE); 1362 1363 high2 = op & 0xc0; 1364 low6 = op & 0x3f; 1365 1366 if (high2 > 0) { 1367 switch (high2) { 1368 case DW_CFA_advance_loc: 1369 case DW_CFA_restore: 1370 break; 1371 case DW_CFA_offset: 1372 RCHECK(WRITE_ULEB128(val1)); 1373 break; 1374 default: 1375 DWARF_SET_ERROR(dbg, error, 1376 DW_DLE_FRAME_INSTR_EXEC_ERROR); 1377 return (DW_DLE_FRAME_INSTR_EXEC_ERROR); 1378 } 1379 return (DW_DLE_NONE); 1380 } 1381 1382 switch (low6) { 1383 case DW_CFA_set_loc: 1384 RCHECK(WRITE_VALUE(val1, dbg->dbg_pointer_size)); 1385 break; 1386 case DW_CFA_advance_loc1: 1387 RCHECK(WRITE_VALUE(val1, 1)); 1388 break; 1389 case DW_CFA_advance_loc2: 1390 RCHECK(WRITE_VALUE(val1, 2)); 1391 break; 1392 case DW_CFA_advance_loc4: 1393 RCHECK(WRITE_VALUE(val1, 4)); 1394 break; 1395 case DW_CFA_offset_extended: 1396 case DW_CFA_def_cfa: 1397 case DW_CFA_register: 1398 RCHECK(WRITE_ULEB128(val1)); 1399 RCHECK(WRITE_ULEB128(val2)); 1400 break; 1401 case DW_CFA_restore_extended: 1402 case DW_CFA_undefined: 1403 case DW_CFA_same_value: 1404 case DW_CFA_def_cfa_register: 1405 case DW_CFA_def_cfa_offset: 1406 RCHECK(WRITE_ULEB128(val1)); 1407 break; 1408 case DW_CFA_remember_state: 1409 case DW_CFA_restore_state: 1410 break; 1411 default: 1412 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_INSTR_EXEC_ERROR); 1413 return (DW_DLE_FRAME_INSTR_EXEC_ERROR); 1414 } 1415 1416 return (DW_DLE_NONE); 1417 1418 gen_fail: 1419 return (ret); 1420 1421 #undef ds 1422 #undef ds_data 1423 #undef ds_cap 1424 #undef ds_size 1425 } 1426 1427 static int 1428 _dwarf_frame_gen_cie(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_P_Cie cie, 1429 Dwarf_Error *error) 1430 { 1431 Dwarf_Unsigned len; 1432 uint64_t offset; 1433 int ret; 1434 1435 assert(dbg != NULL && ds != NULL && cie != NULL); 1436 1437 cie->cie_offset = offset = ds->ds_size; 1438 cie->cie_length = 0; 1439 cie->cie_version = 1; 1440 1441 /* Length placeholder. */ 1442 RCHECK(WRITE_VALUE(cie->cie_length, 4)); 1443 1444 /* .debug_frame use CIE id ~0. */ 1445 RCHECK(WRITE_VALUE(~0U, 4)); 1446 1447 /* .debug_frame version is 1. (DWARF2) */ 1448 RCHECK(WRITE_VALUE(cie->cie_version, 1)); 1449 1450 /* Write augmentation, if present. */ 1451 if (cie->cie_augment != NULL) 1452 RCHECK(WRITE_BLOCK(cie->cie_augment, 1453 strlen((char *) cie->cie_augment) + 1)); 1454 else 1455 RCHECK(WRITE_VALUE(0, 1)); 1456 1457 /* Write caf, daf and ra. */ 1458 RCHECK(WRITE_ULEB128(cie->cie_caf)); 1459 RCHECK(WRITE_SLEB128(cie->cie_daf)); 1460 RCHECK(WRITE_VALUE(cie->cie_ra, 1)); 1461 1462 /* Write initial instructions, if present. */ 1463 if (cie->cie_initinst != NULL) 1464 RCHECK(WRITE_BLOCK(cie->cie_initinst, cie->cie_instlen)); 1465 1466 /* Add padding. */ 1467 len = ds->ds_size - cie->cie_offset - 4; 1468 cie->cie_length = roundup(len, dbg->dbg_pointer_size); 1469 while (len++ < cie->cie_length) 1470 RCHECK(WRITE_VALUE(DW_CFA_nop, 1)); 1471 1472 /* Fill in the length field. */ 1473 dbg->write(ds->ds_data, &offset, cie->cie_length, 4); 1474 1475 return (DW_DLE_NONE); 1476 1477 gen_fail: 1478 return (ret); 1479 } 1480 1481 static int 1482 _dwarf_frame_gen_fde(Dwarf_P_Debug dbg, Dwarf_P_Section ds, 1483 Dwarf_Rel_Section drs, Dwarf_P_Fde fde, Dwarf_Error *error) 1484 { 1485 Dwarf_Unsigned len; 1486 uint64_t offset; 1487 int ret; 1488 1489 assert(dbg != NULL && ds != NULL && drs != NULL); 1490 assert(fde != NULL && fde->fde_cie != NULL); 1491 1492 fde->fde_offset = offset = ds->ds_size; 1493 fde->fde_length = 0; 1494 fde->fde_cieoff = fde->fde_cie->cie_offset; 1495 1496 /* Length placeholder. */ 1497 RCHECK(WRITE_VALUE(fde->fde_length, 4)); 1498 1499 /* Write CIE pointer. */ 1500 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4, 1501 ds->ds_size, 0, fde->fde_cieoff, ".debug_frame", error)); 1502 1503 /* Write FDE initial location. */ 1504 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 1505 dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx, 1506 fde->fde_initloc, NULL, error)); 1507 1508 /* 1509 * Write FDE address range. Use a pair of relocation entries if 1510 * application provided end symbol index. Otherwise write the 1511 * length without assoicating any relocation info. 1512 */ 1513 if (fde->fde_esymndx > 0) 1514 RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds, 1515 dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx, 1516 fde->fde_esymndx, fde->fde_initloc, fde->fde_eoff, error)); 1517 else 1518 RCHECK(WRITE_VALUE(fde->fde_adrange, dbg->dbg_pointer_size)); 1519 1520 /* Write FDE frame instructions. */ 1521 RCHECK(WRITE_BLOCK(fde->fde_inst, fde->fde_instlen)); 1522 1523 /* Add padding. */ 1524 len = ds->ds_size - fde->fde_offset - 4; 1525 fde->fde_length = roundup(len, dbg->dbg_pointer_size); 1526 while (len++ < fde->fde_length) 1527 RCHECK(WRITE_VALUE(DW_CFA_nop, 1)); 1528 1529 /* Fill in the length field. */ 1530 dbg->write(ds->ds_data, &offset, fde->fde_length, 4); 1531 1532 return (DW_DLE_NONE); 1533 1534 gen_fail: 1535 return (ret); 1536 } 1537 1538 int 1539 _dwarf_frame_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 1540 { 1541 Dwarf_P_Section ds; 1542 Dwarf_Rel_Section drs; 1543 Dwarf_P_Cie cie; 1544 Dwarf_P_Fde fde; 1545 int ret; 1546 1547 if (STAILQ_EMPTY(&dbg->dbgp_cielist)) 1548 return (DW_DLE_NONE); 1549 1550 /* Create .debug_frame section. */ 1551 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_frame", 0, error)) != 1552 DW_DLE_NONE) 1553 goto gen_fail0; 1554 1555 /* Create relocation section for .debug_frame */ 1556 RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error)); 1557 1558 /* Generate list of CIE. */ 1559 STAILQ_FOREACH(cie, &dbg->dbgp_cielist, cie_next) 1560 RCHECK(_dwarf_frame_gen_cie(dbg, ds, cie, error)); 1561 1562 /* Generate list of FDE. */ 1563 STAILQ_FOREACH(fde, &dbg->dbgp_fdelist, fde_next) 1564 RCHECK(_dwarf_frame_gen_fde(dbg, ds, drs, fde, error)); 1565 1566 /* Inform application the creation of .debug_frame ELF section. */ 1567 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 1568 1569 /* Finalize relocation section for .debug_frame */ 1570 RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 1571 1572 return (DW_DLE_NONE); 1573 1574 gen_fail: 1575 _dwarf_reloc_section_free(dbg, &drs); 1576 1577 gen_fail0: 1578 _dwarf_section_free(dbg, &ds); 1579 1580 return (ret); 1581 } 1582 1583 void 1584 _dwarf_frame_pro_cleanup(Dwarf_P_Debug dbg) 1585 { 1586 Dwarf_P_Cie cie, tcie; 1587 Dwarf_P_Fde fde, tfde; 1588 1589 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 1590 1591 STAILQ_FOREACH_SAFE(cie, &dbg->dbgp_cielist, cie_next, tcie) { 1592 STAILQ_REMOVE(&dbg->dbgp_cielist, cie, _Dwarf_Cie, cie_next); 1593 if (cie->cie_augment) 1594 free(cie->cie_augment); 1595 if (cie->cie_initinst) 1596 free(cie->cie_initinst); 1597 free(cie); 1598 } 1599 dbg->dbgp_cielen = 0; 1600 1601 STAILQ_FOREACH_SAFE(fde, &dbg->dbgp_fdelist, fde_next, tfde) { 1602 STAILQ_REMOVE(&dbg->dbgp_fdelist, fde, _Dwarf_Fde, fde_next); 1603 if (fde->fde_inst != NULL) 1604 free(fde->fde_inst); 1605 free(fde); 1606 } 1607 dbg->dbgp_fdelen = 0; 1608 } 1609