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