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