xref: /onnv-gate/usr/src/cmd/sgs/libconv/common/elf.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate /*
29*0Sstevel@tonic-gate  * String conversion routines for ELF header attributes.
30*0Sstevel@tonic-gate  */
31*0Sstevel@tonic-gate #include	<stdio.h>
32*0Sstevel@tonic-gate #include	<string.h>
33*0Sstevel@tonic-gate #include	"_conv.h"
34*0Sstevel@tonic-gate #include	"elf_msg.h"
35*0Sstevel@tonic-gate #include	<sys/elf_SPARC.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate static const Msg classes[] = {
38*0Sstevel@tonic-gate 	MSG_ELFCLASSNONE,	MSG_ELFCLASS32,		MSG_ELFCLASS64
39*0Sstevel@tonic-gate };
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate const char *
42*0Sstevel@tonic-gate conv_eclass_str(uchar_t class)
43*0Sstevel@tonic-gate {
44*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate 	if (class >= ELFCLASSNUM)
47*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, class, 0));
48*0Sstevel@tonic-gate 	else
49*0Sstevel@tonic-gate 		return (MSG_ORIG(classes[class]));
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate }
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate static const Msg datas[] = {
54*0Sstevel@tonic-gate 	MSG_ELFDATANONE,	MSG_ELFDATA2LSB, 	MSG_ELFDATA2MSB
55*0Sstevel@tonic-gate };
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate const char *
58*0Sstevel@tonic-gate conv_edata_str(uchar_t data)
59*0Sstevel@tonic-gate {
60*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	if (data >= ELFDATANUM)
63*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, data, 0));
64*0Sstevel@tonic-gate 	else
65*0Sstevel@tonic-gate 		return (MSG_ORIG(datas[data]));
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate }
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate static const Msg machines[EM_NUM] = {
70*0Sstevel@tonic-gate 	MSG_EM_NONE,
71*0Sstevel@tonic-gate 	MSG_EM_M32,
72*0Sstevel@tonic-gate 	MSG_EM_SPARC,
73*0Sstevel@tonic-gate 	MSG_EM_386,
74*0Sstevel@tonic-gate 	MSG_EM_68K,
75*0Sstevel@tonic-gate 	MSG_EM_88K,
76*0Sstevel@tonic-gate 	MSG_EM_486,
77*0Sstevel@tonic-gate 	MSG_EM_860,
78*0Sstevel@tonic-gate 	MSG_EM_MIPS,
79*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN9,
80*0Sstevel@tonic-gate 	MSG_EM_MIPS_RS3_LE,
81*0Sstevel@tonic-gate 	MSG_EM_RS6000,
82*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN12,
83*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN13,
84*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN14,
85*0Sstevel@tonic-gate 	MSG_EM_PA_RISC,
86*0Sstevel@tonic-gate 	MSG_EM_nCUBE,
87*0Sstevel@tonic-gate 	MSG_EM_VPP500,
88*0Sstevel@tonic-gate 	MSG_EM_SPARC32PLUS,
89*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN19,
90*0Sstevel@tonic-gate 	MSG_EM_PPC,
91*0Sstevel@tonic-gate 	MSG_EM_PPC64,
92*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN22,
93*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN23,
94*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN24,
95*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN25,
96*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN26,
97*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN27,
98*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN28,
99*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN29,
100*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN30,
101*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN31,
102*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN32,
103*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN33,
104*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN34,
105*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN35,
106*0Sstevel@tonic-gate 	MSG_EM_Y800,
107*0Sstevel@tonic-gate 	MSG_EM_FR20,
108*0Sstevel@tonic-gate 	MSG_EM_RH32,
109*0Sstevel@tonic-gate 	MSG_EM_RCE,
110*0Sstevel@tonic-gate 	MSG_EM_ARM,
111*0Sstevel@tonic-gate 	MSG_EM_ALPHA,
112*0Sstevel@tonic-gate 	MSG_EM_SH,
113*0Sstevel@tonic-gate 	MSG_EM_SPARCV9,
114*0Sstevel@tonic-gate 	MSG_EM_TRICORE,
115*0Sstevel@tonic-gate 	MSG_EM_ARC,
116*0Sstevel@tonic-gate 	MSG_EM_H8_300,
117*0Sstevel@tonic-gate 	MSG_EM_H8_300H,
118*0Sstevel@tonic-gate 	MSG_EM_H8S,
119*0Sstevel@tonic-gate 	MSG_EM_H8_500,
120*0Sstevel@tonic-gate 	MSG_EM_IA_64,
121*0Sstevel@tonic-gate 	MSG_EM_MIPS_X,
122*0Sstevel@tonic-gate 	MSG_EM_COLDFIRE,
123*0Sstevel@tonic-gate 	MSG_EM_68HC12,
124*0Sstevel@tonic-gate 	MSG_EM_MMA,
125*0Sstevel@tonic-gate 	MSG_EM_PCP,
126*0Sstevel@tonic-gate 	MSG_EM_NCPU,
127*0Sstevel@tonic-gate 	MSG_EM_NDR1,
128*0Sstevel@tonic-gate 	MSG_EM_STARCORE,
129*0Sstevel@tonic-gate 	MSG_EM_ME16,
130*0Sstevel@tonic-gate 	MSG_EM_ST100,
131*0Sstevel@tonic-gate 	MSG_EM_TINYJ,
132*0Sstevel@tonic-gate 	MSG_EM_AMD64,
133*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN63,
134*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN64,
135*0Sstevel@tonic-gate 	MSG_EM_UNKNOWN65,
136*0Sstevel@tonic-gate 	MSG_EM_FX66,
137*0Sstevel@tonic-gate 	MSG_EM_ST9PLUS,
138*0Sstevel@tonic-gate 	MSG_EM_ST7,
139*0Sstevel@tonic-gate 	MSG_EM_68HC16,
140*0Sstevel@tonic-gate 	MSG_EM_68HC11,
141*0Sstevel@tonic-gate 	MSG_EM_68HC08,
142*0Sstevel@tonic-gate 	MSG_EM_68HC05,
143*0Sstevel@tonic-gate 	MSG_EM_SVX,
144*0Sstevel@tonic-gate 	MSG_EM_ST19,
145*0Sstevel@tonic-gate 	MSG_EM_VAX,
146*0Sstevel@tonic-gate 	MSG_EM_CRIS,
147*0Sstevel@tonic-gate 	MSG_EM_JAVELIN,
148*0Sstevel@tonic-gate 	MSG_EM_FIREPATH,
149*0Sstevel@tonic-gate 	MSG_EM_ZSP,
150*0Sstevel@tonic-gate 	MSG_EM_MMIX,
151*0Sstevel@tonic-gate 	MSG_EM_HUANY,
152*0Sstevel@tonic-gate 	MSG_EM_PRISM,
153*0Sstevel@tonic-gate 	MSG_EM_AVR,
154*0Sstevel@tonic-gate 	MSG_EM_FR30,
155*0Sstevel@tonic-gate 	MSG_EM_D10V,
156*0Sstevel@tonic-gate 	MSG_EM_D30V,
157*0Sstevel@tonic-gate 	MSG_EM_V850,
158*0Sstevel@tonic-gate 	MSG_EM_M32R,
159*0Sstevel@tonic-gate 	MSG_EM_MN10300,
160*0Sstevel@tonic-gate 	MSG_EM_MN10200,
161*0Sstevel@tonic-gate 	MSG_EM_PJ,
162*0Sstevel@tonic-gate 	MSG_EM_OPENRISC,
163*0Sstevel@tonic-gate 	MSG_EM_ARC_A5,
164*0Sstevel@tonic-gate 	MSG_EM_XTENSA
165*0Sstevel@tonic-gate };
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate const char *
168*0Sstevel@tonic-gate conv_emach_str(ushort_t machine)
169*0Sstevel@tonic-gate {
170*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	/*
173*0Sstevel@tonic-gate 	 * In order to assure that all values included in sys/elf.h::EM_* are
174*0Sstevel@tonic-gate 	 * included in libconv/elfdump for decoding - we have the below
175*0Sstevel@tonic-gate 	 * #define trap.  Each time the machines[] table is updated, make
176*0Sstevel@tonic-gate 	 * sure the following entry is updated.
177*0Sstevel@tonic-gate 	 */
178*0Sstevel@tonic-gate #if	(EM_NUM != (EM_XTENSA + 1))
179*0Sstevel@tonic-gate #error	"EM_NUM has grown"
180*0Sstevel@tonic-gate #endif
181*0Sstevel@tonic-gate 	if (machine >= (EM_NUM))
182*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, machine, 0));
183*0Sstevel@tonic-gate 	else
184*0Sstevel@tonic-gate 		return (MSG_ORIG(machines[machine]));
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate }
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate static const Msg etypes[] = {
189*0Sstevel@tonic-gate 	MSG_ET_NONE,		MSG_ET_REL,		MSG_ET_EXEC,
190*0Sstevel@tonic-gate 	MSG_ET_DYN,		MSG_ET_CORE
191*0Sstevel@tonic-gate };
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate const char *
194*0Sstevel@tonic-gate conv_etype_str(ushort_t etype)
195*0Sstevel@tonic-gate {
196*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	if (etype == ET_SUNWPSEUDO)
199*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_ET_SUNWPSEUDO));
200*0Sstevel@tonic-gate 	else if (etype >= ET_NUM)
201*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, etype, 0));
202*0Sstevel@tonic-gate 	else
203*0Sstevel@tonic-gate 		return (MSG_ORIG(etypes[etype]));
204*0Sstevel@tonic-gate }
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate static const Msg versions[] = {
207*0Sstevel@tonic-gate 	MSG_EV_NONE,		MSG_EV_CURRENT
208*0Sstevel@tonic-gate };
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate const char *
211*0Sstevel@tonic-gate conv_ever_str(uint_t version)
212*0Sstevel@tonic-gate {
213*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	if (version >= EV_NUM)
216*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, version, 0));
217*0Sstevel@tonic-gate 	else
218*0Sstevel@tonic-gate 		return (MSG_ORIG(versions[version]));
219*0Sstevel@tonic-gate }
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate static const Msg mm_flags[] = {
223*0Sstevel@tonic-gate 	MSG_EF_SPARCV9_TSO,	MSG_EF_SPARCV9_PSO,	MSG_EF_SPARCV9_RMO
224*0Sstevel@tonic-gate };
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate #define	EFLAGSZ	MSG_GBL_OSQBRKT_SIZE + \
227*0Sstevel@tonic-gate 		MSG_EF_SPARCV9_TSO_SIZE + \
228*0Sstevel@tonic-gate 		MSG_EF_SPARC_SUN_US1_SIZE + \
229*0Sstevel@tonic-gate 		MSG_EF_SPARC_HAL_R1_SIZE + \
230*0Sstevel@tonic-gate 		MSG_EF_SPARC_SUN_US3_SIZE + \
231*0Sstevel@tonic-gate 		MSG_GBL_CSQBRKT_SIZE
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate /*
234*0Sstevel@tonic-gate  * Valid vendor extension bits for SPARCV9. This must be updated along with
235*0Sstevel@tonic-gate  * elf_SPARC.h.
236*0Sstevel@tonic-gate  */
237*0Sstevel@tonic-gate const char *
238*0Sstevel@tonic-gate conv_eflags_str(ushort_t mach, uint_t flags)
239*0Sstevel@tonic-gate {
240*0Sstevel@tonic-gate 	static char	string[EFLAGSZ] = { '\0' };
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	/*
243*0Sstevel@tonic-gate 	 * Make a string representation of the e_flags field.  If any bogus
244*0Sstevel@tonic-gate 	 * bits are set, then just return a string containing the numeric value.
245*0Sstevel@tonic-gate 	 */
246*0Sstevel@tonic-gate 	if ((mach == EM_SPARCV9) || (((mach == EM_SPARC) ||
247*0Sstevel@tonic-gate 	    (mach == EM_SPARC32PLUS)) && flags)) {
248*0Sstevel@tonic-gate 		uint_t _flags = flags;
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 		(void) strcpy(string, MSG_ORIG(MSG_GBL_OSQBRKT));
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 		if (mach == EM_SPARCV9) {
253*0Sstevel@tonic-gate 			(void) strcat(string, MSG_ORIG(mm_flags[flags &
254*0Sstevel@tonic-gate 			    EF_SPARCV9_MM]));
255*0Sstevel@tonic-gate 			_flags &= ~EF_SPARCV9_MM;
256*0Sstevel@tonic-gate 		}
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 		if (flags & EF_SPARC_32PLUS) {
259*0Sstevel@tonic-gate 			(void) strcat(string, MSG_ORIG(MSG_EF_SPARC_32PLUS));
260*0Sstevel@tonic-gate 			_flags &= ~EF_SPARC_32PLUS;
261*0Sstevel@tonic-gate 		}
262*0Sstevel@tonic-gate 		if (flags & EF_SPARC_SUN_US1) {
263*0Sstevel@tonic-gate 			(void) strcat(string, MSG_ORIG(MSG_EF_SPARC_SUN_US1));
264*0Sstevel@tonic-gate 			_flags &= ~EF_SPARC_SUN_US1;
265*0Sstevel@tonic-gate 		}
266*0Sstevel@tonic-gate 		if (flags & EF_SPARC_HAL_R1) {
267*0Sstevel@tonic-gate 			(void) strcat(string, MSG_ORIG(MSG_EF_SPARC_HAL_R1));
268*0Sstevel@tonic-gate 			_flags &= ~EF_SPARC_HAL_R1;
269*0Sstevel@tonic-gate 		}
270*0Sstevel@tonic-gate 		if (flags & EF_SPARC_SUN_US3) {
271*0Sstevel@tonic-gate 			(void) strcat(string, MSG_ORIG(MSG_EF_SPARC_SUN_US3));
272*0Sstevel@tonic-gate 			_flags &= ~EF_SPARC_SUN_US3;
273*0Sstevel@tonic-gate 		}
274*0Sstevel@tonic-gate 		if (_flags)
275*0Sstevel@tonic-gate 			(void) sprintf(&string[strlen(string)],
276*0Sstevel@tonic-gate 			    MSG_ORIG(MSG_EF_GEN_1_FLAGS), _flags);
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 		(void) strcat(string, MSG_ORIG(MSG_GBL_CSQBRKT));
279*0Sstevel@tonic-gate 	} else
280*0Sstevel@tonic-gate 		(void) sprintf(string, MSG_ORIG(MSG_EF_GEN_2_FLAGS), flags);
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	return (string);
283*0Sstevel@tonic-gate }
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate /*
286*0Sstevel@tonic-gate  * A generic means of returning additional information for a rejected file in
287*0Sstevel@tonic-gate  * terms of a string.
288*0Sstevel@tonic-gate  */
289*0Sstevel@tonic-gate const char *
290*0Sstevel@tonic-gate conv_reject_str(Rej_desc * rej)
291*0Sstevel@tonic-gate {
292*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 	ushort_t	type = rej->rej_type;
295*0Sstevel@tonic-gate 	uint_t		info = rej->rej_info;
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate 	if (type == SGS_REJ_MACH)
298*0Sstevel@tonic-gate 		/* LINTED */
299*0Sstevel@tonic-gate 		return (conv_emach_str((ushort_t)info));
300*0Sstevel@tonic-gate 	else if (type == SGS_REJ_CLASS)
301*0Sstevel@tonic-gate 		/* LINTED */
302*0Sstevel@tonic-gate 		return (conv_eclass_str((uchar_t)info));
303*0Sstevel@tonic-gate 	else if (type == SGS_REJ_DATA)
304*0Sstevel@tonic-gate 		/* LINTED */
305*0Sstevel@tonic-gate 		return (conv_edata_str((uchar_t)info));
306*0Sstevel@tonic-gate 	else if (type == SGS_REJ_TYPE)
307*0Sstevel@tonic-gate 		/* LINTED */
308*0Sstevel@tonic-gate 		return (conv_etype_str((ushort_t)info));
309*0Sstevel@tonic-gate 	else if ((type == SGS_REJ_BADFLAG) || (type == SGS_REJ_MISFLAG) ||
310*0Sstevel@tonic-gate 	    (type == SGS_REJ_HAL) || (type == SGS_REJ_US3))
311*0Sstevel@tonic-gate 		/*
312*0Sstevel@tonic-gate 		 * Only called from ld.so.1, thus M_MACH is hardcoded.
313*0Sstevel@tonic-gate 		 */
314*0Sstevel@tonic-gate 		return (conv_eflags_str(M_MACH, info));
315*0Sstevel@tonic-gate 	else if (type == SGS_REJ_UNKFILE)
316*0Sstevel@tonic-gate 		return ((const char *)0);
317*0Sstevel@tonic-gate 	else if ((type == SGS_REJ_STR) || (type == SGS_REJ_HWCAP_1)) {
318*0Sstevel@tonic-gate 		if (rej->rej_str)
319*0Sstevel@tonic-gate 			return ((const char *)rej->rej_str);
320*0Sstevel@tonic-gate 		else
321*0Sstevel@tonic-gate 			return (MSG_ORIG(MSG_STR_EMPTY));
322*0Sstevel@tonic-gate 	} else
323*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, info, 1));
324*0Sstevel@tonic-gate }
325