github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 #include "funcdata.h" 9 10 void runtime·sigpanic(void); 11 12 int32 13 runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*callback)(Stkframe*, void*), void *v, bool printall) 14 { 15 int32 i, n, nprint, line; 16 uintptr x, tracepc; 17 bool waspanic, printing; 18 Func *f, *flr; 19 Stkframe frame; 20 Stktop *stk; 21 String file; 22 23 if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp. 24 if(gp->syscallstack != (uintptr)nil) { 25 pc0 = gp->syscallpc; 26 sp0 = gp->syscallsp; 27 lr0 = 0; 28 } else { 29 pc0 = gp->sched.pc; 30 sp0 = gp->sched.sp; 31 lr0 = gp->sched.lr; 32 } 33 } 34 35 nprint = 0; 36 runtime·memclr((byte*)&frame, sizeof frame); 37 frame.pc = pc0; 38 frame.lr = lr0; 39 frame.sp = sp0; 40 waspanic = false; 41 printing = pcbuf==nil && callback==nil; 42 43 // If the PC is zero, it's likely a nil function call. 44 // Start in the caller's frame. 45 if(frame.pc == 0) { 46 frame.pc = frame.lr; 47 frame.lr = 0; 48 } 49 50 f = runtime·findfunc(frame.pc); 51 if(f == nil) { 52 if(callback != nil) { 53 runtime·printf("runtime: unknown pc %p\n", frame.pc); 54 runtime·throw("unknown pc"); 55 } 56 return 0; 57 } 58 frame.fn = f; 59 60 n = 0; 61 stk = (Stktop*)gp->stackbase; 62 while(n < max) { 63 // Typically: 64 // pc is the PC of the running function. 65 // sp is the stack pointer at that program counter. 66 // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown. 67 // stk is the stack containing sp. 68 // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp. 69 70 if(frame.pc == (uintptr)runtime·lessstack) { 71 // Hit top of stack segment. Unwind to next segment. 72 frame.pc = stk->gobuf.pc; 73 frame.sp = stk->gobuf.sp; 74 frame.lr = 0; 75 frame.fp = 0; 76 if(printing && runtime·showframe(nil, gp)) 77 runtime·printf("----- stack segment boundary -----\n"); 78 stk = (Stktop*)stk->stackbase; 79 80 f = runtime·findfunc(frame.pc); 81 if(f == nil) { 82 runtime·printf("runtime: unknown pc %p after stack split\n", frame.pc); 83 if(callback != nil) 84 runtime·throw("unknown pc"); 85 } 86 frame.fn = f; 87 continue; 88 } 89 f = frame.fn; 90 91 // Found an actual function. 92 // Derive frame pointer and link register. 93 if(frame.fp == 0) 94 frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc); 95 if(runtime·topofstack(f)) { 96 frame.lr = 0; 97 flr = nil; 98 } else { 99 if((n == 0 && frame.sp < frame.fp) || frame.lr == 0) 100 frame.lr = *(uintptr*)frame.sp; 101 flr = runtime·findfunc(frame.lr); 102 if(flr == nil) { 103 runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr); 104 if(callback != nil) 105 runtime·throw("unknown caller pc"); 106 } 107 } 108 109 frame.varp = (byte*)frame.fp; 110 111 // Derive size of arguments. 112 // Most functions have a fixed-size argument block, 113 // so we can use metadata about the function f. 114 // Not all, though: there are some variadic functions 115 // in package runtime and reflect, and for those we use call-specific 116 // metadata recorded by f's caller. 117 if(callback != nil || printing) { 118 frame.argp = (byte*)frame.fp + sizeof(uintptr); 119 if(f->args != ArgsSizeUnknown) 120 frame.arglen = f->args; 121 else if(flr == nil) 122 frame.arglen = 0; 123 else if(frame.lr == (uintptr)runtime·lessstack) 124 frame.arglen = stk->argsize; 125 else if((i = runtime·funcarglen(flr, frame.lr)) >= 0) 126 frame.arglen = i; 127 else { 128 runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n", 129 runtime·funcname(f), frame.lr, flr ? runtime·funcname(flr) : "?"); 130 if(callback != nil) 131 runtime·throw("invalid stack"); 132 frame.arglen = 0; 133 } 134 } 135 136 if(skip > 0) { 137 skip--; 138 goto skipped; 139 } 140 141 if(pcbuf != nil) 142 pcbuf[n] = frame.pc; 143 if(callback != nil) 144 callback(&frame, v); 145 if(printing) { 146 if(printall || runtime·showframe(f, gp)) { 147 // Print during crash. 148 // main(0x1, 0x2, 0x3) 149 // /home/rsc/go/src/runtime/x.go:23 +0xf 150 tracepc = frame.pc; // back up to CALL instruction for funcline. 151 if(n > 0 && frame.pc > f->entry && !waspanic) 152 tracepc -= sizeof(uintptr); 153 runtime·printf("%s(", runtime·funcname(f)); 154 for(i = 0; i < frame.arglen/sizeof(uintptr); i++) { 155 if(i >= 5) { 156 runtime·prints(", ..."); 157 break; 158 } 159 if(i != 0) 160 runtime·prints(", "); 161 runtime·printhex(((uintptr*)frame.argp)[i]); 162 } 163 runtime·prints(")\n"); 164 line = runtime·funcline(f, tracepc, &file); 165 runtime·printf("\t%S:%d", file, line); 166 if(frame.pc > f->entry) 167 runtime·printf(" +%p", (uintptr)(frame.pc - f->entry)); 168 if(m->throwing > 0 && gp == m->curg) 169 runtime·printf(" fp=%p", frame.fp); 170 runtime·printf("\n"); 171 nprint++; 172 } 173 } 174 n++; 175 176 skipped: 177 waspanic = f->entry == (uintptr)runtime·sigpanic; 178 179 // Do not unwind past the bottom of the stack. 180 if(flr == nil) 181 break; 182 183 // Unwind to next frame. 184 frame.pc = frame.lr; 185 frame.fn = flr; 186 frame.lr = 0; 187 frame.sp = frame.fp; 188 frame.fp = 0; 189 190 // sighandler saves the lr on stack before faking a call to sigpanic 191 if(waspanic) { 192 x = *(uintptr*)frame.sp; 193 frame.sp += 4; 194 frame.fn = f = runtime·findfunc(frame.pc); 195 if(f == nil) 196 frame.pc = x; 197 else if(f->frame == 0) 198 frame.lr = x; 199 } 200 } 201 202 if(pcbuf == nil && callback == nil) 203 n = nprint; 204 205 return n; 206 } 207 208 void 209 runtime·printcreatedby(G *gp) 210 { 211 int32 line; 212 uintptr pc, tracepc; 213 Func *f; 214 String file; 215 216 // Show what created goroutine, except main goroutine (goid 1). 217 if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && 218 runtime·showframe(f, gp) && gp->goid != 1) { 219 runtime·printf("created by %s\n", runtime·funcname(f)); 220 tracepc = pc; // back up to CALL instruction for funcline. 221 if(pc > f->entry) 222 tracepc -= PCQuantum; 223 line = runtime·funcline(f, tracepc, &file); 224 runtime·printf("\t%S:%d", file, line); 225 if(pc > f->entry) 226 runtime·printf(" +%p", (uintptr)(pc - f->entry)); 227 runtime·printf("\n"); 228 } 229 } 230 231 void 232 runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G *gp) 233 { 234 if(gp->status == Gsyscall) { 235 // Override signal registers if blocked in system call. 236 pc = gp->syscallpc; 237 sp = gp->syscallsp; 238 lr = 0; 239 } 240 241 // Print traceback. By default, omits runtime frames. 242 // If that means we print nothing at all, repeat forcing all frames printed. 243 if(runtime·gentraceback(pc, sp, lr, gp, 0, nil, 100, nil, nil, false) == 0) 244 runtime·gentraceback(pc, sp, lr, gp, 0, nil, 100, nil, nil, true); 245 runtime·printcreatedby(gp); 246 } 247 248 // func caller(n int) (pc uintptr, file string, line int, ok bool) 249 int32 250 runtime·callers(int32 skip, uintptr *pcbuf, int32 m) 251 { 252 uintptr pc, sp; 253 254 sp = runtime·getcallersp(&skip); 255 pc = (uintptr)runtime·getcallerpc(&skip); 256 257 return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, false); 258 }