17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate * All Rights Reserved
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate *
277c478bd9Sstevel@tonic-gate * Copyright (c) 1998 by Sun Microsystems, Inc.
287c478bd9Sstevel@tonic-gate * All rights reserved.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <ctype.h>
327c478bd9Sstevel@tonic-gate #include <setjmp.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <thread.h>
367c478bd9Sstevel@tonic-gate #include "elf_dem.h"
377c478bd9Sstevel@tonic-gate #include "String.h"
387c478bd9Sstevel@tonic-gate #include "msg.h"
397c478bd9Sstevel@tonic-gate
4037f60115SToomas Soome /*
4137f60115SToomas Soome * The variable "hold" contains the pointer to the array initially
427c478bd9Sstevel@tonic-gate * handed to demangle. It is returned if it is not possible to
437c478bd9Sstevel@tonic-gate * demangle the string. NULL is returned if a memory allocation
447c478bd9Sstevel@tonic-gate * problem is encountered. Thus one can do the following:
457c478bd9Sstevel@tonic-gate *
467c478bd9Sstevel@tonic-gate * char *mn = "Some mangled name";
477c478bd9Sstevel@tonic-gate * char *dm = mangle(mn);
487c478bd9Sstevel@tonic-gate * if (dm == NULL)
497c478bd9Sstevel@tonic-gate * printf("allocation error\n");
507c478bd9Sstevel@tonic-gate * else if (dm == mn)
517c478bd9Sstevel@tonic-gate * printf("name could not be demangled\n");
527c478bd9Sstevel@tonic-gate * else
537c478bd9Sstevel@tonic-gate * printf("demangled name is: %s\n",dm);
547c478bd9Sstevel@tonic-gate */
557c478bd9Sstevel@tonic-gate static char *hold;
567c478bd9Sstevel@tonic-gate
5737f60115SToomas Soome /*
5837f60115SToomas Soome * this String is the working buffer for the demangle
597c478bd9Sstevel@tonic-gate * routine. A pointer into this String is returned
607c478bd9Sstevel@tonic-gate * from demangle when it is possible to demangle the
617c478bd9Sstevel@tonic-gate * String. For this reason, the pointer should not
627c478bd9Sstevel@tonic-gate * be saved between calls of demangle(), nor freed.
637c478bd9Sstevel@tonic-gate */
647c478bd9Sstevel@tonic-gate static String *s = 0;
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate static int
getint(char ** c)6737f60115SToomas Soome getint(char **c)
687c478bd9Sstevel@tonic-gate {
6937f60115SToomas Soome return (strtol(*c, c, 10));
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate
7237f60115SToomas Soome /*
7337f60115SToomas Soome * If a mangled name has a __
747c478bd9Sstevel@tonic-gate * that is not at the very beginning
757c478bd9Sstevel@tonic-gate * of the string, then this routine
767c478bd9Sstevel@tonic-gate * is called to demangle that part
777c478bd9Sstevel@tonic-gate * of the name. All overloaded functions,
787c478bd9Sstevel@tonic-gate * and class members fall into this category.
797c478bd9Sstevel@tonic-gate *
807c478bd9Sstevel@tonic-gate * c should start with two underscores followed by a non-zero digit or an F.
817c478bd9Sstevel@tonic-gate */
827c478bd9Sstevel@tonic-gate static char *
second(char * c)8337f60115SToomas Soome second(char *c)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate int n;
867c478bd9Sstevel@tonic-gate if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2))
8737f60115SToomas Soome return (hold);
887c478bd9Sstevel@tonic-gate c += 2;
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate if (!(isdigit(*c) || *c == 'F'))
9137f60115SToomas Soome return (hold);
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate if (isdigit(*c)) {
947c478bd9Sstevel@tonic-gate /* a member */
957c478bd9Sstevel@tonic-gate n = getint(&c);
967c478bd9Sstevel@tonic-gate if (n == 0 || (int)strlen(c) < n)
9737f60115SToomas Soome return (hold);
987c478bd9Sstevel@tonic-gate s = prep_String(MSG_ORIG(MSG_STR_DBLCOL), s);
997c478bd9Sstevel@tonic-gate s = nprep_String(c, s, n);
1007c478bd9Sstevel@tonic-gate c += n;
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate if (*c == 'F') {
1037c478bd9Sstevel@tonic-gate /* an overloaded function */
1047c478bd9Sstevel@tonic-gate switch (*++c) {
1057c478bd9Sstevel@tonic-gate case '\0':
10637f60115SToomas Soome return (hold);
1077c478bd9Sstevel@tonic-gate case 'v':
1087c478bd9Sstevel@tonic-gate s = app_String(s, MSG_ORIG(MSG_STR_OPENCLOSEPAR));
1097c478bd9Sstevel@tonic-gate break;
1107c478bd9Sstevel@tonic-gate default:
1117c478bd9Sstevel@tonic-gate if (demangle_doargs(&s, c) < 0)
11237f60115SToomas Soome return (hold);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate }
11537f60115SToomas Soome return (PTR(s));
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate char *
demangle(char * c)11937f60115SToomas Soome demangle(char *c)
1207c478bd9Sstevel@tonic-gate {
12137f60115SToomas Soome volatile int i = 0;
1227c478bd9Sstevel@tonic-gate extern jmp_buf jbuf;
1237c478bd9Sstevel@tonic-gate static mutex_t mlock = DEFAULTMUTEX;
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate (void) mutex_lock(&mlock);
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate if (setjmp(jbuf)) {
1287c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
12937f60115SToomas Soome return (0);
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate hold = c;
1337c478bd9Sstevel@tonic-gate s = mk_String(s);
1347c478bd9Sstevel@tonic-gate s = set_String(s, MSG_ORIG(MSG_STR_EMPTY));
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate if (c == 0 || *c == 0) {
1377c478bd9Sstevel@tonic-gate c = hold;
1387c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
13937f60115SToomas Soome return (c);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) != 0) {
14337f60115SToomas Soome /*
14437f60115SToomas Soome * If a name does not begin with a __
1457c478bd9Sstevel@tonic-gate * but it does contain one, it is either
1467c478bd9Sstevel@tonic-gate * a member or an overloaded function.
1477c478bd9Sstevel@tonic-gate */
1487c478bd9Sstevel@tonic-gate while (c[i] && strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2))
1497c478bd9Sstevel@tonic-gate i++;
1507c478bd9Sstevel@tonic-gate if (c[i]) {
1517c478bd9Sstevel@tonic-gate /* Advance to first non-underscore */
1527c478bd9Sstevel@tonic-gate while (c[i+2] == '_')
1537c478bd9Sstevel@tonic-gate i++;
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate if (strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) == 0) {
1567c478bd9Sstevel@tonic-gate /* Copy the simple name */
1577c478bd9Sstevel@tonic-gate s = napp_String(s, c, i);
1587c478bd9Sstevel@tonic-gate /* Process the signature */
1597c478bd9Sstevel@tonic-gate c = second(c+i);
1607c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
16137f60115SToomas Soome return (c);
1627c478bd9Sstevel@tonic-gate } else {
1637c478bd9Sstevel@tonic-gate c = hold;
1647c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
16537f60115SToomas Soome return (c);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate } else {
1687c478bd9Sstevel@tonic-gate const char *x;
1697c478bd9Sstevel@tonic-gate int oplen;
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate c += 2;
1727c478bd9Sstevel@tonic-gate
17337f60115SToomas Soome /*
17437f60115SToomas Soome * For automatic variables, or internal static
1757c478bd9Sstevel@tonic-gate * variables, a __(number) is prepended to the
1767c478bd9Sstevel@tonic-gate * name. If this is encountered, strip this off
1777c478bd9Sstevel@tonic-gate * and return.
1787c478bd9Sstevel@tonic-gate */
1797c478bd9Sstevel@tonic-gate if (isdigit(*c)) {
1807c478bd9Sstevel@tonic-gate while (isdigit(*c))
1817c478bd9Sstevel@tonic-gate c++;
1827c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
18337f60115SToomas Soome return (c);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate
18637f60115SToomas Soome /*
18737f60115SToomas Soome * Handle operator functions -- this
1887c478bd9Sstevel@tonic-gate * automatically calls second, since
1897c478bd9Sstevel@tonic-gate * all operator functions are overloaded.
1907c478bd9Sstevel@tonic-gate */
191*7dbbfe77SToomas Soome x = findop(c, &oplen);
192*7dbbfe77SToomas Soome if (x != NULL) {
1937c478bd9Sstevel@tonic-gate s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_1));
1947c478bd9Sstevel@tonic-gate s = app_String(s, x);
1957c478bd9Sstevel@tonic-gate c += oplen;
1967c478bd9Sstevel@tonic-gate c = second(c);
1977c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
19837f60115SToomas Soome return (c);
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate
20137f60115SToomas Soome /*
20237f60115SToomas Soome * Operator cast does not fit the mould
2037c478bd9Sstevel@tonic-gate * of the other operators. Its type name
2047c478bd9Sstevel@tonic-gate * is encoded. The cast function must
2057c478bd9Sstevel@tonic-gate * take a void as an argument.
2067c478bd9Sstevel@tonic-gate */
2077c478bd9Sstevel@tonic-gate if (strncmp(c, MSG_ORIG(MSG_STR_OP), 2) == 0) {
2087c478bd9Sstevel@tonic-gate int r;
2097c478bd9Sstevel@tonic-gate s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_2));
2107c478bd9Sstevel@tonic-gate c += 2;
2117c478bd9Sstevel@tonic-gate r = demangle_doarg(&s, c);
2127c478bd9Sstevel@tonic-gate if (r < 0) {
2137c478bd9Sstevel@tonic-gate c = hold;
2147c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
21537f60115SToomas Soome return (c);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate c += r;
2187c478bd9Sstevel@tonic-gate c = second(c);
2197c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
22037f60115SToomas Soome return (c);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate
22337f60115SToomas Soome /*
22437f60115SToomas Soome * Constructors and Destructors are also
2257c478bd9Sstevel@tonic-gate * a special case of operator name. Note
2267c478bd9Sstevel@tonic-gate * that the destructor, while overloaded,
2277c478bd9Sstevel@tonic-gate * must always take the same arguments --
2287c478bd9Sstevel@tonic-gate * none.
2297c478bd9Sstevel@tonic-gate */
23037f60115SToomas Soome if ((*c == 'c' || *c == 'd') &&
23137f60115SToomas Soome strncmp(c+1, MSG_ORIG(MSG_STR_TDBLUNDBAR), 3) == 0) {
2327c478bd9Sstevel@tonic-gate int n;
2337c478bd9Sstevel@tonic-gate char *c2 = c+2;
2347c478bd9Sstevel@tonic-gate char cx = c[0];
2357c478bd9Sstevel@tonic-gate c += 4;
2367c478bd9Sstevel@tonic-gate n = getint(&c);
2377c478bd9Sstevel@tonic-gate if (n == 0) {
2387c478bd9Sstevel@tonic-gate c = hold;
2397c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
24037f60115SToomas Soome return (c);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate s = napp_String(s, c, n);
2437c478bd9Sstevel@tonic-gate if (cx == 'd')
2447c478bd9Sstevel@tonic-gate s = prep_String(MSG_ORIG(MSG_STR_TILDE), s);
2457c478bd9Sstevel@tonic-gate c = second(c2);
2467c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
24737f60115SToomas Soome return (c);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate c = hold;
2507c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mlock);
25137f60115SToomas Soome return (c);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate }
254