xref: /onnv-gate/usr/src/cmd/sgs/libconv/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	<strings.h>
28*9085SAli.Bahrami@Sun.COM #include	<dwarf.h>
29*9085SAli.Bahrami@Sun.COM #include	"_conv.h"
30*9085SAli.Bahrami@Sun.COM #include	<dwarf_msg.h>
31*9085SAli.Bahrami@Sun.COM 
32*9085SAli.Bahrami@Sun.COM /*
33*9085SAli.Bahrami@Sun.COM  * This code is primarily of interest to elfdump. Separating it from dwarf_ehe
34*9085SAli.Bahrami@Sun.COM  * allows other tools to use dwarf_ehe without also pulling this in.
35*9085SAli.Bahrami@Sun.COM  */
36*9085SAli.Bahrami@Sun.COM 
37*9085SAli.Bahrami@Sun.COM /* Instantiate a local copy of conv_map2str() from _conv.h */
38*9085SAli.Bahrami@Sun.COM DEFINE_conv_map2str
39*9085SAli.Bahrami@Sun.COM 
40*9085SAli.Bahrami@Sun.COM 
41*9085SAli.Bahrami@Sun.COM /*
42*9085SAli.Bahrami@Sun.COM  * Translate DW_CFA_ codes, used to identify Call Frame Instructions.
43*9085SAli.Bahrami@Sun.COM  */
44*9085SAli.Bahrami@Sun.COM const char *
45*9085SAli.Bahrami@Sun.COM conv_dwarf_cfa(uchar_t op, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf)
46*9085SAli.Bahrami@Sun.COM {
47*9085SAli.Bahrami@Sun.COM 	static const Msg	cfa[] = {
48*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_NOP,			MSG_DW_CFA_SET_LOC,
49*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_ADVANCE_LOC_1,	MSG_DW_CFA_ADVANCE_LOC_2,
50*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_ADVANCE_LOC_4,	MSG_DW_CFA_OFFSET_EXTENDED,
51*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_RESTORE_EXTENDED,	MSG_DW_CFA_UNDEFINED,
52*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_SAME_VALUE,		MSG_DW_CFA_REGISTER,
53*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_REMEMBER_STATE,	MSG_DW_CFA_RESTORE_STATE,
54*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_DEF_CFA,		MSG_DW_CFA_DEF_CFA_REGISTER,
55*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_DEF_CFA_OFFSET,	MSG_DW_CFA_DEF_CFA_EXPRESSION,
56*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_EXPRESSION,		MSG_DW_CFA_OFFSET_EXTENDED_SF,
57*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_DEF_CFA_SF,		MSG_DW_CFA_DEF_CFA_OFFSET_SF,
58*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_VAL_OFFSET,		MSG_DW_CFA_VAL_OFFSET_SF,
59*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_VAL_EXPRESSION
60*9085SAli.Bahrami@Sun.COM 	};
61*9085SAli.Bahrami@Sun.COM 	static const Msg	gnu[] = {
62*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_GNU_WINDOW_SAVE,	MSG_DW_CFA_GNU_ARGS_SIZE,
63*9085SAli.Bahrami@Sun.COM 		MSG_DW_CFA_GNU_NEGATIVE_OFF_X
64*9085SAli.Bahrami@Sun.COM 	};
65*9085SAli.Bahrami@Sun.COM 
66*9085SAli.Bahrami@Sun.COM 	/*
67*9085SAli.Bahrami@Sun.COM 	 * DWARF CFA opcodes are bytes. The top 2 bits are a primary
68*9085SAli.Bahrami@Sun.COM 	 * opcode, and if zero, the lower 6 bits specify a sub-opcode
69*9085SAli.Bahrami@Sun.COM 	 */
70*9085SAli.Bahrami@Sun.COM 	switch (op >> 6) {
71*9085SAli.Bahrami@Sun.COM 	case 0x1:
72*9085SAli.Bahrami@Sun.COM 		return (MSG_ORIG(MSG_DW_CFA_ADVANCE_LOC));
73*9085SAli.Bahrami@Sun.COM 	case 0x2:
74*9085SAli.Bahrami@Sun.COM 		return (MSG_ORIG(MSG_DW_CFA_OFFSET));
75*9085SAli.Bahrami@Sun.COM 	case 0x3:
76*9085SAli.Bahrami@Sun.COM 		return (MSG_ORIG(MSG_DW_CFA_RESTORE));
77*9085SAli.Bahrami@Sun.COM 	}
78*9085SAli.Bahrami@Sun.COM 
79*9085SAli.Bahrami@Sun.COM 	if (op == 0x1d)
80*9085SAli.Bahrami@Sun.COM 		return (MSG_ORIG(MSG_DW_CFA_MIPS_ADV_LOC8));
81*9085SAli.Bahrami@Sun.COM 
82*9085SAli.Bahrami@Sun.COM 	if ((op >= 0x2d) && (op <= 0x2f))
83*9085SAli.Bahrami@Sun.COM 		return (conv_map2str(inv_buf, (op - 0x2d),
84*9085SAli.Bahrami@Sun.COM 		    fmt_flags, ARRAY_NELTS(gnu), gnu));
85*9085SAli.Bahrami@Sun.COM 
86*9085SAli.Bahrami@Sun.COM 	return (conv_map2str(inv_buf, op, fmt_flags, ARRAY_NELTS(cfa), cfa));
87*9085SAli.Bahrami@Sun.COM }
88*9085SAli.Bahrami@Sun.COM 
89*9085SAli.Bahrami@Sun.COM /*
90*9085SAli.Bahrami@Sun.COM  * Translate DWARF register numbers to hardware specific names
91*9085SAli.Bahrami@Sun.COM  *
92*9085SAli.Bahrami@Sun.COM  * If good_name is non-NULL, conv_dwarf_regname() will set the variable to
93*9085SAli.Bahrami@Sun.COM  * True(1) if the returned string is considered to be a good name to
94*9085SAli.Bahrami@Sun.COM  * display, and False(0) otherwise. To be considered "good":
95*9085SAli.Bahrami@Sun.COM  *
96*9085SAli.Bahrami@Sun.COM  *    -	The name must be a well known mnemonic for a register
97*9085SAli.Bahrami@Sun.COM  *	from the machine type in question.
98*9085SAli.Bahrami@Sun.COM  *
99*9085SAli.Bahrami@Sun.COM  *    -	The name must be different than the DWARF name for
100*9085SAli.Bahrami@Sun.COM  *	the same register.
101*9085SAli.Bahrami@Sun.COM  *
102*9085SAli.Bahrami@Sun.COM  * The returned string is usable, regardless of the value returned in
103*9085SAli.Bahrami@Sun.COM  * *good_name.
104*9085SAli.Bahrami@Sun.COM  */
105*9085SAli.Bahrami@Sun.COM const char *
106*9085SAli.Bahrami@Sun.COM conv_dwarf_regname(Half mach, Word regno, Conv_fmt_flags_t fmt_flags,
107*9085SAli.Bahrami@Sun.COM     int *good_name, Conv_inv_buf_t *inv_buf)
108*9085SAli.Bahrami@Sun.COM {
109*9085SAli.Bahrami@Sun.COM 	static const Msg	reg_amd64[67] = {
110*9085SAli.Bahrami@Sun.COM 		MSG_REG_RAX,		MSG_REG_RDX,
111*9085SAli.Bahrami@Sun.COM 		MSG_REG_RCX,		MSG_REG_RBX,
112*9085SAli.Bahrami@Sun.COM 		MSG_REG_RSI,		MSG_REG_RDI,
113*9085SAli.Bahrami@Sun.COM 		MSG_REG_RBP,		MSG_REG_RSP,
114*9085SAli.Bahrami@Sun.COM 		MSG_REG_R8,		MSG_REG_R9,
115*9085SAli.Bahrami@Sun.COM 		MSG_REG_R10,		MSG_REG_R11,
116*9085SAli.Bahrami@Sun.COM 		MSG_REG_R12,		MSG_REG_R13,
117*9085SAli.Bahrami@Sun.COM 		MSG_REG_R14,		MSG_REG_R15,
118*9085SAli.Bahrami@Sun.COM 		MSG_REG_RA,		MSG_REG_PERXMM0,
119*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM1,	MSG_REG_PERXMM2,
120*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM3,	MSG_REG_PERXMM4,
121*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM5,	MSG_REG_PERXMM6,
122*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM7,	MSG_REG_PERXMM8,
123*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM9,	MSG_REG_PERXMM10,
124*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM11,	MSG_REG_PERXMM12,
125*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM13,	MSG_REG_PERXMM14,
126*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERXMM15,	MSG_REG_PERST0,
127*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERST1,		MSG_REG_PERST2,
128*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERST3,		MSG_REG_PERST4,
129*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERST5,		MSG_REG_PERST6,
130*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERST7,		MSG_REG_PERMM0,
131*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERMM1,		MSG_REG_PERMM2,
132*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERMM3,		MSG_REG_PERMM4,
133*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERMM5,		MSG_REG_PERMM6,
134*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERMM7,		MSG_REG_PERRFLAGS,
135*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERES,		MSG_REG_PERCS,
136*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERSS,		MSG_REG_PERDS,
137*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERFS,		MSG_REG_PERGS,
138*9085SAli.Bahrami@Sun.COM 		MSG_REG_RESERVED,	MSG_REG_RESERVED,
139*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERFSDOTBASE,	MSG_REG_PERGSDOTBASE,
140*9085SAli.Bahrami@Sun.COM 		MSG_REG_RESERVED,	MSG_REG_RESERVED,
141*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERTR,		MSG_REG_PERLDTR,
142*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERMXCSR,	MSG_REG_PERFCW,
143*9085SAli.Bahrami@Sun.COM 		MSG_REG_PERFSW
144*9085SAli.Bahrami@Sun.COM 	};
145*9085SAli.Bahrami@Sun.COM 
146*9085SAli.Bahrami@Sun.COM 	static const Msg	reg_i386[8] = {
147*9085SAli.Bahrami@Sun.COM 		MSG_REG_EAX,		MSG_REG_ECX,
148*9085SAli.Bahrami@Sun.COM 		MSG_REG_EDX,		MSG_REG_EBX,
149*9085SAli.Bahrami@Sun.COM 		MSG_REG_UESP,		MSG_REG_EBP,
150*9085SAli.Bahrami@Sun.COM 		MSG_REG_ESI,		MSG_REG_EDI
151*9085SAli.Bahrami@Sun.COM 	};
152*9085SAli.Bahrami@Sun.COM 
153*9085SAli.Bahrami@Sun.COM 	static const Msg	reg_sparc[64] = {
154*9085SAli.Bahrami@Sun.COM 		MSG_REG_G0,		MSG_REG_G1,
155*9085SAli.Bahrami@Sun.COM 		MSG_REG_G2,		MSG_REG_G3,
156*9085SAli.Bahrami@Sun.COM 		MSG_REG_G4,		MSG_REG_G5,
157*9085SAli.Bahrami@Sun.COM 		MSG_REG_G6,		MSG_REG_G7,
158*9085SAli.Bahrami@Sun.COM 		MSG_REG_O0,		MSG_REG_O1,
159*9085SAli.Bahrami@Sun.COM 		MSG_REG_O2,		MSG_REG_O3,
160*9085SAli.Bahrami@Sun.COM 		MSG_REG_O4,		MSG_REG_O5,
161*9085SAli.Bahrami@Sun.COM 		MSG_REG_O6,		MSG_REG_O7,
162*9085SAli.Bahrami@Sun.COM 		MSG_REG_L0,		MSG_REG_L1,
163*9085SAli.Bahrami@Sun.COM 		MSG_REG_L2,		MSG_REG_L3,
164*9085SAli.Bahrami@Sun.COM 		MSG_REG_L4,		MSG_REG_L5,
165*9085SAli.Bahrami@Sun.COM 		MSG_REG_L6,		MSG_REG_L7,
166*9085SAli.Bahrami@Sun.COM 		MSG_REG_I0,		MSG_REG_I1,
167*9085SAli.Bahrami@Sun.COM 		MSG_REG_I2,		MSG_REG_I3,
168*9085SAli.Bahrami@Sun.COM 		MSG_REG_I4,		MSG_REG_I5,
169*9085SAli.Bahrami@Sun.COM 		MSG_REG_I6,		MSG_REG_I7,
170*9085SAli.Bahrami@Sun.COM 		MSG_REG_F0,		MSG_REG_F1,
171*9085SAli.Bahrami@Sun.COM 		MSG_REG_F2,		MSG_REG_F3,
172*9085SAli.Bahrami@Sun.COM 		MSG_REG_F4,		MSG_REG_F5,
173*9085SAli.Bahrami@Sun.COM 		MSG_REG_F6,		MSG_REG_F7,
174*9085SAli.Bahrami@Sun.COM 		MSG_REG_F8,		MSG_REG_F9,
175*9085SAli.Bahrami@Sun.COM 		MSG_REG_F10,		MSG_REG_F11,
176*9085SAli.Bahrami@Sun.COM 		MSG_REG_F12,		MSG_REG_F13,
177*9085SAli.Bahrami@Sun.COM 		MSG_REG_F14,		MSG_REG_F15,
178*9085SAli.Bahrami@Sun.COM 		MSG_REG_F16,		MSG_REG_F17,
179*9085SAli.Bahrami@Sun.COM 		MSG_REG_F18,		MSG_REG_F19,
180*9085SAli.Bahrami@Sun.COM 		MSG_REG_F20,		MSG_REG_F21,
181*9085SAli.Bahrami@Sun.COM 		MSG_REG_F22,		MSG_REG_F23,
182*9085SAli.Bahrami@Sun.COM 		MSG_REG_F24,		MSG_REG_F25,
183*9085SAli.Bahrami@Sun.COM 		MSG_REG_F26,		MSG_REG_F27,
184*9085SAli.Bahrami@Sun.COM 		MSG_REG_F28,		MSG_REG_F29,
185*9085SAli.Bahrami@Sun.COM 		MSG_REG_F30,		MSG_REG_F31
186*9085SAli.Bahrami@Sun.COM 	};
187*9085SAli.Bahrami@Sun.COM 
188*9085SAli.Bahrami@Sun.COM 	switch (mach) {
189*9085SAli.Bahrami@Sun.COM 	case EM_AMD64:
190*9085SAli.Bahrami@Sun.COM 		/*
191*9085SAli.Bahrami@Sun.COM 		 * amd64 has several in-bounds names we'd rather not
192*9085SAli.Bahrami@Sun.COM 		 * use. R8-R15 have the same name as their DWARF counterparts.
193*9085SAli.Bahrami@Sun.COM 		 * 56-57, and 60-61 are reserved, and don't have a good name.
194*9085SAli.Bahrami@Sun.COM 		 */
195*9085SAli.Bahrami@Sun.COM 		if (good_name)
196*9085SAli.Bahrami@Sun.COM 			*good_name = ((regno < 8) || (regno > 15)) &&
197*9085SAli.Bahrami@Sun.COM 			    (regno != 56) && (regno != 57) &&
198*9085SAli.Bahrami@Sun.COM 			    (regno != 60) && (regno != 61) &&
199*9085SAli.Bahrami@Sun.COM 			    (regno < ARRAY_NELTS(reg_amd64));
200*9085SAli.Bahrami@Sun.COM 		return (conv_map2str(inv_buf, regno,
201*9085SAli.Bahrami@Sun.COM 		    fmt_flags, ARRAY_NELTS(reg_amd64), reg_amd64));
202*9085SAli.Bahrami@Sun.COM 
203*9085SAli.Bahrami@Sun.COM 	case EM_386:
204*9085SAli.Bahrami@Sun.COM 	case EM_486:
205*9085SAli.Bahrami@Sun.COM 		if (good_name)
206*9085SAli.Bahrami@Sun.COM 			*good_name = (regno < ARRAY_NELTS(reg_i386));
207*9085SAli.Bahrami@Sun.COM 		return (conv_map2str(inv_buf, regno,
208*9085SAli.Bahrami@Sun.COM 		    fmt_flags, ARRAY_NELTS(reg_i386), reg_i386));
209*9085SAli.Bahrami@Sun.COM 
210*9085SAli.Bahrami@Sun.COM 	case EM_SPARC:
211*9085SAli.Bahrami@Sun.COM 	case EM_SPARC32PLUS:
212*9085SAli.Bahrami@Sun.COM 	case EM_SPARCV9:
213*9085SAli.Bahrami@Sun.COM 		if (good_name)
214*9085SAli.Bahrami@Sun.COM 			*good_name = (regno < ARRAY_NELTS(reg_sparc));
215*9085SAli.Bahrami@Sun.COM 		return (conv_map2str(inv_buf, regno,
216*9085SAli.Bahrami@Sun.COM 		    fmt_flags, ARRAY_NELTS(reg_sparc), reg_sparc));
217*9085SAli.Bahrami@Sun.COM 	}
218*9085SAli.Bahrami@Sun.COM 
219*9085SAli.Bahrami@Sun.COM 	if (good_name)
220*9085SAli.Bahrami@Sun.COM 		*good_name = 0;
221*9085SAli.Bahrami@Sun.COM 	return (conv_invalid_val(inv_buf, regno, 0));
222*9085SAli.Bahrami@Sun.COM }
223