elf.c revision 1976:f0691a145b7e
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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2006 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
38
39/* Instantiate a local copy of conv_map2str() from _conv.h */
40DEFINE_conv_map2str
41
42
43
44const char *
45conv_ehdr_class(uchar_t class, int fmt_flags)
46{
47	static char		string[CONV_INV_STRSIZE];
48	static const Msg	classes[] = {
49		MSG_ELFCLASSNONE, MSG_ELFCLASS32, MSG_ELFCLASS64
50	};
51	static const Msg	classes_alt[] = {
52		MSG_ELFCLASSNONE_ALT, MSG_ELFCLASS32_ALT, MSG_ELFCLASS64_ALT
53	};
54
55	return (conv_map2str(string, sizeof (string), class, fmt_flags,
56		ARRAY_NELTS(classes), classes, classes_alt, classes_alt));
57}
58
59const char *
60conv_ehdr_data(uchar_t data, int fmt_flags)
61{
62	static char		string[CONV_INV_STRSIZE];
63	static const Msg	datas[] = {
64		MSG_ELFDATANONE, MSG_ELFDATA2LSB, MSG_ELFDATA2MSB
65	};
66	static const Msg	datas_dump[] = {
67		MSG_ELFDATANONE_ALT, MSG_ELFDATA2LSB_ALT1, MSG_ELFDATA2MSB_ALT1
68	};
69	static const Msg	datas_file[] = {
70		MSG_ELFDATANONE_ALT, MSG_ELFDATA2LSB_ALT2, MSG_ELFDATA2MSB_ALT2
71	};
72
73	return (conv_map2str(string, sizeof (string), data, fmt_flags,
74		ARRAY_NELTS(datas), datas, datas_dump, datas_file));
75}
76
77static const Msg machines[EM_NUM] = {
78	MSG_EM_NONE,		MSG_EM_M32,		MSG_EM_SPARC,
79	MSG_EM_386,		MSG_EM_68K,		MSG_EM_88K,
80	MSG_EM_486,		MSG_EM_860,		MSG_EM_MIPS,
81	MSG_EM_UNKNOWN9,	MSG_EM_MIPS_RS3_LE,	MSG_EM_RS6000,
82	MSG_EM_UNKNOWN12,	MSG_EM_UNKNOWN13,	MSG_EM_UNKNOWN14,
83	MSG_EM_PA_RISC,		MSG_EM_nCUBE,		MSG_EM_VPP500,
84	MSG_EM_SPARC32PLUS,	MSG_EM_UNKNOWN19,	MSG_EM_PPC,
85	MSG_EM_PPC64,		MSG_EM_UNKNOWN22,	MSG_EM_UNKNOWN23,
86	MSG_EM_UNKNOWN24,	MSG_EM_UNKNOWN25,	MSG_EM_UNKNOWN26,
87	MSG_EM_UNKNOWN27,	MSG_EM_UNKNOWN28,	MSG_EM_UNKNOWN29,
88	MSG_EM_UNKNOWN30,	MSG_EM_UNKNOWN31,	MSG_EM_UNKNOWN32,
89	MSG_EM_UNKNOWN33,	MSG_EM_UNKNOWN34,	MSG_EM_UNKNOWN35,
90	MSG_EM_Y800,		MSG_EM_FR20,		MSG_EM_RH32,
91	MSG_EM_RCE,		MSG_EM_ARM,		MSG_EM_ALPHA,
92	MSG_EM_SH,		MSG_EM_SPARCV9,		MSG_EM_TRICORE,
93	MSG_EM_ARC,		MSG_EM_H8_300,		MSG_EM_H8_300H,
94	MSG_EM_H8S,		MSG_EM_H8_500,		MSG_EM_IA_64,
95	MSG_EM_MIPS_X,		MSG_EM_COLDFIRE,	MSG_EM_68HC12,
96	MSG_EM_MMA,		MSG_EM_PCP,		MSG_EM_NCPU,
97	MSG_EM_NDR1,		MSG_EM_STARCORE,	MSG_EM_ME16,
98	MSG_EM_ST100,		MSG_EM_TINYJ,		MSG_EM_AMD64,
99	MSG_EM_UNKNOWN63,	MSG_EM_UNKNOWN64,	MSG_EM_UNKNOWN65,
100	MSG_EM_FX66,		MSG_EM_ST9PLUS,		MSG_EM_ST7,
101	MSG_EM_68HC16,		MSG_EM_68HC11,		MSG_EM_68HC08,
102	MSG_EM_68HC05,		MSG_EM_SVX,		MSG_EM_ST19,
103	MSG_EM_VAX,		MSG_EM_CRIS,		MSG_EM_JAVELIN,
104	MSG_EM_FIREPATH,	MSG_EM_ZSP,		MSG_EM_MMIX,
105	MSG_EM_HUANY,		MSG_EM_PRISM,		MSG_EM_AVR,
106	MSG_EM_FR30,		MSG_EM_D10V,		MSG_EM_D30V,
107	MSG_EM_V850,		MSG_EM_M32R,		MSG_EM_MN10300,
108	MSG_EM_MN10200,		MSG_EM_PJ,		MSG_EM_OPENRISC,
109	MSG_EM_ARC_A5,		MSG_EM_XTENSA
110};
111static const Msg machines_alt[EM_NUM] = {
112	MSG_EM_NONE_ALT,	MSG_EM_M32_ALT,		MSG_EM_SPARC_ALT,
113	MSG_EM_386_ALT,		MSG_EM_68K_ALT,		MSG_EM_88K_ALT,
114	MSG_EM_486_ALT,		MSG_EM_860_ALT,		MSG_EM_MIPS_ALT,
115	MSG_EM_UNKNOWN9,	MSG_EM_MIPS_RS3_LE_ALT,	MSG_EM_RS6000_ALT,
116	MSG_EM_UNKNOWN12,	MSG_EM_UNKNOWN13,	MSG_EM_UNKNOWN14,
117	MSG_EM_PA_RISC_ALT,	MSG_EM_nCUBE_ALT,	MSG_EM_VPP500_ALT,
118	MSG_EM_SPARC32PLUS_ALT,	MSG_EM_UNKNOWN19,	MSG_EM_PPC_ALT,
119	MSG_EM_PPC64_ALT,	MSG_EM_UNKNOWN22,	MSG_EM_UNKNOWN23,
120	MSG_EM_UNKNOWN24,	MSG_EM_UNKNOWN25,	MSG_EM_UNKNOWN26,
121	MSG_EM_UNKNOWN27,	MSG_EM_UNKNOWN28,	MSG_EM_UNKNOWN29,
122	MSG_EM_UNKNOWN30,	MSG_EM_UNKNOWN31,	MSG_EM_UNKNOWN32,
123	MSG_EM_UNKNOWN33,	MSG_EM_UNKNOWN34,	MSG_EM_UNKNOWN35,
124	MSG_EM_Y800,		MSG_EM_FR20,		MSG_EM_RH32,
125	MSG_EM_RCE,		MSG_EM_ARM_ALT,		MSG_EM_ALPHA_ALT,
126	MSG_EM_SH,		MSG_EM_SPARCV9_ALT,	MSG_EM_TRICORE,
127	MSG_EM_ARC,		MSG_EM_H8_300,		MSG_EM_H8_300H,
128	MSG_EM_H8S,		MSG_EM_H8_500,		MSG_EM_IA_64_ALT,
129	MSG_EM_MIPS_X,		MSG_EM_COLDFIRE,	MSG_EM_68HC12,
130	MSG_EM_MMA,		MSG_EM_PCP,		MSG_EM_NCPU,
131	MSG_EM_NDR1,		MSG_EM_STARCORE,	MSG_EM_ME16,
132	MSG_EM_ST100,		MSG_EM_TINYJ,		MSG_EM_AMD64_ALT,
133	MSG_EM_UNKNOWN63,	MSG_EM_UNKNOWN64,	MSG_EM_UNKNOWN65,
134	MSG_EM_FX66,		MSG_EM_ST9PLUS,		MSG_EM_ST7,
135	MSG_EM_68HC16,		MSG_EM_68HC11,		MSG_EM_68HC08,
136	MSG_EM_68HC05,		MSG_EM_SVX,		MSG_EM_ST19,
137	MSG_EM_VAX_ALT,		MSG_EM_CRIS,		MSG_EM_JAVELIN,
138	MSG_EM_FIREPATH,	MSG_EM_ZSP,		MSG_EM_MMIX,
139	MSG_EM_HUANY,		MSG_EM_PRISM,		MSG_EM_AVR,
140	MSG_EM_FR30,		MSG_EM_D10V,		MSG_EM_D30V,
141	MSG_EM_V850,		MSG_EM_M32R,		MSG_EM_MN10300,
142	MSG_EM_MN10200,		MSG_EM_PJ,		MSG_EM_OPENRISC,
143	MSG_EM_ARC_A5,		MSG_EM_XTENSA
144};
145#if	(EM_NUM != (EM_XTENSA + 1))
146#error	"EM_NUM has grown"
147#endif
148
149const char *
150conv_ehdr_mach(Half machine, int fmt_flags)
151{
152	static char	string[CONV_INV_STRSIZE];
153
154	return (conv_map2str(string, sizeof (string), machine, fmt_flags,
155		ARRAY_NELTS(machines), machines, machines_alt, machines_alt));
156}
157
158
159const char *
160conv_ehdr_type(Half etype, int fmt_flags)
161{
162	static char		string[CONV_INV_STRSIZE];
163	static const Msg	etypes[] = {
164		MSG_ET_NONE,		MSG_ET_REL,		MSG_ET_EXEC,
165		MSG_ET_DYN,		MSG_ET_CORE
166	};
167	static const Msg	etypes_alt[] = {
168		MSG_ET_NONE_ALT,	MSG_ET_REL_ALT,		MSG_ET_EXEC_ALT,
169		MSG_ET_DYN_ALT,		MSG_ET_CORE_ALT
170	};
171
172	if (etype == ET_SUNWPSEUDO) {
173		return ((fmt_flags & CONV_FMTALTMASK)
174			? MSG_ORIG(MSG_ET_SUNWPSEUDO_ALT)
175			: MSG_ORIG(MSG_ET_SUNWPSEUDO));
176	}
177
178	return (conv_map2str(string, sizeof (string), etype, fmt_flags,
179		ARRAY_NELTS(etypes), etypes, etypes_alt, etypes_alt));
180
181}
182
183const char *
184conv_ehdr_vers(Word version, int fmt_flags)
185{
186	static char		string[CONV_INV_STRSIZE];
187	static const Msg	versions[] = {
188		MSG_EV_NONE,		MSG_EV_CURRENT
189	};
190	static const Msg	versions_alt[] = {
191		MSG_EV_NONE_ALT,	MSG_EV_CURRENT_ALT
192	};
193
194	return (conv_map2str(string, sizeof (string), version, fmt_flags,
195		ARRAY_NELTS(versions), versions, versions_alt, versions_alt));
196}
197
198#define	EFLAGSZ	MSG_GBL_OSQBRKT_SIZE + \
199		MSG_EF_SPARCV9_TSO_SIZE + \
200		MSG_EF_SPARC_SUN_US1_SIZE + \
201		MSG_EF_SPARC_HAL_R1_SIZE + \
202		MSG_EF_SPARC_SUN_US3_SIZE + \
203		CONV_INV_STRSIZE + MSG_GBL_CSQBRKT_SIZE
204
205/*
206 * Make a string representation of the e_flags field.
207 */
208const char *
209conv_ehdr_flags(Half mach, Word flags)
210{
211	static char	string[EFLAGSZ];
212	static Val_desc vda[] = {
213		{ EF_SPARC_32PLUS,	MSG_ORIG(MSG_EF_SPARC_32PLUS) },
214		{ EF_SPARC_SUN_US1,	MSG_ORIG(MSG_EF_SPARC_SUN_US1) },
215		{ EF_SPARC_HAL_R1,	MSG_ORIG(MSG_EF_SPARC_HAL_R1) },
216		{ EF_SPARC_SUN_US3,	MSG_ORIG(MSG_EF_SPARC_SUN_US3) },
217		{ 0,			0 }
218	};
219	static const Msg mm_flags[] = {
220		MSG_EF_SPARCV9_TSO,	MSG_EF_SPARCV9_PSO,
221		MSG_EF_SPARCV9_RMO
222	};
223	Word		_flags = flags;
224
225	/*
226	 * Non-SPARC architectures presently provide no known flags.
227	 */
228	if ((mach == EM_SPARCV9) || (((mach == EM_SPARC) ||
229	    (mach == EM_SPARC32PLUS)) && flags)) {
230		/*
231		 * Valid vendor extension bits for SPARCV9.  These must be
232		 * updated along with elf_SPARC.h.
233		 */
234		(void) strcpy(string, MSG_ORIG(MSG_GBL_OSQBRKT));
235
236		if ((mach == EM_SPARCV9) && (flags <= EF_SPARCV9_RMO)) {
237		    if (strlcat(string,
238			MSG_ORIG(mm_flags[flags & EF_SPARCV9_MM]),
239			EFLAGSZ) >= EFLAGSZ)
240			    return (conv_invalid_val(string, EFLAGSZ,
241				flags, 0));
242		    _flags &= ~EF_SPARCV9_MM;
243		}
244
245		if (conv_expn_field(string, EFLAGSZ, vda, flags, _flags, 0, 0))
246			(void) strlcat(string, MSG_ORIG(MSG_GBL_CSQBRKT),
247			    EFLAGSZ);
248
249		return (string);
250	}
251	return (conv_invalid_val(string, EFLAGSZ, flags, CONV_FMT_DECIMAL));
252}
253
254/*
255 * A generic means of returning additional information for a rejected file in
256 * terms of a string.
257 */
258const char *
259conv_reject_desc(Rej_desc * rej)
260{
261	static char	string[CONV_INV_STRSIZE];
262
263	ushort_t	type = rej->rej_type;
264	uint_t		info = rej->rej_info;
265
266	if (type == SGS_REJ_MACH)
267		/* LINTED */
268		return (conv_ehdr_mach((Half)info, 0));
269	else if (type == SGS_REJ_CLASS)
270		/* LINTED */
271		return (conv_ehdr_class((uchar_t)info, 0));
272	else if (type == SGS_REJ_DATA)
273		/* LINTED */
274		return (conv_ehdr_data((uchar_t)info, 0));
275	else if (type == SGS_REJ_TYPE)
276		/* LINTED */
277		return (conv_ehdr_type((Half)info, 0));
278	else if ((type == SGS_REJ_BADFLAG) || (type == SGS_REJ_MISFLAG) ||
279	    (type == SGS_REJ_HAL) || (type == SGS_REJ_US3))
280		/*
281		 * Only called from ld.so.1, thus M_MACH is hardcoded.
282		 */
283		return (conv_ehdr_flags(M_MACH, (Word)info));
284	else if (type == SGS_REJ_UNKFILE)
285		return ((const char *)0);
286	else if ((type == SGS_REJ_STR) || (type == SGS_REJ_HWCAP_1)) {
287		if (rej->rej_str)
288			return ((const char *)rej->rej_str);
289		else
290			return (MSG_ORIG(MSG_STR_EMPTY));
291	} else
292		return (conv_invalid_val(string, CONV_INV_STRSIZE, info,
293		    CONV_FMT_DECIMAL));
294}
295