name mangling, process control

This commit is contained in:
rsc 2005-11-28 00:40:04 +00:00
parent 689be54125
commit 7d6f5677c1
6 changed files with 780 additions and 10 deletions

View file

@ -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;
}

73
src/libmach/mangle.c Normal file
View file

@ -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

337
src/libmach/manglegcc2.c Normal file
View file

@ -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;
}

339
src/libmach/manglegcc3.c Normal file
View file

@ -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;
}

View file

@ -32,6 +32,9 @@ OFILES=\
macho.$O\
machocorepower.$O\
machpower.$O\
mangle.$O\
manglegcc2.$O\
manglegcc3.$O\
map.$O\
regs.$O\
stabs.$O\

View file

@ -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;