summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/6l/6.out.h1
-rw-r--r--src/cmd/6l/obj.c1
-rw-r--r--src/cmd/6l/pass.c94
-rw-r--r--src/runtime/Makefile2
-rw-r--r--src/runtime/iface.c11
-rw-r--r--src/runtime/print.c2
-rw-r--r--src/runtime/rt2_amd64.c31
-rw-r--r--src/runtime/runtime.c75
-rw-r--r--src/runtime/runtime.h50
-rw-r--r--src/runtime/string.c15
-rw-r--r--src/runtime/symtab.c190
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)&empty;
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;
+}