diff options
author | rsc <devnull@localhost> | 2005-11-28 00:40:04 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-11-28 00:40:04 +0000 |
commit | 7d6f5677c1ce9bdce141dea16364478216d0f4cc (patch) | |
tree | 03daffa36e5693eed2573b05816a0b1bf6a3db82 /src/libmach | |
parent | 689be541258e9e701a600d6bd2fc3e5241726867 (diff) | |
download | plan9port-7d6f5677c1ce9bdce141dea16364478216d0f4cc.tar.gz plan9port-7d6f5677c1ce9bdce141dea16364478216d0f4cc.tar.bz2 plan9port-7d6f5677c1ce9bdce141dea16364478216d0f4cc.zip |
name mangling, process control
Diffstat (limited to 'src/libmach')
-rw-r--r-- | src/libmach/Linux.c | 30 | ||||
-rw-r--r-- | src/libmach/mangle.c | 73 | ||||
-rw-r--r-- | src/libmach/manglegcc2.c | 337 | ||||
-rw-r--r-- | src/libmach/manglegcc3.c | 339 | ||||
-rw-r--r-- | src/libmach/mkfile | 3 | ||||
-rw-r--r-- | src/libmach/sym.c | 8 |
6 files changed, 780 insertions, 10 deletions
diff --git a/src/libmach/Linux.c b/src/libmach/Linux.c index 530150d8..bef03ba1 100644 --- a/src/libmach/Linux.c +++ b/src/libmach/Linux.c @@ -47,13 +47,6 @@ ptraceattach(int pid) { int i; - /* - if(nattached==1 && attachedpids[0] == pid) - goto already; - if(nattached) - detachproc(attachedpids[0]); - */ - for(i=0; i<nattached; i++) if(attachedpids[i]==pid) return 0; @@ -243,7 +236,7 @@ ptraceregrw(Regs *regs, char *name, ulong *val, int isr) *val = u; }else{ u = *val; - if(ptrace(PTRACE_POKEUSER, pid, addr, &u) < 0) + if(ptrace(PTRACE_POKEUSER, pid, addr, (void*)u) < 0) goto ptraceerr; } return 0; @@ -321,7 +314,6 @@ isstopped(int pid) 36. processor */ - int procnotes(int pid, char ***pnotes) { @@ -386,7 +378,19 @@ procnotes(int pid, char ***pnotes) int ctlproc(int pid, char *msg) { - int p, status; + int i, p, status; + + if(strcmp(msg, "attached") == 0){ + for(i=0; i<nattached; i++) + if(attachedpids[i]==pid) + return 0; + if(nattached == nelem(attachedpids)){ + werrstr("attached to too many processes"); + return -1; + } + attachedpids[nattached++] = pid; + return 0; + } if(strcmp(msg, "hang") == 0){ if(pid == getpid()) @@ -411,6 +415,11 @@ ctlproc(int pid, char *msg) return -1; goto waitstop; } + if(strcmp(msg, "step") == 0){ + if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) < 0) + return -1; + goto waitstop; + } if(strcmp(msg, "waitstop") == 0){ waitstop: if(isstopped(pid)) @@ -424,6 +433,7 @@ ctlproc(int pid, char *msg) } return -1; } +//fprint(2, "got pid %d status %x\n", pid, status); if(WIFEXITED(status) || WIFSTOPPED(status)) return 0; } diff --git a/src/libmach/mangle.c b/src/libmach/mangle.c new file mode 100644 index 00000000..e9030252 --- /dev/null +++ b/src/libmach/mangle.c @@ -0,0 +1,73 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> + +static char *(*demanglers[])(char*, char*) = +{ + demanglegcc2, + demanglegcc3, +}; + +char* +demangle(char *s, char *buf, int strip) +{ + char *t; + char *r, *w; + int i, nangle, nparen; + + for(i=0; i<nelem(demanglers); i++){ + t = demanglers[i](s, buf); + if(t != s) + break; + } + if(t == s || !strip) + return t; + + /* copy name without <> and () - not right, but convenient */ + /* convert :: to $ - not right, but convenient (should fix acid) */ + nangle = 0; + nparen = 0; + for(r=w=buf; *r; r++){ + switch(*r){ + case '<': + nangle++; + break; + case '>': + nangle--; + break; + case '(': + nparen++; + break; + case ')': + nparen--; + break; + default: + if(nparen == 0 && nangle == 0){ + if(*r == ':' && *(r+1) == ':'){ + *w++ = '$'; + r++; + } + else + *w++ = *r; + } + break; + } + } + *w = 0; + return buf; +} + +#ifdef TEST +void +main(int argc, char **argv) +{ + int i; + + for(i=1; i<argc; i++){ + print("%s\n", demangle(argv[i], 0)); + print("\t%s\n", demangle(argv[i], 1)); + } + exits(nil); +} +#endif diff --git a/src/libmach/manglegcc2.c b/src/libmach/manglegcc2.c new file mode 100644 index 00000000..035ffd35 --- /dev/null +++ b/src/libmach/manglegcc2.c @@ -0,0 +1,337 @@ +/* + * gcc2 name demangler. + */ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> + +#define debug 0 + +typedef struct Chartab Chartab; +struct Chartab +{ + char c; + char *s; +}; + +static char* +chartabsearch(Chartab *ct, int c) +{ + for(; ct->c; ct++) + if(ct->c == c) + return ct->s; + return nil; +} + +typedef struct Gccstate Gccstate; +struct Gccstate +{ + char *name[128]; + int nname; +}; +static int gccname(char**, char**, Gccstate*); +char* +demanglegcc2(char *s, char *buf) +{ + char *p, *os, *name, *t; + int namelen; + Gccstate state; + + state.nname = 0; + os = s; + p = buf; + + if(memcmp(os, "_._", 3) == 0){ + name = "destructor"; + namelen = strlen(name); + s = os+3; + }else{ + /* the mangled part begins with the final __ */ + if((s = strstr(os, "__")) == nil) + return os; + do{ + t = s; + if(strchr("123456789FHQt", s[2])) + break; + }while((s = strstr(t+1, "__")) != nil); + + s = t; + name = os; + namelen = t - os; + if(namelen == 0){ + name = "constructor"; + namelen = strlen(name); + } + s += 2; + } + + switch(*s){ + default: + return os; + + case 'F': /* plain function */ + s++; + break; + + case 'Q': + case 'H': + case 't': + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if(!gccname(&s, &p, &state)){ + if(debug) fprint(2, "bad name: %s\n", os); + return os; + } + strcpy(p, "::"); + p += 2; + break; + } + + memmove(p, name, namelen); + p += namelen; + + if(*s && *s != '_'){ + /* the rest of the name is the argument types */ + *p++ = '('; + while(*s != 0 && *s != '_' && gccname(&s, &p, &state)) + *p++ = ','; + if(*(p-1) == ',') + p--; + *p++ = ')'; + } + + if(*s == '_'){ + /* the remainder is the type of the return value */ + } + + *p = 0; + return buf; +} + +static Chartab typetab[] = +{ + 'b', "bool", + 'c', "char", + 'd', "double", + 'i', "int", + 'l', "long", + 'v', "void", + 0, 0 +}; + +static int +gccnumber(char **ps, int *pn) +{ + char *s; + int n; + + s = *ps; + if(!isdigit((uchar)*s)) + return 0; + n = strtol(s, &s, 10); + if(*s == '_') + s++; + *ps = s; + *pn = n; + return 1; +} + +/* + * Pick apart the next mangled name section. + * Names and types are treated as the same. + * Let's see how far we can go before that becomes a problem. + */ +static int +gccname(char **ps, char **pp, Gccstate *state) +{ + int i, n, m, val; + char c, *os, *s, *t, *p; + + s = *ps; + os = s; + p = *pp; + +/* print("\tgccname: %s\n", s); */ + +#if 0 + /* overloaded operators */ + for(i=0; operators[i].shrt; i++){ + if(memcmp(operators[i].shrt, s, 2) == 0){ + strcpy(p, "operator$"); + strcat(p, operators[i].lng); + p += strlen(p); + s += 2; + goto suffix; + } + } +#endif + /* basic types */ + if((t = chartabsearch(typetab, *s)) != nil){ + s++; + strcpy(p, t); + p += strlen(t); + goto suffix; + } + + switch(*s){ + default: + bad: + if(debug) fprint(2, "gccname: %s (%s)\n", os, s); + return 0; + + case '1': case '2': case '3': case '4': /* name length */ + case '5': case '6': case '7': case '8': case '9': + n = strtol(s, &s, 10); + memmove(p, s, n); + p += n; + s += n; + break; + + case 'C': /* const */ + s++; + strcpy(p, "const "); + p += strlen(p); + if(!gccname(&s, &p, state)) + return 0; + break; + + case 'U': /* unsigned */ + s++; + strcpy(p, "unsigned "); + p += strlen(p); + if(!gccname(&s, &p, state)) + return 0; + break; + +#if 0 + case 'L': /* default value */ + t = s; + s++; + if(!gccname(&s, &p, state)) + return 0; + if(!isdigit((uchar)*s)){ + fprint(2, "bad value: %s\n", t); + return 0; + } + n = strtol(s, &s, 10); + if(*s != 'E'){ + fprint(2, "bad value2: %s\n", t); + return 0; + } + sprint(p, "=%d", n); + p += strlen(p); + s++; + break; +#endif + + case 'N': /* repeated name/type */ + case 'X': + c = *s++; + if(!isdigit((uchar)*s) || !isdigit((uchar)*(s+1))) + goto bad; + n = *s++ - '0'; + m = *s++ - '0'; + sprint(p, "%c%d/%d", c, n, m); + p += strlen(p); + break; + + case 'Q': /* hierarchical name */ + s++; + if(!isdigit((uchar)*s)) + goto bad; + n = *s++ - '0'; + for(i=0; i<n; i++){ + if(!gccname(&s, &p, state)){ + if(debug) fprint(2, "bad name in hierarchy: %s in %s\n", s, os); + return 0; + } + if(i+1 < n){ + strcpy(p, "::"); + p += 2; + } + } + break; + + case 'P': /* pointer to */ + s++; + if(!gccname(&s, &p, state)) + return 0; + *p++ = '*'; + break; + + case 'R': /* reference to */ + s++; + if(!gccname(&s, &p, state)) + return 0; + *p++ = '&'; + break; + + case 'S': /* standard or previously-seen name */ + s++; + if('0' <= *s && *s <= '9'){ + /* previously seen */ + t = s-1; + n = strtol(s, &s, 10); + if(*s != '_'){ + fprint(2, "bad S: %s\n", t); + return 0; + } + s++; + sprint(p, "S%d_", n); + p += strlen(p); + break; + } + goto bad; + + case 't': /* named template */ + c = *s++; + if(!gccname(&s, &p, state)) + return 0; + goto template; + case 'H': /* nameless template */ + c = *s++; + template: + if(!gccnumber(&s, &n)) + goto bad; + *p++ = '<'; + for(i=0; i<n; i++){ + val = 1; + if(*s == 'Z'){ + val = 0; + s++; + } + if(!gccname(&s, &p, state)) + goto bad; + if(val){ + if(!gccnumber(&s, &m)) + goto bad; + sprint(p, "=%d", m); + p += strlen(p); + } + if(i+1 < n) + *p++ = ','; + } + *p++ = '>'; + if(c == 'H'){ + if(*s != '_') + goto bad; + s++; + } + break; + + case 'T': /* previously-seen type??? e.g., T2 */ + t = s; + for(s++; isdigit((uchar)*s); s++) + ; + memmove(p, t, s-t); + p += s-t; + break; + } + +suffix: + *ps = s; + *pp = p; + return 1; +} + diff --git a/src/libmach/manglegcc3.c b/src/libmach/manglegcc3.c new file mode 100644 index 00000000..eca26eb1 --- /dev/null +++ b/src/libmach/manglegcc3.c @@ -0,0 +1,339 @@ +/* + * gcc3 name demangler. + */ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> + +typedef struct Chartab Chartab; +struct Chartab +{ + char c; + char *s; +}; + +static char* +chartabsearch(Chartab *ct, int c) +{ + for(; ct->c; ct++) + if(ct->c == c) + return ct->s; + return nil; +} + +typedef struct Gccstate Gccstate; +struct Gccstate +{ + char *name[128]; + int nname; +}; +static int gccname(char**, char**, Gccstate*); +char* +demanglegcc3(char *s, char *buf) +{ + char *p, *os; + Gccstate state; + + state.nname = 0; + os = s; + /* mangled names always start with _Z */ + if(s[0] != '_' || s[1] != 'Z') + return s; + s += 2; + + p = buf; + if(!gccname(&s, &p, &state)){ + if(strchr(os, '@') == nil) + fprint(2, "demangle: %s\n"); + return os; + } + if(*s){ + /* the rest of the name is the argument types */ + *p++ = '('; + while(*s != 0 && gccname(&s, &p, &state)) + *p++ = ','; + if(*(p-1) == ',') + p--; + *p++ = ')'; + } + *p = 0; + return buf; +} + +static Chartab stdnames[] = +{ + 'a', "std::allocator", + 'b', "std::basic_string", + 'd', "std::iostream", + 'i', "std::istream", + 'o', "std::ostream", + 's', "std::string", + 0, 0 +}; + +static Chartab typetab[] = +{ + 'b', "bool", + 'c', "char", + 'd', "double", + 'i', "int", + 'j', "uint", + 'v', "void", + 0, 0 +}; + +static struct { + char *shrt; + char *actual; + char *lng; +} operators[] = +{ + "aN", "&=", "andeq", + "aS", "=", "assign", + "aa", "&&", "andand", + "ad", "&", "and", + "an", "&", "and", + "cl", "()", "construct", + "cm", ",", "comma", + "co", "~", "twiddle", + "dV", "/=", "diveq", + "da", "delete[]", "deletearray", + "de", "*", "star", + "dl", "delete", "delete", + "dv", "/", "div", + "eO", "^=", "xoreq", + "eo", "^", "xor", + "eq", "==", "eq", + "ge", ">=", "geq", + "gt", ">", "gt", + "ix", "[]", "index", + "IS", "<<=", "lsheq", + "le", "<=", "leq", + "ls", "<<", "lsh", + "lt", "<", "lt", + "ml", "-=", "subeq", + "mL", "*=", "muleq", + "mi", "-", "sub", + "mI", "*", "mul", + "mm", "--", "dec", + "na", "new[]", "newarray", + "ne", "!=", "neq", + "ng", "-", "neg", + "nt", "!", "not", + "nw", "new", "new", + "oR", "|=", "oreq", + "oo", "||", "oror", + "or", "|", "or", + "pL", "+=", "addeq", + "pl", "+", "add", + "pm", "->*", "pointstoderef", + "pp", "++", "inc", + "ps", "+", "pos", + "pt", "->", "pointsto", + "qu", "?", "question", + "rM", "%=", "modeq", + "rS", ">>=", "rsheq", + "rm", "%", "mod", + "rs", ">>", "rsh", + "st", "sizeof", "sizeoftype", + "sz", "sizeof", "sizeofexpr", + + 0,0,0 +}; + +/* + * Pick apart the next mangled name section. + * Names and types are treated as the same. + * Let's see how far we can go before that becomes a problem. + */ +static int +gccname(char **ps, char **pp, Gccstate *state) +{ + int i, n; + char *os, *s, *t, *p; + Gccstate nstate; + + s = *ps; + os = s; + p = *pp; + +/* print("\tgccname: %s\n", s); */ + + /* overloaded operators */ + for(i=0; operators[i].shrt; i++){ + if(memcmp(operators[i].shrt, s, 2) == 0){ + strcpy(p, "operator$"); + strcat(p, operators[i].lng); + p += strlen(p); + s += 2; + goto suffix; + } + } + + /* basic types */ + if((t = chartabsearch(typetab, *s)) != nil){ + s++; + strcpy(p, t); + p += strlen(t); + goto suffix; + } + + switch(*s){ + default: + bad: + fprint(2, "bad name: %s\n", s); + return 0; + + case '1': case '2': case '3': case '4': /* name length */ + case '5': case '6': case '7': case '8': case '9': + n = strtol(s, &s, 10); + memmove(p, s, n); + p += n; + s += n; + break; + + case 'C': /* C1: constructor? */ + strtol(s+1, &s, 10); + strcpy(p, "constructor"); + p += strlen(p); + break; + + case 'D': /* D1: destructor? */ + strtol(s+1, &s, 10); + strcpy(p, "destructor"); + p += strlen(p); + break; + + case 'K': /* const */ + s++; + strcpy(p, "const "); + p += strlen(p); + if(!gccname(&s, &p, state)) + return 0; + break; + + case 'L': /* default value */ + t = s; + s++; + if(!gccname(&s, &p, state)) + return 0; + if(!isdigit((uchar)*s)){ + fprint(2, "bad value: %s\n", t); + return 0; + } + n = strtol(s, &s, 10); + if(*s != 'E'){ + fprint(2, "bad value2: %s\n", t); + return 0; + } + sprint(p, "=%d", n); + p += strlen(p); + s++; + break; + + case 'N': /* hierarchical name */ + s++; + while(*s != 'E'){ + if(!gccname(&s, &p, state)){ + fprint(2, "bad name in hierarchy: %s in %s\n", s, os); + return 0; + } + strcpy(p, "::"); + p += 2; + } + p -= 2; + s++; + break; + + case 'P': /* pointer to */ + s++; + if(!gccname(&s, &p, state)) + return 0; + *p++ = '*'; + break; + + case 'R': /* reference to */ + s++; + if(!gccname(&s, &p, state)) + return 0; + *p++ = '&'; + break; + + case 'S': /* standard or previously-seen name */ + s++; + if('0' <= *s && *s <= '9'){ + /* previously seen */ + t = s-1; + n = strtol(s, &s, 10); + if(*s != '_'){ + fprint(2, "bad S: %s\n", t); + return 0; + } + s++; + sprint(p, "S%d_", n); + p += strlen(p); + break; + } + /* SA_ ??? */ + if(*s == 'A' && *(s+1) == '_'){ + strcpy(p, "SA_"); + p += 3; + s += 2; + break; + } + + /* standard name */ + if(*s == 't'){ + strcpy(p, "std::"); + p += 5; + s++; + if(!gccname(&s, &p, state)) + return 0; + }else if((t = chartabsearch(stdnames, *s)) != nil){ + strcpy(p, t); + p += strlen(p); + s++; + }else{ + strcpy(p, "std::"); + p += 5; + *p++ = *s++; + } + break; + + case 'T': /* previously-seen type??? T0_ also T_*/ + t = s; + for(; *s != '_'; s++){ + if(*s == 0){ + s = t; + goto bad; + } + } + s++; + memmove(p, t, s-t); + p += s-t; + break; + } + +suffix: + if(*s == 'I'){ + /* template suffix */ + nstate.nname = 0; + *p++ = '<'; + s++; + while(*s != 'E'){ + if(!gccname(&s, &p, &nstate)){ + fprint(2, "bad name in template: %s\n", s); + return 0; + } + *p++ = ','; + } + *(p-1) = '>'; + s++; + } + + *ps = s; + *pp = p; + return 1; +} + diff --git a/src/libmach/mkfile b/src/libmach/mkfile index a6d6507e..d66f3f35 100644 --- a/src/libmach/mkfile +++ b/src/libmach/mkfile @@ -32,6 +32,9 @@ OFILES=\ macho.$O\ machocorepower.$O\ machpower.$O\ + mangle.$O\ + manglegcc2.$O\ + manglegcc3.$O\ map.$O\ regs.$O\ stabs.$O\ diff --git a/src/libmach/sym.c b/src/libmach/sym.c index 4730fdc1..c3d05191 100644 --- a/src/libmach/sym.c +++ b/src/libmach/sym.c @@ -491,6 +491,8 @@ symclose(Fhdr *hdr) Symbol* _addsym(Fhdr *fp, Symbol *sym) { + char *t; + static char buf[65536]; Symbol *s; if(fp->nsym%128 == 0){ @@ -502,6 +504,12 @@ _addsym(Fhdr *fp, Symbol *sym) if(machdebug) fprint(2, "sym %s %c %L\n", sym->name, sym->type, sym->loc); sym->fhdr = fp; + t = demangle(sym->name, buf, 1); + if(t != sym->name){ + sym->name = strdup(t); + if(sym->name == nil) + return nil; + } s = &fp->sym[fp->nsym++]; *s = *sym; return s; |