diff --git a/include/mach_amd64.h b/include/mach_amd64.h index 1ffa44033c..140240993e 100644 --- a/include/mach_amd64.h +++ b/include/mach_amd64.h @@ -84,6 +84,7 @@ struct Sym uint sig; char type; char *name; + char *gotype; }; /* * End of Plan 9 a.out.h diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index 0c4c15fbf3..901c988509 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -121,10 +121,11 @@ asmb(void) { Prog *p; int32 v, magic; - int a; + int a, np; uchar *op1; - vlong vl, va, fo, w; + vlong vl, va, fo, w, symo; int strtabsize; + vlong symdatva = 0x99LL<<32; strtabsize = 0; @@ -221,6 +222,7 @@ asmb(void) symsize = 0; spsize = 0; lcsize = 0; + symo = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); @@ -230,15 +232,17 @@ asmb(void) case 2: case 5: debug['s'] = 1; - seek(cout, HEADR+textsize+datsize, 0); + symo = HEADR+textsize+datsize; break; case 6: - seek(cout, rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND), 0); + symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND); break; case 7: - seek(cout, rnd(HEADR+textsize, INITRND)+datsize+strtabsize, 0); + symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; + symo = rnd(symo, INITRND); break; } + seek(cout, symo+8, 0); if(!debug['s']) asmsym(); if(debug['v']) @@ -252,6 +256,10 @@ asmb(void) if(dlm) asmdyn(); cflush(); + seek(cout, symo, 0); + lputl(symsize); + lputl(lcsize); + cflush(); } else if(dlm){ seek(cout, HEADR+textsize+datsize, 0); @@ -352,7 +360,7 @@ asmb(void) if (debug['s']) lputl(4); /* number of loads */ else - lputl(6); /* number of loads */ + lputl(7); /* number of loads */ lputl(machheadr()-32); /* size of loads */ lputl(1); /* flags - no undefines */ lputl(0); /* reserved */ @@ -394,6 +402,13 @@ asmb(void) machstack(va+HEADR); if (!debug['s']) { + machseg("__SYMDAT", + symdatva, /* vaddr */ + 8+symsize+lcsize, /* vsize */ + symo, 8+symsize+lcsize, /* fileoffset filesize */ + 7, 5, /* protects */ + 0, 0); /* sections flags */ + v += rnd(datsize, INITRND); machsymseg(v,symsize); /* fileoffset,filesize */ v += symsize; @@ -413,11 +428,14 @@ asmb(void) lputl(1L); /* version = CURRENT */ llputl(entryvalue()); /* entry vaddr */ llputl(64L); /* offset to first phdr */ - llputl(64L+56*3); /* offset to first shdr */ + np = 3; + if(!debug['s']) + np++; + llputl(64L+56*np); /* offset to first shdr */ lputl(0L); /* processor specific flags */ wputl(64); /* Ehdr size */ wputl(56); /* Phdr size */ - wputl(3); /* # of Phdrs */ + wputl(np); /* # of Phdrs */ wputl(64); /* Shdr size */ if (!debug['s']) wputl(7); /* # of Shdrs */ @@ -451,6 +469,17 @@ asmb(void) w+bsssize, /* memory size */ INITRND); /* alignment */ + if(!debug['s']) { + linuxphdr(1, /* data - type = PT_LOAD */ + 2L+4L, /* data - flags = PF_W+PF_R */ + symo, /* file offset */ + symdatva, /* vaddr */ + symdatva, /* paddr */ + 8+symsize+lcsize, /* file size */ + 8+symsize+lcsize, /* memory size */ + INITRND); /* alignment */ + } + linuxphdr(0x6474e551, /* gok - type = gok */ 1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */ 0, /* file offset */ @@ -533,7 +562,7 @@ asmb(void) if (debug['s']) break; - fo += w; + fo = symo+8; w = symsize; linuxshdr(".gosymtab", /* name */ @@ -829,6 +858,7 @@ machheadr(void) a += 20; /* bss sect */ a += 46; /* stack sect */ if (!debug['s']) { + a += 18; /* symdat seg */ a += 4; /* symtab seg */ a += 4; /* lctab seg */ } @@ -853,6 +883,7 @@ linuxheadr(void) a += 64; /* .bss sect */ a += 64; /* .shstrtab sect - strings for headers */ if (!debug['s']) { + a += 56; /* symdat seg */ a += 64; /* .gosymtab sect */ a += 64; /* .gopclntab sect */ } diff --git a/src/cmd/6l/go.c b/src/cmd/6l/go.c index e073959ded..5128c51fa9 100644 --- a/src/cmd/6l/go.c +++ b/src/cmd/6l/go.c @@ -70,6 +70,27 @@ ilookup(char *name) return x; } +char* +gotypefor(char *name) +{ + Import *x; + char *s, *p; + + s = strdup(name); + p = utfrune(s, 0xB7); // center dot + if(p == nil) + return nil; + *p++ = '.'; + memmove(p, p+1, strlen(p)); + x = ilookup(s); + free(s); + if(x == nil || x->prefix == nil) + return nil; + if(strcmp(x->prefix, "var") != 0 && strcmp(x->prefix, "func") != 0) + return nil; + return x->def; +} + static void loadpkgdata(char*, char*, int); static int parsemethod(char**, char*, char**); static int parsepkgdata(char*, char**, char*, int*, char**, char**, char**); diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index b9e8dd37a3..ce3ff8eaf6 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -397,6 +397,8 @@ int find2(int32, int); void follow(void); void addstachmark(void); void gethunk(void); +void gotypestrings(void); +char* gotypefor(char*); void histtoauto(void); double ieeedtod(Ieee*); int32 ieeedtof(Ieee*); diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c index acb8f071d4..8ac0543a88 100644 --- a/src/cmd/6l/span.c +++ b/src/cmd/6l/span.c @@ -150,9 +150,9 @@ xdefine(char *p, int t, vlong v) } void -putsymb(char *s, int t, vlong v, int ver) +putsymb(char *s, int t, vlong v, int ver, char *go) { - int i, f, l; + int i, j, f, l; if(t == 'f') s++; @@ -181,7 +181,13 @@ putsymb(char *s, int t, vlong v, int ver) cput(s[i]); cput(0); } - symsize += l + 1 + i + 1; + j = 0; + if(go) { + for(j=0; go[j]; j++) + cput(go[j]); + } + cput(0); + symsize += l + 1 + i + 1 + j + 1; if(debug['n']) { if(t == 'z' || t == 'Z') { @@ -194,9 +200,9 @@ putsymb(char *s, int t, vlong v, int ver) return; } if(ver) - Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver); + Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s, ver, go); else - Bprint(&bso, "%c %.8llux %s\n", t, v, s); + Bprint(&bso, "%c %.8llux %s %s\n", t, v, s, go); } } @@ -210,25 +216,25 @@ asmsym(void) s = lookup("etext", 0); if(s->type == STEXT) - putsymb(s->name, 'T', s->value, s->version); + putsymb(s->name, 'T', s->value, s->version, nil); for(h=0; hlink) switch(s->type) { case SCONST: - putsymb(s->name, 'D', s->value, s->version); + putsymb(s->name, 'D', s->value, s->version, gotypefor(s->name)); continue; case SDATA: - putsymb(s->name, 'D', s->value+INITDAT, s->version); + putsymb(s->name, 'D', s->value+INITDAT, s->version, gotypefor(s->name)); continue; case SBSS: - putsymb(s->name, 'B', s->value+INITDAT, s->version); + putsymb(s->name, 'B', s->value+INITDAT, s->version, gotypefor(s->name)); continue; case SFILE: - putsymb(s->name, 'f', s->value, s->version); + putsymb(s->name, 'f', s->value, s->version, nil); continue; } @@ -240,22 +246,23 @@ asmsym(void) /* filenames first */ for(a=p->to.autom; a; a=a->link) if(a->type == D_FILE) - putsymb(a->asym->name, 'z', a->aoffset, 0); + putsymb(a->asym->name, 'z', a->aoffset, 0, nil); else if(a->type == D_FILE1) - putsymb(a->asym->name, 'Z', a->aoffset, 0); + putsymb(a->asym->name, 'Z', a->aoffset, 0, nil); - putsymb(s->name, 'T', s->value, s->version); + putsymb(s->name, 'T', s->value, s->version, gotypefor(s->name)); /* frame, auto and param after */ - putsymb(".frame", 'm', p->to.offset+8, 0); + putsymb(".frame", 'm', p->to.offset+8, 0, nil); + /* TODO(rsc): Add types for D_AUTO and D_PARAM */ for(a=p->to.autom; a; a=a->link) if(a->type == D_AUTO) - putsymb(a->asym->name, 'a', -a->aoffset, 0); + putsymb(a->asym->name, 'a', -a->aoffset, 0, nil); else if(a->type == D_PARAM) - putsymb(a->asym->name, 'p', a->aoffset, 0); + putsymb(a->asym->name, 'p', a->aoffset, 0, nil); } if(debug['v'] || debug['n']) Bprint(&bso, "symsize = %lud\n", symsize); diff --git a/src/cmd/gc/sys.go b/src/cmd/gc/sys.go index 910bbd8c62..1f34e0cd6c 100644 --- a/src/cmd/gc/sys.go +++ b/src/cmd/gc/sys.go @@ -89,3 +89,6 @@ export func bytestorune(*byte, int, int) (int, int); // convert bytes to runes export func stringtorune(string, int) (int, int); // convert bytes to runes export func exit(int); + +export func symdat() (symtab *[]byte, pclntab *[]byte); + diff --git a/src/cmd/gc/sysimport.c b/src/cmd/gc/sysimport.c index 64dd1a98d1..ba09bb970e 100644 --- a/src/cmd/gc/sysimport.c +++ b/src/cmd/gc/sysimport.c @@ -1,4 +1,4 @@ -char *sysimport = +char *sysimport = "package sys\n" "export func sys.mal (? int32) (? *any)\n" "export func sys.breakpoint ()\n" @@ -70,5 +70,6 @@ char *sysimport = "export func sys.bytestorune (? *uint8, ? int, ? int) (? int, ? int)\n" "export func sys.stringtorune (? string, ? int) (? int, ? int)\n" "export func sys.exit (? int)\n" + "export func sys.symdat () (symtab *[]uint8, pclntab *[]uint8)\n" "\n" "$$\n"; diff --git a/src/cmd/nm/nm.c b/src/cmd/nm/nm.c index 7c77f66c61..63c77bd921 100644 --- a/src/cmd/nm/nm.c +++ b/src/cmd/nm/nm.c @@ -52,6 +52,7 @@ int nflag; int sflag; int uflag; int Tflag; +int tflag; Sym **fnames; /* file path translation table */ Sym **symptr; @@ -90,6 +91,7 @@ main(int argc, char *argv[]) case 'n': nflag = 1; break; case 's': sflag = 1; break; case 'u': uflag = 1; break; + case 't': tflag = 1; break; case 'T': Tflag = 1; break; } ARGEND if (argc == 0) @@ -298,7 +300,7 @@ printsyms(Sym **symptr, long nsym) if(!sflag) qsort(symptr, nsym, sizeof(*symptr), (void*)cmp); - + wid = 0; for (i=0; ivalue >= 0x100000000LL && wid == 8) wid = 16; - } + } for (i=0; ivalue); else Bprint(&bout, "%*s ", wid, ""); - Bprint(&bout, "%c %s\n", s->type, cp); + Bprint(&bout, "%c %s", s->type, cp); + if(tflag && s->gotype && s->gotype[0]) + Bprint(&bout, " %s", s->gotype); + Bprint(&bout, "\n"); } } diff --git a/src/libmach_amd64/sym.c b/src/libmach_amd64/sym.c index aedd2afde1..7faf5cd2f4 100644 --- a/src/libmach_amd64/sym.c +++ b/src/libmach_amd64/sym.c @@ -87,6 +87,7 @@ static uvlong firstinstr; /* as found from symtab; needed for amd64 */ static void cleansyms(void); static int32 decodename(Biobuf*, Sym*); +static int32 decodegotype(Biobuf*, Sym*); static short *encfname(char*); static int fline(char*, int, int32, Hist*, Hist**); static void fillsym(Sym*, Symbol*); @@ -151,6 +152,10 @@ syminit(int fd, Fhdr *fp) if(i < 0) return -1; size += i+svalsz+sizeof(p->type); + i = decodegotype(&b, p); + if(i < 0) + return -1; + size += i; /* count global & auto vars, text symbols, and file names */ switch (p->type) { @@ -293,6 +298,27 @@ decodename(Biobuf *bp, Sym *p) return n; } +static int32 +decodegotype(Biobuf *bp, Sym *p) +{ + char *cp; + int32 n; + + cp = Brdline(bp, '\0'); + if(cp == 0) { + werrstr("can't read go type"); + return -1; + } + n = Blinelen(bp); + p->gotype = malloc(n); + if(p->gotype == 0) { + werrstr("can't malloc %ld bytes", n); + return -1; + } + strcpy(p->gotype, cp); + return n; +} + /* * free any previously loaded symbol tables */ diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 5dd4336e79..0a72b146ba 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -743,3 +743,34 @@ algarray[3] = // { pointerhash, pointerequal, pointerprint, pointercopy }, // 2 { 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); +}