diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/6l/6.out.h | 1 | ||||
-rw-r--r-- | src/cmd/6l/obj.c | 1 | ||||
-rw-r--r-- | src/cmd/6l/pass.c | 94 | ||||
-rw-r--r-- | src/runtime/Makefile | 2 | ||||
-rw-r--r-- | src/runtime/iface.c | 11 | ||||
-rw-r--r-- | src/runtime/print.c | 2 | ||||
-rw-r--r-- | src/runtime/rt2_amd64.c | 31 | ||||
-rw-r--r-- | src/runtime/runtime.c | 75 | ||||
-rw-r--r-- | src/runtime/runtime.h | 50 | ||||
-rw-r--r-- | src/runtime/string.c | 15 | ||||
-rw-r--r-- | src/runtime/symtab.c | 190 |
11 files changed, 268 insertions, 204 deletions
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h index 4abbbf057..0c22944fa 100644 --- a/src/cmd/6l/6.out.h +++ b/src/cmd/6l/6.out.h @@ -33,7 +33,6 @@ #define NOPROF (1<<0) #define DUPOK (1<<1) #define NOSPLIT (1<<2) -#define SOFmark "\xa7\xf1\xd9\x2a\x82\xc8\xd8\xfe" /* * amd64 diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index 9777cdf42..8ecb035b4 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -402,7 +402,6 @@ main(int argc, char *argv[]) doprof1(); else doprof2(); - addstackmark(); span(); doinit(); asmb(); diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c index 9f765e836..3ddc1e937 100644 --- a/src/cmd/6l/pass.c +++ b/src/cmd/6l/pass.c @@ -293,100 +293,6 @@ byteq(int v) return p; } -void -markstk(Prog *l) -{ - Prog *p0, *p, *q, *r; - int32 i, n, line; - Sym *s; - - version++; - s = lookup(l->from.sym->name, version); - s->type = STEXT; - line = l->line; - - // start with fake copy of ATEXT - p0 = prg(); - p = p0; - *p = *l; // note this gets p->pcond and p->line - - p->from.type = D_STATIC; - p->from.sym = s; - p->to.offset = 0; - - // put out magic sequence - n = strlen(SOFmark); - for(i=0; i<n; i++) { - q = byteq(SOFmark[i]); - q->line = line; - p->link = q; - p = q; - } - - // put out stack offset - n = l->to.offset; - if(n < 0) - n = 0; - for(i=0; i<3; i++) { - q = byteq(n); - q->line = line; - p->link = q; - p = q; - n = n>>8; - } - - // put out null terminated name - for(i=0;; i++) { - n = s->name[i]; - q = byteq(n); - q->line = line; - p->link = q; - p = q; - if(n == 0) - break; - } - - // put out return instruction - q = prg(); - q->as = ARET; - q->line = line; - p->link = q; - p = q; - - r = l->pcond; - l->pcond = p0; - p->link = r; - p0->pcond = r; - - // hard part is linking end of - // the text body to my fake ATEXT - for(p=l;; p=q) { - q = p->link; - if(q == r) { - p->link = p0; - return; - } - } -} - -void -addstackmark(void) -{ - Prog *p; - - if(debug['v']) - Bprint(&bso, "%5.2f stkmark\n", cputime()); - Bflush(&bso); - - for(p=textp; p!=P; p=p->pcond) { - markstk(p); // splice in new body - p = p->pcond; // skip the one we just put in - } - -// for(p=textp; p!=P; p=p->pcond) -// print("%P\n", p); -} - int relinv(int a) { diff --git a/src/runtime/Makefile b/src/runtime/Makefile index df33b5801..cd1cf2821 100644 --- a/src/runtime/Makefile +++ b/src/runtime/Makefile @@ -26,6 +26,7 @@ LIBOFILES=\ rune.$O\ proc.$O\ string.$O\ + symtab.$O\ sys_file.$O\ OFILES=$(RT0OFILES) $(LIBOFILES) @@ -61,3 +62,4 @@ sys_file.$O: sys_file.c sys_types.h $(OS_H) runtime.acid: runtime.h proc.c $(CC) -a proc.c >runtime.acid + diff --git a/src/runtime/iface.c b/src/runtime/iface.c index 07bd32584..5062075c3 100644 --- a/src/runtime/iface.c +++ b/src/runtime/iface.c @@ -420,21 +420,12 @@ sys·printinter(Map *im, void *it) void sys·reflect(Map *im, void *it, uint64 retit, string rettype) { - string s; - int32 n; - byte *type; - if(im == nil) { retit = 0; rettype = nil; } else { retit = (uint64)it; - type = im->sigt->name; - n = findnull((int8*)type); - s = mal(sizeof *s + n + 1); - s->len = n; - mcpy(s->str, type, n); - rettype = s; + rettype = gostring(im->sigt->name); } FLUSH(&retit); FLUSH(&rettype); diff --git a/src/runtime/print.c b/src/runtime/print.c index 26d59a739..6266d1658 100644 --- a/src/runtime/print.c +++ b/src/runtime/print.c @@ -25,7 +25,7 @@ dump(byte *p, int32 n) void prints(int8 *s) { - sys·write(1, s, findnull(s)); + sys·write(1, s, findnull((byte*)s)); } void diff --git a/src/runtime/rt2_amd64.c b/src/runtime/rt2_amd64.c index 38eeddb49..5a388bfe0 100644 --- a/src/runtime/rt2_amd64.c +++ b/src/runtime/rt2_amd64.c @@ -6,8 +6,6 @@ extern int32 debug; -static int8 spmark[] = "\xa7\xf1\xd9\x2a\x82\xc8\xd8\xfe"; - extern uint8 end; void @@ -18,7 +16,8 @@ traceback(uint8 *pc, uint8 *sp, void* r15) uint8* callpc; int32 counter; int32 i; - int8* name; + string name; + Func *f; G g; Stktop *stktop; @@ -33,7 +32,7 @@ traceback(uint8 *pc, uint8 *sp, void* r15) } counter = 0; - name = "panic"; + name = gostring((byte*)"panic"); for(;;){ callpc = pc; if((uint8*)retfromnewstack == pc) { @@ -46,21 +45,11 @@ traceback(uint8 *pc, uint8 *sp, void* r15) sp += 16; // two irrelevant calls on stack - morestack, plus the call morestack made continue; } - /* find SP offset by stepping back through instructions to SP offset marker */ - while(pc > (uint8*)0x1000+sizeof spmark-1) { - if(pc >= &end) - return; - for(spp = spmark; *spp != '\0' && *pc++ == (uint8)*spp++; ) - ; - if(*spp == '\0'){ - spoff = *pc++; - spoff += *pc++ << 8; - spoff += *pc++ << 16; - name = (int8*)pc; - sp += spoff + 8; - break; - } - } + f = findfunc((uint64)callpc); + if(f == nil) + return; + name = f->name; + sp += f->frame; if(counter++ > 100){ prints("stack trace terminated\n"); break; @@ -73,7 +62,7 @@ traceback(uint8 *pc, uint8 *sp, void* r15) sys·printpointer(callpc - 1); // -1 to get to CALL instr. prints("?zi\n"); prints("\t"); - prints(name); + sys·printstring(name); prints("("); for(i = 0; i < 3; i++){ if(i != 0) @@ -82,7 +71,7 @@ traceback(uint8 *pc, uint8 *sp, void* r15) } prints(", ...)\n"); prints("\t"); - prints(name); + sys·printstring(name); prints("("); for(i = 0; i < 3; i++){ if(i != 0) diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 13f9cacef..33f2abcea 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -107,6 +107,15 @@ mmov(byte *t, byte *f, uint32 n) } } +byte* +mchr(byte *p, byte c, byte *ep) +{ + for(; p < ep; p++) + if(*p == c) + return p; + return nil; +} + uint32 rnd(uint32 n, uint32 m) { @@ -464,7 +473,7 @@ getenv(int8 *s) byte *v, *bs; bs = (byte*)s; - len = findnull(s); + len = findnull(bs); for(i=0; i<envc; i++){ v = envv[i]; for(j=0; j<len; j++) @@ -509,21 +518,10 @@ sys·envc(int32 v) void sys·argv(int32 i, string s) { - uint8* str; - int32 l; - - if(i < 0 || i >= argc) { + if(i >= 0 && i < argc) + s = gostring(argv[i]); + else s = emptystring; - goto out; - } - - str = argv[i]; - l = findnull((int8*)str); - s = mal(sizeof(s->len)+l); - s->len = l; - mcpy(s->str, str, l); - -out: FLUSH(&s); } @@ -531,21 +529,10 @@ out: void sys·envv(int32 i, string s) { - uint8* str; - int32 l; - - if(i < 0 || i >= envc) { + if(i >= 0 && i < envc) + s = gostring(envv[i]); + else s = emptystring; - goto out; - } - - str = envv[i]; - l = findnull((int8*)str); - s = mal(sizeof(s->len)+l); - s->len = l; - mcpy(s->str, str, l); - -out: FLUSH(&s); } @@ -742,33 +729,3 @@ algarray[3] = { memhash, memequal, memprint, memcopy }, // 2 - treat pointers as ints }; - -// Return a pointer to a byte array containing the symbol table segment. -// -// NOTE(rsc): I expect that we will clean up both the method of getting -// at the symbol table and the exact format of the symbol table at some -// point in the future. It probably needs to be better integrated with -// the type strings table too. This is just a quick way to get started -// and figure out what we want from/can do with it. -void -sys·symdat(Array *symtab, Array *pclntab) -{ - Array *a; - int32 *v; - - v = (int32*)(0x99LL<<32); /* known to 6l */ - - a = mal(sizeof *a); - a->nel = v[0]; - a->cap = a->nel; - a->array = (byte*)&v[2]; - symtab = a; - FLUSH(&symtab); - - a = mal(sizeof *a); - a->nel = v[1]; - a->cap = a->nel; - a->array = (byte*)&v[2] + v[0]; - pclntab = a; - FLUSH(&pclntab); -} diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 842ac8ed2..7ec9c7d9b 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -19,32 +19,35 @@ typedef uint64 uintptr; /* * get rid of C types + * the / / / forces a syntax error immediately, + * which will show "last name: XXunsigned". */ -#define unsigned XXunsigned -#define signed XXsigned -#define char XXchar -#define short XXshort -#define int XXint -#define long XXlong -#define float XXfloat -#define double XXdouble +#define unsigned XXunsigned / / / +#define signed XXsigned / / / +#define char XXchar / / / +#define short XXshort / / / +#define int XXint / / / +#define long XXlong / / / +#define float XXfloat / / / +#define double XXdouble / / / /* * defined types */ typedef uint8 bool; typedef uint8 byte; -typedef struct String *string; +typedef struct Alg Alg; typedef struct Array Array; -typedef struct Gobuf Gobuf; +typedef struct Func Func; typedef struct G G; -typedef struct M M; -typedef struct Stktop Stktop; -typedef struct Alg Alg; +typedef struct Gobuf Gobuf; typedef struct Lock Lock; -typedef union Note Note; +typedef struct M M; typedef struct Mem Mem; -typedef struct Usema Usema; +typedef union Note Note; +typedef struct Stktop Stktop; +typedef struct String *string; +typedef struct Usema Usema; /* * per cpu declaration @@ -179,6 +182,18 @@ struct SigTab int8 *name; }; +// (will be) shared with go; edit ../cmd/6g/sys.go too. +// should move out of sys.go eventually. +// also eventually, the loaded symbol table should +// be closer to this form. +struct Func +{ + string name; + string type; + uint64 entry; + int64 frame; +}; + /* * defined macros * you need super-goru privilege @@ -202,7 +217,7 @@ extern int32 maxround; * common functions and data */ int32 strcmp(byte*, byte*); -int32 findnull(int8*); +int32 findnull(byte*); void dump(byte*, int32); int32 runetochar(byte*, int32); int32 chartorune(uint32*, byte*); @@ -220,10 +235,12 @@ void* getu(void); void throw(int8*); uint32 rnd(uint32, uint32); void prints(int8*); +byte* mchr(byte*, byte, byte*); void mcpy(byte*, byte*, uint32); void mmov(byte*, byte*, uint32); void* mal(uint32); uint32 cmpstring(string, string); +string gostring(byte*); void initsig(void); int32 gotraceback(void); void traceback(uint8 *pc, uint8 *sp, G* gp); @@ -243,6 +260,7 @@ void sigaltstack(void*, void*); void signalstack(byte*, int32); G* malg(int32); void minit(void); +Func* findfunc(uint64); /* * mutual exclusion locks. in the uncontended case, diff --git a/src/runtime/string.c b/src/runtime/string.c index fec66f8a8..4dba5ad7e 100644 --- a/src/runtime/string.c +++ b/src/runtime/string.c @@ -8,7 +8,7 @@ static int32 empty = 0; string emptystring = (string)∅ int32 -findnull(int8 *s) +findnull(byte *s) { int32 l; @@ -17,6 +17,19 @@ findnull(int8 *s) return l; } +string +gostring(byte *str) +{ + int32 l; + string s; + + l = findnull(str); + s = mal(sizeof(s->len)+l+1); + s->len = l; + mcpy(s->str, str, l+1); + return s; +} + void sys·catstring(string s1, string s2, string s3) { diff --git a/src/runtime/symtab.c b/src/runtime/symtab.c new file mode 100644 index 000000000..734f39100 --- /dev/null +++ b/src/runtime/symtab.c @@ -0,0 +1,190 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" + +// Runtime symbol table access. +// Very much a work in progress. + +#define SYMCOUNTS ((int32*)(0x99LL<<32)) // known to 6l +#define SYMDATA ((byte*)(0x99LL<<32) + 8) + +// Return a pointer to a byte array containing the symbol table segment. +// +// NOTE(rsc): I expect that we will clean up both the method of getting +// at the symbol table and the exact format of the symbol table at some +// point in the future. It probably needs to be better integrated with +// the type strings table too. This is just a quick way to get started +// and figure out what we want from/can do with it. +void +sys·symdat(Array *symtab, Array *pclntab) +{ + Array *a; + int32 *v; + + v = SYMCOUNTS; + + a = mal(sizeof *a); + a->nel = v[0]; + a->cap = a->nel; + a->array = SYMDATA; + symtab = a; + FLUSH(&symtab); + + a = mal(sizeof *a); + a->nel = v[1]; + a->cap = a->nel; + a->array = SYMDATA + v[0]; + pclntab = a; + FLUSH(&pclntab); +} + +typedef struct Sym Sym; +struct Sym +{ + uint64 value; + byte symtype; + byte *name; + byte *gotype; +}; + +// Walk over symtab, calling fn(&s) for each symbol. +void +walksymtab(void (*fn)(Sym*)) +{ + int32 *v; + byte *p, *ep, *q; + Sym s; + + v = SYMCOUNTS; + p = SYMDATA; + ep = p + v[0]; + while(p < ep) { + if(p + 7 > ep) + break; + s.value = ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]); + if(!(p[4]&0x80)) + break; + s.symtype = p[4] & ~0x80; + p += 5; + if(s.symtype == 'z' || s.symtype == 'Z') { + // path reference string - skip first byte, + // then 2-byte pairs ending at two zeros. + // for now, just skip over it and ignore it. + q = p+1; + for(;;) { + if(q+2 > ep) + return; + if(q[0] == '\0' && q[1] == '\0') + break; + q += 2; + } + p = q+2; + s.name = nil; + }else{ + q = mchr(p, '\0', ep); + if(q == nil) + break; + s.name = p; + p = q+1; + } + q = mchr(p, '\0', ep); + if(q == nil) + break; + s.gotype = p; + p = q+1; + fn(&s); + } +} + +// Symtab walker; accumulates info about functions. + +Func *func; +int32 nfunc; + +static void +dofunc(Sym *sym) +{ + static byte *lastfuncname; + static Func *lastfunc; + Func *f; + + if(lastfunc && sym->symtype == 'm') { + lastfunc->frame = sym->value; + return; + } + if(sym->symtype != 'T' && sym->symtype != 't') + return; + if(strcmp(sym->name, (byte*)"etext") == 0) + return; + if(func == nil) { + nfunc++; + return; + } + + f = &func[nfunc++]; + f->name = gostring(sym->name); + f->entry = sym->value; + lastfunc = f; +} + +static void +buildfuncs(void) +{ + extern byte etext[]; + + if(func != nil) + return; + nfunc = 0; + walksymtab(dofunc); + func = mal((nfunc+1)*sizeof func[0]); + nfunc = 0; + walksymtab(dofunc); + func[nfunc].entry = (uint64)etext; +} + +Func* +findfunc(uint64 addr) +{ + Func *f; + int32 i, nf, n; + + if(func == nil) + buildfuncs(); + if(nfunc == 0) + return nil; + if(addr < func[0].entry || addr >= func[nfunc].entry) + return nil; + + // linear search, for debugging + if(0) { + for(i=0; i<nfunc; i++) { + if(func[i].entry <= addr && addr < func[i+1].entry) + return &func[i]; + } + return nil; + } + + // binary search to find func with entry <= addr. + f = func; + nf = nfunc; + while(nf > 0) { + n = nf/2; + if(f[n].entry <= addr && addr < f[n+1].entry) + return &f[n]; + else if(addr < f[n].entry) + nf = n; + else { + f += n+1; + nf -= n+1; + } + } + + // can't get here -- we already checked above + // that the address was in the table bounds. + // this can only happen if the table isn't sorted + // by address or if the binary search above is buggy. + prints("findfunc unreachable\n"); + return nil; +} |