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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
40 * Data from eh_frame section used by dump_cfi()
45 Half e_machine
; /* ehdr->e_machine */
46 uchar_t
*e_ident
; /* ehdr->e_ident */
47 uint64_t sh_addr
; /* Address of eh_frame section */
48 int do_swap
; /* True if object and system byte */
50 int cieRflag
; /* R flag from current CIE */
51 uint64_t ciecalign
; /* CIE code align factor */
52 int64_t ciedalign
; /* CIE data align factor */
53 uint64_t fdeinitloc
; /* FDE initial location */
54 uint64_t gotaddr
; /* Address of the GOT */
59 * Extract an unsigned integer value from an .eh_frame section, converting it
60 * from its native byte order to that of the running machine if necessary.
63 * data - Base address from which to extract datum
64 * ndx - Address of variable giving index to start byte in data.
65 * size - # of bytes in datum. Must be one of: 1, 2, 4, 8
66 * do_swap - True if the data is in a different byte order than that
70 * *ndx is incremented by the size of the extracted datum.
72 * The requested datum is extracted, byte swapped if necessary,
76 dwarf_extract_uint(uchar_t
*data
, size_t len
, uint64_t *ndx
, int size
,
77 int do_swap
, uint64_t *ret
)
79 if (((*ndx
+ size
) > len
) ||
80 ((*ndx
+ size
) < *ndx
))
85 *ret
= (data
[(*ndx
)++]);
90 uchar_t
*p
= (uchar_t
*)&r
;
94 UL_ASSIGN_BSWAP_HALF(p
, data
);
96 UL_ASSIGN_HALF(p
, data
);
105 uchar_t
*p
= (uchar_t
*)&r
;
109 UL_ASSIGN_BSWAP_WORD(p
, data
);
111 UL_ASSIGN_WORD(p
, data
);
121 uchar_t
*p
= (uchar_t
*)&r
;
125 UL_ASSIGN_BSWAP_LWORD(p
, data
);
127 UL_ASSIGN_LWORD(p
, data
);
134 return (DW_BAD_ENCODING
);
141 * Map a DWARF register constant to the machine register name it
142 * corresponds to, formatting the result into buf.
144 * The assignment of DWARF register numbers is part of the system
145 * specific ABI for each platform.
148 * regno - DWARF register number
149 * mach - ELF machine code for platform
150 * buf, bufsize - Buffer to receive the formatted result string
153 * The results are formatted into buf, and buf is returned.
154 * If the generated output would exceed the size of the buffer
155 * provided, it will be clipped to fit.
158 dwarf_regname(Half mach
, int regno
, char *buf
, size_t bufsize
)
160 Conv_inv_buf_t inv_buf
;
164 name
= conv_dwarf_regname(mach
, regno
, 0, &good_name
, &inv_buf
);
167 * If there is a good mnemonic machine name for the register,
168 * format the result as 'r# (mnemonic)'. If there is no good
169 * name for it, then simply format the dwarf name as 'r#'.
172 (void) snprintf(buf
, bufsize
, MSG_ORIG(MSG_REG_FMT_NAME
),
175 (void) snprintf(buf
, bufsize
, MSG_ORIG(MSG_REG_FMT_BASIC
),
183 * Decode eh_frame Call Frame Instructions, printing each one on a
187 * data - Address of base of eh_frame section being processed
188 * off - Offset of current FDE within eh_frame
189 * ndx - Index of current position within current FDE
190 * len - Length of FDE
191 * state - Object, CIE, and FDE state for current request
192 * msg - Header message to issue before producing output.
193 * indent - # of indentation characters issued for each line of output.
196 * The Call Frame Instructions have been decoded and printed.
198 * *ndx has been incremented to contain the index of the next
199 * byte of data to be processed in eh_frame.
202 * The format of Call Frame Instructions in .eh_frame sections is based
203 * on the DWARF specification.
206 dump_cfi(uchar_t
*data
, uint64_t off
, uint64_t *ndx
, uint_t len
,
207 dump_cfi_state_t
*state
, const char *msg
, int indent
)
210 * We use %*s%s to insert leading whitespace and the op name.
211 * PREFIX supplies these arguments.
213 #define PREFIX indent, MSG_ORIG(MSG_STR_EMPTY), opname
215 /* Hide boilerplate clutter in calls to dwarf_regname() */
216 #define REGNAME(_rnum, _buf) \
217 dwarf_regname(state->e_machine, _rnum, _buf, sizeof (_buf))
219 /* Extract the lower 6 bits from an op code */
220 #define LOW_OP(_op) (_op & 0x3f)
222 char rbuf1
[32], rbuf2
[32];
223 Conv_inv_buf_t inv_buf
;
226 uint64_t oper1
, oper2
, cur_pc
;
234 * In a CIE/FDE, the length field does not include it's own
235 * size. Hence, the value passed in is 4 less than the index
236 * of the actual final location.
241 * There is a concept of the 'current location', which is the PC
242 * to which the current item applies. It starts out set to the
243 * FDE initial location, and can be set or incremented by
244 * various OP codes. cur_pc is used to track this.
246 * We want to use 'initloc' in the output the first time the location
247 * is referenced, and then switch to 'loc' for subsequent references.
248 * loc_str is used to manage that.
250 cur_pc
= state
->fdeinitloc
;
251 loc_str
= MSG_ORIG(MSG_STR_INITLOC
);
255 * The first byte contains the primary op code in the top
256 * 2 bits, so there are 4 of them. Primary OP code
257 * 0 uses the lower 6 bits to specify a sub-opcode, allowing
258 * for 64 of them. The other 3 primary op codes use the
259 * lower 6 bits to hold an operand (a register #, or value).
261 * Check the primary OP code. If it's 1-3, handle it
262 * and move to the next loop iteration. For OP code 0,
263 * fall through to decode the sub-code.
265 op
= data
[off
+ (*ndx
)++];
266 opname
= conv_dwarf_cfa(op
, 0, &inv_buf
);
268 case 0x1: /* v2: DW_CFA_advance_loc, delta */
269 oper1
= state
->ciecalign
* LOW_OP(op
);
271 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC
), PREFIX
,
272 loc_str
, EC_XWORD(oper1
), EC_XWORD(cur_pc
));
273 loc_str
= MSG_ORIG(MSG_STR_LOC
);
276 case 0x2: /* v2: DW_CFA_offset, reg, offset */
277 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
279 (void) fprintf(stderr
,
280 MSG_INTL(MSG_ERR_DWOVRFLW
),
281 state
->file
, state
->sh_name
);
285 oper1
*= state
->ciedalign
;
286 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF
), PREFIX
,
287 REGNAME(LOW_OP(op
), rbuf1
), EC_XWORD(oper1
));
290 case 0x3: /* v2: DW_CFA_restore, reg */
291 dbg_print(0, MSG_ORIG(MSG_CFA_REG
), PREFIX
,
292 REGNAME(LOW_OP(op
), rbuf1
));
297 * If we're here, the high order 2 bits are 0. The low 6 bits
298 * specify a sub-opcode defining the operation.
301 case 0x00: /* v2: DW_CFA_nop */
303 * No-ops are used to fill unused space required
304 * for alignment. It is common for there to be
305 * multiple adjacent nops. It saves space to report
306 * them all with a single line of output.
309 (*ndx
< len
) && (data
[off
+ *ndx
] == 0);
312 dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLEREP
), PREFIX
, i
);
315 case 0x0a: /* v2: DW_CFA_remember_state */
316 case 0x0b: /* v2: DW_CFA_restore_state */
317 case 0x2d: /* GNU: DW_CFA_GNU_window_save */
318 dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLE
), PREFIX
);
321 case 0x01: /* v2: DW_CFA_set_loc, address */
322 switch (dwarf_ehe_extract(&data
[off
], len
, ndx
,
323 &cur_pc
, state
->cieRflag
, state
->e_ident
, B_FALSE
,
324 state
->sh_addr
, off
+ *ndx
, state
->gotaddr
)) {
326 (void) fprintf(stderr
,
327 MSG_INTL(MSG_ERR_DWOVRFLW
),
328 state
->file
, state
->sh_name
);
330 case DW_BAD_ENCODING
:
331 (void) fprintf(stderr
,
332 MSG_INTL(MSG_ERR_DWBADENC
),
333 state
->file
, state
->sh_name
,
339 dbg_print(0, MSG_ORIG(MSG_CFA_CFASET
), PREFIX
,
343 case 0x02: /* v2: DW_CFA_advance_loc_1, 1-byte delta */
344 case 0x03: /* v2: DW_CFA_advance_loc_2, 2-byte delta */
345 case 0x04: /* v2: DW_CFA_advance_loc_4, 4-byte delta */
347 * Since the codes are contiguous, and the sizes are
348 * powers of 2, we can compute the word width from
351 i
= 1 << (op
- 0x02);
352 switch (dwarf_extract_uint(data
+ off
, len
,
353 ndx
, i
, state
->do_swap
, &oper1
)) {
354 case DW_BAD_ENCODING
:
355 (void) fprintf(stderr
,
356 MSG_INTL(MSG_ERR_DWBADENC
),
357 state
->file
, state
->sh_name
,
361 (void) fprintf(stderr
,
362 MSG_INTL(MSG_ERR_DWOVRFLW
),
363 state
->file
, state
->sh_name
);
368 oper1
*= state
->ciecalign
;
370 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC
), PREFIX
,
371 loc_str
, EC_XWORD(oper1
), EC_XWORD(cur_pc
));
372 loc_str
= MSG_ORIG(MSG_STR_LOC
);
375 case 0x05: /* v2: DW_CFA_offset_extended,reg,off */
376 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
378 (void) fprintf(stderr
,
379 MSG_INTL(MSG_ERR_DWOVRFLW
),
380 state
->file
, state
->sh_name
);
384 if (sleb_extract(&data
[off
], ndx
, len
, &soper
) ==
386 (void) fprintf(stderr
,
387 MSG_INTL(MSG_ERR_DWOVRFLW
),
388 state
->file
, state
->sh_name
);
392 soper
*= state
->ciedalign
;
393 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF
), PREFIX
,
394 REGNAME(oper1
, rbuf1
), EC_SXWORD(soper
));
397 case 0x06: /* v2: DW_CFA_restore_extended, reg */
398 case 0x0d: /* v2: DW_CFA_def_cfa_register, reg */
399 case 0x08: /* v2: DW_CFA_same_value, reg */
400 case 0x07: /* v2: DW_CFA_undefined, reg */
401 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
403 (void) fprintf(stderr
,
404 MSG_INTL(MSG_ERR_DWOVRFLW
),
405 state
->file
, state
->sh_name
);
409 dbg_print(0, MSG_ORIG(MSG_CFA_REG
), PREFIX
,
410 REGNAME(oper1
, rbuf1
));
414 case 0x09: /* v2: DW_CFA_register, reg, reg */
415 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
417 (void) fprintf(stderr
,
418 MSG_INTL(MSG_ERR_DWOVRFLW
),
419 state
->file
, state
->sh_name
);
423 if (uleb_extract(&data
[off
], ndx
, len
, &oper2
) ==
425 (void) fprintf(stderr
,
426 MSG_INTL(MSG_ERR_DWOVRFLW
),
427 state
->file
, state
->sh_name
);
430 dbg_print(0, MSG_ORIG(MSG_CFA_REG_REG
), PREFIX
,
431 REGNAME(oper1
, rbuf1
), REGNAME(oper2
, rbuf2
));
434 case 0x0c: /* v2: DW_CFA_def_cfa, reg, offset */
435 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
437 (void) fprintf(stderr
,
438 MSG_INTL(MSG_ERR_DWOVRFLW
),
439 state
->file
, state
->sh_name
);
443 if (uleb_extract(&data
[off
], ndx
, len
, &oper2
) ==
445 (void) fprintf(stderr
,
446 MSG_INTL(MSG_ERR_DWOVRFLW
),
447 state
->file
, state
->sh_name
);
450 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLU
), PREFIX
,
451 REGNAME(oper1
, rbuf1
), EC_XWORD(oper2
));
454 case 0x0e: /* v2: DW_CFA_def_cfa_offset, offset */
455 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
457 (void) fprintf(stderr
,
458 MSG_INTL(MSG_ERR_DWOVRFLW
),
459 state
->file
, state
->sh_name
);
462 dbg_print(0, MSG_ORIG(MSG_CFA_LLU
), PREFIX
,
466 case 0x0f: /* v3: DW_CFA_def_cfa_expression, blk */
467 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
469 (void) fprintf(stderr
,
470 MSG_INTL(MSG_ERR_DWOVRFLW
),
471 state
->file
, state
->sh_name
);
474 dbg_print(0, MSG_ORIG(MSG_CFA_EBLK
), PREFIX
,
476 /* We currently do not decode the expression block */
480 case 0x10: /* v3: DW_CFA_expression, reg, blk */
481 case 0x16: /* v3: DW_CFA_val_expression,reg,blk */
482 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
484 (void) fprintf(stderr
,
485 MSG_INTL(MSG_ERR_DWOVRFLW
),
486 state
->file
, state
->sh_name
);
490 if (uleb_extract(&data
[off
], ndx
, len
, &oper2
) ==
492 (void) fprintf(stderr
,
493 MSG_INTL(MSG_ERR_DWOVRFLW
),
494 state
->file
, state
->sh_name
);
497 dbg_print(0, MSG_ORIG(MSG_CFA_REG_EBLK
), PREFIX
,
498 REGNAME(oper1
, rbuf1
), EC_XWORD(oper2
));
499 /* We currently do not decode the expression block */
503 case 0x11: /* v3: DW_CFA_offset_extended_sf, reg, off */
504 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
506 (void) fprintf(stderr
,
507 MSG_INTL(MSG_ERR_DWOVRFLW
),
508 state
->file
, state
->sh_name
);
512 if (sleb_extract(&data
[off
], ndx
, len
, &soper
) ==
514 (void) fprintf(stderr
,
515 MSG_INTL(MSG_ERR_DWOVRFLW
),
516 state
->file
, state
->sh_name
);
520 soper
*= state
->ciedalign
;
521 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF
), PREFIX
,
522 REGNAME(oper1
, rbuf1
), EC_SXWORD(soper
));
525 case 0x12: /* v3: DW_CFA_def_cfa_sf, reg, offset */
526 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
528 (void) fprintf(stderr
,
529 MSG_INTL(MSG_ERR_DWOVRFLW
),
530 state
->file
, state
->sh_name
);
534 if (sleb_extract(&data
[off
], ndx
, len
, &soper
) ==
536 (void) fprintf(stderr
,
537 MSG_INTL(MSG_ERR_DWOVRFLW
),
538 state
->file
, state
->sh_name
);
542 soper
*= state
->ciedalign
;
543 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD
), PREFIX
,
544 REGNAME(oper1
, rbuf1
), EC_SXWORD(soper
));
547 case 0x13: /* DW_CFA_def_cfa_offset_sf, offset */
548 if (sleb_extract(&data
[off
], ndx
, len
, &soper
) ==
550 (void) fprintf(stderr
,
551 MSG_INTL(MSG_ERR_DWOVRFLW
),
552 state
->file
, state
->sh_name
);
556 soper
*= state
->ciedalign
;
557 dbg_print(0, MSG_ORIG(MSG_CFA_LLD
), PREFIX
,
561 case 0x14: /* v3: DW_CFA_val_offset, reg, offset */
562 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
564 (void) fprintf(stderr
,
565 MSG_INTL(MSG_ERR_DWOVRFLW
),
566 state
->file
, state
->sh_name
);
570 if (sleb_extract(&data
[off
], ndx
, len
, &soper
) ==
572 (void) fprintf(stderr
,
573 MSG_INTL(MSG_ERR_DWOVRFLW
),
574 state
->file
, state
->sh_name
);
578 soper
*= state
->ciedalign
;
579 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD
), PREFIX
,
580 REGNAME(oper1
, rbuf1
), EC_SXWORD(soper
));
583 case 0x15: /* v3: DW_CFA_val_offset_sf, reg, offset */
584 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
586 (void) fprintf(stderr
,
587 MSG_INTL(MSG_ERR_DWOVRFLW
),
588 state
->file
, state
->sh_name
);
592 if (sleb_extract(&data
[off
], ndx
, len
, &soper
) ==
594 (void) fprintf(stderr
,
595 MSG_INTL(MSG_ERR_DWOVRFLW
),
596 state
->file
, state
->sh_name
);
600 soper
*= state
->ciedalign
;
601 dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD
), PREFIX
,
602 REGNAME(oper1
, rbuf1
), EC_SXWORD(soper
));
605 case 0x1d: /* GNU: DW_CFA_MIPS_advance_loc8, delta */
606 switch (dwarf_extract_uint(data
+ off
, len
,
607 ndx
, 8, state
->do_swap
, &oper1
)) {
608 case DW_BAD_ENCODING
:
609 (void) fprintf(stderr
,
610 MSG_INTL(MSG_ERR_DWBADENC
),
611 state
->file
, state
->sh_name
,
615 (void) fprintf(stderr
,
616 MSG_INTL(MSG_ERR_DWOVRFLW
),
617 state
->file
, state
->sh_name
);
622 oper1
*= state
->ciecalign
;
624 dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC
), PREFIX
,
625 loc_str
, EC_XWORD(oper1
), EC_XWORD(cur_pc
));
626 loc_str
= MSG_ORIG(MSG_STR_LOC
);
629 case 0x2e: /* GNU: DW_CFA_GNU_args_size, size */
630 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
632 (void) fprintf(stderr
,
633 MSG_INTL(MSG_ERR_DWOVRFLW
),
634 state
->file
, state
->sh_name
);
638 dbg_print(0, MSG_ORIG(MSG_CFA_LLU
), PREFIX
,
643 case 0x2f: /* GNU:DW_CFA_GNU_negative_offset_extended,reg,off */
644 if (uleb_extract(&data
[off
], ndx
, len
, &oper1
) ==
646 (void) fprintf(stderr
,
647 MSG_INTL(MSG_ERR_DWOVRFLW
),
648 state
->file
, state
->sh_name
);
652 if (sleb_extract(&data
[off
], ndx
, len
, &soper
) ==
654 (void) fprintf(stderr
,
655 MSG_INTL(MSG_ERR_DWOVRFLW
),
656 state
->file
, state
->sh_name
);
659 soper
= -soper
* state
->ciedalign
;
660 soper
*= state
->ciedalign
;
661 dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF
), PREFIX
,
662 REGNAME(oper1
, rbuf1
), EC_SXWORD(soper
));
667 * Unrecognized OP code: DWARF data is variable length,
668 * so we don't know how many bytes to skip in order to
669 * advance to the next item. We cannot decode beyond
670 * this point, so dump the remainder in hex.
672 (*ndx
)--; /* Back up to unrecognized opcode */
673 dump_hex_bytes(data
+ off
+ *ndx
, len
- *ndx
,
686 dump_eh_frame(const char *file
, char *sh_name
, uchar_t
*data
, size_t datasize
,
687 uint64_t sh_addr
, Half e_machine
, uchar_t
*e_ident
, uint64_t gotaddr
)
689 Conv_dwarf_ehe_buf_t dwarf_ehe_buf
;
690 dump_cfi_state_t cfi_state
;
691 uint64_t off
, ndx
, length
, id
;
692 uint_t cieid
, cielength
, cieversion
, cieretaddr
;
693 int ciePflag
= 0, cieZflag
= 0, cieLflag
= 0;
694 int cieLflag_present
= 0;
696 char *cieaugstr
= NULL
;
697 boolean_t have_cie
= B_FALSE
;
699 cfi_state
.file
= file
;
700 cfi_state
.sh_name
= sh_name
;
701 cfi_state
.e_machine
= e_machine
;
702 cfi_state
.e_ident
= e_ident
;
703 cfi_state
.sh_addr
= sh_addr
;
704 cfi_state
.do_swap
= _elf_sys_encoding() != e_ident
[EI_DATA
];
705 cfi_state
.gotaddr
= gotaddr
;
708 while (off
< datasize
) {
712 * Extract length in native format. A zero length indicates
713 * that this CIE is a terminator and that processing for this
714 * unwind information should end. However, skip this entry and
715 * keep processing, just in case there is any other information
716 * remaining in this section. Note, ld(1) will terminate the
717 * processing of the .eh_frame contents for this file after a
718 * zero length CIE, thus any information that does follow is
719 * ignored by ld(1), and is therefore questionable.
721 if (dwarf_extract_uint(data
+ off
, datasize
- off
,
722 &ndx
, 4, cfi_state
.do_swap
, &length
) == DW_OVERFLOW
) {
723 (void) fprintf(stderr
,
724 MSG_INTL(MSG_ERR_DWOVRFLW
),
730 dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM
));
735 if (length
> (datasize
- off
)) {
736 (void) fprintf(stderr
, MSG_INTL(MSG_ERR_BADCIEFDELEN
),
737 file
, sh_name
, EC_XWORD(length
),
738 EC_XWORD(sh_addr
+ off
));
740 * If length is wrong, we have no means to find the
741 * next entry, just give up
747 * extract CIE id in native format
749 if (dwarf_extract_uint(data
+ off
, datasize
- off
, &ndx
,
750 4, cfi_state
.do_swap
, &id
) == DW_OVERFLOW
) {
751 (void) fprintf(stderr
,
752 MSG_INTL(MSG_ERR_DWOVRFLW
),
758 * A CIE record has an id of '0', otherwise this is a
759 * FDE entry and the 'id' is the CIE pointer.
762 uint64_t persVal
, ndx_save
= 0;
769 ciePflag
= cfi_state
.cieRflag
= cieZflag
= 0;
770 cieLflag
= cieLflag_present
= 0;
772 dbg_print(0, MSG_ORIG(MSG_UNW_CIE
),
773 EC_XWORD(sh_addr
+ off
));
774 dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH
),
777 cieversion
= data
[off
+ ndx
];
779 cieaugstr
= (char *)(&data
[off
+ ndx
]);
780 ndx
+= strlen(cieaugstr
) + 1;
782 dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS
),
783 cieversion
, cieaugstr
);
785 if (uleb_extract(&data
[off
], &ndx
, datasize
- off
,
786 &cfi_state
.ciecalign
) == DW_OVERFLOW
) {
787 (void) fprintf(stderr
,
788 MSG_INTL(MSG_ERR_DWOVRFLW
),
793 if (sleb_extract(&data
[off
], &ndx
, datasize
- off
,
794 &cfi_state
.ciedalign
) == DW_OVERFLOW
) {
795 (void) fprintf(stderr
,
796 MSG_INTL(MSG_ERR_DWOVRFLW
),
800 cieretaddr
= data
[off
+ ndx
];
803 dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN
),
804 EC_XWORD(cfi_state
.ciecalign
),
805 EC_XWORD(cfi_state
.ciedalign
), cieretaddr
);
808 dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXVAL
));
810 for (cieaugndx
= 0; cieaugstr
[cieaugndx
]; cieaugndx
++) {
811 switch (cieaugstr
[cieaugndx
]) {
813 if (uleb_extract(&data
[off
], &ndx
,
814 datasize
- off
, &axsize
) ==
816 (void) fprintf(stderr
,
817 MSG_INTL(MSG_ERR_DWOVRFLW
),
822 dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXSIZ
),
826 * The auxiliary section can contain
827 * unused padding bytes at the end, so
828 * save the current index. Along with
829 * axsize, we will use it to set ndx to
830 * the proper continuation index after
831 * the aux data has been processed.
836 ciePflag
= data
[off
+ ndx
];
839 switch (dwarf_ehe_extract(&data
[off
],
840 datasize
- off
, &ndx
, &persVal
,
841 ciePflag
, e_ident
, B_FALSE
, sh_addr
,
842 off
+ ndx
, gotaddr
)) {
844 (void) fprintf(stderr
,
845 MSG_INTL(MSG_ERR_DWOVRFLW
),
848 case DW_BAD_ENCODING
:
849 (void) fprintf(stderr
,
850 MSG_INTL(MSG_ERR_DWBADENC
),
851 file
, sh_name
, ciePflag
);
857 MSG_ORIG(MSG_UNW_CIEAXPERS
));
859 MSG_ORIG(MSG_UNW_CIEAXPERSENC
),
860 ciePflag
, conv_dwarf_ehe(ciePflag
,
863 MSG_ORIG(MSG_UNW_CIEAXPERSRTN
),
867 cfi_state
.cieRflag
= data
[off
+ ndx
];
870 MSG_ORIG(MSG_UNW_CIEAXCENC
),
872 conv_dwarf_ehe(cfi_state
.cieRflag
,
876 cieLflag_present
= 1;
877 cieLflag
= data
[off
+ ndx
];
880 MSG_ORIG(MSG_UNW_CIEAXLSDA
),
881 cieLflag
, conv_dwarf_ehe(
882 cieLflag
, &dwarf_ehe_buf
));
886 MSG_ORIG(MSG_UNW_CIEAXUNEC
),
887 cieaugstr
[cieaugndx
]);
893 * If the z flag was present, reposition ndx using the
894 * length given. This will safely move us past any
895 * unaccessed padding bytes in the auxiliary section.
898 ndx
= ndx_save
+ axsize
;
901 * Any remaining data are Call Frame Instructions
903 if ((cielength
+ 4) > ndx
)
904 dump_cfi(data
, off
, &ndx
, cielength
, &cfi_state
,
905 MSG_ORIG(MSG_UNW_CIECFI
), 3);
906 off
+= cielength
+ 4;
909 uint_t fdelength
= length
;
911 uint64_t fdeaddrrange
;
914 (void) fprintf(stderr
,
915 MSG_INTL(MSG_ERR_DWNOCIE
), file
, sh_name
);
919 dbg_print(0, MSG_ORIG(MSG_UNW_FDE
),
920 EC_XWORD(sh_addr
+ off
));
921 dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH
),
922 fdelength
, fdecieptr
);
924 switch (dwarf_ehe_extract(&data
[off
], datasize
- off
,
925 &ndx
, &cfi_state
.fdeinitloc
, cfi_state
.cieRflag
,
926 e_ident
, B_FALSE
, sh_addr
, off
+ ndx
, gotaddr
)) {
928 (void) fprintf(stderr
,
929 MSG_INTL(MSG_ERR_DWOVRFLW
), file
, sh_name
);
931 case DW_BAD_ENCODING
:
932 (void) fprintf(stderr
,
933 MSG_INTL(MSG_ERR_DWBADENC
), file
, sh_name
,
940 switch (dwarf_ehe_extract(&data
[off
], datasize
- off
,
942 (cfi_state
.cieRflag
& ~DW_EH_PE_pcrel
), e_ident
,
943 B_FALSE
, sh_addr
, off
+ ndx
, gotaddr
)) {
945 (void) fprintf(stderr
,
946 MSG_INTL(MSG_ERR_DWOVRFLW
), file
, sh_name
);
948 case DW_BAD_ENCODING
:
949 (void) fprintf(stderr
,
950 MSG_INTL(MSG_ERR_DWBADENC
), file
, sh_name
,
951 (cfi_state
.cieRflag
& ~DW_EH_PE_pcrel
));
957 dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC
),
958 EC_XWORD(cfi_state
.fdeinitloc
),
959 EC_XWORD(fdeaddrrange
),
960 EC_XWORD(cfi_state
.fdeinitloc
+ fdeaddrrange
- 1));
962 if ((cieaugstr
!= NULL
) && (cieaugstr
[0] != '\0'))
963 dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXVAL
));
968 if (uleb_extract(&data
[off
], &ndx
,
969 datasize
- off
, &val
) == DW_OVERFLOW
) {
970 (void) fprintf(stderr
,
971 MSG_INTL(MSG_ERR_DWOVRFLW
),
977 dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXSIZE
),
979 if (val
&& cieLflag_present
) {
982 switch (dwarf_ehe_extract(&data
[off
],
983 datasize
- off
, &lndx
, &lsda
,
984 cieLflag
, e_ident
, B_FALSE
, sh_addr
,
985 off
+ lndx
, gotaddr
)) {
987 (void) fprintf(stderr
,
988 MSG_INTL(MSG_ERR_DWOVRFLW
),
991 case DW_BAD_ENCODING
:
992 (void) fprintf(stderr
,
993 MSG_INTL(MSG_ERR_DWBADENC
),
994 file
, sh_name
, cieLflag
);
1000 MSG_ORIG(MSG_UNW_FDEAXLSDA
),
1004 if ((fdelength
+ 4) > ndx
)
1005 dump_cfi(data
, off
, &ndx
, fdelength
, &cfi_state
,
1006 MSG_ORIG(MSG_UNW_FDECFI
), 6);
1007 off
+= fdelength
+ 4;