github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/traceback_arm.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "runtime.h" 6 #include "arch_GOARCH.h" 7 #include "malloc.h" 8 9 void runtime·deferproc(void); 10 void runtime·newproc(void); 11 void runtime·newstack(void); 12 void runtime·morestack(void); 13 void runtime·sigpanic(void); 14 void _div(void); 15 void _mod(void); 16 void _divu(void); 17 void _modu(void); 18 19 int32 20 runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*fn)(Func*, byte*, byte*, void*), void *arg) 21 { 22 int32 i, n; 23 uintptr pc, lr, tracepc, x; 24 byte *fp; 25 bool waspanic; 26 Stktop *stk; 27 Func *f; 28 29 pc = (uintptr)pc0; 30 lr = (uintptr)lr0; 31 fp = nil; 32 waspanic = false; 33 34 // If the PC is goexit, the goroutine hasn't started yet. 35 if(pc == (uintptr)runtime·goexit && gp->fnstart != nil) { 36 pc = (uintptr)gp->fnstart->fn; 37 lr = (uintptr)runtime·goexit; 38 } 39 40 // If the PC is zero, it's likely a nil function call. 41 // Start in the caller's frame. 42 if(pc == 0) { 43 pc = lr; 44 lr = 0; 45 } 46 47 n = 0; 48 stk = (Stktop*)gp->stackbase; 49 while(n < max) { 50 // Typically: 51 // pc is the PC of the running function. 52 // sp is the stack pointer at that program counter. 53 // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown. 54 // stk is the stack containing sp. 55 // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp. 56 57 if(pc == (uintptr)runtime·lessstack) { 58 // Hit top of stack segment. Unwind to next segment. 59 pc = (uintptr)stk->gobuf.pc; 60 sp = (byte*)stk->gobuf.sp; 61 lr = 0; 62 fp = nil; 63 if(pcbuf == nil && fn == nil && runtime·showframe(nil, gp == m->curg)) 64 runtime·printf("----- stack segment boundary -----\n"); 65 stk = (Stktop*)stk->stackbase; 66 continue; 67 } 68 69 if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) { 70 if(fn != nil) 71 runtime·throw("unknown pc"); 72 break; 73 } 74 75 // Found an actual function. 76 if(lr == 0) 77 lr = *(uintptr*)sp; 78 if(fp == nil) { 79 fp = sp; 80 if(pc > f->entry && f->frame >= sizeof(uintptr)) 81 fp += f->frame - sizeof(uintptr); 82 fp += sizeof(uintptr); 83 } 84 85 if(skip > 0) 86 skip--; 87 else if(pcbuf != nil) 88 pcbuf[n++] = pc; 89 else if(fn != nil) 90 (*fn)(f, (byte*)pc, sp, arg); 91 else { 92 if(runtime·showframe(f, gp == m->curg)) { 93 // Print during crash. 94 // main(0x1, 0x2, 0x3) 95 // /home/rsc/go/src/runtime/x.go:23 +0xf 96 tracepc = pc; // back up to CALL instruction for funcline. 97 if(n > 0 && pc > f->entry && !waspanic) 98 tracepc -= sizeof(uintptr); 99 if(m->throwing && gp == m->curg) 100 runtime·printf("[fp=%p] ", fp); 101 runtime·printf("%S(", f->name); 102 for(i = 0; i < f->args/sizeof(uintptr); i++) { 103 if(i != 0) 104 runtime·prints(", "); 105 runtime·printhex(((uintptr*)fp)[1+i]); 106 if(i >= 4) { 107 runtime·prints(", ..."); 108 break; 109 } 110 } 111 runtime·prints(")\n"); 112 runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); 113 if(pc > f->entry) 114 runtime·printf(" +%p", (uintptr)(pc - f->entry)); 115 runtime·printf("\n"); 116 } 117 n++; 118 } 119 120 waspanic = f->entry == (uintptr)runtime·sigpanic; 121 122 if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·newstack && gp == m->g0) { 123 runtime·printf("----- newstack called from goroutine %D -----\n", m->curg->goid); 124 pc = (uintptr)m->morepc; 125 sp = (byte*)m->moreargp - sizeof(void*); 126 lr = (uintptr)m->morebuf.pc; 127 fp = (byte*)m->morebuf.sp; 128 gp = m->curg; 129 stk = (Stktop*)gp->stackbase; 130 continue; 131 } 132 133 if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) { 134 runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid); 135 gp = m->curg; 136 stk = (Stktop*)gp->stackbase; 137 sp = (byte*)stk->gobuf.sp; 138 pc = (uintptr)stk->gobuf.pc; 139 fp = nil; 140 lr = 0; 141 continue; 142 } 143 144 // Do not unwind past the bottom of the stack. 145 if(pc == (uintptr)runtime·goexit) 146 break; 147 148 // Unwind to next frame. 149 pc = lr; 150 lr = 0; 151 sp = fp; 152 fp = nil; 153 154 // If this was div or divu or mod or modu, the caller had 155 // an extra 8 bytes on its stack. Adjust sp. 156 if(f->entry == (uintptr)_div || f->entry == (uintptr)_divu || f->entry == (uintptr)_mod || f->entry == (uintptr)_modu) 157 sp += 8; 158 159 // If this was deferproc or newproc, the caller had an extra 12. 160 if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc) 161 sp += 12; 162 163 // sighandler saves the lr on stack before faking a call to sigpanic 164 if(waspanic) { 165 x = *(uintptr *)sp; 166 sp += 4; 167 f = runtime·findfunc(pc); 168 if (f == nil) { 169 pc = x; 170 } else if (f->frame == 0) 171 lr = x; 172 } 173 } 174 175 if(pcbuf == nil && fn == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil 176 && runtime·showframe(f, gp == m->curg) && gp->goid != 1) { 177 runtime·printf("created by %S\n", f->name); 178 tracepc = pc; // back up to CALL instruction for funcline. 179 if(n > 0 && pc > f->entry) 180 tracepc -= sizeof(uintptr); 181 runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); 182 if(pc > f->entry) 183 runtime·printf(" +%p", (uintptr)(pc - f->entry)); 184 runtime·printf("\n"); 185 } 186 187 return n; 188 } 189 190 void 191 runtime·traceback(byte *pc0, byte *sp, byte *lr, G *gp) 192 { 193 if(gp->status == Gsyscall) { 194 // Override signal registers if blocked in system call. 195 pc0 = gp->sched.pc; 196 sp = (byte*)gp->sched.sp; 197 lr = nil; 198 } 199 runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100, nil, nil); 200 } 201 202 // func caller(n int) (pc uintptr, file string, line int, ok bool) 203 int32 204 runtime·callers(int32 skip, uintptr *pcbuf, int32 m) 205 { 206 byte *pc, *sp; 207 208 sp = runtime·getcallersp(&skip); 209 pc = runtime·getcallerpc(&skip); 210 211 return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil); 212 }