aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/traceback_arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/traceback_arm.c')
-rw-r--r--src/pkg/runtime/traceback_arm.c96
1 files changed, 57 insertions, 39 deletions
diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c
index e5a475f80f..6cd924da0d 100644
--- a/src/pkg/runtime/traceback_arm.c
+++ b/src/pkg/runtime/traceback_arm.c
@@ -6,30 +6,21 @@
#include "arch_GOARCH.h"
#include "malloc.h"
-void runtime·deferproc(void);
-void runtime·newproc(void);
-void runtime·morestack(void);
void runtime·sigpanic(void);
-void _div(void);
-void _mod(void);
-void _divu(void);
-void _modu(void);
static String unknown = { (uint8*)"?", 1 };
int32
runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*callback)(Stkframe*, void*), void *v, bool printall)
{
- int32 i, n, nprint, skip0, line;
+ int32 i, n, nprint, line;
uintptr x, tracepc;
bool waspanic, printing;
- Func *f, *f2;
+ Func *f, *flr;
Stkframe frame;
Stktop *stk;
String file;
- skip0 = skip;
-
nprint = 0;
runtime·memclr((byte*)&frame, sizeof frame);
frame.pc = pc0;
@@ -44,6 +35,16 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.pc = frame.lr;
frame.lr = 0;
}
+
+ f = runtime·findfunc(frame.pc);
+ if(f == nil) {
+ if(callback != nil) {
+ runtime·printf("runtime: unknown pc %p\n", frame.pc);
+ runtime·throw("unknown pc");
+ }
+ return 0;
+ }
+ frame.fn = f;
n = 0;
stk = (Stktop*)gp->stackbase;
@@ -64,41 +65,57 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
if(printing && runtime·showframe(nil, gp))
runtime·printf("----- stack segment boundary -----\n");
stk = (Stktop*)stk->stackbase;
- continue;
- }
-
- if(frame.pc <= 0x1000 || (frame.fn = f = runtime·findfunc(frame.pc)) == nil) {
- if(callback != nil) {
- runtime·printf("runtime: unknown pc %p at frame %d\n", frame.pc, skip0-skip+n);
- runtime·throw("invalid stack");
+
+ f = runtime·findfunc(frame.pc);
+ if(f == nil) {
+ runtime·printf("runtime: unknown pc %p after stack split\n", frame.pc);
+ runtime·throw("unknown pc");
}
- break;
+ frame.fn = f;
+ continue;
}
+ f = frame.fn;
// Found an actual function.
// Derive frame pointer and link register.
- if(frame.lr == 0)
- frame.lr = *(uintptr*)frame.sp;
if(frame.fp == 0)
frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc);
-
+ if(runtime·topofstack(f)) {
+ frame.lr = 0;
+ flr = nil;
+ } else {
+ if(frame.lr == 0)
+ frame.lr = *(uintptr*)frame.sp;
+ flr = runtime·findfunc(frame.lr);
+ if(flr == nil) {
+ runtime·printf("runtime: unexpected return pc for %S called from %p", *f->name, frame.lr);
+ runtime·throw("unknown caller pc");
+ }
+ }
+
// Derive size of arguments.
- frame.argp = (byte*)frame.fp + sizeof(uintptr);
- frame.arglen = 0;
- if(f->args != ArgsSizeUnknown)
- frame.arglen = f->args;
- else if(runtime·haszeroargs(f->entry))
- frame.arglen = 0;
- else if(frame.lr == (uintptr)runtime·lessstack)
- frame.arglen = stk->argsize;
- else if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
- frame.arglen = 3*sizeof(uintptr) + *(int32*)frame.argp;
- else if((f2 = runtime·findfunc(frame.lr)) != nil && f2->frame >= sizeof(uintptr))
- frame.arglen = f2->frame; // conservative overestimate
- else {
- runtime·printf("runtime: unknown argument frame size for %S\n", *f->name);
- if(!printing)
- runtime·throw("invalid stack");
+ // Most functions have a fixed-size argument block,
+ // so we can use metadata about the function f.
+ // Not all, though: there are some variadic functions
+ // in package runtime, and for those we use call-specific
+ // metadata recorded by f's caller.
+ if(callback != nil || printing) {
+ frame.argp = (byte*)frame.fp + sizeof(uintptr);
+ if(f->args != ArgsSizeUnknown)
+ frame.arglen = f->args;
+ else if(flr == nil)
+ frame.arglen = 0;
+ else if(frame.lr == (uintptr)runtime·lessstack)
+ frame.arglen = stk->argsize;
+ else if((i = runtime·funcarglen(flr, frame.lr)) >= 0)
+ frame.arglen = i;
+ else {
+ runtime·printf("runtime: unknown argument frame size for %S called from %p [%S]\n",
+ *f->name, frame.lr, flr ? *flr->name : unknown);
+ if(!printing)
+ runtime·throw("invalid stack");
+ frame.arglen = 0;
+ }
}
// Derive location and size of local variables.
@@ -165,11 +182,12 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
waspanic = f->entry == (uintptr)runtime·sigpanic;
// Do not unwind past the bottom of the stack.
- if(f->entry == (uintptr)runtime·goexit || f->entry == (uintptr)runtime·mstart || f->entry == (uintptr)runtime·mcall || f->entry == (uintptr)_rt0_go)
+ if(flr == nil)
break;
// Unwind to next frame.
frame.pc = frame.lr;
+ frame.fn = flr;
frame.lr = 0;
frame.sp = frame.fp;
frame.fp = 0;