1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <_libelf.h> 28 #include <dwarf.h> 29 #include <stdio.h> 30 #include <unistd.h> 31 #include <errno.h> 32 #include <strings.h> 33 #include <debug.h> 34 #include <conv.h> 35 #include <msg.h> 36 #include <_elfdump.h> 37 38 39 /* 40 * Data from eh_frame section used by dump_cfi() 41 */ 42 typedef struct { 43 Half e_machine; /* ehdr->e_machine */ 44 uchar_t *e_ident; /* ehdr->e_ident */ 45 uint64_t sh_addr; /* Address of eh_frame section */ 46 int do_swap; /* True if object and system byte */ 47 /* order differs */ 48 int cieRflag; /* R flag from current CIE */ 49 uint64_t ciecalign; /* CIE code align factor */ 50 int64_t ciedalign; /* CIE data align factor */ 51 uint64_t fdeinitloc; /* FDE initial location */ 52 } dump_cfi_state_t; 53 54 55 /* 56 * Extract an unsigned integer value from an .eh_frame section, converting it 57 * from its native byte order to that of the running machine if necessary. 58 * 59 * entry: 60 * data - Base address from which to extract datum 61 * ndx - Address of variable giving index to start byte in data. 62 * size - # of bytes in datum. Must be one of: 1, 2, 4, 8 63 * do_swap - True if the data is in a different byte order than that 64 * of the host system. 65 * 66 * exit: 67 * *ndx is incremented by the size of the extracted datum. 68 * 69 * The requested datum is extracted, byte swapped if necessary, 70 * and returned. 71 */ 72 static uint64_t 73 dwarf_extract_uint(uchar_t *data, uint64_t *ndx, int size, int do_swap) 74 { 75 switch (size) { 76 case 1: 77 return (data[(*ndx)++]); 78 case 2: 79 { 80 Half r; 81 uchar_t *p = (uchar_t *)&r; 82 83 data += *ndx; 84 if (do_swap) 85 UL_ASSIGN_BSWAP_HALF(p, data); 86 else 87 UL_ASSIGN_HALF(p, data); 88 89 (*ndx) += 2; 90 return (r); 91 } 92 case 4: 93 { 94 Word r; 95 uchar_t *p = (uchar_t *)&r; 96 97 data += *ndx; 98 if (do_swap) 99 UL_ASSIGN_BSWAP_WORD(p, data); 100 else 101 UL_ASSIGN_WORD(p, data); 102 103 (*ndx) += 4; 104 return (r); 105 } 106 107 case 8: 108 { 109 uint64_t r; 110 uchar_t *p = (uchar_t *)&r; 111 112 data += *ndx; 113 if (do_swap) 114 UL_ASSIGN_BSWAP_LWORD(p, data); 115 else 116 UL_ASSIGN_LWORD(p, data); 117 118 (*ndx) += 8; 119 return (r); 120 } 121 } 122 123 /* If here, an invalid size was specified */ 124 assert(0); 125 return (0); 126 } 127 128 /* 129 * Map a DWARF register constant to the machine register name it 130 * corresponds to, formatting the result into buf. 131 * 132 * The assignment of DWARF register numbers is part of the system 133 * specific ABI for each platform. 134 * 135 * entry: 136 * regno - DWARF register number 137 * mach - ELF machine code for platform 138 * buf, bufsize - Buffer to receive the formatted result string 139 * 140 * exit: 141 * The results are formatted into buf, and buf is returned. 142 * If the generated output would exceed the size of the buffer 143 * provided, it will be clipped to fit. 144 */ 145 static const char * 146 dwarf_regname(Half mach, int regno, char *buf, size_t bufsize) 147 { 148 Conv_inv_buf_t inv_buf; 149 const char *name; 150 int good_name; 151 152 name = conv_dwarf_regname(mach, regno, 0, &good_name, &inv_buf); 153 154 /* 155 * If there is a good mnemonic machine name for the register, 156 * format the result as 'r# (mnemonic)'. If there is no good 157 * name for it, then simply format the dwarf name as 'r#'. 158 */ 159 if (good_name) 160 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_NAME), 161 regno, name); 162 else 163 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_BASIC), 164 regno); 165 166 return (buf); 167 } 168 169 170 /* 171 * Decode eh_frame Call Frame Instructions, printing each one on a 172 * separate line. 173 * 174 * entry: 175 * data - Address of base of eh_frame section being processed 176 * off - Offset of current FDE within eh_frame 177 * ndx - Index of current position within current FDE 178 * len - Length of eh_frame section 179 * state - Object, CIE, and FDE state for current request 180 * msg - Header message to issue before producing output. 181 * indent - # of indentation characters issued for each line of output. 182 * 183 * exit: 184 * The Call Frame Instructions have been decoded and printed. 185 * 186 * *ndx has been incremented to contain the index of the next 187 * byte of data to be processed in eh_frame. 188 * 189 * note: 190 * The format of Call Frame Instructions in .eh_frame sections is based 191 * on the DWARF specification. 192 */ 193 static void 194 dump_cfi(uchar_t *data, uint64_t off, uint64_t *ndx, uint_t len, 195 dump_cfi_state_t *state, const char *msg, int indent) 196 { 197 /* 198 * We use %*s%s to insert leading whitespace and the op name. 199 * PREFIX supplies these arguments. 200 */ 201 #define PREFIX indent, MSG_ORIG(MSG_STR_EMPTY), opname 202 203 /* Hide boilerplate clutter in calls to dwarf_regname() */ 204 #define REGNAME(_rnum, _buf) \ 205 dwarf_regname(state->e_machine, _rnum, _buf, sizeof (_buf)) 206 207 /* Extract the lower 6 bits from an op code */ 208 #define LOW_OP(_op) (_op & 0x3f) 209 210 char rbuf1[32], rbuf2[32]; 211 Conv_inv_buf_t inv_buf; 212 uchar_t op; 213 const char *opname; 214 uint64_t oper1, oper2, cur_pc; 215 int64_t soper; 216 const char *loc_str; 217 int i; 218 219 dbg_print(0, msg); 220 221 /* 222 * In a CIE/FDE, the length field does not include it's own 223 * size. Hence, the value passed in is 4 less than the index 224 * of the actual final location. 225 */ 226 len += 4; 227 228 /* 229 * There is a concept of the 'current location', which is the PC 230 * to which the current item applies. It starts out set to the 231 * FDE initial location, and can be set or incremented by 232 * various OP codes. cur_pc is used to track this. 233 * 234 * We want to use 'initloc' in the output the first time the location 235 * is referenced, and then switch to 'loc' for subsequent references. 236 * loc_str is used to manage that. 237 */ 238 cur_pc = state->fdeinitloc; 239 loc_str = MSG_ORIG(MSG_STR_INITLOC); 240 241 while (*ndx < len) { 242 /* 243 * The first byte contains the primary op code in the top 244 * 2 bits, so there are 4 of them. Primary OP code 245 * 0 uses the lower 6 bits to specify a sub-opcode, allowing 246 * for 64 of them. The other 3 primary op codes use the 247 * lower 6 bits to hold an operand (a register #, or value). 248 * 249 * Check the primary OP code. If it's 1-3, handle it 250 * and move to the next loop iteration. For OP code 0, 251 * fall through to decode the sub-code. 252 */ 253 op = data[off + (*ndx)++]; 254 opname = conv_dwarf_cfa(op, 0, &inv_buf); 255 switch (op >> 6) { 256 case 0x1: /* v2: DW_CFA_advance_loc, delta */ 257 oper1 = state->ciecalign * LOW_OP(op); 258 cur_pc += oper1; 259 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX, 260 loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc)); 261 loc_str = MSG_ORIG(MSG_STR_LOC); 262 continue; 263 264 case 0x2: /* v2: DW_CFA_offset, reg, offset */ 265 soper = uleb_extract(&data[off], ndx) * 266 state->ciedalign; 267 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX, 268 REGNAME(LOW_OP(op), rbuf1), EC_SXWORD(soper)); 269 continue; 270 271 case 0x3: /* v2: DW_CFA_restore, reg */ 272 dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX, 273 REGNAME(LOW_OP(op), rbuf1)); 274 continue; 275 } 276 277 /* 278 * If we're here, the high order 2 bits are 0. The low 6 bits 279 * specify a sub-opcode defining the operation. 280 */ 281 switch (op) { 282 case 0x00: /* v2: DW_CFA_nop */ 283 /* 284 * No-ops are used to fill unused space required 285 * for alignment. It is common for there to be 286 * multiple adjacent nops. It saves space to report 287 * them all with a single line of output. 288 */ 289 for (i = 1; 290 (*ndx < len) && (data[off + *ndx] == 0); 291 i++, (*ndx)++) 292 ; 293 dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLEREP), PREFIX, i); 294 break; 295 296 case 0x0a: /* v2: DW_CFA_remember_state */ 297 case 0x0b: /* v2: DW_CFA_restore_state */ 298 case 0x2d: /* GNU: DW_CFA_GNU_window_save */ 299 dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLE), PREFIX); 300 break; 301 302 case 0x01: /* v2: DW_CFA_set_loc, address */ 303 cur_pc = dwarf_ehe_extract(&data[off], ndx, 304 state->cieRflag, state->e_ident, 305 state->sh_addr, off + *ndx); 306 dbg_print(0, MSG_ORIG(MSG_CFA_CFASET), PREFIX, 307 EC_XWORD(cur_pc)); 308 break; 309 310 case 0x02: /* v2: DW_CFA_advance_loc_1, 1-byte delta */ 311 case 0x03: /* v2: DW_CFA_advance_loc_2, 2-byte delta */ 312 case 0x04: /* v2: DW_CFA_advance_loc_4, 4-byte delta */ 313 /* 314 * Since the codes are contiguous, and the sizes are 315 * powers of 2, we can compute the word width from 316 * the code. 317 */ 318 i = 1 << (op - 0x02); 319 oper1 = dwarf_extract_uint(data + off, ndx, i, 320 state->do_swap) * state->ciecalign; 321 cur_pc += oper1; 322 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX, 323 loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc)); 324 loc_str = MSG_ORIG(MSG_STR_LOC); 325 break; 326 327 case 0x05: /* v2: DW_CFA_offset_extended,reg,off */ 328 oper1 = uleb_extract(&data[off], ndx); 329 soper = uleb_extract(&data[off], ndx) * 330 state->ciedalign; 331 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX, 332 REGNAME(oper1, rbuf1), EC_SXWORD(soper)); 333 break; 334 335 case 0x06: /* v2: DW_CFA_restore_extended, reg */ 336 case 0x0d: /* v2: DW_CFA_def_cfa_register, reg */ 337 case 0x08: /* v2: DW_CFA_same_value, reg */ 338 case 0x07: /* v2: DW_CFA_undefined, reg */ 339 oper1 = uleb_extract(&data[off], ndx); 340 dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX, 341 REGNAME(oper1, rbuf1)); 342 break; 343 344 345 case 0x09: /* v2: DW_CFA_register, reg, reg */ 346 oper1 = uleb_extract(&data[off], ndx); 347 oper2 = uleb_extract(&data[off], ndx); 348 dbg_print(0, MSG_ORIG(MSG_CFA_REG_REG), PREFIX, 349 REGNAME(oper1, rbuf1), REGNAME(oper2, rbuf2)); 350 break; 351 352 case 0x0c: /* v2: DW_CFA_def_cfa, reg, offset */ 353 oper1 = uleb_extract(&data[off], ndx); 354 oper2 = uleb_extract(&data[off], ndx); 355 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLU), PREFIX, 356 REGNAME(oper1, rbuf1), EC_XWORD(oper2)); 357 break; 358 359 case 0x0e: /* v2: DW_CFA_def_cfa_offset, offset */ 360 oper1 = uleb_extract(&data[off], ndx); 361 dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX, 362 EC_XWORD(oper1)); 363 break; 364 365 case 0x0f: /* v3: DW_CFA_def_cfa_expression, blk */ 366 oper1 = uleb_extract(&data[off], ndx); 367 dbg_print(0, MSG_ORIG(MSG_CFA_EBLK), PREFIX, 368 EC_XWORD(oper1)); 369 /* We currently do not decode the expression block */ 370 *ndx += oper1; 371 break; 372 373 case 0x10: /* v3: DW_CFA_expression, reg, blk */ 374 case 0x16: /* v3: DW_CFA_val_expression,reg,blk */ 375 oper1 = uleb_extract(&data[off], ndx); 376 oper2 = uleb_extract(&data[off], ndx); 377 dbg_print(0, MSG_ORIG(MSG_CFA_REG_EBLK), PREFIX, 378 REGNAME(oper1, rbuf1), EC_XWORD(oper2)); 379 /* We currently do not decode the expression block */ 380 *ndx += oper2; 381 break; 382 383 case 0x11: /* v3: DW_CFA_offset_extended_sf, reg, off */ 384 oper1 = uleb_extract(&data[off], ndx); 385 soper = sleb_extract(&data[off], ndx) * 386 state->ciedalign; 387 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX, 388 REGNAME(oper1, rbuf1), EC_SXWORD(soper)); 389 break; 390 391 case 0x12: /* v3: DW_CFA_def_cfa_sf, reg, offset */ 392 oper1 = uleb_extract(&data[off], ndx); 393 soper = sleb_extract(&data[off], ndx) * 394 state->ciedalign; 395 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX, 396 REGNAME(oper1, rbuf1), EC_SXWORD(soper)); 397 break; 398 399 case 0x13: /* DW_CFA_def_cfa_offset_sf, offset */ 400 soper = sleb_extract(&data[off], ndx) * 401 state->ciedalign; 402 dbg_print(0, MSG_ORIG(MSG_CFA_LLD), PREFIX, 403 EC_SXWORD(soper)); 404 break; 405 406 case 0x14: /* v3: DW_CFA_val_offset, reg, offset */ 407 oper1 = uleb_extract(&data[off], ndx); 408 soper = uleb_extract(&data[off], ndx) * 409 state->ciedalign; 410 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX, 411 REGNAME(oper1, rbuf1), EC_SXWORD(soper)); 412 break; 413 414 case 0x15: /* v3: DW_CFA_val_offset_sf, reg, offset */ 415 oper1 = uleb_extract(&data[off], ndx); 416 soper = sleb_extract(&data[off], ndx) * 417 state->ciedalign; 418 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX, 419 REGNAME(oper1, rbuf1), EC_SXWORD(soper)); 420 break; 421 422 case 0x1d: /* GNU: DW_CFA_MIPS_advance_loc8, delta */ 423 oper1 = dwarf_extract_uint(data + off, ndx, i, 424 state->do_swap) * state->ciecalign; 425 cur_pc += oper1; 426 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX, 427 loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc)); 428 loc_str = MSG_ORIG(MSG_STR_LOC); 429 break; 430 431 case 0x2e: /* GNU: DW_CFA_GNU_args_size, size */ 432 oper1 = uleb_extract(&data[off], ndx); 433 dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX, 434 EC_XWORD(oper1)); 435 436 break; 437 438 case 0x2f: /* GNU:DW_CFA_GNU_negative_offset_extended,reg,off */ 439 oper1 = uleb_extract(&data[off], ndx); 440 soper = -uleb_extract(&data[off], ndx) * 441 state->ciedalign; 442 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX, 443 REGNAME(oper1, rbuf1), EC_SXWORD(soper)); 444 break; 445 446 default: 447 /* 448 * Unrecognized OP code: DWARF data is variable length, 449 * so we don't know how many bytes to skip in order to 450 * advance to the next item. We cannot decode beyond 451 * this point, so dump the remainder in hex. 452 */ 453 (*ndx)--; /* Back up to unrecognized opcode */ 454 dump_hex_bytes(data + off + *ndx, len - *ndx, 455 indent, 8, 1); 456 (*ndx) = len; 457 break; 458 } 459 } 460 461 #undef PREFIX 462 #undef REGNAME 463 #undef LOW_OP 464 } 465 466 void 467 dump_eh_frame(uchar_t *data, size_t datasize, uint64_t sh_addr, 468 Half e_machine, uchar_t *e_ident) 469 { 470 Conv_dwarf_ehe_buf_t dwarf_ehe_buf; 471 dump_cfi_state_t cfi_state; 472 uint64_t off, ndx; 473 uint_t cieid, cielength, cieversion, cieretaddr; 474 int ciePflag, cieZflag, cieLflag, cieLflag_present; 475 uint_t cieaugndx, length, id; 476 char *cieaugstr; 477 478 cfi_state.e_machine = e_machine; 479 cfi_state.e_ident = e_ident; 480 cfi_state.sh_addr = sh_addr; 481 cfi_state.do_swap = _elf_sys_encoding() != e_ident[EI_DATA]; 482 483 off = 0; 484 while (off < datasize) { 485 ndx = 0; 486 487 /* 488 * Extract length in native format. A zero length indicates 489 * that this CIE is a terminator and that processing for this 490 * unwind information should end. However, skip this entry and 491 * keep processing, just in case there is any other information 492 * remaining in this section. Note, ld(1) will terminate the 493 * processing of the .eh_frame contents for this file after a 494 * zero length CIE, thus any information that does follow is 495 * ignored by ld(1), and is therefore questionable. 496 */ 497 length = (uint_t)dwarf_extract_uint(data + off, &ndx, 498 4, cfi_state.do_swap); 499 if (length == 0) { 500 dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM)); 501 off += 4; 502 continue; 503 } 504 505 /* 506 * extract CIE id in native format 507 */ 508 id = (uint_t)dwarf_extract_uint(data + off, &ndx, 509 4, cfi_state.do_swap); 510 511 /* 512 * A CIE record has an id of '0', otherwise this is a 513 * FDE entry and the 'id' is the CIE pointer. 514 */ 515 if (id == 0) { 516 uint64_t persVal, ndx_save; 517 uint_t axsize; 518 519 cielength = length; 520 cieid = id; 521 ciePflag = cfi_state.cieRflag = cieZflag = 0; 522 cieLflag = cieLflag_present = 0; 523 524 dbg_print(0, MSG_ORIG(MSG_UNW_CIE), 525 EC_XWORD(sh_addr + off)); 526 dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH), 527 cielength, cieid); 528 529 cieversion = data[off + ndx]; 530 ndx += 1; 531 cieaugstr = (char *)(&data[off + ndx]); 532 ndx += strlen(cieaugstr) + 1; 533 534 dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS), 535 cieversion, cieaugstr); 536 537 cfi_state.ciecalign = uleb_extract(&data[off], &ndx); 538 cfi_state.ciedalign = sleb_extract(&data[off], &ndx); 539 cieretaddr = data[off + ndx]; 540 ndx += 1; 541 542 dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN), 543 EC_XWORD(cfi_state.ciecalign), 544 EC_XWORD(cfi_state.ciedalign), cieretaddr); 545 546 if (cieaugstr[0]) 547 dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXVAL)); 548 549 for (cieaugndx = 0; cieaugstr[cieaugndx]; cieaugndx++) { 550 switch (cieaugstr[cieaugndx]) { 551 case 'z': 552 axsize = uleb_extract(&data[off], &ndx); 553 dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXSIZ), 554 axsize); 555 cieZflag = 1; 556 /* 557 * The auxiliary section can contain 558 * unused padding bytes at the end, so 559 * save the current index. Along with 560 * axsize, we will use it to set ndx to 561 * the proper continuation index after 562 * the aux data has been processed. 563 */ 564 ndx_save = ndx; 565 break; 566 case 'P': 567 ciePflag = data[off + ndx]; 568 ndx += 1; 569 570 persVal = dwarf_ehe_extract(&data[off], 571 &ndx, ciePflag, e_ident, 572 sh_addr, off + ndx); 573 dbg_print(0, 574 MSG_ORIG(MSG_UNW_CIEAXPERS)); 575 dbg_print(0, 576 MSG_ORIG(MSG_UNW_CIEAXPERSENC), 577 ciePflag, conv_dwarf_ehe(ciePflag, 578 &dwarf_ehe_buf)); 579 dbg_print(0, 580 MSG_ORIG(MSG_UNW_CIEAXPERSRTN), 581 EC_XWORD(persVal)); 582 break; 583 case 'R': 584 cfi_state.cieRflag = data[off + ndx]; 585 ndx += 1; 586 dbg_print(0, 587 MSG_ORIG(MSG_UNW_CIEAXCENC), 588 cfi_state.cieRflag, 589 conv_dwarf_ehe(cfi_state.cieRflag, 590 &dwarf_ehe_buf)); 591 break; 592 case 'L': 593 cieLflag_present = 1; 594 cieLflag = data[off + ndx]; 595 ndx += 1; 596 dbg_print(0, 597 MSG_ORIG(MSG_UNW_CIEAXLSDA), 598 cieLflag, conv_dwarf_ehe( 599 cieLflag, &dwarf_ehe_buf)); 600 break; 601 default: 602 dbg_print(0, 603 MSG_ORIG(MSG_UNW_CIEAXUNEC), 604 cieaugstr[cieaugndx]); 605 break; 606 } 607 } 608 609 /* 610 * If the z flag was present, reposition ndx using the 611 * length given. This will safely move us past any 612 * unaccessed padding bytes in the auxiliary section. 613 */ 614 if (cieZflag) 615 ndx = ndx_save + axsize; 616 617 /* 618 * Any remaining data are Call Frame Instructions 619 */ 620 if ((cielength + 4) > ndx) 621 dump_cfi(data, off, &ndx, cielength, &cfi_state, 622 MSG_ORIG(MSG_UNW_CIECFI), 3); 623 off += cielength + 4; 624 625 } else { 626 uint_t fdelength = length; 627 int fdecieptr = id; 628 uint64_t fdeaddrrange; 629 630 dbg_print(0, MSG_ORIG(MSG_UNW_FDE), 631 EC_XWORD(sh_addr + off)); 632 dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH), 633 fdelength, fdecieptr); 634 635 cfi_state.fdeinitloc = dwarf_ehe_extract(&data[off], 636 &ndx, cfi_state.cieRflag, e_ident, 637 sh_addr, off + ndx); 638 fdeaddrrange = dwarf_ehe_extract(&data[off], &ndx, 639 (cfi_state.cieRflag & ~DW_EH_PE_pcrel), 640 e_ident, sh_addr, off + ndx); 641 642 dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC), 643 EC_XWORD(cfi_state.fdeinitloc), 644 EC_XWORD(fdeaddrrange), 645 EC_XWORD(cfi_state.fdeinitloc + fdeaddrrange - 1)); 646 647 if (cieaugstr[0]) 648 dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXVAL)); 649 if (cieZflag) { 650 uint64_t val; 651 uint64_t lndx; 652 653 val = uleb_extract(&data[off], &ndx); 654 lndx = ndx; 655 ndx += val; 656 dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXSIZE), 657 EC_XWORD(val)); 658 if (val && cieLflag_present) { 659 uint64_t lsda; 660 661 lsda = dwarf_ehe_extract(&data[off], 662 &lndx, cieLflag, e_ident, 663 sh_addr, off + lndx); 664 dbg_print(0, 665 MSG_ORIG(MSG_UNW_FDEAXLSDA), 666 EC_XWORD(lsda)); 667 } 668 } 669 if ((fdelength + 4) > ndx) 670 dump_cfi(data, off, &ndx, fdelength, &cfi_state, 671 MSG_ORIG(MSG_UNW_FDECFI), 6); 672 off += fdelength + 4; 673 } 674 } 675 } 676