xref: /onnv-gate/usr/src/cmd/sgs/libconv/common/elf.c (revision 1618:8c9a4f31d225)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*1618Srie  * Common Development and Distribution License (the "License").
6*1618Srie  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*1618Srie 
220Sstevel@tonic-gate /*
23*1618Srie  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * String conversion routines for ELF header attributes.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate #include	<stdio.h>
320Sstevel@tonic-gate #include	<string.h>
330Sstevel@tonic-gate #include	"_conv.h"
340Sstevel@tonic-gate #include	"elf_msg.h"
350Sstevel@tonic-gate #include	<sys/elf_SPARC.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate const char *
38*1618Srie conv_ehdr_class(uchar_t class)
390Sstevel@tonic-gate {
40*1618Srie 	static char		string[CONV_INV_STRSIZE];
41*1618Srie 	static const Msg	classes[] = {
42*1618Srie 		MSG_ELFCLASSNONE,	MSG_ELFCLASS32,		MSG_ELFCLASS64
43*1618Srie 	};
440Sstevel@tonic-gate 
450Sstevel@tonic-gate 	if (class >= ELFCLASSNUM)
46*1618Srie 		return (conv_invalid_val(string, CONV_INV_STRSIZE, class, 0));
470Sstevel@tonic-gate 	else
480Sstevel@tonic-gate 		return (MSG_ORIG(classes[class]));
490Sstevel@tonic-gate }
500Sstevel@tonic-gate 
510Sstevel@tonic-gate const char *
52*1618Srie conv_ehdr_data(uchar_t data)
530Sstevel@tonic-gate {
54*1618Srie 	static char		string[CONV_INV_STRSIZE];
55*1618Srie 	static const Msg	datas[] = {
56*1618Srie 		MSG_ELFDATANONE,	MSG_ELFDATA2LSB, 	MSG_ELFDATA2MSB
57*1618Srie 	};
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	if (data >= ELFDATANUM)
60*1618Srie 		return (conv_invalid_val(string, CONV_INV_STRSIZE, data, 0));
610Sstevel@tonic-gate 	else
620Sstevel@tonic-gate 		return (MSG_ORIG(datas[data]));
630Sstevel@tonic-gate }
640Sstevel@tonic-gate 
650Sstevel@tonic-gate static const Msg machines[EM_NUM] = {
66*1618Srie 	MSG_EM_NONE,		MSG_EM_M32,		MSG_EM_SPARC,
67*1618Srie 	MSG_EM_386,		MSG_EM_68K,		MSG_EM_88K,
68*1618Srie 	MSG_EM_486,		MSG_EM_860,		MSG_EM_MIPS,
69*1618Srie 	MSG_EM_UNKNOWN9,	MSG_EM_MIPS_RS3_LE,	MSG_EM_RS6000,
70*1618Srie 	MSG_EM_UNKNOWN12,	MSG_EM_UNKNOWN13,	MSG_EM_UNKNOWN14,
71*1618Srie 	MSG_EM_PA_RISC,		MSG_EM_nCUBE,		MSG_EM_VPP500,
72*1618Srie 	MSG_EM_SPARC32PLUS,	MSG_EM_UNKNOWN19,	MSG_EM_PPC,
73*1618Srie 	MSG_EM_PPC64,		MSG_EM_UNKNOWN22,	MSG_EM_UNKNOWN23,
74*1618Srie 	MSG_EM_UNKNOWN24,	MSG_EM_UNKNOWN25,	MSG_EM_UNKNOWN26,
75*1618Srie 	MSG_EM_UNKNOWN27,	MSG_EM_UNKNOWN28,	MSG_EM_UNKNOWN29,
76*1618Srie 	MSG_EM_UNKNOWN30,	MSG_EM_UNKNOWN31,	MSG_EM_UNKNOWN32,
77*1618Srie 	MSG_EM_UNKNOWN33,	MSG_EM_UNKNOWN34,	MSG_EM_UNKNOWN35,
78*1618Srie 	MSG_EM_Y800,		MSG_EM_FR20,		MSG_EM_RH32,
79*1618Srie 	MSG_EM_RCE,		MSG_EM_ARM,		MSG_EM_ALPHA,
80*1618Srie 	MSG_EM_SH,		MSG_EM_SPARCV9,		MSG_EM_TRICORE,
81*1618Srie 	MSG_EM_ARC,		MSG_EM_H8_300,		MSG_EM_H8_300H,
82*1618Srie 	MSG_EM_H8S,		MSG_EM_H8_500,		MSG_EM_IA_64,
83*1618Srie 	MSG_EM_MIPS_X,		MSG_EM_COLDFIRE,	MSG_EM_68HC12,
84*1618Srie 	MSG_EM_MMA,		MSG_EM_PCP,		MSG_EM_NCPU,
85*1618Srie 	MSG_EM_NDR1,		MSG_EM_STARCORE,	MSG_EM_ME16,
86*1618Srie 	MSG_EM_ST100,		MSG_EM_TINYJ,		MSG_EM_AMD64,
87*1618Srie 	MSG_EM_UNKNOWN63,	MSG_EM_UNKNOWN64,	MSG_EM_UNKNOWN65,
88*1618Srie 	MSG_EM_FX66,		MSG_EM_ST9PLUS,		MSG_EM_ST7,
89*1618Srie 	MSG_EM_68HC16,		MSG_EM_68HC11,		MSG_EM_68HC08,
90*1618Srie 	MSG_EM_68HC05,		MSG_EM_SVX,		MSG_EM_ST19,
91*1618Srie 	MSG_EM_VAX,		MSG_EM_CRIS,		MSG_EM_JAVELIN,
92*1618Srie 	MSG_EM_FIREPATH,	MSG_EM_ZSP,		MSG_EM_MMIX,
93*1618Srie 	MSG_EM_HUANY,		MSG_EM_PRISM,		MSG_EM_AVR,
94*1618Srie 	MSG_EM_FR30,		MSG_EM_D10V,		MSG_EM_D30V,
95*1618Srie 	MSG_EM_V850,		MSG_EM_M32R,		MSG_EM_MN10300,
96*1618Srie 	MSG_EM_MN10200,		MSG_EM_PJ,		MSG_EM_OPENRISC,
97*1618Srie 	MSG_EM_ARC_A5,		MSG_EM_XTENSA
980Sstevel@tonic-gate };
990Sstevel@tonic-gate #if	(EM_NUM != (EM_XTENSA + 1))
1000Sstevel@tonic-gate #error	"EM_NUM has grown"
1010Sstevel@tonic-gate #endif
102*1618Srie 
103*1618Srie const char *
104*1618Srie conv_ehdr_mach(Half machine)
105*1618Srie {
106*1618Srie 	static char	string[CONV_INV_STRSIZE];
107*1618Srie 
1080Sstevel@tonic-gate 	if (machine >= (EM_NUM))
109*1618Srie 		return (conv_invalid_val(string, CONV_INV_STRSIZE, machine, 0));
1100Sstevel@tonic-gate 	else
1110Sstevel@tonic-gate 		return (MSG_ORIG(machines[machine]));
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate const char *
115*1618Srie conv_ehdr_type(Half etype)
1160Sstevel@tonic-gate {
117*1618Srie 	static char		string[CONV_INV_STRSIZE];
118*1618Srie 	static const Msg	etypes[] = {
119*1618Srie 		MSG_ET_NONE,		MSG_ET_REL,		MSG_ET_EXEC,
120*1618Srie 		MSG_ET_DYN,		MSG_ET_CORE
121*1618Srie 	};
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	if (etype == ET_SUNWPSEUDO)
1240Sstevel@tonic-gate 		return (MSG_ORIG(MSG_ET_SUNWPSEUDO));
1250Sstevel@tonic-gate 	else if (etype >= ET_NUM)
126*1618Srie 		return (conv_invalid_val(string, CONV_INV_STRSIZE, etype, 0));
1270Sstevel@tonic-gate 	else
1280Sstevel@tonic-gate 		return (MSG_ORIG(etypes[etype]));
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate const char *
132*1618Srie conv_ehdr_vers(Word version)
1330Sstevel@tonic-gate {
134*1618Srie 	static char		string[CONV_INV_STRSIZE];
135*1618Srie 	static const Msg	versions[] = {
136*1618Srie 		MSG_EV_NONE,		MSG_EV_CURRENT
137*1618Srie 	};
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (version >= EV_NUM)
140*1618Srie 		return (conv_invalid_val(string, CONV_INV_STRSIZE, version, 0));
1410Sstevel@tonic-gate 	else
1420Sstevel@tonic-gate 		return (MSG_ORIG(versions[version]));
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate #define	EFLAGSZ	MSG_GBL_OSQBRKT_SIZE + \
1460Sstevel@tonic-gate 		MSG_EF_SPARCV9_TSO_SIZE + \
1470Sstevel@tonic-gate 		MSG_EF_SPARC_SUN_US1_SIZE + \
1480Sstevel@tonic-gate 		MSG_EF_SPARC_HAL_R1_SIZE + \
1490Sstevel@tonic-gate 		MSG_EF_SPARC_SUN_US3_SIZE + \
150*1618Srie 		CONV_INV_STRSIZE + MSG_GBL_CSQBRKT_SIZE
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate /*
153*1618Srie  * Make a string representation of the e_flags field.
1540Sstevel@tonic-gate  */
1550Sstevel@tonic-gate const char *
156*1618Srie conv_ehdr_flags(Half mach, Word flags)
1570Sstevel@tonic-gate {
158*1618Srie 	static char	string[EFLAGSZ];
159*1618Srie 	static Val_desc vda[] = {
160*1618Srie 		{ EF_SPARC_32PLUS,	MSG_ORIG(MSG_EF_SPARC_32PLUS) },
161*1618Srie 		{ EF_SPARC_SUN_US1,	MSG_ORIG(MSG_EF_SPARC_SUN_US1) },
162*1618Srie 		{ EF_SPARC_HAL_R1,	MSG_ORIG(MSG_EF_SPARC_HAL_R1) },
163*1618Srie 		{ EF_SPARC_SUN_US3,	MSG_ORIG(MSG_EF_SPARC_SUN_US3) },
164*1618Srie 		{ 0,			0 }
165*1618Srie 	};
166*1618Srie 	static const Msg mm_flags[] = {
167*1618Srie 		MSG_EF_SPARCV9_TSO,	MSG_EF_SPARCV9_PSO,
168*1618Srie 		MSG_EF_SPARCV9_RMO
169*1618Srie 	};
170*1618Srie 	Word		_flags = flags;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	/*
173*1618Srie 	 * Non-SPARC architectures presently provide no known flags.
1740Sstevel@tonic-gate 	 */
1750Sstevel@tonic-gate 	if ((mach == EM_SPARCV9) || (((mach == EM_SPARC) ||
1760Sstevel@tonic-gate 	    (mach == EM_SPARC32PLUS)) && flags)) {
177*1618Srie 		/*
178*1618Srie 		 * Valid vendor extension bits for SPARCV9.  These must be
179*1618Srie 		 * updated along with elf_SPARC.h.
180*1618Srie 		 */
1810Sstevel@tonic-gate 		(void) strcpy(string, MSG_ORIG(MSG_GBL_OSQBRKT));
1820Sstevel@tonic-gate 
183*1618Srie 		if ((mach == EM_SPARCV9) && (flags <= EF_SPARCV9_RMO)) {
184*1618Srie 		    if (strlcat(string,
185*1618Srie 			MSG_ORIG(mm_flags[flags & EF_SPARCV9_MM]),
186*1618Srie 			EFLAGSZ) >= EFLAGSZ)
187*1618Srie 			    return (conv_invalid_val(string, EFLAGSZ,
188*1618Srie 				flags, 0));
189*1618Srie 		    _flags &= ~EF_SPARCV9_MM;
1900Sstevel@tonic-gate 		}
1910Sstevel@tonic-gate 
192*1618Srie 		if (conv_expn_field(string, EFLAGSZ, vda, flags, _flags, 0, 0))
193*1618Srie 			(void) strlcat(string, MSG_ORIG(MSG_GBL_CSQBRKT),
194*1618Srie 			    EFLAGSZ);
1950Sstevel@tonic-gate 
196*1618Srie 		return (string);
197*1618Srie 	}
198*1618Srie 	return (conv_invalid_val(string, EFLAGSZ, flags, CONV_INV_DECIMAL));
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate  * A generic means of returning additional information for a rejected file in
2030Sstevel@tonic-gate  * terms of a string.
2040Sstevel@tonic-gate  */
2050Sstevel@tonic-gate const char *
206*1618Srie conv_reject_desc(Rej_desc * rej)
2070Sstevel@tonic-gate {
208*1618Srie 	static char	string[CONV_INV_STRSIZE];
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	ushort_t	type = rej->rej_type;
2110Sstevel@tonic-gate 	uint_t		info = rej->rej_info;
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	if (type == SGS_REJ_MACH)
2140Sstevel@tonic-gate 		/* LINTED */
215*1618Srie 		return (conv_ehdr_mach((Half)info));
2160Sstevel@tonic-gate 	else if (type == SGS_REJ_CLASS)
2170Sstevel@tonic-gate 		/* LINTED */
218*1618Srie 		return (conv_ehdr_class((uchar_t)info));
2190Sstevel@tonic-gate 	else if (type == SGS_REJ_DATA)
2200Sstevel@tonic-gate 		/* LINTED */
221*1618Srie 		return (conv_ehdr_data((uchar_t)info));
2220Sstevel@tonic-gate 	else if (type == SGS_REJ_TYPE)
2230Sstevel@tonic-gate 		/* LINTED */
224*1618Srie 		return (conv_ehdr_type((Half)info));
2250Sstevel@tonic-gate 	else if ((type == SGS_REJ_BADFLAG) || (type == SGS_REJ_MISFLAG) ||
2260Sstevel@tonic-gate 	    (type == SGS_REJ_HAL) || (type == SGS_REJ_US3))
2270Sstevel@tonic-gate 		/*
2280Sstevel@tonic-gate 		 * Only called from ld.so.1, thus M_MACH is hardcoded.
2290Sstevel@tonic-gate 		 */
230*1618Srie 		return (conv_ehdr_flags(M_MACH, (Word)info));
2310Sstevel@tonic-gate 	else if (type == SGS_REJ_UNKFILE)
2320Sstevel@tonic-gate 		return ((const char *)0);
2330Sstevel@tonic-gate 	else if ((type == SGS_REJ_STR) || (type == SGS_REJ_HWCAP_1)) {
2340Sstevel@tonic-gate 		if (rej->rej_str)
2350Sstevel@tonic-gate 			return ((const char *)rej->rej_str);
2360Sstevel@tonic-gate 		else
2370Sstevel@tonic-gate 			return (MSG_ORIG(MSG_STR_EMPTY));
2380Sstevel@tonic-gate 	} else
239*1618Srie 		return (conv_invalid_val(string, CONV_INV_STRSIZE, info,
240*1618Srie 		    CONV_INV_DECIMAL));
2410Sstevel@tonic-gate }
242