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