5aefb6555731130ca4fd295960123d71f2d21fe8rie/*
5aefb6555731130ca4fd295960123d71f2d21fe8rie * CDDL HEADER START
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * The contents of this file are subject to the terms of the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Common Development and Distribution License (the "License").
5aefb6555731130ca4fd295960123d71f2d21fe8rie * You may not use this file except in compliance with the License.
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5aefb6555731130ca4fd295960123d71f2d21fe8rie * or http://www.opensolaris.org/os/licensing.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * See the License for the specific language governing permissions
5aefb6555731130ca4fd295960123d71f2d21fe8rie * and limitations under the License.
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * When distributing Covered Code, include this CDDL HEADER in each
5aefb6555731130ca4fd295960123d71f2d21fe8rie * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * If applicable, add the following below this CDDL HEADER, with the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * fields enclosed by brackets "[]" replaced with your own identifying
5aefb6555731130ca4fd295960123d71f2d21fe8rie * information: Portions Copyright [yyyy] [name of copyright owner]
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * CDDL HEADER END
5aefb6555731130ca4fd295960123d71f2d21fe8rie */
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie/*
23a1ccea6aac035f084a7a4cdc968687d1b02dafRoger A. Faulkner * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
5aefb6555731130ca4fd295960123d71f2d21fe8rie */
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie#include <stdio.h>
5aefb6555731130ca4fd295960123d71f2d21fe8rie#include <demangle.h>
5aefb6555731130ca4fd295960123d71f2d21fe8rie#include "_conv.h"
5aefb6555731130ca4fd295960123d71f2d21fe8rie#include "demangle_msg.h"
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie/*
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Demangle C++ symbols.
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * This routine acts as a generic routine for use by liblddbg (and hence tools
5aefb6555731130ca4fd295960123d71f2d21fe8rie * like elfdump(1) and pvs(1)), ld(1) and ld.so.1(1).
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * The C++ ABI-2 places no limits on symbol names, thus when demangling a name
5aefb6555731130ca4fd295960123d71f2d21fe8rie * it's possible the buffer won't be big enough (DEMANGLE_ESPACE) so here we
5aefb6555731130ca4fd295960123d71f2d21fe8rie * try to allocate bigger buffers. However, we place a limit on this buffer
5aefb6555731130ca4fd295960123d71f2d21fe8rie * size for fear of a C++ error sending us into an infinit loop.
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * NOTE. we create and use a common buffer for use by cplus_demangle(), thus
5aefb6555731130ca4fd295960123d71f2d21fe8rie * each call to this routine will override the contents of any existing call.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Normally this is sufficient for typical error diagnostics referencing one
5aefb6555731130ca4fd295960123d71f2d21fe8rie * symbol. For those diagnostics using more than one symbol name, all but the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * last name must be copied to a temporary buffer (regardless of whether
5aefb6555731130ca4fd295960123d71f2d21fe8rie * demangling occurred, as the process of attempting to demangle may damage the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * buffer). One model is:
5aefb6555731130ca4fd295960123d71f2d21fe8rie *
5aefb6555731130ca4fd295960123d71f2d21fe8rie * if ((_name1 = demangle(name1)) != name1) {
23a1ccea6aac035f084a7a4cdc968687d1b02dafRoger A. Faulkner * char * __name1 = strdupa(_name1);
5aefb6555731130ca4fd295960123d71f2d21fe8rie * name1 = (const char *)__name1;
5aefb6555731130ca4fd295960123d71f2d21fe8rie * }
5aefb6555731130ca4fd295960123d71f2d21fe8rie * name2 = demangle(name2);
5aefb6555731130ca4fd295960123d71f2d21fe8rie * eprintf(format, name1, name2);
5aefb6555731130ca4fd295960123d71f2d21fe8rie */
5aefb6555731130ca4fd295960123d71f2d21fe8rie#define SYM_MAX 1000
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rieconst char *
5aefb6555731130ca4fd295960123d71f2d21fe8rieconv_demangle_name(const char *name)
5aefb6555731130ca4fd295960123d71f2d21fe8rie{
5aefb6555731130ca4fd295960123d71f2d21fe8rie static char _str[SYM_MAX], *str = _str;
5aefb6555731130ca4fd295960123d71f2d21fe8rie static size_t size = SYM_MAX;
5aefb6555731130ca4fd295960123d71f2d21fe8rie static int again = 1;
5aefb6555731130ca4fd295960123d71f2d21fe8rie static int (*fptr)() = 0;
5aefb6555731130ca4fd295960123d71f2d21fe8rie int error;
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie if (str == 0)
5aefb6555731130ca4fd295960123d71f2d21fe8rie return (name);
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie /*
5aefb6555731130ca4fd295960123d71f2d21fe8rie * If we haven't located the demangler yet try now (we do this rather
5aefb6555731130ca4fd295960123d71f2d21fe8rie * than maintain a static dependency on libdemangle as it's part of an
5aefb6555731130ca4fd295960123d71f2d21fe8rie * optional package). Null the str element out to reject any other
5aefb6555731130ca4fd295960123d71f2d21fe8rie * callers until this operation is complete - under ld.so.1 we can get
5aefb6555731130ca4fd295960123d71f2d21fe8rie * into serious recursion without this.
5aefb6555731130ca4fd295960123d71f2d21fe8rie */
5aefb6555731130ca4fd295960123d71f2d21fe8rie if (fptr == 0) {
5aefb6555731130ca4fd295960123d71f2d21fe8rie void *hdl;
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie str = 0;
5aefb6555731130ca4fd295960123d71f2d21fe8rie if (!(hdl = dlopen(MSG_ORIG(MSG_DEM_LIB), RTLD_LAZY)) ||
5aefb6555731130ca4fd295960123d71f2d21fe8rie !(fptr = (int (*)())dlsym(hdl, MSG_ORIG(MSG_DEM_SYM))))
5aefb6555731130ca4fd295960123d71f2d21fe8rie return (name);
5aefb6555731130ca4fd295960123d71f2d21fe8rie str = _str;
5aefb6555731130ca4fd295960123d71f2d21fe8rie }
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie if ((error = (*fptr)(name, str, size)) == 0)
5aefb6555731130ca4fd295960123d71f2d21fe8rie return ((const char *)str);
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie while ((error == DEMANGLE_ESPACE) && again) {
5aefb6555731130ca4fd295960123d71f2d21fe8rie char *_str;
5aefb6555731130ca4fd295960123d71f2d21fe8rie size_t _size = size;
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie /*
5aefb6555731130ca4fd295960123d71f2d21fe8rie * If we haven't allocated our maximum try incrementing the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * present buffer size. Use malloc() rather than realloc() so
5aefb6555731130ca4fd295960123d71f2d21fe8rie * that we at least have the old buffer on failure.
5aefb6555731130ca4fd295960123d71f2d21fe8rie */
5aefb6555731130ca4fd295960123d71f2d21fe8rie if (((_size += SYM_MAX) > (SYM_MAX * 4)) ||
5aefb6555731130ca4fd295960123d71f2d21fe8rie ((_str = malloc(_size)) == 0)) {
5aefb6555731130ca4fd295960123d71f2d21fe8rie again = 0;
5aefb6555731130ca4fd295960123d71f2d21fe8rie break;
5aefb6555731130ca4fd295960123d71f2d21fe8rie }
5aefb6555731130ca4fd295960123d71f2d21fe8rie if (size != SYM_MAX) {
5aefb6555731130ca4fd295960123d71f2d21fe8rie free(str);
5aefb6555731130ca4fd295960123d71f2d21fe8rie }
5aefb6555731130ca4fd295960123d71f2d21fe8rie str = _str;
5aefb6555731130ca4fd295960123d71f2d21fe8rie size = _size;
5aefb6555731130ca4fd295960123d71f2d21fe8rie
5aefb6555731130ca4fd295960123d71f2d21fe8rie if ((error = (*fptr)(name, str, size)) == 0)
5aefb6555731130ca4fd295960123d71f2d21fe8rie return ((const char *)str);
5aefb6555731130ca4fd295960123d71f2d21fe8rie }
5aefb6555731130ca4fd295960123d71f2d21fe8rie return (name);
5aefb6555731130ca4fd295960123d71f2d21fe8rie}