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