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