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