manglegcc3.c (5672B)
1 /* 2 * gcc3 name demangler. 3 */ 4 #include <u.h> 5 #include <libc.h> 6 #include <bio.h> 7 #include <mach.h> 8 9 typedef struct Chartab Chartab; 10 struct Chartab 11 { 12 char c; 13 char *s; 14 }; 15 16 static char* 17 chartabsearch(Chartab *ct, int c) 18 { 19 for(; ct->c; ct++) 20 if(ct->c == c) 21 return ct->s; 22 return nil; 23 } 24 25 typedef struct Gccstate Gccstate; 26 struct Gccstate 27 { 28 char *name[128]; 29 int nname; 30 }; 31 static int gccname(char**, char**, Gccstate*); 32 char* 33 demanglegcc3(char *s, char *buf) 34 { 35 char *p, *os; 36 Gccstate state; 37 38 state.nname = 0; 39 os = s; 40 /* mangled names always start with _Z */ 41 if(s[0] != '_' || s[1] != 'Z') 42 return s; 43 s += 2; 44 45 p = buf; 46 if(!gccname(&s, &p, &state)){ 47 if(strchr(os, '@') == nil) 48 fprint(2, "demangle: %s\n"); 49 return os; 50 } 51 if(*s){ 52 /* the rest of the name is the argument types */ 53 *p++ = '('; 54 while(*s != 0 && gccname(&s, &p, &state)) 55 *p++ = ','; 56 if(*(p-1) == ',') 57 p--; 58 *p++ = ')'; 59 } 60 *p = 0; 61 return buf; 62 } 63 64 static Chartab stdnames[] = 65 { 66 'a', "std::allocator", 67 'b', "std::basic_string", 68 'd', "std::iostream", 69 'i', "std::istream", 70 'o', "std::ostream", 71 's', "std::string", 72 0, 0 73 }; 74 75 static Chartab typetab[] = 76 { 77 'b', "bool", 78 'c', "char", 79 'd', "double", 80 'i', "int", 81 'j', "uint", 82 'v', "void", 83 0, 0 84 }; 85 86 static struct { 87 char *shrt; 88 char *actual; 89 char *lng; 90 } operators[] = 91 { 92 "aN", "&=", "andeq", 93 "aS", "=", "assign", 94 "aa", "&&", "andand", 95 "ad", "&", "and", 96 "an", "&", "and", 97 "cl", "()", "construct", 98 "cm", ",", "comma", 99 "co", "~", "twiddle", 100 "dV", "/=", "diveq", 101 "da", "delete[]", "deletearray", 102 "de", "*", "star", 103 "dl", "delete", "delete", 104 "dv", "/", "div", 105 "eO", "^=", "xoreq", 106 "eo", "^", "xor", 107 "eq", "==", "eq", 108 "ge", ">=", "geq", 109 "gt", ">", "gt", 110 "ix", "[]", "index", 111 "IS", "<<=", "lsheq", 112 "le", "<=", "leq", 113 "ls", "<<", "lsh", 114 "lt", "<", "lt", 115 "ml", "-=", "subeq", 116 "mL", "*=", "muleq", 117 "mi", "-", "sub", 118 "mI", "*", "mul", 119 "mm", "--", "dec", 120 "na", "new[]", "newarray", 121 "ne", "!=", "neq", 122 "ng", "-", "neg", 123 "nt", "!", "not", 124 "nw", "new", "new", 125 "oR", "|=", "oreq", 126 "oo", "||", "oror", 127 "or", "|", "or", 128 "pL", "+=", "addeq", 129 "pl", "+", "add", 130 "pm", "->*", "pointstoderef", 131 "pp", "++", "inc", 132 "ps", "+", "pos", 133 "pt", "->", "pointsto", 134 "qu", "?", "question", 135 "rM", "%=", "modeq", 136 "rS", ">>=", "rsheq", 137 "rm", "%", "mod", 138 "rs", ">>", "rsh", 139 "st", "sizeof", "sizeoftype", 140 "sz", "sizeof", "sizeofexpr", 141 142 0,0,0 143 }; 144 145 /* 146 * Pick apart the next mangled name section. 147 * Names and types are treated as the same. 148 * Let's see how far we can go before that becomes a problem. 149 */ 150 static int 151 gccname(char **ps, char **pp, Gccstate *state) 152 { 153 int i, n; 154 char *os, *s, *t, *p; 155 Gccstate nstate; 156 157 s = *ps; 158 os = s; 159 p = *pp; 160 161 /* print("\tgccname: %s\n", s); */ 162 163 /* overloaded operators */ 164 for(i=0; operators[i].shrt; i++){ 165 if(memcmp(operators[i].shrt, s, 2) == 0){ 166 strcpy(p, "operator$"); 167 strcat(p, operators[i].lng); 168 p += strlen(p); 169 s += 2; 170 goto suffix; 171 } 172 } 173 174 /* basic types */ 175 if((t = chartabsearch(typetab, *s)) != nil){ 176 s++; 177 strcpy(p, t); 178 p += strlen(t); 179 goto suffix; 180 } 181 182 switch(*s){ 183 default: 184 bad: 185 fprint(2, "bad name: %s\n", s); 186 return 0; 187 188 case '1': case '2': case '3': case '4': /* name length */ 189 case '5': case '6': case '7': case '8': case '9': 190 n = strtol(s, &s, 10); 191 memmove(p, s, n); 192 p += n; 193 s += n; 194 break; 195 196 case 'C': /* C1: constructor? */ 197 strtol(s+1, &s, 10); 198 strcpy(p, "constructor"); 199 p += strlen(p); 200 break; 201 202 case 'D': /* D1: destructor? */ 203 strtol(s+1, &s, 10); 204 strcpy(p, "destructor"); 205 p += strlen(p); 206 break; 207 208 case 'K': /* const */ 209 s++; 210 strcpy(p, "const "); 211 p += strlen(p); 212 if(!gccname(&s, &p, state)) 213 return 0; 214 break; 215 216 case 'L': /* default value */ 217 t = s; 218 s++; 219 if(!gccname(&s, &p, state)) 220 return 0; 221 if(!isdigit((uchar)*s)){ 222 fprint(2, "bad value: %s\n", t); 223 return 0; 224 } 225 n = strtol(s, &s, 10); 226 if(*s != 'E'){ 227 fprint(2, "bad value2: %s\n", t); 228 return 0; 229 } 230 sprint(p, "=%d", n); 231 p += strlen(p); 232 s++; 233 break; 234 235 case 'N': /* hierarchical name */ 236 s++; 237 while(*s != 'E'){ 238 if(!gccname(&s, &p, state)){ 239 fprint(2, "bad name in hierarchy: %s in %s\n", s, os); 240 return 0; 241 } 242 strcpy(p, "::"); 243 p += 2; 244 } 245 p -= 2; 246 s++; 247 break; 248 249 case 'P': /* pointer to */ 250 s++; 251 if(!gccname(&s, &p, state)) 252 return 0; 253 *p++ = '*'; 254 break; 255 256 case 'R': /* reference to */ 257 s++; 258 if(!gccname(&s, &p, state)) 259 return 0; 260 *p++ = '&'; 261 break; 262 263 case 'S': /* standard or previously-seen name */ 264 s++; 265 if('0' <= *s && *s <= '9'){ 266 /* previously seen */ 267 t = s-1; 268 n = strtol(s, &s, 10); 269 if(*s != '_'){ 270 fprint(2, "bad S: %s\n", t); 271 return 0; 272 } 273 s++; 274 sprint(p, "S%d_", n); 275 p += strlen(p); 276 break; 277 } 278 /* SA_ ??? */ 279 if(*s == 'A' && *(s+1) == '_'){ 280 strcpy(p, "SA_"); 281 p += 3; 282 s += 2; 283 break; 284 } 285 286 /* standard name */ 287 if(*s == 't'){ 288 strcpy(p, "std::"); 289 p += 5; 290 s++; 291 if(!gccname(&s, &p, state)) 292 return 0; 293 }else if((t = chartabsearch(stdnames, *s)) != nil){ 294 strcpy(p, t); 295 p += strlen(p); 296 s++; 297 }else{ 298 strcpy(p, "std::"); 299 p += 5; 300 *p++ = *s++; 301 } 302 break; 303 304 case 'T': /* previously-seen type??? T0_ also T_*/ 305 t = s; 306 for(; *s != '_'; s++){ 307 if(*s == 0){ 308 s = t; 309 goto bad; 310 } 311 } 312 s++; 313 memmove(p, t, s-t); 314 p += s-t; 315 break; 316 } 317 318 suffix: 319 if(*s == 'I'){ 320 /* template suffix */ 321 nstate.nname = 0; 322 *p++ = '<'; 323 s++; 324 while(*s != 'E'){ 325 if(!gccname(&s, &p, &nstate)){ 326 fprint(2, "bad name in template: %s\n", s); 327 return 0; 328 } 329 *p++ = ','; 330 } 331 *(p-1) = '>'; 332 s++; 333 } 334 335 *ps = s; 336 *pp = p; 337 return 1; 338 }