From 72d7979c6f00dbe37b2d2049a35c8913e337ee13 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 18 Feb 2014 23:41:15 -0500 Subject: cmd/ld: remove Plan 9 symbol table Update issue 6853 Nothing reads the Plan 9 symbol table anymore. The last holdout was 'go tool nm', but since being rewritten in Go it uses the standard symbol table for the binary format (ELF, Mach-O, PE) instead. Removing the Plan 9 symbol table saves ~15% disk space on most binaries. Two supporting changes included in this CL: debug/gosym: use Go 1.2 pclntab to synthesize func-only symbol table when there is no Plan 9 symbol table debug/elf, debug/macho, debug/pe: ignore final EOF from ReadAt LGTM=r R=r, bradfitz CC=golang-codereviews https://codereview.appspot.com/65740045 --- src/cmd/ld/symtab.c | 170 ----------------------------------------- src/pkg/debug/elf/file.go | 3 + src/pkg/debug/gosym/pclntab.go | 27 +++++++ src/pkg/debug/gosym/symtab.go | 7 ++ src/pkg/debug/macho/file.go | 6 ++ src/pkg/debug/pe/file.go | 3 + 6 files changed, 46 insertions(+), 170 deletions(-) diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c index 0789c8a3e..bd14d9be7 100644 --- a/src/cmd/ld/symtab.c +++ b/src/cmd/ld/symtab.c @@ -270,47 +270,6 @@ asmplan9sym(void) static LSym *symt; -static void -scput(int b) -{ - uchar *p; - - symgrow(ctxt, symt, symt->size+1); - p = symt->p + symt->size; - *p = b; - symt->size++; -} - -static void -slputb(int32 v) -{ - uchar *p; - - symgrow(ctxt, symt, symt->size+4); - p = symt->p + symt->size; - *p++ = v>>24; - *p++ = v>>16; - *p++ = v>>8; - *p = v; - symt->size += 4; -} - -static void -slputl(int32 v) -{ - uchar *p; - - symgrow(ctxt, symt, symt->size+4); - p = symt->p + symt->size; - *p++ = v; - *p++ = v>>8; - *p++ = v>>16; - *p = v>>24; - symt->size += 4; -} - -static void (*slput)(int32); - void wputl(ushort w) { @@ -357,108 +316,6 @@ vputl(uint64 v) lputl(v >> 32); } -// Emit symbol table entry. -// The table format is described at the top of ../../pkg/runtime/symtab.c. -void -putsymb(LSym *s, char *name, int t, vlong v, vlong size, int ver, LSym *typ) -{ - int i, f, c; - vlong v1; - Reloc *rel; - - USED(size); - - // type byte - if('A' <= t && t <= 'Z') - c = t - 'A' + (ver ? 26 : 0); - else if('a' <= t && t <= 'z') - c = t - 'a' + 26; - else { - diag("invalid symbol table type %c", t); - errorexit(); - return; - } - - if(s != nil) - c |= 0x40; // wide value - if(typ != nil) - c |= 0x80; // has go type - scput(c); - - // value - if(s != nil) { - // full width - rel = addrel(symt); - rel->siz = PtrSize; - rel->sym = s; - rel->type = D_ADDR; - rel->off = symt->size; - if(PtrSize == 8) - slput(0); - slput(0); - } else { - // varint - if(v < 0) { - diag("negative value in symbol table: %s %lld", name, v); - errorexit(); - } - v1 = v; - while(v1 >= 0x80) { - scput(v1 | 0x80); - v1 >>= 7; - } - scput(v1); - } - - // go type if present - if(typ != nil) { - if(!typ->reachable) - diag("unreachable type %s", typ->name); - rel = addrel(symt); - rel->siz = PtrSize; - rel->sym = typ; - rel->type = D_ADDR; - rel->off = symt->size; - if(PtrSize == 8) - slput(0); - slput(0); - } - - // name - if(t == 'f') - name++; - - if(t == 'Z' || t == 'z') { - scput(name[0]); - for(i=1; name[i] != 0 || name[i+1] != 0; i += 2) { - scput(name[i]); - scput(name[i+1]); - } - scput(0); - scput(0); - } else { - for(i=0; name[i]; i++) - scput(name[i]); - scput(0); - } - - if(debug['n']) { - if(t == 'z' || t == 'Z') { - Bprint(&bso, "%c %.8llux ", t, v); - for(i=1; name[i] != 0 || name[i+1] != 0; i+=2) { - f = ((name[i]&0xff) << 8) | (name[i+1]&0xff); - Bprint(&bso, "/%x", f); - } - Bprint(&bso, "\n"); - return; - } - if(ver) - Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, name, ver, typ ? typ->name : ""); - else - Bprint(&bso, "%c %.8llux %s %s\n", t, v, name, typ ? typ->name : ""); - } -} - void symtab(void) { @@ -553,31 +410,4 @@ symtab(void) s->outer = symgofunc; } } - - if(debug['s']) - return; - - switch(thechar) { - default: - diag("unknown architecture %c", thechar); - errorexit(); - case '5': - case '6': - case '8': - // little-endian symbol table - slput = slputl; - break; - case 'v': - // big-endian symbol table - slput = slputb; - break; - } - // new symbol table header. - slput(0xfffffffd); - scput(0); - scput(0); - scput(0); - scput(PtrSize); - - genasmsym(putsymb); } diff --git a/src/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go index a40617099..2840f0767 100644 --- a/src/pkg/debug/elf/file.go +++ b/src/pkg/debug/elf/file.go @@ -76,6 +76,9 @@ type Section struct { func (s *Section) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } diff --git a/src/pkg/debug/gosym/pclntab.go b/src/pkg/debug/gosym/pclntab.go index 3e6a8046b..6620aefb0 100644 --- a/src/pkg/debug/gosym/pclntab.go +++ b/src/pkg/debug/gosym/pclntab.go @@ -196,6 +196,33 @@ func (t *LineTable) go12Init() { t.go12 = 1 // so far so good } +// go12Funcs returns a slice of Funcs derived from the Go 1.2 pcln table. +func (t *LineTable) go12Funcs() []Func { + // Assume it is malformed and return nil on error. + defer func() { + recover() + }() + + n := len(t.functab) / int(t.ptrsize) / 2 + funcs := make([]Func, n) + for i := range funcs { + f := &funcs[i] + f.Entry = uint64(t.uintptr(t.functab[2*i*int(t.ptrsize):])) + f.End = uint64(t.uintptr(t.functab[(2*i+2)*int(t.ptrsize):])) + info := t.Data[t.uintptr(t.functab[(2*i+1)*int(t.ptrsize):]):] + f.LineTable = t + f.FrameSize = int(t.binary.Uint32(info[t.ptrsize+2*4:])) + f.Sym = &Sym{ + Value: f.Entry, + Type: 'T', + Name: t.string(t.binary.Uint32(info[t.ptrsize:])), + GoType: 0, + Func: f, + } + } + return funcs +} + // findFunc returns the func corresponding to the given program counter. func (t *LineTable) findFunc(pc uint64) []byte { if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) { diff --git a/src/pkg/debug/gosym/symtab.go b/src/pkg/debug/gosym/symtab.go index 9ab05bac2..3864e3cb4 100644 --- a/src/pkg/debug/gosym/symtab.go +++ b/src/pkg/debug/gosym/symtab.go @@ -129,6 +129,9 @@ var ( ) func walksymtab(data []byte, fn func(sym) error) error { + if len(data) == 0 { // missing symtab is okay + return nil + } var order binary.ByteOrder = binary.BigEndian newTable := false switch { @@ -455,6 +458,10 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) { i = end - 1 // loop will i++ } } + + if t.go12line != nil && nf == 0 { + t.Funcs = t.go12line.go12Funcs() + } if obj != nil { obj.Funcs = t.Funcs[lastf:] } diff --git a/src/pkg/debug/macho/file.go b/src/pkg/debug/macho/file.go index c799fa49d..2b19f7f65 100644 --- a/src/pkg/debug/macho/file.go +++ b/src/pkg/debug/macho/file.go @@ -74,6 +74,9 @@ type Segment struct { func (s *Segment) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } @@ -109,6 +112,9 @@ type Section struct { func (s *Section) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } diff --git a/src/pkg/debug/pe/file.go b/src/pkg/debug/pe/file.go index a2859bf37..d0005bacf 100644 --- a/src/pkg/debug/pe/file.go +++ b/src/pkg/debug/pe/file.go @@ -72,6 +72,9 @@ type ImportDirectory struct { func (s *Section) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } -- cgit v1.2.1