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