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