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 (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * 27 * Copyright (c) 1998 by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #include <ctype.h> 32 #include <setjmp.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <thread.h> 36 #include "elf_dem.h" 37 #include "String.h" 38 #include "msg.h" 39 40 /* 41 * The variable "hold" contains the pointer to the array initially 42 * handed to demangle. It is returned if it is not possible to 43 * demangle the string. NULL is returned if a memory allocation 44 * problem is encountered. Thus one can do the following: 45 * 46 * char *mn = "Some mangled name"; 47 * char *dm = mangle(mn); 48 * if (dm == NULL) 49 * printf("allocation error\n"); 50 * else if (dm == mn) 51 * printf("name could not be demangled\n"); 52 * else 53 * printf("demangled name is: %s\n",dm); 54 */ 55 static char *hold; 56 57 /* 58 * this String is the working buffer for the demangle 59 * routine. A pointer into this String is returned 60 * from demangle when it is possible to demangle the 61 * String. For this reason, the pointer should not 62 * be saved between calls of demangle(), nor freed. 63 */ 64 static String *s = 0; 65 66 static int 67 getint(char **c) 68 { 69 return (strtol(*c, c, 10)); 70 } 71 72 /* 73 * If a mangled name has a __ 74 * that is not at the very beginning 75 * of the string, then this routine 76 * is called to demangle that part 77 * of the name. All overloaded functions, 78 * and class members fall into this category. 79 * 80 * c should start with two underscores followed by a non-zero digit or an F. 81 */ 82 static char * 83 second(char *c) 84 { 85 int n; 86 if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2)) 87 return (hold); 88 c += 2; 89 90 if (!(isdigit(*c) || *c == 'F')) 91 return (hold); 92 93 if (isdigit(*c)) { 94 /* a member */ 95 n = getint(&c); 96 if (n == 0 || (int)strlen(c) < n) 97 return (hold); 98 s = prep_String(MSG_ORIG(MSG_STR_DBLCOL), s); 99 s = nprep_String(c, s, n); 100 c += n; 101 } 102 if (*c == 'F') { 103 /* an overloaded function */ 104 switch (*++c) { 105 case '\0': 106 return (hold); 107 case 'v': 108 s = app_String(s, MSG_ORIG(MSG_STR_OPENCLOSEPAR)); 109 break; 110 default: 111 if (demangle_doargs(&s, c) < 0) 112 return (hold); 113 } 114 } 115 return (PTR(s)); 116 } 117 118 char * 119 demangle(char *c) 120 { 121 volatile int i = 0; 122 extern jmp_buf jbuf; 123 static mutex_t mlock = DEFAULTMUTEX; 124 125 (void) mutex_lock(&mlock); 126 127 if (setjmp(jbuf)) { 128 (void) mutex_unlock(&mlock); 129 return (0); 130 } 131 132 hold = c; 133 s = mk_String(s); 134 s = set_String(s, MSG_ORIG(MSG_STR_EMPTY)); 135 136 if (c == 0 || *c == 0) { 137 c = hold; 138 (void) mutex_unlock(&mlock); 139 return (c); 140 } 141 142 if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) != 0) { 143 /* 144 * If a name does not begin with a __ 145 * but it does contain one, it is either 146 * a member or an overloaded function. 147 */ 148 while (c[i] && strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2)) 149 i++; 150 if (c[i]) { 151 /* Advance to first non-underscore */ 152 while (c[i+2] == '_') 153 i++; 154 } 155 if (strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) == 0) { 156 /* Copy the simple name */ 157 s = napp_String(s, c, i); 158 /* Process the signature */ 159 c = second(c+i); 160 (void) mutex_unlock(&mlock); 161 return (c); 162 } else { 163 c = hold; 164 (void) mutex_unlock(&mlock); 165 return (c); 166 } 167 } else { 168 const char *x; 169 int oplen; 170 171 c += 2; 172 173 /* 174 * For automatic variables, or internal static 175 * variables, a __(number) is prepended to the 176 * name. If this is encountered, strip this off 177 * and return. 178 */ 179 if (isdigit(*c)) { 180 while (isdigit(*c)) 181 c++; 182 (void) mutex_unlock(&mlock); 183 return (c); 184 } 185 186 /* 187 * Handle operator functions -- this 188 * automatically calls second, since 189 * all operator functions are overloaded. 190 */ 191 x = findop(c, &oplen); 192 if (x != NULL) { 193 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_1)); 194 s = app_String(s, x); 195 c += oplen; 196 c = second(c); 197 (void) mutex_unlock(&mlock); 198 return (c); 199 } 200 201 /* 202 * Operator cast does not fit the mould 203 * of the other operators. Its type name 204 * is encoded. The cast function must 205 * take a void as an argument. 206 */ 207 if (strncmp(c, MSG_ORIG(MSG_STR_OP), 2) == 0) { 208 int r; 209 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_2)); 210 c += 2; 211 r = demangle_doarg(&s, c); 212 if (r < 0) { 213 c = hold; 214 (void) mutex_unlock(&mlock); 215 return (c); 216 } 217 c += r; 218 c = second(c); 219 (void) mutex_unlock(&mlock); 220 return (c); 221 } 222 223 /* 224 * Constructors and Destructors are also 225 * a special case of operator name. Note 226 * that the destructor, while overloaded, 227 * must always take the same arguments -- 228 * none. 229 */ 230 if ((*c == 'c' || *c == 'd') && 231 strncmp(c+1, MSG_ORIG(MSG_STR_TDBLUNDBAR), 3) == 0) { 232 int n; 233 char *c2 = c+2; 234 char cx = c[0]; 235 c += 4; 236 n = getint(&c); 237 if (n == 0) { 238 c = hold; 239 (void) mutex_unlock(&mlock); 240 return (c); 241 } 242 s = napp_String(s, c, n); 243 if (cx == 'd') 244 s = prep_String(MSG_ORIG(MSG_STR_TILDE), s); 245 c = second(c2); 246 (void) mutex_unlock(&mlock); 247 return (c); 248 } 249 c = hold; 250 (void) mutex_unlock(&mlock); 251 return (c); 252 } 253 } 254