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 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ 31 32 #include <ctype.h> 33 #include <setjmp.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <thread.h> 37 #include <note.h> 38 #include "elf_dem.h" 39 #include "String.h" 40 #include "msg.h" 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 /* 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(c) 68 char **c; 69 { 70 return strtol(*c, c, 10); 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(c) 84 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(c) 121 char *c; 122 { 123 register int i = 0; 124 extern jmp_buf jbuf; 125 static mutex_t mlock = DEFAULTMUTEX; 126 127 NOTE(MUTEX_PROTECTS_DATA(mlock, String)) 128 (void) mutex_lock(&mlock); 129 130 if (setjmp(jbuf)) { 131 (void) mutex_unlock(&mlock); 132 return 0; 133 } 134 135 hold = c; 136 s = mk_String(s); 137 s = set_String(s, MSG_ORIG(MSG_STR_EMPTY)); 138 139 if(c == 0 || *c == 0) { 140 c = hold; 141 (void) mutex_unlock(&mlock); 142 return c; 143 } 144 145 if(strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) != 0) { 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 /* For automatic variables, or internal static 176 * variables, a __(number) is prepended to the 177 * name. If this is encountered, strip this off 178 * and return. 179 */ 180 if(isdigit(*c)) { 181 while(isdigit(*c)) 182 c++; 183 (void) mutex_unlock(&mlock); 184 return c; 185 } 186 187 /* Handle operator functions -- this 188 * automatically calls second, since 189 * all operator functions are overloaded. 190 */ 191 if(x = findop(c, &oplen)) { 192 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_1)); 193 s = app_String(s,x); 194 c += oplen; 195 c = second(c); 196 (void) mutex_unlock(&mlock); 197 return c; 198 } 199 200 /* Operator cast does not fit the mould 201 * of the other operators. Its type name 202 * is encoded. The cast function must 203 * take a void as an argument. 204 */ 205 if(strncmp(c, MSG_ORIG(MSG_STR_OP), 2) == 0) { 206 int r; 207 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_2)); 208 c += 2; 209 r = demangle_doarg(&s,c); 210 if(r < 0) { 211 c = hold; 212 (void) mutex_unlock(&mlock); 213 return c; 214 } 215 c += r; 216 c = second(c); 217 (void) mutex_unlock(&mlock); 218 return c; 219 } 220 221 /* Constructors and Destructors are also 222 * a special case of operator name. Note 223 * that the destructor, while overloaded, 224 * must always take the same arguments -- 225 * none. 226 */ 227 if ((*c == 'c' || *c == 'd') && strncmp(c+1, 228 MSG_ORIG(MSG_STR_TDBLUNDBAR), 3) == 0) { 229 int n; 230 char *c2 = c+2; 231 char cx = c[0]; 232 c += 4; 233 n = getint(&c); 234 if(n == 0) { 235 c = hold; 236 (void) mutex_unlock(&mlock); 237 return c; 238 } 239 s = napp_String(s,c,n); 240 if(cx == 'd') 241 s = prep_String(MSG_ORIG(MSG_STR_TILDE), s); 242 c = second(c2); 243 (void) mutex_unlock(&mlock); 244 return c; 245 } 246 c = hold; 247 (void) mutex_unlock(&mlock); 248 return c; 249 } 250 } 251