Commit 964f6d3e authored by Russ Cox's avatar Russ Cox

cmd/ld: remove Plan 9 symbol table

Update #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://golang.org/cl/65740045
parent cce25c88
......@@ -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);
}
......@@ -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
}
......
......@@ -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):]) {
......
......@@ -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:]
}
......
......@@ -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
}
......
......@@ -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
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment