1*1618Srie /* 2*1618Srie * CDDL HEADER START 3*1618Srie * 4*1618Srie * 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. 7*1618Srie * 8*1618Srie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1618Srie * or http://www.opensolaris.org/os/licensing. 10*1618Srie * See the License for the specific language governing permissions 11*1618Srie * and limitations under the License. 12*1618Srie * 13*1618Srie * When distributing Covered Code, include this CDDL HEADER in each 14*1618Srie * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1618Srie * If applicable, add the following below this CDDL HEADER, with the 16*1618Srie * fields enclosed by brackets "[]" replaced with your own identifying 17*1618Srie * information: Portions Copyright [yyyy] [name of copyright owner] 18*1618Srie * 19*1618Srie * CDDL HEADER END 20*1618Srie */ 21*1618Srie 22*1618Srie /* 23*1618Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1618Srie * Use is subject to license terms. 25*1618Srie */ 26*1618Srie #pragma ident "%Z%%M% %I% %E% SMI" 27*1618Srie 28*1618Srie #include <stdio.h> 29*1618Srie #include <demangle.h> 30*1618Srie #include "_conv.h" 31*1618Srie #include "demangle_msg.h" 32*1618Srie 33*1618Srie /* 34*1618Srie * Demangle C++ symbols. 35*1618Srie * 36*1618Srie * This routine acts as a generic routine for use by liblddbg (and hence tools 37*1618Srie * like elfdump(1) and pvs(1)), ld(1) and ld.so.1(1). 38*1618Srie * 39*1618Srie * The C++ ABI-2 places no limits on symbol names, thus when demangling a name 40*1618Srie * it's possible the buffer won't be big enough (DEMANGLE_ESPACE) so here we 41*1618Srie * try to allocate bigger buffers. However, we place a limit on this buffer 42*1618Srie * size for fear of a C++ error sending us into an infinit loop. 43*1618Srie * 44*1618Srie * NOTE. we create and use a common buffer for use by cplus_demangle(), thus 45*1618Srie * each call to this routine will override the contents of any existing call. 46*1618Srie * Normally this is sufficient for typical error diagnostics referencing one 47*1618Srie * symbol. For those diagnostics using more than one symbol name, all but the 48*1618Srie * last name must be copied to a temporary buffer (regardless of whether 49*1618Srie * demangling occurred, as the process of attempting to demangle may damage the 50*1618Srie * buffer). One model is: 51*1618Srie * 52*1618Srie * if ((_name1 = demangle(name1)) != name1) { 53*1618Srie * char * __name1 = alloca(strlen(_name1) + 1); 54*1618Srie * (void) strcpy(__name1, _name1); 55*1618Srie * name1 = (const char *)__name1; 56*1618Srie * } 57*1618Srie * name2 = demangle(name2); 58*1618Srie * eprintf(format, name1, name2); 59*1618Srie */ 60*1618Srie #define SYM_MAX 1000 61*1618Srie 62*1618Srie const char * 63*1618Srie conv_demangle_name(const char *name) 64*1618Srie { 65*1618Srie static char _str[SYM_MAX], *str = _str; 66*1618Srie static size_t size = SYM_MAX; 67*1618Srie static int again = 1; 68*1618Srie static int (*fptr)() = 0; 69*1618Srie int error; 70*1618Srie 71*1618Srie if (str == 0) 72*1618Srie return (name); 73*1618Srie 74*1618Srie /* 75*1618Srie * If we haven't located the demangler yet try now (we do this rather 76*1618Srie * than maintain a static dependency on libdemangle as it's part of an 77*1618Srie * optional package). Null the str element out to reject any other 78*1618Srie * callers until this operation is complete - under ld.so.1 we can get 79*1618Srie * into serious recursion without this. 80*1618Srie */ 81*1618Srie if (fptr == 0) { 82*1618Srie void *hdl; 83*1618Srie 84*1618Srie str = 0; 85*1618Srie if (!(hdl = dlopen(MSG_ORIG(MSG_DEM_LIB), RTLD_LAZY)) || 86*1618Srie !(fptr = (int (*)())dlsym(hdl, MSG_ORIG(MSG_DEM_SYM)))) 87*1618Srie return (name); 88*1618Srie str = _str; 89*1618Srie } 90*1618Srie 91*1618Srie if ((error = (*fptr)(name, str, size)) == 0) 92*1618Srie return ((const char *)str); 93*1618Srie 94*1618Srie while ((error == DEMANGLE_ESPACE) && again) { 95*1618Srie char *_str; 96*1618Srie size_t _size = size; 97*1618Srie 98*1618Srie /* 99*1618Srie * If we haven't allocated our maximum try incrementing the 100*1618Srie * present buffer size. Use malloc() rather than realloc() so 101*1618Srie * that we at least have the old buffer on failure. 102*1618Srie */ 103*1618Srie if (((_size += SYM_MAX) > (SYM_MAX * 4)) || 104*1618Srie ((_str = malloc(_size)) == 0)) { 105*1618Srie again = 0; 106*1618Srie break; 107*1618Srie } 108*1618Srie if (size != SYM_MAX) { 109*1618Srie free(str); 110*1618Srie } 111*1618Srie str = _str; 112*1618Srie size = _size; 113*1618Srie 114*1618Srie if ((error = (*fptr)(name, str, size)) == 0) 115*1618Srie return ((const char *)str); 116*1618Srie } 117*1618Srie return (name); 118*1618Srie } 119