xref: /onnv-gate/usr/src/cmd/sgs/libconv/common/symbols.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 2004 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 symbol attributes.
30*0Sstevel@tonic-gate  */
31*0Sstevel@tonic-gate #include	<stdio.h>
32*0Sstevel@tonic-gate #include	<demangle.h>
33*0Sstevel@tonic-gate #include	"_conv.h"
34*0Sstevel@tonic-gate #include	"symbols_msg.h"
35*0Sstevel@tonic-gate #include	<sys/elf_SPARC.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate static const char vis_types[4] = {
38*0Sstevel@tonic-gate 	'D',	/* STV_DEFAULT */
39*0Sstevel@tonic-gate 	'I',	/* STV_INTERNAL */
40*0Sstevel@tonic-gate 	'H',	/* STV_HIDDEN */
41*0Sstevel@tonic-gate 	'P'	/* STV_PROTECTED */
42*0Sstevel@tonic-gate 	};
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate const char *
45*0Sstevel@tonic-gate conv_sym_stother(uchar_t stother)
46*0Sstevel@tonic-gate {
47*0Sstevel@tonic-gate 	uint_t	vis = ELF_ST_VISIBILITY(stother);
48*0Sstevel@tonic-gate 	static char	string[STRSIZE];
49*0Sstevel@tonic-gate 	uint_t	ndx = 0;
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate 	string[ndx++] = vis_types[vis];
52*0Sstevel@tonic-gate 	/*
53*0Sstevel@tonic-gate 	 * If unkown bits are present in stother - throw out a '?'
54*0Sstevel@tonic-gate 	 */
55*0Sstevel@tonic-gate 	if (stother & ~MSK_SYM_VISIBILITY)
56*0Sstevel@tonic-gate 		string[ndx++] = '?';
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate 	string[ndx++] = '\0';
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate 	return (string);
61*0Sstevel@tonic-gate }
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate static const Msg types[] = {
64*0Sstevel@tonic-gate 	MSG_STT_NOTYPE,		MSG_STT_OBJECT,		MSG_STT_FUNC,
65*0Sstevel@tonic-gate 	MSG_STT_SECTION,	MSG_STT_FILE,		MSG_STT_COMMON,
66*0Sstevel@tonic-gate 	MSG_STT_TLS
67*0Sstevel@tonic-gate };
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate const char *
70*0Sstevel@tonic-gate conv_info_type_str(ushort_t mach, uchar_t type)
71*0Sstevel@tonic-gate {
72*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate 	if (type < STT_NUM)
76*0Sstevel@tonic-gate 		return (MSG_ORIG(types[type]));
77*0Sstevel@tonic-gate 	else if (((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
78*0Sstevel@tonic-gate 	    (mach == EM_SPARCV9)) && (type == STT_SPARC_REGISTER))
79*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_STT_REGISTER));
80*0Sstevel@tonic-gate 	else
81*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, type, 0));
82*0Sstevel@tonic-gate }
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate static const Msg binds[] = {
85*0Sstevel@tonic-gate 	MSG_STB_LOCAL,		MSG_STB_GLOBAL,		MSG_STB_WEAK
86*0Sstevel@tonic-gate };
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate const char *
89*0Sstevel@tonic-gate conv_info_bind_str(uchar_t bind)
90*0Sstevel@tonic-gate {
91*0Sstevel@tonic-gate 	static char	string[STRSIZE] = { '\0' };
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	if (bind >= STB_NUM)
94*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, bind, 0));
95*0Sstevel@tonic-gate 	else
96*0Sstevel@tonic-gate 		return (MSG_ORIG(binds[bind]));
97*0Sstevel@tonic-gate }
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate const char *
100*0Sstevel@tonic-gate conv_shndx_str(ushort_t shndx)
101*0Sstevel@tonic-gate {
102*0Sstevel@tonic-gate 	static	char	string[STRSIZE] = { '\0' };
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	if (shndx == SHN_UNDEF)
105*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_SHN_UNDEF));
106*0Sstevel@tonic-gate 	else if (shndx == SHN_SUNW_IGNORE)
107*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_SHN_SUNW_IGNORE));
108*0Sstevel@tonic-gate 	else if (shndx == SHN_ABS)
109*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_SHN_ABS));
110*0Sstevel@tonic-gate 	else if (shndx == SHN_COMMON)
111*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_SHN_COMMON));
112*0Sstevel@tonic-gate 	else if (shndx == SHN_AFTER)
113*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_SHN_AFTER));
114*0Sstevel@tonic-gate 	else if (shndx == SHN_BEFORE)
115*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_SHN_BEFORE));
116*0Sstevel@tonic-gate 	else if (shndx == SHN_XINDEX)
117*0Sstevel@tonic-gate 		return (MSG_ORIG(MSG_SHN_XINDEX));
118*0Sstevel@tonic-gate 	else
119*0Sstevel@tonic-gate 		return (conv_invalid_str(string, STRSIZE, shndx, 1));
120*0Sstevel@tonic-gate }
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate const char *
123*0Sstevel@tonic-gate conv_sym_value_str(ushort_t mach, uint_t type, uint64_t value)
124*0Sstevel@tonic-gate {
125*0Sstevel@tonic-gate 	static char	string[STRSIZE64] = { '\0' };
126*0Sstevel@tonic-gate 	const char	*fmt;
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 	if (((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
129*0Sstevel@tonic-gate 	    (mach == EM_SPARCV9)) && (type == STT_SPARC_REGISTER))
130*0Sstevel@tonic-gate 		return (conv_sym_SPARC_value_str(value));
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	/*
133*0Sstevel@tonic-gate 	 * Should obtain the elf class rather than relying on e_machine here...
134*0Sstevel@tonic-gate 	 */
135*0Sstevel@tonic-gate 	if (mach == EM_SPARCV9)
136*0Sstevel@tonic-gate 		fmt = MSG_ORIG(MSG_FMT_VAL_64);
137*0Sstevel@tonic-gate 	else
138*0Sstevel@tonic-gate 		fmt = MSG_ORIG(MSG_FMT_VAL);
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	(void) sprintf(string, fmt, EC_XWORD(value));
141*0Sstevel@tonic-gate 	return (string);
142*0Sstevel@tonic-gate }
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate /*
145*0Sstevel@tonic-gate  * Demangle C++ symbols.
146*0Sstevel@tonic-gate  *
147*0Sstevel@tonic-gate  * This routine acts as a generic routine for use by liblddbg (and hence tools
148*0Sstevel@tonic-gate  * like elfdump(1) and pvs(1)), ld(1) and ld.so.1(1).
149*0Sstevel@tonic-gate  *
150*0Sstevel@tonic-gate  * The C++ ABI-2 places no limits on symbol names, thus when demangling a name
151*0Sstevel@tonic-gate  * it's possible the buffer won't be big enough (DEMANGLE_ESPACE) so here we
152*0Sstevel@tonic-gate  * try to allocate bigger buffers.  However, we place a limit on this buffer
153*0Sstevel@tonic-gate  * size for fear of a C++ error sending us into an infinit loop.
154*0Sstevel@tonic-gate  *
155*0Sstevel@tonic-gate  * NOTE. we create and use a common buffer for use by cplus_demangle(), thus
156*0Sstevel@tonic-gate  * each call to this routine will override the contents of any existing call.
157*0Sstevel@tonic-gate  * Normally this is sufficient for typical error diagnostics referencing one
158*0Sstevel@tonic-gate  * symbol.  For those diagnostics using more than one symbol name, all but the
159*0Sstevel@tonic-gate  * last name must be copied to a temporary buffer (regardless of whether
160*0Sstevel@tonic-gate  * demangling occurred, as the process of attempting to demangle may damage the
161*0Sstevel@tonic-gate  * buffer).  One model is:
162*0Sstevel@tonic-gate  *
163*0Sstevel@tonic-gate  *	if ((_name1 = demangle(name1)) != name1) {
164*0Sstevel@tonic-gate  *		char *	__name1 = alloca(strlen(_name1) + 1);
165*0Sstevel@tonic-gate  *		(void) strcpy(__name1, _name1);
166*0Sstevel@tonic-gate  *		name1 = (const char *)__name1;
167*0Sstevel@tonic-gate  *	}
168*0Sstevel@tonic-gate  *	name2 = demangle(name2);
169*0Sstevel@tonic-gate  *	eprintf(format, name1, name2);
170*0Sstevel@tonic-gate  */
171*0Sstevel@tonic-gate #define	SYM_MAX	1000
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate const char *
174*0Sstevel@tonic-gate conv_sym_dem(const char *name)
175*0Sstevel@tonic-gate {
176*0Sstevel@tonic-gate 	static char	_str[SYM_MAX], *str = _str;
177*0Sstevel@tonic-gate 	static size_t	size = SYM_MAX;
178*0Sstevel@tonic-gate 	static int	again = 1;
179*0Sstevel@tonic-gate 	static int	(*fptr)() = 0;
180*0Sstevel@tonic-gate 	int		error;
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate 	if (str == 0)
183*0Sstevel@tonic-gate 		return (name);
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	/*
186*0Sstevel@tonic-gate 	 * If we haven't located the demangler yet try now (we do this rather
187*0Sstevel@tonic-gate 	 * than maintain a static dependency on libdemangle as it's part of an
188*0Sstevel@tonic-gate 	 * optional package).  Null the str element out to reject any other
189*0Sstevel@tonic-gate 	 * callers until this operation is complete - under ld.so.1 we can get
190*0Sstevel@tonic-gate 	 * into serious recursion without this.
191*0Sstevel@tonic-gate 	 */
192*0Sstevel@tonic-gate 	if (fptr == 0) {
193*0Sstevel@tonic-gate 		void	*hdl;
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 		str = 0;
196*0Sstevel@tonic-gate 		if (!(hdl = dlopen(MSG_ORIG(MSG_DEM_LIB), RTLD_LAZY)) ||
197*0Sstevel@tonic-gate 		    !(fptr = (int (*)())dlsym(hdl, MSG_ORIG(MSG_DEM_SYM))))
198*0Sstevel@tonic-gate 			return (name);
199*0Sstevel@tonic-gate 		str = _str;
200*0Sstevel@tonic-gate 	}
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 	if ((error = (*fptr)(name, str, size)) == 0)
203*0Sstevel@tonic-gate 		return ((const char *)str);
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	while ((error == DEMANGLE_ESPACE) && again) {
206*0Sstevel@tonic-gate 		char	*_str;
207*0Sstevel@tonic-gate 		size_t	_size = size;
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 		/*
210*0Sstevel@tonic-gate 		 * If we haven't allocated our maximum try incrementing the
211*0Sstevel@tonic-gate 		 * present buffer size. Use malloc() rather than realloc() so
212*0Sstevel@tonic-gate 		 * that we at least have the old buffer on failure.
213*0Sstevel@tonic-gate 		 */
214*0Sstevel@tonic-gate 		if (((_size += SYM_MAX) > (SYM_MAX * 4)) ||
215*0Sstevel@tonic-gate 		    ((_str = malloc(_size)) == 0)) {
216*0Sstevel@tonic-gate 			again = 0;
217*0Sstevel@tonic-gate 			break;
218*0Sstevel@tonic-gate 		}
219*0Sstevel@tonic-gate 		if (size != SYM_MAX) {
220*0Sstevel@tonic-gate 			free(str);
221*0Sstevel@tonic-gate 		}
222*0Sstevel@tonic-gate 		str = _str;
223*0Sstevel@tonic-gate 		size = _size;
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 		if ((error = (*fptr)(name, str, size)) == 0)
226*0Sstevel@tonic-gate 			return ((const char *)str);
227*0Sstevel@tonic-gate 	}
228*0Sstevel@tonic-gate 	return (name);
229*0Sstevel@tonic-gate }
230