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