Blob
1 /*2 * gcc3 name demangler.3 */4 #include <u.h>5 #include <libc.h>6 #include <bio.h>7 #include <mach.h>9 typedef struct Chartab Chartab;10 struct Chartab11 {12 char c;13 char *s;14 };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 }25 typedef struct Gccstate Gccstate;26 struct Gccstate27 {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;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;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 }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, 073 };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, 084 };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",142 0,0,0143 };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 int151 gccname(char **ps, char **pp, Gccstate *state)152 {153 int i, n;154 char *os, *s, *t, *p;155 Gccstate nstate;157 s = *ps;158 os = s;159 p = *pp;161 /* print("\tgccname: %s\n", s); */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 }174 /* basic types */175 if((t = chartabsearch(typetab, *s)) != nil){176 s++;177 strcpy(p, t);178 p += strlen(t);179 goto suffix;180 }182 switch(*s){183 default:184 bad:185 fprint(2, "bad name: %s\n", s);186 return 0;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;196 case 'C': /* C1: constructor? */197 strtol(s+1, &s, 10);198 strcpy(p, "constructor");199 p += strlen(p);200 break;202 case 'D': /* D1: destructor? */203 strtol(s+1, &s, 10);204 strcpy(p, "destructor");205 p += strlen(p);206 break;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;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;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;249 case 'P': /* pointer to */250 s++;251 if(!gccname(&s, &p, state))252 return 0;253 *p++ = '*';254 break;256 case 'R': /* reference to */257 s++;258 if(!gccname(&s, &p, state))259 return 0;260 *p++ = '&';261 break;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 }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;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 }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 }335 *ps = s;336 *pp = p;337 return 1;338 }