17e16fca0SAli Bahrami /*
27e16fca0SAli Bahrami * CDDL HEADER START
37e16fca0SAli Bahrami *
47e16fca0SAli Bahrami * The contents of this file are subject to the terms of the
57e16fca0SAli Bahrami * Common Development and Distribution License (the "License").
67e16fca0SAli Bahrami * You may not use this file except in compliance with the License.
77e16fca0SAli Bahrami *
87e16fca0SAli Bahrami * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97e16fca0SAli Bahrami * or http://www.opensolaris.org/os/licensing.
107e16fca0SAli Bahrami * See the License for the specific language governing permissions
117e16fca0SAli Bahrami * and limitations under the License.
127e16fca0SAli Bahrami *
137e16fca0SAli Bahrami * When distributing Covered Code, include this CDDL HEADER in each
147e16fca0SAli Bahrami * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157e16fca0SAli Bahrami * If applicable, add the following below this CDDL HEADER, with the
167e16fca0SAli Bahrami * fields enclosed by brackets "[]" replaced with your own identifying
177e16fca0SAli Bahrami * information: Portions Copyright [yyyy] [name of copyright owner]
187e16fca0SAli Bahrami *
197e16fca0SAli Bahrami * CDDL HEADER END
207e16fca0SAli Bahrami */
217e16fca0SAli Bahrami
227e16fca0SAli Bahrami /*
237e16fca0SAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247e16fca0SAli Bahrami * Use is subject to license terms.
257e16fca0SAli Bahrami */
267e16fca0SAli Bahrami
277e16fca0SAli Bahrami #include <_libelf.h>
287e16fca0SAli Bahrami #include <dwarf.h>
297e16fca0SAli Bahrami #include <stdio.h>
307e16fca0SAli Bahrami #include <unistd.h>
317e16fca0SAli Bahrami #include <errno.h>
327e16fca0SAli Bahrami #include <strings.h>
337e16fca0SAli Bahrami #include <debug.h>
347e16fca0SAli Bahrami #include <conv.h>
357e16fca0SAli Bahrami #include <msg.h>
367e16fca0SAli Bahrami #include <_elfdump.h>
377e16fca0SAli Bahrami
387e16fca0SAli Bahrami
397e16fca0SAli Bahrami /*
407e16fca0SAli Bahrami * Data from eh_frame section used by dump_cfi()
417e16fca0SAli Bahrami */
427e16fca0SAli Bahrami typedef struct {
43*37915d86SRichard Lowe const char *file;
44*37915d86SRichard Lowe const char *sh_name;
457e16fca0SAli Bahrami Half e_machine; /* ehdr->e_machine */
467e16fca0SAli Bahrami uchar_t *e_ident; /* ehdr->e_ident */
477e16fca0SAli Bahrami uint64_t sh_addr; /* Address of eh_frame section */
487e16fca0SAli Bahrami int do_swap; /* True if object and system byte */
497e16fca0SAli Bahrami /* order differs */
507e16fca0SAli Bahrami int cieRflag; /* R flag from current CIE */
517e16fca0SAli Bahrami uint64_t ciecalign; /* CIE code align factor */
527e16fca0SAli Bahrami int64_t ciedalign; /* CIE data align factor */
537e16fca0SAli Bahrami uint64_t fdeinitloc; /* FDE initial location */
54965630c1SRichard Lowe uint64_t gotaddr; /* Address of the GOT */
557e16fca0SAli Bahrami } dump_cfi_state_t;
567e16fca0SAli Bahrami
577e16fca0SAli Bahrami
587e16fca0SAli Bahrami /*
597e16fca0SAli Bahrami * Extract an unsigned integer value from an .eh_frame section, converting it
607e16fca0SAli Bahrami * from its native byte order to that of the running machine if necessary.
617e16fca0SAli Bahrami *
627e16fca0SAli Bahrami * entry:
637e16fca0SAli Bahrami * data - Base address from which to extract datum
647e16fca0SAli Bahrami * ndx - Address of variable giving index to start byte in data.
657e16fca0SAli Bahrami * size - # of bytes in datum. Must be one of: 1, 2, 4, 8
667e16fca0SAli Bahrami * do_swap - True if the data is in a different byte order than that
677e16fca0SAli Bahrami * of the host system.
687e16fca0SAli Bahrami *
697e16fca0SAli Bahrami * exit:
707e16fca0SAli Bahrami * *ndx is incremented by the size of the extracted datum.
717e16fca0SAli Bahrami *
727e16fca0SAli Bahrami * The requested datum is extracted, byte swapped if necessary,
737e16fca0SAli Bahrami * and returned.
747e16fca0SAli Bahrami */
75*37915d86SRichard Lowe static dwarf_error_t
dwarf_extract_uint(uchar_t * data,size_t len,uint64_t * ndx,int size,int do_swap,uint64_t * ret)76*37915d86SRichard Lowe dwarf_extract_uint(uchar_t *data, size_t len, uint64_t *ndx, int size,
77*37915d86SRichard Lowe int do_swap, uint64_t *ret)
787e16fca0SAli Bahrami {
79*37915d86SRichard Lowe if (((*ndx + size) > len) ||
80*37915d86SRichard Lowe ((*ndx + size) < *ndx))
81*37915d86SRichard Lowe return (DW_OVERFLOW);
82*37915d86SRichard Lowe
837e16fca0SAli Bahrami switch (size) {
847e16fca0SAli Bahrami case 1:
85*37915d86SRichard Lowe *ret = (data[(*ndx)++]);
86*37915d86SRichard Lowe return (DW_SUCCESS);
877e16fca0SAli Bahrami case 2:
887e16fca0SAli Bahrami {
897e16fca0SAli Bahrami Half r;
907e16fca0SAli Bahrami uchar_t *p = (uchar_t *)&r;
917e16fca0SAli Bahrami
927e16fca0SAli Bahrami data += *ndx;
937e16fca0SAli Bahrami if (do_swap)
947e16fca0SAli Bahrami UL_ASSIGN_BSWAP_HALF(p, data);
957e16fca0SAli Bahrami else
967e16fca0SAli Bahrami UL_ASSIGN_HALF(p, data);
977e16fca0SAli Bahrami
987e16fca0SAli Bahrami (*ndx) += 2;
99*37915d86SRichard Lowe *ret = r;
100*37915d86SRichard Lowe return (DW_SUCCESS);
1017e16fca0SAli Bahrami }
1027e16fca0SAli Bahrami case 4:
1037e16fca0SAli Bahrami {
1047e16fca0SAli Bahrami Word r;
1057e16fca0SAli Bahrami uchar_t *p = (uchar_t *)&r;
1067e16fca0SAli Bahrami
1077e16fca0SAli Bahrami data += *ndx;
1087e16fca0SAli Bahrami if (do_swap)
1097e16fca0SAli Bahrami UL_ASSIGN_BSWAP_WORD(p, data);
1107e16fca0SAli Bahrami else
1117e16fca0SAli Bahrami UL_ASSIGN_WORD(p, data);
1127e16fca0SAli Bahrami
1137e16fca0SAli Bahrami (*ndx) += 4;
114*37915d86SRichard Lowe *ret = r;
115*37915d86SRichard Lowe return (DW_SUCCESS);
1167e16fca0SAli Bahrami }
1177e16fca0SAli Bahrami
1187e16fca0SAli Bahrami case 8:
1197e16fca0SAli Bahrami {
1207e16fca0SAli Bahrami uint64_t r;
1217e16fca0SAli Bahrami uchar_t *p = (uchar_t *)&r;
1227e16fca0SAli Bahrami
1237e16fca0SAli Bahrami data += *ndx;
1247e16fca0SAli Bahrami if (do_swap)
1257e16fca0SAli Bahrami UL_ASSIGN_BSWAP_LWORD(p, data);
1267e16fca0SAli Bahrami else
1277e16fca0SAli Bahrami UL_ASSIGN_LWORD(p, data);
1287e16fca0SAli Bahrami
1297e16fca0SAli Bahrami (*ndx) += 8;
130*37915d86SRichard Lowe *ret = r;
131*37915d86SRichard Lowe return (DW_SUCCESS);
1327e16fca0SAli Bahrami }
133*37915d86SRichard Lowe default:
134*37915d86SRichard Lowe return (DW_BAD_ENCODING);
1357e16fca0SAli Bahrami }
1367e16fca0SAli Bahrami
137*37915d86SRichard Lowe /* NOTREACHED */
1387e16fca0SAli Bahrami }
1397e16fca0SAli Bahrami
1407e16fca0SAli Bahrami /*
1417e16fca0SAli Bahrami * Map a DWARF register constant to the machine register name it
1427e16fca0SAli Bahrami * corresponds to, formatting the result into buf.
1437e16fca0SAli Bahrami *
1447e16fca0SAli Bahrami * The assignment of DWARF register numbers is part of the system
1457e16fca0SAli Bahrami * specific ABI for each platform.
1467e16fca0SAli Bahrami *
1477e16fca0SAli Bahrami * entry:
1487e16fca0SAli Bahrami * regno - DWARF register number
1497e16fca0SAli Bahrami * mach - ELF machine code for platform
1507e16fca0SAli Bahrami * buf, bufsize - Buffer to receive the formatted result string
1517e16fca0SAli Bahrami *
1527e16fca0SAli Bahrami * exit:
1537e16fca0SAli Bahrami * The results are formatted into buf, and buf is returned.
1547e16fca0SAli Bahrami * If the generated output would exceed the size of the buffer
1557e16fca0SAli Bahrami * provided, it will be clipped to fit.
1567e16fca0SAli Bahrami */
1577e16fca0SAli Bahrami static const char *
dwarf_regname(Half mach,int regno,char * buf,size_t bufsize)1587e16fca0SAli Bahrami dwarf_regname(Half mach, int regno, char *buf, size_t bufsize)
1597e16fca0SAli Bahrami {
1607e16fca0SAli Bahrami Conv_inv_buf_t inv_buf;
1617e16fca0SAli Bahrami const char *name;
1627e16fca0SAli Bahrami int good_name;
1637e16fca0SAli Bahrami
1647e16fca0SAli Bahrami name = conv_dwarf_regname(mach, regno, 0, &good_name, &inv_buf);
1657e16fca0SAli Bahrami
1667e16fca0SAli Bahrami /*
1677e16fca0SAli Bahrami * If there is a good mnemonic machine name for the register,
1687e16fca0SAli Bahrami * format the result as 'r# (mnemonic)'. If there is no good
1697e16fca0SAli Bahrami * name for it, then simply format the dwarf name as 'r#'.
1707e16fca0SAli Bahrami */
1717e16fca0SAli Bahrami if (good_name)
1727e16fca0SAli Bahrami (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_NAME),
1737e16fca0SAli Bahrami regno, name);
1747e16fca0SAli Bahrami else
1757e16fca0SAli Bahrami (void) snprintf(buf, bufsize, MSG_ORIG(MSG_REG_FMT_BASIC),
1767e16fca0SAli Bahrami regno);
1777e16fca0SAli Bahrami
1787e16fca0SAli Bahrami return (buf);
1797e16fca0SAli Bahrami }
1807e16fca0SAli Bahrami
1817e16fca0SAli Bahrami
1827e16fca0SAli Bahrami /*
1837e16fca0SAli Bahrami * Decode eh_frame Call Frame Instructions, printing each one on a
1847e16fca0SAli Bahrami * separate line.
1857e16fca0SAli Bahrami *
1867e16fca0SAli Bahrami * entry:
1877e16fca0SAli Bahrami * data - Address of base of eh_frame section being processed
1887e16fca0SAli Bahrami * off - Offset of current FDE within eh_frame
1897e16fca0SAli Bahrami * ndx - Index of current position within current FDE
190*37915d86SRichard Lowe * len - Length of FDE
1917e16fca0SAli Bahrami * state - Object, CIE, and FDE state for current request
1927e16fca0SAli Bahrami * msg - Header message to issue before producing output.
1937e16fca0SAli Bahrami * indent - # of indentation characters issued for each line of output.
1947e16fca0SAli Bahrami *
1957e16fca0SAli Bahrami * exit:
1967e16fca0SAli Bahrami * The Call Frame Instructions have been decoded and printed.
1977e16fca0SAli Bahrami *
1987e16fca0SAli Bahrami * *ndx has been incremented to contain the index of the next
1997e16fca0SAli Bahrami * byte of data to be processed in eh_frame.
2007e16fca0SAli Bahrami *
2017e16fca0SAli Bahrami * note:
2027e16fca0SAli Bahrami * The format of Call Frame Instructions in .eh_frame sections is based
2037e16fca0SAli Bahrami * on the DWARF specification.
2047e16fca0SAli Bahrami */
2057e16fca0SAli Bahrami static void
dump_cfi(uchar_t * data,uint64_t off,uint64_t * ndx,uint_t len,dump_cfi_state_t * state,const char * msg,int indent)2067e16fca0SAli Bahrami dump_cfi(uchar_t *data, uint64_t off, uint64_t *ndx, uint_t len,
2077e16fca0SAli Bahrami dump_cfi_state_t *state, const char *msg, int indent)
2087e16fca0SAli Bahrami {
2097e16fca0SAli Bahrami /*
2107e16fca0SAli Bahrami * We use %*s%s to insert leading whitespace and the op name.
2117e16fca0SAli Bahrami * PREFIX supplies these arguments.
2127e16fca0SAli Bahrami */
2137e16fca0SAli Bahrami #define PREFIX indent, MSG_ORIG(MSG_STR_EMPTY), opname
2147e16fca0SAli Bahrami
2157e16fca0SAli Bahrami /* Hide boilerplate clutter in calls to dwarf_regname() */
2167e16fca0SAli Bahrami #define REGNAME(_rnum, _buf) \
2177e16fca0SAli Bahrami dwarf_regname(state->e_machine, _rnum, _buf, sizeof (_buf))
2187e16fca0SAli Bahrami
2197e16fca0SAli Bahrami /* Extract the lower 6 bits from an op code */
2207e16fca0SAli Bahrami #define LOW_OP(_op) (_op & 0x3f)
2217e16fca0SAli Bahrami
2227e16fca0SAli Bahrami char rbuf1[32], rbuf2[32];
2237e16fca0SAli Bahrami Conv_inv_buf_t inv_buf;
2247e16fca0SAli Bahrami uchar_t op;
2257e16fca0SAli Bahrami const char *opname;
2267e16fca0SAli Bahrami uint64_t oper1, oper2, cur_pc;
2277e16fca0SAli Bahrami int64_t soper;
2287e16fca0SAli Bahrami const char *loc_str;
2297e16fca0SAli Bahrami int i;
2307e16fca0SAli Bahrami
2317e16fca0SAli Bahrami dbg_print(0, msg);
2327e16fca0SAli Bahrami
2337e16fca0SAli Bahrami /*
2347e16fca0SAli Bahrami * In a CIE/FDE, the length field does not include it's own
2357e16fca0SAli Bahrami * size. Hence, the value passed in is 4 less than the index
2367e16fca0SAli Bahrami * of the actual final location.
2377e16fca0SAli Bahrami */
2387e16fca0SAli Bahrami len += 4;
2397e16fca0SAli Bahrami
2407e16fca0SAli Bahrami /*
2417e16fca0SAli Bahrami * There is a concept of the 'current location', which is the PC
2427e16fca0SAli Bahrami * to which the current item applies. It starts out set to the
2437e16fca0SAli Bahrami * FDE initial location, and can be set or incremented by
2447e16fca0SAli Bahrami * various OP codes. cur_pc is used to track this.
2457e16fca0SAli Bahrami *
2467e16fca0SAli Bahrami * We want to use 'initloc' in the output the first time the location
2477e16fca0SAli Bahrami * is referenced, and then switch to 'loc' for subsequent references.
2487e16fca0SAli Bahrami * loc_str is used to manage that.
2497e16fca0SAli Bahrami */
2507e16fca0SAli Bahrami cur_pc = state->fdeinitloc;
2517e16fca0SAli Bahrami loc_str = MSG_ORIG(MSG_STR_INITLOC);
2527e16fca0SAli Bahrami
2537e16fca0SAli Bahrami while (*ndx < len) {
2547e16fca0SAli Bahrami /*
2557e16fca0SAli Bahrami * The first byte contains the primary op code in the top
2567e16fca0SAli Bahrami * 2 bits, so there are 4 of them. Primary OP code
2577e16fca0SAli Bahrami * 0 uses the lower 6 bits to specify a sub-opcode, allowing
2587e16fca0SAli Bahrami * for 64 of them. The other 3 primary op codes use the
2597e16fca0SAli Bahrami * lower 6 bits to hold an operand (a register #, or value).
2607e16fca0SAli Bahrami *
2617e16fca0SAli Bahrami * Check the primary OP code. If it's 1-3, handle it
2627e16fca0SAli Bahrami * and move to the next loop iteration. For OP code 0,
2637e16fca0SAli Bahrami * fall through to decode the sub-code.
2647e16fca0SAli Bahrami */
2657e16fca0SAli Bahrami op = data[off + (*ndx)++];
2667e16fca0SAli Bahrami opname = conv_dwarf_cfa(op, 0, &inv_buf);
2677e16fca0SAli Bahrami switch (op >> 6) {
2687e16fca0SAli Bahrami case 0x1: /* v2: DW_CFA_advance_loc, delta */
2697e16fca0SAli Bahrami oper1 = state->ciecalign * LOW_OP(op);
2707e16fca0SAli Bahrami cur_pc += oper1;
2717e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
2727e16fca0SAli Bahrami loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
2737e16fca0SAli Bahrami loc_str = MSG_ORIG(MSG_STR_LOC);
2747e16fca0SAli Bahrami continue;
2757e16fca0SAli Bahrami
2767e16fca0SAli Bahrami case 0x2: /* v2: DW_CFA_offset, reg, offset */
277*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
278*37915d86SRichard Lowe DW_OVERFLOW) {
279*37915d86SRichard Lowe (void) fprintf(stderr,
280*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
281*37915d86SRichard Lowe state->file, state->sh_name);
282*37915d86SRichard Lowe return;
283*37915d86SRichard Lowe }
284*37915d86SRichard Lowe
285*37915d86SRichard Lowe oper1 *= state->ciedalign;
2867e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
287*37915d86SRichard Lowe REGNAME(LOW_OP(op), rbuf1), EC_XWORD(oper1));
2887e16fca0SAli Bahrami continue;
2897e16fca0SAli Bahrami
2907e16fca0SAli Bahrami case 0x3: /* v2: DW_CFA_restore, reg */
2917e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
2927e16fca0SAli Bahrami REGNAME(LOW_OP(op), rbuf1));
2937e16fca0SAli Bahrami continue;
2947e16fca0SAli Bahrami }
2957e16fca0SAli Bahrami
2967e16fca0SAli Bahrami /*
2977e16fca0SAli Bahrami * If we're here, the high order 2 bits are 0. The low 6 bits
2987e16fca0SAli Bahrami * specify a sub-opcode defining the operation.
2997e16fca0SAli Bahrami */
3007e16fca0SAli Bahrami switch (op) {
3017e16fca0SAli Bahrami case 0x00: /* v2: DW_CFA_nop */
3027e16fca0SAli Bahrami /*
3037e16fca0SAli Bahrami * No-ops are used to fill unused space required
3047e16fca0SAli Bahrami * for alignment. It is common for there to be
3057e16fca0SAli Bahrami * multiple adjacent nops. It saves space to report
3067e16fca0SAli Bahrami * them all with a single line of output.
3077e16fca0SAli Bahrami */
3087e16fca0SAli Bahrami for (i = 1;
3097e16fca0SAli Bahrami (*ndx < len) && (data[off + *ndx] == 0);
3107e16fca0SAli Bahrami i++, (*ndx)++)
3117e16fca0SAli Bahrami ;
3127e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLEREP), PREFIX, i);
3137e16fca0SAli Bahrami break;
3147e16fca0SAli Bahrami
3157e16fca0SAli Bahrami case 0x0a: /* v2: DW_CFA_remember_state */
3167e16fca0SAli Bahrami case 0x0b: /* v2: DW_CFA_restore_state */
3177e16fca0SAli Bahrami case 0x2d: /* GNU: DW_CFA_GNU_window_save */
3187e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLE), PREFIX);
3197e16fca0SAli Bahrami break;
3207e16fca0SAli Bahrami
3217e16fca0SAli Bahrami case 0x01: /* v2: DW_CFA_set_loc, address */
322*37915d86SRichard Lowe switch (dwarf_ehe_extract(&data[off], len, ndx,
323*37915d86SRichard Lowe &cur_pc, state->cieRflag, state->e_ident, B_FALSE,
324*37915d86SRichard Lowe state->sh_addr, off + *ndx, state->gotaddr)) {
325*37915d86SRichard Lowe case DW_OVERFLOW:
326*37915d86SRichard Lowe (void) fprintf(stderr,
327*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
328*37915d86SRichard Lowe state->file, state->sh_name);
329*37915d86SRichard Lowe return;
330*37915d86SRichard Lowe case DW_BAD_ENCODING:
331*37915d86SRichard Lowe (void) fprintf(stderr,
332*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWBADENC),
333*37915d86SRichard Lowe state->file, state->sh_name,
334*37915d86SRichard Lowe state->cieRflag);
335*37915d86SRichard Lowe return;
336*37915d86SRichard Lowe case DW_SUCCESS:
337*37915d86SRichard Lowe break;
338*37915d86SRichard Lowe }
3397e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_CFASET), PREFIX,
3407e16fca0SAli Bahrami EC_XWORD(cur_pc));
3417e16fca0SAli Bahrami break;
3427e16fca0SAli Bahrami
3437e16fca0SAli Bahrami case 0x02: /* v2: DW_CFA_advance_loc_1, 1-byte delta */
3447e16fca0SAli Bahrami case 0x03: /* v2: DW_CFA_advance_loc_2, 2-byte delta */
3457e16fca0SAli Bahrami case 0x04: /* v2: DW_CFA_advance_loc_4, 4-byte delta */
3467e16fca0SAli Bahrami /*
3477e16fca0SAli Bahrami * Since the codes are contiguous, and the sizes are
3487e16fca0SAli Bahrami * powers of 2, we can compute the word width from
3497e16fca0SAli Bahrami * the code.
3507e16fca0SAli Bahrami */
3517e16fca0SAli Bahrami i = 1 << (op - 0x02);
352*37915d86SRichard Lowe switch (dwarf_extract_uint(data + off, len,
353*37915d86SRichard Lowe ndx, i, state->do_swap, &oper1)) {
354*37915d86SRichard Lowe case DW_BAD_ENCODING:
355*37915d86SRichard Lowe (void) fprintf(stderr,
356*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWBADENC),
357*37915d86SRichard Lowe state->file, state->sh_name,
358*37915d86SRichard Lowe i);
359*37915d86SRichard Lowe return;
360*37915d86SRichard Lowe case DW_OVERFLOW:
361*37915d86SRichard Lowe (void) fprintf(stderr,
362*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
363*37915d86SRichard Lowe state->file, state->sh_name);
364*37915d86SRichard Lowe return;
365*37915d86SRichard Lowe case DW_SUCCESS:
366*37915d86SRichard Lowe break;
367*37915d86SRichard Lowe }
368*37915d86SRichard Lowe oper1 *= state->ciecalign;
3697e16fca0SAli Bahrami cur_pc += oper1;
3707e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
3717e16fca0SAli Bahrami loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
3727e16fca0SAli Bahrami loc_str = MSG_ORIG(MSG_STR_LOC);
3737e16fca0SAli Bahrami break;
3747e16fca0SAli Bahrami
3757e16fca0SAli Bahrami case 0x05: /* v2: DW_CFA_offset_extended,reg,off */
376*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
377*37915d86SRichard Lowe DW_OVERFLOW) {
378*37915d86SRichard Lowe (void) fprintf(stderr,
379*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
380*37915d86SRichard Lowe state->file, state->sh_name);
381*37915d86SRichard Lowe return;
382*37915d86SRichard Lowe }
383*37915d86SRichard Lowe
384*37915d86SRichard Lowe if (sleb_extract(&data[off], ndx, len, &soper) ==
385*37915d86SRichard Lowe DW_OVERFLOW) {
386*37915d86SRichard Lowe (void) fprintf(stderr,
387*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
388*37915d86SRichard Lowe state->file, state->sh_name);
389*37915d86SRichard Lowe return;
390*37915d86SRichard Lowe }
391*37915d86SRichard Lowe
392*37915d86SRichard Lowe soper *= state->ciedalign;
3937e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
3947e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_SXWORD(soper));
3957e16fca0SAli Bahrami break;
3967e16fca0SAli Bahrami
3977e16fca0SAli Bahrami case 0x06: /* v2: DW_CFA_restore_extended, reg */
3987e16fca0SAli Bahrami case 0x0d: /* v2: DW_CFA_def_cfa_register, reg */
3997e16fca0SAli Bahrami case 0x08: /* v2: DW_CFA_same_value, reg */
4007e16fca0SAli Bahrami case 0x07: /* v2: DW_CFA_undefined, reg */
401*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
402*37915d86SRichard Lowe DW_OVERFLOW) {
403*37915d86SRichard Lowe (void) fprintf(stderr,
404*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
405*37915d86SRichard Lowe state->file, state->sh_name);
406*37915d86SRichard Lowe return;
407*37915d86SRichard Lowe }
408*37915d86SRichard Lowe
4097e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
4107e16fca0SAli Bahrami REGNAME(oper1, rbuf1));
4117e16fca0SAli Bahrami break;
4127e16fca0SAli Bahrami
4137e16fca0SAli Bahrami
4147e16fca0SAli Bahrami case 0x09: /* v2: DW_CFA_register, reg, reg */
415*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
416*37915d86SRichard Lowe DW_OVERFLOW) {
417*37915d86SRichard Lowe (void) fprintf(stderr,
418*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
419*37915d86SRichard Lowe state->file, state->sh_name);
420*37915d86SRichard Lowe return;
421*37915d86SRichard Lowe }
422*37915d86SRichard Lowe
423*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper2) ==
424*37915d86SRichard Lowe DW_OVERFLOW) {
425*37915d86SRichard Lowe (void) fprintf(stderr,
426*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
427*37915d86SRichard Lowe state->file, state->sh_name);
428*37915d86SRichard Lowe return;
429*37915d86SRichard Lowe }
4307e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG_REG), PREFIX,
4317e16fca0SAli Bahrami REGNAME(oper1, rbuf1), REGNAME(oper2, rbuf2));
4327e16fca0SAli Bahrami break;
4337e16fca0SAli Bahrami
4347e16fca0SAli Bahrami case 0x0c: /* v2: DW_CFA_def_cfa, reg, offset */
435*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
436*37915d86SRichard Lowe DW_OVERFLOW) {
437*37915d86SRichard Lowe (void) fprintf(stderr,
438*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
439*37915d86SRichard Lowe state->file, state->sh_name);
440*37915d86SRichard Lowe return;
441*37915d86SRichard Lowe }
442*37915d86SRichard Lowe
443*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper2) ==
444*37915d86SRichard Lowe DW_OVERFLOW) {
445*37915d86SRichard Lowe (void) fprintf(stderr,
446*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
447*37915d86SRichard Lowe state->file, state->sh_name);
448*37915d86SRichard Lowe return;
449*37915d86SRichard Lowe }
4507e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLU), PREFIX,
4517e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_XWORD(oper2));
4527e16fca0SAli Bahrami break;
4537e16fca0SAli Bahrami
4547e16fca0SAli Bahrami case 0x0e: /* v2: DW_CFA_def_cfa_offset, offset */
455*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
456*37915d86SRichard Lowe DW_OVERFLOW) {
457*37915d86SRichard Lowe (void) fprintf(stderr,
458*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
459*37915d86SRichard Lowe state->file, state->sh_name);
460*37915d86SRichard Lowe return;
461*37915d86SRichard Lowe }
4627e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
4637e16fca0SAli Bahrami EC_XWORD(oper1));
4647e16fca0SAli Bahrami break;
4657e16fca0SAli Bahrami
4667e16fca0SAli Bahrami case 0x0f: /* v3: DW_CFA_def_cfa_expression, blk */
467*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
468*37915d86SRichard Lowe DW_OVERFLOW) {
469*37915d86SRichard Lowe (void) fprintf(stderr,
470*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
471*37915d86SRichard Lowe state->file, state->sh_name);
472*37915d86SRichard Lowe return;
473*37915d86SRichard Lowe }
4747e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_EBLK), PREFIX,
4757e16fca0SAli Bahrami EC_XWORD(oper1));
4767e16fca0SAli Bahrami /* We currently do not decode the expression block */
4777e16fca0SAli Bahrami *ndx += oper1;
4787e16fca0SAli Bahrami break;
4797e16fca0SAli Bahrami
4807e16fca0SAli Bahrami case 0x10: /* v3: DW_CFA_expression, reg, blk */
4817e16fca0SAli Bahrami case 0x16: /* v3: DW_CFA_val_expression,reg,blk */
482*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
483*37915d86SRichard Lowe DW_OVERFLOW) {
484*37915d86SRichard Lowe (void) fprintf(stderr,
485*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
486*37915d86SRichard Lowe state->file, state->sh_name);
487*37915d86SRichard Lowe return;
488*37915d86SRichard Lowe }
489*37915d86SRichard Lowe
490*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper2) ==
491*37915d86SRichard Lowe DW_OVERFLOW) {
492*37915d86SRichard Lowe (void) fprintf(stderr,
493*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
494*37915d86SRichard Lowe state->file, state->sh_name);
495*37915d86SRichard Lowe return;
496*37915d86SRichard Lowe }
4977e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG_EBLK), PREFIX,
4987e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_XWORD(oper2));
4997e16fca0SAli Bahrami /* We currently do not decode the expression block */
5007e16fca0SAli Bahrami *ndx += oper2;
5017e16fca0SAli Bahrami break;
5027e16fca0SAli Bahrami
5037e16fca0SAli Bahrami case 0x11: /* v3: DW_CFA_offset_extended_sf, reg, off */
504*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
505*37915d86SRichard Lowe DW_OVERFLOW) {
506*37915d86SRichard Lowe (void) fprintf(stderr,
507*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
508*37915d86SRichard Lowe state->file, state->sh_name);
509*37915d86SRichard Lowe return;
510*37915d86SRichard Lowe }
511*37915d86SRichard Lowe
512*37915d86SRichard Lowe if (sleb_extract(&data[off], ndx, len, &soper) ==
513*37915d86SRichard Lowe DW_OVERFLOW) {
514*37915d86SRichard Lowe (void) fprintf(stderr,
515*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
516*37915d86SRichard Lowe state->file, state->sh_name);
517*37915d86SRichard Lowe return;
518*37915d86SRichard Lowe }
519*37915d86SRichard Lowe
520*37915d86SRichard Lowe soper *= state->ciedalign;
5217e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
5227e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_SXWORD(soper));
5237e16fca0SAli Bahrami break;
5247e16fca0SAli Bahrami
5257e16fca0SAli Bahrami case 0x12: /* v3: DW_CFA_def_cfa_sf, reg, offset */
526*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
527*37915d86SRichard Lowe DW_OVERFLOW) {
528*37915d86SRichard Lowe (void) fprintf(stderr,
529*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
530*37915d86SRichard Lowe state->file, state->sh_name);
531*37915d86SRichard Lowe return;
532*37915d86SRichard Lowe }
533*37915d86SRichard Lowe
534*37915d86SRichard Lowe if (sleb_extract(&data[off], ndx, len, &soper) ==
535*37915d86SRichard Lowe DW_OVERFLOW) {
536*37915d86SRichard Lowe (void) fprintf(stderr,
537*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
538*37915d86SRichard Lowe state->file, state->sh_name);
539*37915d86SRichard Lowe return;
540*37915d86SRichard Lowe }
541*37915d86SRichard Lowe
542*37915d86SRichard Lowe soper *= state->ciedalign;
5437e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
5447e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_SXWORD(soper));
5457e16fca0SAli Bahrami break;
5467e16fca0SAli Bahrami
5477e16fca0SAli Bahrami case 0x13: /* DW_CFA_def_cfa_offset_sf, offset */
548*37915d86SRichard Lowe if (sleb_extract(&data[off], ndx, len, &soper) ==
549*37915d86SRichard Lowe DW_OVERFLOW) {
550*37915d86SRichard Lowe (void) fprintf(stderr,
551*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
552*37915d86SRichard Lowe state->file, state->sh_name);
553*37915d86SRichard Lowe return;
554*37915d86SRichard Lowe }
555*37915d86SRichard Lowe
556*37915d86SRichard Lowe soper *= state->ciedalign;
5577e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_LLD), PREFIX,
5587e16fca0SAli Bahrami EC_SXWORD(soper));
5597e16fca0SAli Bahrami break;
5607e16fca0SAli Bahrami
5617e16fca0SAli Bahrami case 0x14: /* v3: DW_CFA_val_offset, reg, offset */
562*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
563*37915d86SRichard Lowe DW_OVERFLOW) {
564*37915d86SRichard Lowe (void) fprintf(stderr,
565*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
566*37915d86SRichard Lowe state->file, state->sh_name);
567*37915d86SRichard Lowe return;
568*37915d86SRichard Lowe }
569*37915d86SRichard Lowe
570*37915d86SRichard Lowe if (sleb_extract(&data[off], ndx, len, &soper) ==
571*37915d86SRichard Lowe DW_OVERFLOW) {
572*37915d86SRichard Lowe (void) fprintf(stderr,
573*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
574*37915d86SRichard Lowe state->file, state->sh_name);
575*37915d86SRichard Lowe return;
576*37915d86SRichard Lowe }
577*37915d86SRichard Lowe
578*37915d86SRichard Lowe soper *= state->ciedalign;
5797e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
5807e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_SXWORD(soper));
5817e16fca0SAli Bahrami break;
5827e16fca0SAli Bahrami
5837e16fca0SAli Bahrami case 0x15: /* v3: DW_CFA_val_offset_sf, reg, offset */
584*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
585*37915d86SRichard Lowe DW_OVERFLOW) {
586*37915d86SRichard Lowe (void) fprintf(stderr,
587*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
588*37915d86SRichard Lowe state->file, state->sh_name);
589*37915d86SRichard Lowe return;
590*37915d86SRichard Lowe }
591*37915d86SRichard Lowe
592*37915d86SRichard Lowe if (sleb_extract(&data[off], ndx, len, &soper) ==
593*37915d86SRichard Lowe DW_OVERFLOW) {
594*37915d86SRichard Lowe (void) fprintf(stderr,
595*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
596*37915d86SRichard Lowe state->file, state->sh_name);
597*37915d86SRichard Lowe return;
598*37915d86SRichard Lowe }
599*37915d86SRichard Lowe
600*37915d86SRichard Lowe soper *= state->ciedalign;
6017e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
6027e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_SXWORD(soper));
6037e16fca0SAli Bahrami break;
6047e16fca0SAli Bahrami
6057e16fca0SAli Bahrami case 0x1d: /* GNU: DW_CFA_MIPS_advance_loc8, delta */
606*37915d86SRichard Lowe switch (dwarf_extract_uint(data + off, len,
607*37915d86SRichard Lowe ndx, 8, state->do_swap, &oper1)) {
608*37915d86SRichard Lowe case DW_BAD_ENCODING:
609*37915d86SRichard Lowe (void) fprintf(stderr,
610*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWBADENC),
611*37915d86SRichard Lowe state->file, state->sh_name,
612*37915d86SRichard Lowe 8);
613*37915d86SRichard Lowe return;
614*37915d86SRichard Lowe case DW_OVERFLOW:
615*37915d86SRichard Lowe (void) fprintf(stderr,
616*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
617*37915d86SRichard Lowe state->file, state->sh_name);
618*37915d86SRichard Lowe return;
619*37915d86SRichard Lowe case DW_SUCCESS:
620*37915d86SRichard Lowe break;
621*37915d86SRichard Lowe }
622*37915d86SRichard Lowe oper1 *= state->ciecalign;
6237e16fca0SAli Bahrami cur_pc += oper1;
6247e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
6257e16fca0SAli Bahrami loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
6267e16fca0SAli Bahrami loc_str = MSG_ORIG(MSG_STR_LOC);
6277e16fca0SAli Bahrami break;
6287e16fca0SAli Bahrami
6297e16fca0SAli Bahrami case 0x2e: /* GNU: DW_CFA_GNU_args_size, size */
630*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
631*37915d86SRichard Lowe DW_OVERFLOW) {
632*37915d86SRichard Lowe (void) fprintf(stderr,
633*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
634*37915d86SRichard Lowe state->file, state->sh_name);
635*37915d86SRichard Lowe return;
636*37915d86SRichard Lowe }
637*37915d86SRichard Lowe
6387e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
6397e16fca0SAli Bahrami EC_XWORD(oper1));
6407e16fca0SAli Bahrami
6417e16fca0SAli Bahrami break;
6427e16fca0SAli Bahrami
6437e16fca0SAli Bahrami case 0x2f: /* GNU:DW_CFA_GNU_negative_offset_extended,reg,off */
644*37915d86SRichard Lowe if (uleb_extract(&data[off], ndx, len, &oper1) ==
645*37915d86SRichard Lowe DW_OVERFLOW) {
646*37915d86SRichard Lowe (void) fprintf(stderr,
647*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
648*37915d86SRichard Lowe state->file, state->sh_name);
649*37915d86SRichard Lowe return;
650*37915d86SRichard Lowe }
651*37915d86SRichard Lowe
652*37915d86SRichard Lowe if (sleb_extract(&data[off], ndx, len, &soper) ==
653*37915d86SRichard Lowe DW_OVERFLOW) {
654*37915d86SRichard Lowe (void) fprintf(stderr,
655*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
656*37915d86SRichard Lowe state->file, state->sh_name);
657*37915d86SRichard Lowe return;
658*37915d86SRichard Lowe }
659*37915d86SRichard Lowe soper = -soper * state->ciedalign;
660*37915d86SRichard Lowe soper *= state->ciedalign;
6617e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
6627e16fca0SAli Bahrami REGNAME(oper1, rbuf1), EC_SXWORD(soper));
6637e16fca0SAli Bahrami break;
6647e16fca0SAli Bahrami
6657e16fca0SAli Bahrami default:
6667e16fca0SAli Bahrami /*
6677e16fca0SAli Bahrami * Unrecognized OP code: DWARF data is variable length,
6687e16fca0SAli Bahrami * so we don't know how many bytes to skip in order to
6697e16fca0SAli Bahrami * advance to the next item. We cannot decode beyond
6707e16fca0SAli Bahrami * this point, so dump the remainder in hex.
6717e16fca0SAli Bahrami */
6727e16fca0SAli Bahrami (*ndx)--; /* Back up to unrecognized opcode */
6737e16fca0SAli Bahrami dump_hex_bytes(data + off + *ndx, len - *ndx,
6747e16fca0SAli Bahrami indent, 8, 1);
6757e16fca0SAli Bahrami (*ndx) = len;
6767e16fca0SAli Bahrami break;
6777e16fca0SAli Bahrami }
6787e16fca0SAli Bahrami }
6797e16fca0SAli Bahrami
6807e16fca0SAli Bahrami #undef PREFIX
6817e16fca0SAli Bahrami #undef REGNAME
6827e16fca0SAli Bahrami #undef LOW_OP
6837e16fca0SAli Bahrami }
6847e16fca0SAli Bahrami
6857e16fca0SAli Bahrami void
dump_eh_frame(const char * file,char * sh_name,uchar_t * data,size_t datasize,uint64_t sh_addr,Half e_machine,uchar_t * e_ident,uint64_t gotaddr)686*37915d86SRichard Lowe dump_eh_frame(const char *file, char *sh_name, uchar_t *data, size_t datasize,
687*37915d86SRichard Lowe uint64_t sh_addr, Half e_machine, uchar_t *e_ident, uint64_t gotaddr)
6887e16fca0SAli Bahrami {
6897e16fca0SAli Bahrami Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
6907e16fca0SAli Bahrami dump_cfi_state_t cfi_state;
691*37915d86SRichard Lowe uint64_t off, ndx, length, id;
6927e16fca0SAli Bahrami uint_t cieid, cielength, cieversion, cieretaddr;
693*37915d86SRichard Lowe int ciePflag = 0, cieZflag = 0, cieLflag = 0;
694*37915d86SRichard Lowe int cieLflag_present = 0;
695*37915d86SRichard Lowe uint_t cieaugndx;
696*37915d86SRichard Lowe char *cieaugstr = NULL;
697*37915d86SRichard Lowe boolean_t have_cie = B_FALSE;
698*37915d86SRichard Lowe
699*37915d86SRichard Lowe cfi_state.file = file;
700*37915d86SRichard Lowe cfi_state.sh_name = sh_name;
7017e16fca0SAli Bahrami cfi_state.e_machine = e_machine;
7027e16fca0SAli Bahrami cfi_state.e_ident = e_ident;
7037e16fca0SAli Bahrami cfi_state.sh_addr = sh_addr;
7047e16fca0SAli Bahrami cfi_state.do_swap = _elf_sys_encoding() != e_ident[EI_DATA];
705965630c1SRichard Lowe cfi_state.gotaddr = gotaddr;
7067e16fca0SAli Bahrami
7077e16fca0SAli Bahrami off = 0;
7087e16fca0SAli Bahrami while (off < datasize) {
7097e16fca0SAli Bahrami ndx = 0;
7107e16fca0SAli Bahrami
7117e16fca0SAli Bahrami /*
7127e16fca0SAli Bahrami * Extract length in native format. A zero length indicates
7137e16fca0SAli Bahrami * that this CIE is a terminator and that processing for this
7147e16fca0SAli Bahrami * unwind information should end. However, skip this entry and
7157e16fca0SAli Bahrami * keep processing, just in case there is any other information
7167e16fca0SAli Bahrami * remaining in this section. Note, ld(1) will terminate the
7177e16fca0SAli Bahrami * processing of the .eh_frame contents for this file after a
7187e16fca0SAli Bahrami * zero length CIE, thus any information that does follow is
7197e16fca0SAli Bahrami * ignored by ld(1), and is therefore questionable.
7207e16fca0SAli Bahrami */
721*37915d86SRichard Lowe if (dwarf_extract_uint(data + off, datasize - off,
722*37915d86SRichard Lowe &ndx, 4, cfi_state.do_swap, &length) == DW_OVERFLOW) {
723*37915d86SRichard Lowe (void) fprintf(stderr,
724*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
725*37915d86SRichard Lowe file, sh_name);
726*37915d86SRichard Lowe return;
727*37915d86SRichard Lowe }
728*37915d86SRichard Lowe
7297e16fca0SAli Bahrami if (length == 0) {
7307e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM));
7317e16fca0SAli Bahrami off += 4;
7327e16fca0SAli Bahrami continue;
7337e16fca0SAli Bahrami }
7347e16fca0SAli Bahrami
735*37915d86SRichard Lowe if (length > (datasize - off)) {
736*37915d86SRichard Lowe (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADCIEFDELEN),
737*37915d86SRichard Lowe file, sh_name, EC_XWORD(length),
738*37915d86SRichard Lowe EC_XWORD(sh_addr + off));
739*37915d86SRichard Lowe /*
740*37915d86SRichard Lowe * If length is wrong, we have no means to find the
741*37915d86SRichard Lowe * next entry, just give up
742*37915d86SRichard Lowe */
743*37915d86SRichard Lowe return;
744*37915d86SRichard Lowe }
745*37915d86SRichard Lowe
7467e16fca0SAli Bahrami /*
7477e16fca0SAli Bahrami * extract CIE id in native format
7487e16fca0SAli Bahrami */
749*37915d86SRichard Lowe if (dwarf_extract_uint(data + off, datasize - off, &ndx,
750*37915d86SRichard Lowe 4, cfi_state.do_swap, &id) == DW_OVERFLOW) {
751*37915d86SRichard Lowe (void) fprintf(stderr,
752*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
753*37915d86SRichard Lowe file, sh_name);
754*37915d86SRichard Lowe return;
755*37915d86SRichard Lowe }
7567e16fca0SAli Bahrami
7577e16fca0SAli Bahrami /*
7587e16fca0SAli Bahrami * A CIE record has an id of '0', otherwise this is a
7597e16fca0SAli Bahrami * FDE entry and the 'id' is the CIE pointer.
7607e16fca0SAli Bahrami */
7617e16fca0SAli Bahrami if (id == 0) {
762*37915d86SRichard Lowe uint64_t persVal, ndx_save = 0;
763*37915d86SRichard Lowe uint64_t axsize;
7647e16fca0SAli Bahrami
765*37915d86SRichard Lowe
766*37915d86SRichard Lowe have_cie = B_TRUE;
7677e16fca0SAli Bahrami cielength = length;
7687e16fca0SAli Bahrami cieid = id;
7697e16fca0SAli Bahrami ciePflag = cfi_state.cieRflag = cieZflag = 0;
7707e16fca0SAli Bahrami cieLflag = cieLflag_present = 0;
7717e16fca0SAli Bahrami
7727e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_CIE),
7737e16fca0SAli Bahrami EC_XWORD(sh_addr + off));
7747e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_CIELNGTH),
7757e16fca0SAli Bahrami cielength, cieid);
7767e16fca0SAli Bahrami
7777e16fca0SAli Bahrami cieversion = data[off + ndx];
7787e16fca0SAli Bahrami ndx += 1;
7797e16fca0SAli Bahrami cieaugstr = (char *)(&data[off + ndx]);
7807e16fca0SAli Bahrami ndx += strlen(cieaugstr) + 1;
7817e16fca0SAli Bahrami
7827e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
7837e16fca0SAli Bahrami cieversion, cieaugstr);
7847e16fca0SAli Bahrami
785*37915d86SRichard Lowe if (uleb_extract(&data[off], &ndx, datasize - off,
786*37915d86SRichard Lowe &cfi_state.ciecalign) == DW_OVERFLOW) {
787*37915d86SRichard Lowe (void) fprintf(stderr,
788*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
789*37915d86SRichard Lowe file, sh_name);
790*37915d86SRichard Lowe return;
791*37915d86SRichard Lowe }
792*37915d86SRichard Lowe
793*37915d86SRichard Lowe if (sleb_extract(&data[off], &ndx, datasize - off,
794*37915d86SRichard Lowe &cfi_state.ciedalign) == DW_OVERFLOW) {
795*37915d86SRichard Lowe (void) fprintf(stderr,
796*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
797*37915d86SRichard Lowe file, sh_name);
798*37915d86SRichard Lowe return;
799*37915d86SRichard Lowe }
8007e16fca0SAli Bahrami cieretaddr = data[off + ndx];
8017e16fca0SAli Bahrami ndx += 1;
8027e16fca0SAli Bahrami
8037e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
8047e16fca0SAli Bahrami EC_XWORD(cfi_state.ciecalign),
8057e16fca0SAli Bahrami EC_XWORD(cfi_state.ciedalign), cieretaddr);
8067e16fca0SAli Bahrami
8077e16fca0SAli Bahrami if (cieaugstr[0])
8087e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXVAL));
8097e16fca0SAli Bahrami
8107e16fca0SAli Bahrami for (cieaugndx = 0; cieaugstr[cieaugndx]; cieaugndx++) {
8117e16fca0SAli Bahrami switch (cieaugstr[cieaugndx]) {
8127e16fca0SAli Bahrami case 'z':
813*37915d86SRichard Lowe if (uleb_extract(&data[off], &ndx,
814*37915d86SRichard Lowe datasize - off, &axsize) ==
815*37915d86SRichard Lowe DW_OVERFLOW) {
816*37915d86SRichard Lowe (void) fprintf(stderr,
817*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
818*37915d86SRichard Lowe file, sh_name);
819*37915d86SRichard Lowe return;
820*37915d86SRichard Lowe }
821*37915d86SRichard Lowe
8227e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXSIZ),
823*37915d86SRichard Lowe EC_XWORD(axsize));
8247e16fca0SAli Bahrami cieZflag = 1;
8257e16fca0SAli Bahrami /*
8267e16fca0SAli Bahrami * The auxiliary section can contain
8277e16fca0SAli Bahrami * unused padding bytes at the end, so
8287e16fca0SAli Bahrami * save the current index. Along with
8297e16fca0SAli Bahrami * axsize, we will use it to set ndx to
8307e16fca0SAli Bahrami * the proper continuation index after
8317e16fca0SAli Bahrami * the aux data has been processed.
8327e16fca0SAli Bahrami */
8337e16fca0SAli Bahrami ndx_save = ndx;
8347e16fca0SAli Bahrami break;
8357e16fca0SAli Bahrami case 'P':
8367e16fca0SAli Bahrami ciePflag = data[off + ndx];
8377e16fca0SAli Bahrami ndx += 1;
8387e16fca0SAli Bahrami
839*37915d86SRichard Lowe switch (dwarf_ehe_extract(&data[off],
840*37915d86SRichard Lowe datasize - off, &ndx, &persVal,
841*37915d86SRichard Lowe ciePflag, e_ident, B_FALSE, sh_addr,
842*37915d86SRichard Lowe off + ndx, gotaddr)) {
843*37915d86SRichard Lowe case DW_OVERFLOW:
844*37915d86SRichard Lowe (void) fprintf(stderr,
845*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
846*37915d86SRichard Lowe file, sh_name);
847*37915d86SRichard Lowe return;
848*37915d86SRichard Lowe case DW_BAD_ENCODING:
849*37915d86SRichard Lowe (void) fprintf(stderr,
850*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWBADENC),
851*37915d86SRichard Lowe file, sh_name, ciePflag);
852*37915d86SRichard Lowe return;
853*37915d86SRichard Lowe case DW_SUCCESS:
854*37915d86SRichard Lowe break;
855*37915d86SRichard Lowe }
8567e16fca0SAli Bahrami dbg_print(0,
8577e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_CIEAXPERS));
8587e16fca0SAli Bahrami dbg_print(0,
8597e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_CIEAXPERSENC),
8607e16fca0SAli Bahrami ciePflag, conv_dwarf_ehe(ciePflag,
8617e16fca0SAli Bahrami &dwarf_ehe_buf));
8627e16fca0SAli Bahrami dbg_print(0,
8637e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_CIEAXPERSRTN),
8647e16fca0SAli Bahrami EC_XWORD(persVal));
8657e16fca0SAli Bahrami break;
8667e16fca0SAli Bahrami case 'R':
8677e16fca0SAli Bahrami cfi_state.cieRflag = data[off + ndx];
8687e16fca0SAli Bahrami ndx += 1;
8697e16fca0SAli Bahrami dbg_print(0,
8707e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_CIEAXCENC),
8717e16fca0SAli Bahrami cfi_state.cieRflag,
8727e16fca0SAli Bahrami conv_dwarf_ehe(cfi_state.cieRflag,
8737e16fca0SAli Bahrami &dwarf_ehe_buf));
8747e16fca0SAli Bahrami break;
8757e16fca0SAli Bahrami case 'L':
8767e16fca0SAli Bahrami cieLflag_present = 1;
8777e16fca0SAli Bahrami cieLflag = data[off + ndx];
8787e16fca0SAli Bahrami ndx += 1;
8797e16fca0SAli Bahrami dbg_print(0,
8807e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_CIEAXLSDA),
8817e16fca0SAli Bahrami cieLflag, conv_dwarf_ehe(
8827e16fca0SAli Bahrami cieLflag, &dwarf_ehe_buf));
8837e16fca0SAli Bahrami break;
8847e16fca0SAli Bahrami default:
8857e16fca0SAli Bahrami dbg_print(0,
8867e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_CIEAXUNEC),
8877e16fca0SAli Bahrami cieaugstr[cieaugndx]);
8887e16fca0SAli Bahrami break;
8897e16fca0SAli Bahrami }
8907e16fca0SAli Bahrami }
8917e16fca0SAli Bahrami
8927e16fca0SAli Bahrami /*
8937e16fca0SAli Bahrami * If the z flag was present, reposition ndx using the
8947e16fca0SAli Bahrami * length given. This will safely move us past any
8957e16fca0SAli Bahrami * unaccessed padding bytes in the auxiliary section.
8967e16fca0SAli Bahrami */
8977e16fca0SAli Bahrami if (cieZflag)
8987e16fca0SAli Bahrami ndx = ndx_save + axsize;
8997e16fca0SAli Bahrami
9007e16fca0SAli Bahrami /*
9017e16fca0SAli Bahrami * Any remaining data are Call Frame Instructions
9027e16fca0SAli Bahrami */
9037e16fca0SAli Bahrami if ((cielength + 4) > ndx)
9047e16fca0SAli Bahrami dump_cfi(data, off, &ndx, cielength, &cfi_state,
9057e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_CIECFI), 3);
9067e16fca0SAli Bahrami off += cielength + 4;
9077e16fca0SAli Bahrami
9087e16fca0SAli Bahrami } else {
9097e16fca0SAli Bahrami uint_t fdelength = length;
9107e16fca0SAli Bahrami int fdecieptr = id;
9117e16fca0SAli Bahrami uint64_t fdeaddrrange;
9127e16fca0SAli Bahrami
913*37915d86SRichard Lowe if (!have_cie) {
914*37915d86SRichard Lowe (void) fprintf(stderr,
915*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWNOCIE), file, sh_name);
916*37915d86SRichard Lowe return;
917*37915d86SRichard Lowe }
918*37915d86SRichard Lowe
9197e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
9207e16fca0SAli Bahrami EC_XWORD(sh_addr + off));
9217e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
9227e16fca0SAli Bahrami fdelength, fdecieptr);
9237e16fca0SAli Bahrami
924*37915d86SRichard Lowe switch (dwarf_ehe_extract(&data[off], datasize - off,
925*37915d86SRichard Lowe &ndx, &cfi_state.fdeinitloc, cfi_state.cieRflag,
926*37915d86SRichard Lowe e_ident, B_FALSE, sh_addr, off + ndx, gotaddr)) {
927*37915d86SRichard Lowe case DW_OVERFLOW:
928*37915d86SRichard Lowe (void) fprintf(stderr,
929*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW), file, sh_name);
930*37915d86SRichard Lowe return;
931*37915d86SRichard Lowe case DW_BAD_ENCODING:
932*37915d86SRichard Lowe (void) fprintf(stderr,
933*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWBADENC), file, sh_name,
934*37915d86SRichard Lowe cfi_state.cieRflag);
935*37915d86SRichard Lowe return;
936*37915d86SRichard Lowe case DW_SUCCESS:
937*37915d86SRichard Lowe break;
938*37915d86SRichard Lowe }
939*37915d86SRichard Lowe
940*37915d86SRichard Lowe switch (dwarf_ehe_extract(&data[off], datasize - off,
941*37915d86SRichard Lowe &ndx, &fdeaddrrange,
942*37915d86SRichard Lowe (cfi_state.cieRflag & ~DW_EH_PE_pcrel), e_ident,
943*37915d86SRichard Lowe B_FALSE, sh_addr, off + ndx, gotaddr)) {
944*37915d86SRichard Lowe case DW_OVERFLOW:
945*37915d86SRichard Lowe (void) fprintf(stderr,
946*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW), file, sh_name);
947*37915d86SRichard Lowe return;
948*37915d86SRichard Lowe case DW_BAD_ENCODING:
949*37915d86SRichard Lowe (void) fprintf(stderr,
950*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWBADENC), file, sh_name,
951*37915d86SRichard Lowe (cfi_state.cieRflag & ~DW_EH_PE_pcrel));
952*37915d86SRichard Lowe return;
953*37915d86SRichard Lowe case DW_SUCCESS:
954*37915d86SRichard Lowe break;
955*37915d86SRichard Lowe }
9567e16fca0SAli Bahrami
9577e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
9587e16fca0SAli Bahrami EC_XWORD(cfi_state.fdeinitloc),
9597e16fca0SAli Bahrami EC_XWORD(fdeaddrrange),
9607e16fca0SAli Bahrami EC_XWORD(cfi_state.fdeinitloc + fdeaddrrange - 1));
9617e16fca0SAli Bahrami
962*37915d86SRichard Lowe if ((cieaugstr != NULL) && (cieaugstr[0] != '\0'))
9637e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXVAL));
9647e16fca0SAli Bahrami if (cieZflag) {
9657e16fca0SAli Bahrami uint64_t val;
9667e16fca0SAli Bahrami uint64_t lndx;
9677e16fca0SAli Bahrami
968*37915d86SRichard Lowe if (uleb_extract(&data[off], &ndx,
969*37915d86SRichard Lowe datasize - off, &val) == DW_OVERFLOW) {
970*37915d86SRichard Lowe (void) fprintf(stderr,
971*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
972*37915d86SRichard Lowe file, sh_name);
973*37915d86SRichard Lowe return;
974*37915d86SRichard Lowe }
9757e16fca0SAli Bahrami lndx = ndx;
9767e16fca0SAli Bahrami ndx += val;
9777e16fca0SAli Bahrami dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXSIZE),
9787e16fca0SAli Bahrami EC_XWORD(val));
9797e16fca0SAli Bahrami if (val && cieLflag_present) {
9807e16fca0SAli Bahrami uint64_t lsda;
9817e16fca0SAli Bahrami
982*37915d86SRichard Lowe switch (dwarf_ehe_extract(&data[off],
983*37915d86SRichard Lowe datasize - off, &lndx, &lsda,
984*37915d86SRichard Lowe cieLflag, e_ident, B_FALSE, sh_addr,
985*37915d86SRichard Lowe off + lndx, gotaddr)) {
986*37915d86SRichard Lowe case DW_OVERFLOW:
987*37915d86SRichard Lowe (void) fprintf(stderr,
988*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWOVRFLW),
989*37915d86SRichard Lowe file, sh_name);
990*37915d86SRichard Lowe return;
991*37915d86SRichard Lowe case DW_BAD_ENCODING:
992*37915d86SRichard Lowe (void) fprintf(stderr,
993*37915d86SRichard Lowe MSG_INTL(MSG_ERR_DWBADENC),
994*37915d86SRichard Lowe file, sh_name, cieLflag);
995*37915d86SRichard Lowe return;
996*37915d86SRichard Lowe case DW_SUCCESS:
997*37915d86SRichard Lowe break;
998*37915d86SRichard Lowe }
9997e16fca0SAli Bahrami dbg_print(0,
10007e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_FDEAXLSDA),
10017e16fca0SAli Bahrami EC_XWORD(lsda));
10027e16fca0SAli Bahrami }
10037e16fca0SAli Bahrami }
10047e16fca0SAli Bahrami if ((fdelength + 4) > ndx)
10057e16fca0SAli Bahrami dump_cfi(data, off, &ndx, fdelength, &cfi_state,
10067e16fca0SAli Bahrami MSG_ORIG(MSG_UNW_FDECFI), 6);
10077e16fca0SAli Bahrami off += fdelength + 4;
10087e16fca0SAli Bahrami }
10097e16fca0SAli Bahrami }
10107e16fca0SAli Bahrami }
1011