summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-04-16 17:11:44 -0400
committerRuss Cox <rsc@golang.org>2014-04-16 17:11:44 -0400
commitbc23140a4fe44718db247cb32d3f7ffa86235219 (patch)
treecaf87ecd56781f1496724fbd3e8b0b168da8cb22
parentc82b4a7bf263130588b8b235850d8d1f4057afc5 (diff)
downloadgo-bc23140a4fe44718db247cb32d3f7ffa86235219.tar.gz
liblink: add leaf bit to object file format
Without the leaf bit, the linker cannot record the correct frame size in the symbol table, and then stack traces get mangled. (Only for ARM.) Fixes issue 7338. Fixes issue 7347. LGTM=iant R=iant CC=golang-codereviews https://codereview.appspot.com/88550043
-rw-r--r--src/cmd/ld/pcln.c7
-rw-r--r--src/cmd/link/testdata/autosection.6bin888 -> 889 bytes
-rw-r--r--src/cmd/link/testdata/autoweak.6bin425 -> 426 bytes
-rw-r--r--src/cmd/link/testdata/dead.6bin1054 -> 1060 bytes
-rw-r--r--src/cmd/link/testdata/hello.6bin271 -> 272 bytes
-rw-r--r--src/cmd/link/testdata/layout.6bin429 -> 430 bytes
-rw-r--r--src/cmd/link/testdata/pclntab.6bin4603 -> 4607 bytes
-rw-r--r--src/liblink/objfile.c8
-rw-r--r--src/pkg/debug/goobj/read.go2
9 files changed, 14 insertions, 3 deletions
diff --git a/src/cmd/ld/pcln.c b/src/cmd/ld/pcln.c
index bdb139f7a..b2370f2a9 100644
--- a/src/cmd/ld/pcln.c
+++ b/src/cmd/ld/pcln.c
@@ -112,7 +112,7 @@ pclntab(void)
{
int32 i, nfunc, start, funcstart;
LSym *ftab, *s;
- int32 off, end;
+ int32 off, end, frameptrsize;
int64 funcdata_bytes;
Pcln *pcln;
Pciter it;
@@ -173,7 +173,10 @@ pclntab(void)
// when a called function doesn't have argument information.
// We need to make sure everything has argument information
// and then remove this.
- off = setuint32(ctxt, ftab, off, ctxt->cursym->locals + PtrSize);
+ frameptrsize = PtrSize;
+ if(ctxt->cursym->leaf)
+ frameptrsize = 0;
+ off = setuint32(ctxt, ftab, off, ctxt->cursym->locals + frameptrsize);
if(pcln != &zpcln) {
renumberfiles(pcln->file, pcln->nfile, &pcln->pcfile);
diff --git a/src/cmd/link/testdata/autosection.6 b/src/cmd/link/testdata/autosection.6
index 3a2e35a5b..f392e4168 100644
--- a/src/cmd/link/testdata/autosection.6
+++ b/src/cmd/link/testdata/autosection.6
Binary files differ
diff --git a/src/cmd/link/testdata/autoweak.6 b/src/cmd/link/testdata/autoweak.6
index 1fd54ed7e..a694e4729 100644
--- a/src/cmd/link/testdata/autoweak.6
+++ b/src/cmd/link/testdata/autoweak.6
Binary files differ
diff --git a/src/cmd/link/testdata/dead.6 b/src/cmd/link/testdata/dead.6
index e0cdecea9..270416f0b 100644
--- a/src/cmd/link/testdata/dead.6
+++ b/src/cmd/link/testdata/dead.6
Binary files differ
diff --git a/src/cmd/link/testdata/hello.6 b/src/cmd/link/testdata/hello.6
index 9ec799b4f..448d40f76 100644
--- a/src/cmd/link/testdata/hello.6
+++ b/src/cmd/link/testdata/hello.6
Binary files differ
diff --git a/src/cmd/link/testdata/layout.6 b/src/cmd/link/testdata/layout.6
index c5121ff15..56d416a1a 100644
--- a/src/cmd/link/testdata/layout.6
+++ b/src/cmd/link/testdata/layout.6
Binary files differ
diff --git a/src/cmd/link/testdata/pclntab.6 b/src/cmd/link/testdata/pclntab.6
index 0f7ab6dd7..91583a3fd 100644
--- a/src/cmd/link/testdata/pclntab.6
+++ b/src/cmd/link/testdata/pclntab.6
Binary files differ
diff --git a/src/liblink/objfile.c b/src/liblink/objfile.c
index b52b29ca5..0c51e795f 100644
--- a/src/liblink/objfile.c
+++ b/src/liblink/objfile.c
@@ -49,6 +49,7 @@
//
// - args [int]
// - locals [int]
+// - leaf [int]
// - nlocal [int]
// - local [nlocal automatics]
// - pcln [pcln table]
@@ -291,8 +292,11 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
if(s->dupok)
Bprint(ctxt->bso, "dupok ");
Bprint(ctxt->bso, "size=%lld value=%lld", (vlong)s->size, (vlong)s->value);
- if(s->type == STEXT)
+ if(s->type == STEXT) {
Bprint(ctxt->bso, " args=%#llux locals=%#llux", (uvlong)s->args, (uvlong)s->locals);
+ if(s->leaf)
+ Bprint(ctxt->bso, " leaf");
+ }
Bprint(ctxt->bso, "\n");
for(p=s->text; p != nil; p = p->link)
Bprint(ctxt->bso, "\t%#06ux %P\n", (int)p->pc, p);
@@ -346,6 +350,7 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
if(s->type == STEXT) {
wrint(b, s->args);
wrint(b, s->locals);
+ wrint(b, s->leaf);
n = 0;
for(a = s->autom; a != nil; a = a->link)
n++;
@@ -566,6 +571,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
if(s->type == STEXT) {
s->args = rdint(f);
s->locals = rdint(f);
+ s->leaf = rdint(f);
n = rdint(f);
for(i=0; i<n; i++) {
a = emallocz(sizeof *a);
diff --git a/src/pkg/debug/goobj/read.go b/src/pkg/debug/goobj/read.go
index 8882eae53..c2e6fa092 100644
--- a/src/pkg/debug/goobj/read.go
+++ b/src/pkg/debug/goobj/read.go
@@ -190,6 +190,7 @@ type Var struct {
type Func struct {
Args int // size in bytes of of argument frame: inputs and outputs
Frame int // size in bytes of local variable frame
+ Leaf bool // function omits save of link register (ARM)
Var []Var // detail about local variables
PCSP Data // PC → SP offset map
PCFile Data // PC → file number map (index into File)
@@ -621,6 +622,7 @@ func (r *objReader) parseObject(prefix []byte) error {
s.Func = f
f.Args = r.readInt()
f.Frame = r.readInt()
+ f.Leaf = r.readInt() != 0
f.Var = make([]Var, r.readInt())
for i := range f.Var {
v := &f.Var[i]