Commit 4e2aa9bf authored by Russ Cox's avatar Russ Cox

cmd/ld: use native-endian symbol values in symbol table

The Plan 9 symbol table format defines big-endian symbol values
for portability, but we want to be able to generate an ELF object file
and let the host linker link it, as part of the solution to issue 4069.
The symbol table itself, since it is loaded into memory at run time,
must be filled in by the final host linker, using relocation directives
to set the symbol values. On a little-endian machine, the linker will
only fill in little-endian values during relocation, so we are forced
to use little-endian symbol values.

To preserve most of the original portability of the symbol table
format, we make the table itself say whether it uses big- or
little-endian values. If the table begins with the magic sequence
        fe ff ff ff 00 00
then the actual table begins after those six bytes and contains
little-endian symbol values. Otherwise, the table is in the original
format and contains big-endian symbol values. The magic sequence
looks like an "end of table" entry (the fifth byte is zero), so legacy
readers will see a little-endian table as an empty table.

All the gc architectures are little-endian today, so the practical
effect of this CL is to make all the generated tables little-endian,
but if a big-endian system comes along, ld will not generate
the magic sequence, and the various readers will fall back to the
original big-endian interpretation.

R=ken2
CC=golang-dev
https://golang.org/cl/7066043
parent f1e4ee3f
...@@ -66,6 +66,15 @@ to adjust frame pointer offsets. ...@@ -66,6 +66,15 @@ to adjust frame pointer offsets.
The implementation now includes a built-in <a href="/doc/articles/race_detector.html">data race detector</a>. The implementation now includes a built-in <a href="/doc/articles/race_detector.html">data race detector</a>.
</p> </p>
<h3 id="symtab">Symbol table</h3>
<p>
In the gc toolchain, the symbol table format has been extended to allow
little-endian encoding of symbol values, and the extension is used in
binaries generated by the Go 1.1 version of the gc linker.
To the Go 1.0 toolchain and libraries, these new symbol tables appear empty.
</p>
<h2 id="library">Changes to the standard library</h2> <h2 id="library">Changes to the standard library</h2>
<h3 id="debug/elf">debug/elf</h3> <h3 id="debug/elf">debug/elf</h3>
......
...@@ -150,14 +150,14 @@ relocsym(Sym *s) ...@@ -150,14 +150,14 @@ relocsym(Sym *s)
int32 i, off, siz, fl; int32 i, off, siz, fl;
vlong o; vlong o;
uchar *cast; uchar *cast;
cursym = s; cursym = s;
memset(&p, 0, sizeof p); memset(&p, 0, sizeof p);
for(r=s->r; r<s->r+s->nr; r++) { for(r=s->r; r<s->r+s->nr; r++) {
off = r->off; off = r->off;
siz = r->siz; siz = r->siz;
if(off < 0 || off+(siz&~Rbig) > s->np) { if(off < 0 || off+siz > s->np) {
diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz&~Rbig, 0, s->np); diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np);
continue; continue;
} }
if(r->sym != S && (r->sym->type & SMASK == 0 || r->sym->type & SMASK == SXREF)) { if(r->sym != S && (r->sym->type & SMASK == 0 || r->sym->type & SMASK == SXREF)) {
...@@ -198,20 +198,6 @@ relocsym(Sym *s) ...@@ -198,20 +198,6 @@ relocsym(Sym *s)
default: default:
cursym = s; cursym = s;
diag("bad reloc size %#ux for %s", siz, r->sym->name); diag("bad reloc size %#ux for %s", siz, r->sym->name);
case 4 + Rbig:
fl = o;
s->p[off] = fl>>24;
s->p[off+1] = fl>>16;
s->p[off+2] = fl>>8;
s->p[off+3] = fl;
break;
case 4 + Rlittle:
fl = o;
s->p[off] = fl;
s->p[off+1] = fl>>8;
s->p[off+2] = fl>>16;
s->p[off+3] = fl>>24;
break;
case 4: case 4:
fl = o; fl = o;
cast = (uchar*)&fl; cast = (uchar*)&fl;
...@@ -223,7 +209,7 @@ relocsym(Sym *s) ...@@ -223,7 +209,7 @@ relocsym(Sym *s)
for(i=0; i<8; i++) for(i=0; i<8; i++)
s->p[off+i] = cast[inuxi8[i]]; s->p[off+i] = cast[inuxi8[i]];
break; break;
} }
} }
} }
...@@ -231,7 +217,7 @@ void ...@@ -231,7 +217,7 @@ void
reloc(void) reloc(void)
{ {
Sym *s; Sym *s;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f reloc\n", cputime()); Bprint(&bso, "%5.2f reloc\n", cputime());
Bflush(&bso); Bflush(&bso);
...@@ -246,10 +232,10 @@ void ...@@ -246,10 +232,10 @@ void
dynrelocsym(Sym *s) dynrelocsym(Sym *s)
{ {
Reloc *r; Reloc *r;
if(HEADTYPE == Hwindows) { if(HEADTYPE == Hwindows) {
Sym *rel, *targ; Sym *rel, *targ;
rel = lookup(".rel", 0); rel = lookup(".rel", 0);
if(s == rel) if(s == rel)
return; return;
...@@ -259,7 +245,7 @@ dynrelocsym(Sym *s) ...@@ -259,7 +245,7 @@ dynrelocsym(Sym *s)
targ->plt = rel->size; targ->plt = rel->size;
r->sym = rel; r->sym = rel;
r->add = targ->plt; r->add = targ->plt;
// jmp *addr // jmp *addr
if(thechar == '8') { if(thechar == '8') {
adduint8(rel, 0xff); adduint8(rel, 0xff);
...@@ -291,7 +277,7 @@ void ...@@ -291,7 +277,7 @@ void
dynreloc(void) dynreloc(void)
{ {
Sym *s; Sym *s;
// -d supresses dynamic loader format, so we may as well not // -d supresses dynamic loader format, so we may as well not
// compute these sections or mark their symbols as reachable. // compute these sections or mark their symbols as reachable.
if(debug['d'] && HEADTYPE != Hwindows) if(debug['d'] && HEADTYPE != Hwindows)
...@@ -364,12 +350,12 @@ savedata(Sym *s, Prog *p, char *pn) ...@@ -364,12 +350,12 @@ savedata(Sym *s, Prog *p, char *pn)
break; break;
} }
break; break;
case D_SCONST: case D_SCONST:
for(i=0; i<siz; i++) for(i=0; i<siz; i++)
s->p[off+i] = p->to.scon[i]; s->p[off+i] = p->to.scon[i];
break; break;
case D_CONST: case D_CONST:
if(p->to.sym) if(p->to.sym)
goto Addr; goto Addr;
...@@ -450,12 +436,12 @@ blk(Sym *start, int32 addr, int32 size) ...@@ -450,12 +436,12 @@ blk(Sym *start, int32 addr, int32 size)
errorexit(); errorexit();
} }
} }
for(; addr < eaddr; addr++) for(; addr < eaddr; addr++)
cput(0); cput(0);
cflush(); cflush();
} }
void void
codeblk(int32 addr, int32 size) codeblk(int32 addr, int32 size)
{ {
...@@ -498,7 +484,7 @@ codeblk(int32 addr, int32 size) ...@@ -498,7 +484,7 @@ codeblk(int32 addr, int32 size)
Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name); Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name);
n = sym->size; n = sym->size;
q = sym->p; q = sym->p;
while(n >= 16) { while(n >= 16) {
Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q); Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q);
addr += 16; addr += 16;
...@@ -510,7 +496,7 @@ codeblk(int32 addr, int32 size) ...@@ -510,7 +496,7 @@ codeblk(int32 addr, int32 size)
addr += n; addr += n;
continue; continue;
} }
Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p); Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p);
for(p = p->link; p != P; p = p->link) { for(p = p->link; p != P; p = p->link) {
if(p->link != P) if(p->link != P)
...@@ -532,7 +518,7 @@ codeblk(int32 addr, int32 size) ...@@ -532,7 +518,7 @@ codeblk(int32 addr, int32 size)
} }
Bflush(&bso); Bflush(&bso);
} }
void void
datblk(int32 addr, int32 size) datblk(int32 addr, int32 size)
{ {
...@@ -595,7 +581,7 @@ addstrdata(char *name, char *value) ...@@ -595,7 +581,7 @@ addstrdata(char *name, char *value)
{ {
Sym *s, *sp; Sym *s, *sp;
char *p; char *p;
p = smprint("%s.str", name); p = smprint("%s.str", name);
sp = lookup(p, 0); sp = lookup(p, 0);
free(p); free(p);
...@@ -775,7 +761,7 @@ addpcrelplus(Sym *s, Sym *t, int32 add) ...@@ -775,7 +761,7 @@ addpcrelplus(Sym *s, Sym *t, int32 add)
{ {
vlong i; vlong i;
Reloc *r; Reloc *r;
if(s->type == 0) if(s->type == 0)
s->type = SDATA; s->type = SDATA;
s->reachable = 1; s->reachable = 1;
...@@ -972,7 +958,7 @@ dodata(void) ...@@ -972,7 +958,7 @@ dodata(void)
* symbol, which is itself data. * symbol, which is itself data.
*/ */
dynreloc(); dynreloc();
/* some symbols may no longer belong in datap (Mach-O) */ /* some symbols may no longer belong in datap (Mach-O) */
for(l=&datap; (s=*l) != nil; ) { for(l=&datap; (s=*l) != nil; ) {
if(s->type <= STEXT || SXREF <= s->type) if(s->type <= STEXT || SXREF <= s->type)
...@@ -1099,7 +1085,7 @@ dodata(void) ...@@ -1099,7 +1085,7 @@ dodata(void)
} }
sect->len = datsize - sect->vaddr; sect->len = datsize - sect->vaddr;
datsize = rnd(datsize, PtrSize); datsize = rnd(datsize, PtrSize);
/* gcdata */ /* gcdata */
sect = addsection(&segtext, ".gcdata", 04); sect = addsection(&segtext, ".gcdata", 04);
sect->vaddr = datsize; sect->vaddr = datsize;
...@@ -1169,7 +1155,7 @@ textaddress(void) ...@@ -1169,7 +1155,7 @@ textaddress(void)
addsection(&segtext, ".text", 05); addsection(&segtext, ".text", 05);
// Assign PCs in text segment. // Assign PCs in text segment.
// Could parallelize, by assigning to text // Could parallelize, by assigning to text
// and then letting threads copy down, but probably not worth it. // and then letting threads copy down, but probably not worth it.
sect = segtext.sect; sect = segtext.sect;
va = INITTEXT; va = INITTEXT;
...@@ -1192,7 +1178,7 @@ textaddress(void) ...@@ -1192,7 +1178,7 @@ textaddress(void)
} }
va += sym->size; va += sym->size;
} }
// Align end of code so that rodata starts aligned. // Align end of code so that rodata starts aligned.
// 128 bytes is likely overkill but definitely cheap. // 128 bytes is likely overkill but definitely cheap.
va = rnd(va, 128); va = rnd(va, 128);
...@@ -1267,7 +1253,7 @@ address(void) ...@@ -1267,7 +1253,7 @@ address(void)
for(sub = sym->sub; sub != nil; sub = sub->sub) for(sub = sym->sub; sub != nil; sub = sub->sub)
sub->value += sym->value; sub->value += sym->value;
} }
xdefine("text", STEXT, text->vaddr); xdefine("text", STEXT, text->vaddr);
xdefine("etext", STEXT, text->vaddr + text->len); xdefine("etext", STEXT, text->vaddr + text->len);
xdefine("rodata", SRODATA, rodata->vaddr); xdefine("rodata", SRODATA, rodata->vaddr);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
enum enum
{ {
Sxxx, Sxxx,
/* order here is order in output file */ /* order here is order in output file */
STEXT, STEXT,
SMACHOPLT, SMACHOPLT,
...@@ -246,12 +246,6 @@ struct Endian ...@@ -246,12 +246,6 @@ struct Endian
extern Endian be, le; extern Endian be, le;
// relocation size bits
enum {
Rbig = 128,
Rlittle = 64,
};
/* set by call to mywhatsys() */ /* set by call to mywhatsys() */
extern char* goroot; extern char* goroot;
extern char* goarch; extern char* goarch;
......
...@@ -199,7 +199,7 @@ static void ...@@ -199,7 +199,7 @@ static void
slputb(int32 v) slputb(int32 v)
{ {
uchar *p; uchar *p;
symgrow(symt, symt->size+4); symgrow(symt, symt->size+4);
p = symt->p + symt->size; p = symt->p + symt->size;
*p++ = v>>24; *p++ = v>>24;
...@@ -209,6 +209,22 @@ slputb(int32 v) ...@@ -209,6 +209,22 @@ slputb(int32 v)
symt->size += 4; symt->size += 4;
} }
static void
slputl(int32 v)
{
uchar *p;
symgrow(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 void
wputl(ushort w) wputl(ushort w)
{ {
...@@ -269,15 +285,24 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ) ...@@ -269,15 +285,24 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
// l = 8; // l = 8;
if(s != nil) { if(s != nil) {
rel = addrel(symt); rel = addrel(symt);
rel->siz = l + Rbig; rel->siz = l;
rel->sym = s; rel->sym = s;
rel->type = D_ADDR; rel->type = D_ADDR;
rel->off = symt->size; rel->off = symt->size;
v = 0; v = 0;
} }
if(l == 8)
slputb(v>>32); if(l == 8) {
slputb(v); if(slput == slputl) {
slputl(v);
slputl(v>>32);
} else {
slputb(v>>32);
slputb(v);
}
} else
slput(v);
if(ver) if(ver)
t += 'a' - 'A'; t += 'a' - 'A';
scput(t+0x80); /* 0x80 is variable length */ scput(t+0x80); /* 0x80 is variable length */
...@@ -306,8 +331,8 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ) ...@@ -306,8 +331,8 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
rel->off = symt->size; rel->off = symt->size;
} }
if(l == 8) if(l == 8)
slputb(0); slput(0);
slputb(0); slput(0);
if(debug['n']) { if(debug['n']) {
if(t == 'z' || t == 'Z') { if(t == 'z' || t == 'Z') {
...@@ -356,7 +381,7 @@ symtab(void) ...@@ -356,7 +381,7 @@ symtab(void)
xdefine("end", SBSS, 0); xdefine("end", SBSS, 0);
xdefine("epclntab", SRODATA, 0); xdefine("epclntab", SRODATA, 0);
xdefine("esymtab", SRODATA, 0); xdefine("esymtab", SRODATA, 0);
// pseudo-symbols to mark locations of type, string, and go string data. // pseudo-symbols to mark locations of type, string, and go string data.
s = lookup("type.*", 0); s = lookup("type.*", 0);
s->type = STYPE; s->type = STYPE;
...@@ -372,7 +397,7 @@ symtab(void) ...@@ -372,7 +397,7 @@ symtab(void)
symt->type = SSYMTAB; symt->type = SSYMTAB;
symt->size = 0; symt->size = 0;
symt->reachable = 1; symt->reachable = 1;
// assign specific types so that they sort together. // assign specific types so that they sort together.
// within a type they sort by size, so the .* symbols // within a type they sort by size, so the .* symbols
// just defined above will be first. // just defined above will be first.
...@@ -396,5 +421,25 @@ symtab(void) ...@@ -396,5 +421,25 @@ symtab(void)
if(debug['s']) if(debug['s'])
return; return;
switch(thechar) {
default:
diag("unknown architecture %c", thechar);
errorexit();
case '5':
case '6':
case '8':
// magic entry to denote little-endian symbol table
slputl(0xfffffffe);
scput(0);
scput(0);
slput = slputl;
break;
case 'v':
// big-endian (in case one comes along)
slput = slputb;
break;
}
genasmsym(putsymb); genasmsym(putsymb);
} }
// Inferno libmach/sym.c // Inferno libmach/sym.c
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/sym.c // http://code.google.com/p/inferno-os/source/browse/utils/libmach/sym.c
// //
// Copyright © 1994-1999 Lucent Technologies Inc. // Copyright © 1994-1999 Lucent Technologies Inc.
// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net). // Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
// Portions Copyright © 1997-1999 Vita Nuova Limited. // Portions Copyright © 1997-1999 Vita Nuova Limited.
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others. // Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
// Portions Copyright © 2009 The Go Authors. All rights reserved. // Portions Copyright © 2009 The Go Authors. All rights reserved.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
...@@ -113,12 +113,18 @@ syminit(int fd, Fhdr *fp) ...@@ -113,12 +113,18 @@ syminit(int fd, Fhdr *fp)
vlong vl; vlong vl;
Biobuf b; Biobuf b;
int svalsz; int svalsz;
uvlong (*swav)(uvlong);
uint32 (*swal)(uint32);
uchar buf[6];
if(fp->symsz == 0) if(fp->symsz == 0)
return 0; return 0;
if(fp->type == FNONE) if(fp->type == FNONE)
return 0; return 0;
swav = beswav;
swal = beswal;
cleansyms(); cleansyms();
textseg(fp->txtaddr, fp); textseg(fp->txtaddr, fp);
/* minimum symbol record size = 4+1+2 bytes */ /* minimum symbol record size = 4+1+2 bytes */
...@@ -129,6 +135,15 @@ syminit(int fd, Fhdr *fp) ...@@ -129,6 +135,15 @@ syminit(int fd, Fhdr *fp)
} }
Binit(&b, fd, OREAD); Binit(&b, fd, OREAD);
Bseek(&b, fp->symoff, 0); Bseek(&b, fp->symoff, 0);
memset(buf, 0, sizeof buf);
Bread(&b, buf, sizeof buf);
if(memcmp(buf, "\xfe\xff\xff\xff\x00\x00", 6) == 0) {
swav = leswav;
swal = leswal;
} else {
Bseek(&b, fp->symoff, 0);
}
nsym = 0; nsym = 0;
size = 0; size = 0;
for(p = symbols; size < fp->symsz; p++, nsym++) { for(p = symbols; size < fp->symsz; p++, nsym++) {
...@@ -136,13 +151,13 @@ syminit(int fd, Fhdr *fp) ...@@ -136,13 +151,13 @@ syminit(int fd, Fhdr *fp)
svalsz = 8; svalsz = 8;
if(Bread(&b, &vl, 8) != 8) if(Bread(&b, &vl, 8) != 8)
return symerrmsg(8, "symbol"); return symerrmsg(8, "symbol");
p->value = beswav(vl); p->value = swav(vl);
} }
else{ else{
svalsz = 4; svalsz = 4;
if(Bread(&b, &l, 4) != 4) if(Bread(&b, &l, 4) != 4)
return symerrmsg(4, "symbol"); return symerrmsg(4, "symbol");
p->value = (u32int)beswal(l); p->value = (u32int)swal(l);
} }
if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type)) if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
return symerrmsg(sizeof(p->value), "symbol"); return symerrmsg(sizeof(p->value), "symbol");
...@@ -155,12 +170,12 @@ syminit(int fd, Fhdr *fp) ...@@ -155,12 +170,12 @@ syminit(int fd, Fhdr *fp)
if(svalsz == 8){ if(svalsz == 8){
if(Bread(&b, &vl, 8) != 8) if(Bread(&b, &vl, 8) != 8)
return symerrmsg(8, "symbol"); return symerrmsg(8, "symbol");
p->gotype = beswav(vl); p->gotype = swav(vl);
} }
else{ else{
if(Bread(&b, &l, 4) != 4) if(Bread(&b, &l, 4) != 4)
return symerrmsg(4, "symbol"); return symerrmsg(4, "symbol");
p->gotype = (u32int)beswal(l); p->gotype = (u32int)swal(l);
} }
size += svalsz; size += svalsz;
......
...@@ -129,7 +129,7 @@ func TestLineFromAline(t *testing.T) { ...@@ -129,7 +129,7 @@ func TestLineFromAline(t *testing.T) {
if !ok { if !ok {
t.Errorf("file %s starts on line %d", path, line) t.Errorf("file %s starts on line %d", path, line)
} else if line != ll+1 { } else if line != ll+1 {
t.Errorf("expected next line of file %s to be %d, got %d", path, ll+1, line) t.Fatalf("expected next line of file %s to be %d, got %d", path, ll+1, line)
} }
lastline[path] = line lastline[path] = line
} }
......
...@@ -13,6 +13,7 @@ package gosym ...@@ -13,6 +13,7 @@ package gosym
// and the Go format is the runtime source, specifically ../../runtime/symtab.c. // and the Go format is the runtime source, specifically ../../runtime/symtab.c.
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"strconv" "strconv"
...@@ -104,11 +105,18 @@ type sym struct { ...@@ -104,11 +105,18 @@ type sym struct {
name []byte name []byte
} }
var littleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00}
func walksymtab(data []byte, fn func(sym) error) error { func walksymtab(data []byte, fn func(sym) error) error {
var order binary.ByteOrder = binary.BigEndian
if bytes.HasPrefix(data, littleEndianSymtab) {
data = data[6:]
order = binary.LittleEndian
}
var s sym var s sym
p := data p := data
for len(p) >= 6 { for len(p) >= 6 {
s.value = binary.BigEndian.Uint32(p[0:4]) s.value = order.Uint32(p[0:4])
typ := p[4] typ := p[4]
if typ&0x80 == 0 { if typ&0x80 == 0 {
return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ} return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ}
...@@ -139,7 +147,7 @@ func walksymtab(data []byte, fn func(sym) error) error { ...@@ -139,7 +147,7 @@ func walksymtab(data []byte, fn func(sym) error) error {
} }
s.name = p[0:i] s.name = p[0:i]
i += nnul i += nnul
s.gotype = binary.BigEndian.Uint32(p[i : i+4]) s.gotype = order.Uint32(p[i : i+4])
p = p[i+4:] p = p[i+4:]
fn(s) fn(s)
} }
......
...@@ -40,13 +40,26 @@ walksymtab(void (*fn)(Sym*)) ...@@ -40,13 +40,26 @@ walksymtab(void (*fn)(Sym*))
{ {
byte *p, *ep, *q; byte *p, *ep, *q;
Sym s; Sym s;
int32 bigend;
p = symtab; p = symtab;
ep = esymtab; ep = esymtab;
// Default is big-endian value encoding.
// If table begins fe ff ff ff 00 00, little-endian.
bigend = 1;
if(symtab[0] == 0xfe && symtab[1] == 0xff && symtab[2] == 0xff && symtab[3] == 0xff && symtab[4] == 0x00 && symtab[5] == 0x00) {
p += 6;
bigend = 0;
}
while(p < ep) { while(p < ep) {
if(p + 7 > ep) if(p + 7 > ep)
break; break;
s.value = ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]);
if(bigend)
s.value = ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]);
else
s.value = ((uint32)p[3]<<24) | ((uint32)p[2]<<16) | ((uint32)p[1]<<8) | ((uint32)p[0]);
if(!(p[4]&0x80)) if(!(p[4]&0x80))
break; break;
...@@ -304,7 +317,7 @@ splitpcln(void) ...@@ -304,7 +317,7 @@ splitpcln(void)
line += *p++; line += *p++;
else else
line -= *p++ - 64; line -= *p++ - 64;
// pc, line now match. // pc, line now match.
// Because the state machine begins at pc==entry and line==0, // Because the state machine begins at pc==entry and line==0,
// it can happen - just at the beginning! - that the update may // it can happen - just at the beginning! - that the update may
...@@ -326,7 +339,7 @@ splitpcln(void) ...@@ -326,7 +339,7 @@ splitpcln(void)
while(f < ef && pc >= (f+1)->entry); while(f < ef && pc >= (f+1)->entry);
f->pcln.array = p; f->pcln.array = p;
// pc0 and ln0 are the starting values for // pc0 and ln0 are the starting values for
// the loop over f->pcln, so pc must be // the loop over f->pcln, so pc must be
// adjusted by the same pcquant update // adjusted by the same pcquant update
// that we're going to do as we continue our loop. // that we're going to do as we continue our loop.
f->pc0 = pc + pcquant; f->pc0 = pc + pcquant;
...@@ -352,11 +365,11 @@ runtime·funcline(Func *f, uintptr targetpc) ...@@ -352,11 +365,11 @@ runtime·funcline(Func *f, uintptr targetpc)
uintptr pc; uintptr pc;
int32 line; int32 line;
int32 pcquant; int32 pcquant;
enum { enum {
debug = 0 debug = 0
}; };
switch(thechar) { switch(thechar) {
case '5': case '5':
pcquant = 4; pcquant = 4;
...@@ -383,7 +396,7 @@ runtime·funcline(Func *f, uintptr targetpc) ...@@ -383,7 +396,7 @@ runtime·funcline(Func *f, uintptr targetpc)
if(debug && !runtime·panicking) if(debug && !runtime·panicking)
runtime·printf("pc<%p targetpc=%p line=%d\n", pc, targetpc, line); runtime·printf("pc<%p targetpc=%p line=%d\n", pc, targetpc, line);
// If the pc has advanced too far or we're out of data, // If the pc has advanced too far or we're out of data,
// stop and the last known line number. // stop and the last known line number.
if(pc > targetpc || p >= ep) if(pc > targetpc || p >= ep)
...@@ -519,7 +532,7 @@ static bool ...@@ -519,7 +532,7 @@ static bool
hasprefix(String s, int8 *p) hasprefix(String s, int8 *p)
{ {
int32 i; int32 i;
for(i=0; i<s.len; i++) { for(i=0; i<s.len; i++) {
if(p[i] == 0) if(p[i] == 0)
return 1; return 1;
...@@ -533,7 +546,7 @@ static bool ...@@ -533,7 +546,7 @@ static bool
contains(String s, int8 *p) contains(String s, int8 *p)
{ {
int32 i; int32 i;
if(p[0] == 0) if(p[0] == 0)
return 1; return 1;
for(i=0; i<s.len; i++) { for(i=0; i<s.len; i++) {
...@@ -549,7 +562,7 @@ bool ...@@ -549,7 +562,7 @@ bool
runtime·showframe(Func *f) runtime·showframe(Func *f)
{ {
static int32 traceback = -1; static int32 traceback = -1;
if(traceback < 0) if(traceback < 0)
traceback = runtime·gotraceback(); traceback = runtime·gotraceback();
return traceback > 1 || contains(f->name, ".") && !hasprefix(f->name, "runtime."); return traceback > 1 || contains(f->name, ".") && !hasprefix(f->name, "runtime.");
......
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