runtime: handle non-standard call sequences in arm traceback

R=r
CC=golang-dev
https://golang.org/cl/4191048
This commit is contained in:
Russ Cox 2011-02-18 13:30:29 -05:00
parent f07a45f23d
commit 7081e67565

View file

@ -9,6 +9,10 @@ void runtime·deferproc(void);
void runtime·newproc(void);
void runtime·newstack(void);
void runtime·morestack(void);
void _div(void);
void _mod(void);
void _divu(void);
void _modu(void);
static int32
gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
@ -113,7 +117,7 @@ gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, i
// Print during crash.
// main+0xf /home/rsc/go/src/runtime/x.go:23
// main(0x1, 0x2, 0x3)
runtime·printf("%S", f->name);
runtime·printf("[%p] %S", fp, f->name);
if(pc > f->entry)
runtime·printf("+%p", (uintptr)(pc - f->entry));
tracepc = pc; // back up to CALL instruction for funcline.
@ -150,6 +154,15 @@ gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, i
lr = 0;
sp = fp;
fp = nil;
// If this was div or divu or mod or modu, the caller had
// an extra 8 bytes on its stack. Adjust sp.
if(f->entry == (uintptr)_div || f->entry == (uintptr)_divu || f->entry == (uintptr)_mod || f->entry == (uintptr)_modu)
sp += 8;
// If this was deferproc or newproc, the caller had an extra 12.
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
sp += 12;
}
return n;
}