name mangling, process control
This commit is contained in:
parent
689be54125
commit
7d6f5677c1
6 changed files with 780 additions and 10 deletions
337
src/libmach/manglegcc2.c
Normal file
337
src/libmach/manglegcc2.c
Normal 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;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue