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