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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*574Sseizo * Copyright 2005 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 symbol attributes. 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate #include <stdio.h> 320Sstevel@tonic-gate #include <demangle.h> 330Sstevel@tonic-gate #include "_conv.h" 340Sstevel@tonic-gate #include "symbols_msg.h" 350Sstevel@tonic-gate #include <sys/elf_SPARC.h> 36*574Sseizo #include <sys/elf_amd64.h> 370Sstevel@tonic-gate 380Sstevel@tonic-gate static const char vis_types[4] = { 390Sstevel@tonic-gate 'D', /* STV_DEFAULT */ 400Sstevel@tonic-gate 'I', /* STV_INTERNAL */ 410Sstevel@tonic-gate 'H', /* STV_HIDDEN */ 420Sstevel@tonic-gate 'P' /* STV_PROTECTED */ 430Sstevel@tonic-gate }; 440Sstevel@tonic-gate 450Sstevel@tonic-gate const char * 460Sstevel@tonic-gate conv_sym_stother(uchar_t stother) 470Sstevel@tonic-gate { 480Sstevel@tonic-gate uint_t vis = ELF_ST_VISIBILITY(stother); 490Sstevel@tonic-gate static char string[STRSIZE]; 500Sstevel@tonic-gate uint_t ndx = 0; 510Sstevel@tonic-gate 520Sstevel@tonic-gate string[ndx++] = vis_types[vis]; 530Sstevel@tonic-gate /* 540Sstevel@tonic-gate * If unkown bits are present in stother - throw out a '?' 550Sstevel@tonic-gate */ 560Sstevel@tonic-gate if (stother & ~MSK_SYM_VISIBILITY) 570Sstevel@tonic-gate string[ndx++] = '?'; 580Sstevel@tonic-gate 590Sstevel@tonic-gate string[ndx++] = '\0'; 600Sstevel@tonic-gate 610Sstevel@tonic-gate return (string); 620Sstevel@tonic-gate } 630Sstevel@tonic-gate 640Sstevel@tonic-gate static const Msg types[] = { 650Sstevel@tonic-gate MSG_STT_NOTYPE, MSG_STT_OBJECT, MSG_STT_FUNC, 660Sstevel@tonic-gate MSG_STT_SECTION, MSG_STT_FILE, MSG_STT_COMMON, 670Sstevel@tonic-gate MSG_STT_TLS 680Sstevel@tonic-gate }; 690Sstevel@tonic-gate 700Sstevel@tonic-gate const char * 710Sstevel@tonic-gate conv_info_type_str(ushort_t mach, uchar_t type) 720Sstevel@tonic-gate { 730Sstevel@tonic-gate static char string[STRSIZE] = { '\0' }; 740Sstevel@tonic-gate 750Sstevel@tonic-gate 760Sstevel@tonic-gate if (type < STT_NUM) 770Sstevel@tonic-gate return (MSG_ORIG(types[type])); 780Sstevel@tonic-gate else if (((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) || 790Sstevel@tonic-gate (mach == EM_SPARCV9)) && (type == STT_SPARC_REGISTER)) 800Sstevel@tonic-gate return (MSG_ORIG(MSG_STT_REGISTER)); 810Sstevel@tonic-gate else 820Sstevel@tonic-gate return (conv_invalid_str(string, STRSIZE, type, 0)); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate static const Msg binds[] = { 860Sstevel@tonic-gate MSG_STB_LOCAL, MSG_STB_GLOBAL, MSG_STB_WEAK 870Sstevel@tonic-gate }; 880Sstevel@tonic-gate 890Sstevel@tonic-gate const char * 900Sstevel@tonic-gate conv_info_bind_str(uchar_t bind) 910Sstevel@tonic-gate { 920Sstevel@tonic-gate static char string[STRSIZE] = { '\0' }; 930Sstevel@tonic-gate 940Sstevel@tonic-gate if (bind >= STB_NUM) 950Sstevel@tonic-gate return (conv_invalid_str(string, STRSIZE, bind, 0)); 960Sstevel@tonic-gate else 970Sstevel@tonic-gate return (MSG_ORIG(binds[bind])); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate 1000Sstevel@tonic-gate const char * 1010Sstevel@tonic-gate conv_shndx_str(ushort_t shndx) 1020Sstevel@tonic-gate { 1030Sstevel@tonic-gate static char string[STRSIZE] = { '\0' }; 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate if (shndx == SHN_UNDEF) 1060Sstevel@tonic-gate return (MSG_ORIG(MSG_SHN_UNDEF)); 1070Sstevel@tonic-gate else if (shndx == SHN_SUNW_IGNORE) 1080Sstevel@tonic-gate return (MSG_ORIG(MSG_SHN_SUNW_IGNORE)); 1090Sstevel@tonic-gate else if (shndx == SHN_ABS) 1100Sstevel@tonic-gate return (MSG_ORIG(MSG_SHN_ABS)); 1110Sstevel@tonic-gate else if (shndx == SHN_COMMON) 1120Sstevel@tonic-gate return (MSG_ORIG(MSG_SHN_COMMON)); 113*574Sseizo else if (shndx == SHN_X86_64_LCOMMON) 114*574Sseizo return (MSG_ORIG(MSG_SHN_X86_64_LCOMMON)); 1150Sstevel@tonic-gate else if (shndx == SHN_AFTER) 1160Sstevel@tonic-gate return (MSG_ORIG(MSG_SHN_AFTER)); 1170Sstevel@tonic-gate else if (shndx == SHN_BEFORE) 1180Sstevel@tonic-gate return (MSG_ORIG(MSG_SHN_BEFORE)); 1190Sstevel@tonic-gate else if (shndx == SHN_XINDEX) 1200Sstevel@tonic-gate return (MSG_ORIG(MSG_SHN_XINDEX)); 1210Sstevel@tonic-gate else 1220Sstevel@tonic-gate return (conv_invalid_str(string, STRSIZE, shndx, 1)); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate const char * 1260Sstevel@tonic-gate conv_sym_value_str(ushort_t mach, uint_t type, uint64_t value) 1270Sstevel@tonic-gate { 1280Sstevel@tonic-gate static char string[STRSIZE64] = { '\0' }; 1290Sstevel@tonic-gate const char *fmt; 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate if (((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) || 1320Sstevel@tonic-gate (mach == EM_SPARCV9)) && (type == STT_SPARC_REGISTER)) 1330Sstevel@tonic-gate return (conv_sym_SPARC_value_str(value)); 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate /* 1360Sstevel@tonic-gate * Should obtain the elf class rather than relying on e_machine here... 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate if (mach == EM_SPARCV9) 1390Sstevel@tonic-gate fmt = MSG_ORIG(MSG_FMT_VAL_64); 1400Sstevel@tonic-gate else 1410Sstevel@tonic-gate fmt = MSG_ORIG(MSG_FMT_VAL); 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate (void) sprintf(string, fmt, EC_XWORD(value)); 1440Sstevel@tonic-gate return (string); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* 1480Sstevel@tonic-gate * Demangle C++ symbols. 1490Sstevel@tonic-gate * 1500Sstevel@tonic-gate * This routine acts as a generic routine for use by liblddbg (and hence tools 1510Sstevel@tonic-gate * like elfdump(1) and pvs(1)), ld(1) and ld.so.1(1). 1520Sstevel@tonic-gate * 1530Sstevel@tonic-gate * The C++ ABI-2 places no limits on symbol names, thus when demangling a name 1540Sstevel@tonic-gate * it's possible the buffer won't be big enough (DEMANGLE_ESPACE) so here we 1550Sstevel@tonic-gate * try to allocate bigger buffers. However, we place a limit on this buffer 1560Sstevel@tonic-gate * size for fear of a C++ error sending us into an infinit loop. 1570Sstevel@tonic-gate * 1580Sstevel@tonic-gate * NOTE. we create and use a common buffer for use by cplus_demangle(), thus 1590Sstevel@tonic-gate * each call to this routine will override the contents of any existing call. 1600Sstevel@tonic-gate * Normally this is sufficient for typical error diagnostics referencing one 1610Sstevel@tonic-gate * symbol. For those diagnostics using more than one symbol name, all but the 1620Sstevel@tonic-gate * last name must be copied to a temporary buffer (regardless of whether 1630Sstevel@tonic-gate * demangling occurred, as the process of attempting to demangle may damage the 1640Sstevel@tonic-gate * buffer). One model is: 1650Sstevel@tonic-gate * 1660Sstevel@tonic-gate * if ((_name1 = demangle(name1)) != name1) { 1670Sstevel@tonic-gate * char * __name1 = alloca(strlen(_name1) + 1); 1680Sstevel@tonic-gate * (void) strcpy(__name1, _name1); 1690Sstevel@tonic-gate * name1 = (const char *)__name1; 1700Sstevel@tonic-gate * } 1710Sstevel@tonic-gate * name2 = demangle(name2); 1720Sstevel@tonic-gate * eprintf(format, name1, name2); 1730Sstevel@tonic-gate */ 1740Sstevel@tonic-gate #define SYM_MAX 1000 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate const char * 1770Sstevel@tonic-gate conv_sym_dem(const char *name) 1780Sstevel@tonic-gate { 1790Sstevel@tonic-gate static char _str[SYM_MAX], *str = _str; 1800Sstevel@tonic-gate static size_t size = SYM_MAX; 1810Sstevel@tonic-gate static int again = 1; 1820Sstevel@tonic-gate static int (*fptr)() = 0; 1830Sstevel@tonic-gate int error; 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate if (str == 0) 1860Sstevel@tonic-gate return (name); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * If we haven't located the demangler yet try now (we do this rather 1900Sstevel@tonic-gate * than maintain a static dependency on libdemangle as it's part of an 1910Sstevel@tonic-gate * optional package). Null the str element out to reject any other 1920Sstevel@tonic-gate * callers until this operation is complete - under ld.so.1 we can get 1930Sstevel@tonic-gate * into serious recursion without this. 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate if (fptr == 0) { 1960Sstevel@tonic-gate void *hdl; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate str = 0; 1990Sstevel@tonic-gate if (!(hdl = dlopen(MSG_ORIG(MSG_DEM_LIB), RTLD_LAZY)) || 2000Sstevel@tonic-gate !(fptr = (int (*)())dlsym(hdl, MSG_ORIG(MSG_DEM_SYM)))) 2010Sstevel@tonic-gate return (name); 2020Sstevel@tonic-gate str = _str; 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate if ((error = (*fptr)(name, str, size)) == 0) 2060Sstevel@tonic-gate return ((const char *)str); 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate while ((error == DEMANGLE_ESPACE) && again) { 2090Sstevel@tonic-gate char *_str; 2100Sstevel@tonic-gate size_t _size = size; 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* 2130Sstevel@tonic-gate * If we haven't allocated our maximum try incrementing the 2140Sstevel@tonic-gate * present buffer size. Use malloc() rather than realloc() so 2150Sstevel@tonic-gate * that we at least have the old buffer on failure. 2160Sstevel@tonic-gate */ 2170Sstevel@tonic-gate if (((_size += SYM_MAX) > (SYM_MAX * 4)) || 2180Sstevel@tonic-gate ((_str = malloc(_size)) == 0)) { 2190Sstevel@tonic-gate again = 0; 2200Sstevel@tonic-gate break; 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate if (size != SYM_MAX) { 2230Sstevel@tonic-gate free(str); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate str = _str; 2260Sstevel@tonic-gate size = _size; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate if ((error = (*fptr)(name, str, size)) == 0) 2290Sstevel@tonic-gate return ((const char *)str); 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate return (name); 2320Sstevel@tonic-gate } 233