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