github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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 11 void runtime·deferproc(void); 12 void runtime·newproc(void); 13 void runtime·newstack(void); 14 void runtime·morestack(void); 15 void runtime·sigpanic(void); 16 17 // This code is also used for the 386 tracebacks. 18 // Use uintptr for an appropriate word-sized integer. 19 20 // Generic traceback. Handles runtime stack prints (pcbuf == nil), 21 // the runtime.Callers function (pcbuf != nil), as well as the garbage 22 // collector (fn != nil). A little clunky to merge the two but avoids 23 // duplicating the code and all its subtlety. 24 int32 25 runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, void (*fn)(Func*, byte*, byte*, void*), void *arg) 26 { 27 int32 i, n, sawnewstack; 28 uintptr pc, lr, tracepc; 29 byte *fp; 30 Stktop *stk; 31 Func *f; 32 bool waspanic; 33 34 USED(lr0); 35 pc = (uintptr)pc0; 36 lr = 0; 37 fp = nil; 38 waspanic = false; 39 40 // If the PC is goexit, the goroutine hasn't started yet. 41 if(pc0 == gp->sched.pc && sp == (byte*)gp->sched.sp && pc0 == (byte*)runtime·goexit && gp->fnstart != nil) { 42 fp = sp; 43 lr = pc; 44 pc = (uintptr)gp->fnstart->fn; 45 } 46 47 // If the PC is zero, it's likely a nil function call. 48 // Start in the caller's frame. 49 if(pc == 0) { 50 pc = *(uintptr*)sp; 51 sp += sizeof(uintptr); 52 } 53 54 n = 0; 55 sawnewstack = 0; 56 stk = (Stktop*)gp->stackbase; 57 while(n < max) { 58 // Typically: 59 // pc is the PC of the running function. 60 // sp is the stack pointer at that program counter. 61 // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown. 62 // stk is the stack containing sp. 63 // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp. 64 65 if(pc == (uintptr)runtime·lessstack) { 66 // Hit top of stack segment. Unwind to next segment. 67 pc = (uintptr)stk->gobuf.pc; 68 sp = (byte*)stk->gobuf.sp; 69 lr = 0; 70 fp = nil; 71 if(pcbuf == nil && fn == nil && runtime·showframe(nil, gp == m->curg)) 72 runtime·printf("----- stack segment boundary -----\n"); 73 stk = (Stktop*)stk->stackbase; 74 continue; 75 } 76 if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) { 77 if(fn != nil) 78 runtime·throw("unknown pc"); 79 break; 80 } 81 82 // Found an actual function. 83 if(fp == nil) { 84 fp = sp; 85 if(pc > f->entry && f->frame >= sizeof(uintptr)) 86 fp += f->frame - sizeof(uintptr); 87 if(lr == 0) 88 lr = *(uintptr*)fp; 89 fp += sizeof(uintptr); 90 } else if(lr == 0) 91 lr = *(uintptr*)fp; 92 93 if(skip > 0) 94 skip--; 95 else if(pcbuf != nil) 96 pcbuf[n++] = pc; 97 else if(fn != nil) 98 (*fn)(f, (byte*)pc, sp, arg); 99 else { 100 if(runtime·showframe(f, gp == m->curg)) { 101 // Print during crash. 102 // main(0x1, 0x2, 0x3) 103 // /home/rsc/go/src/runtime/x.go:23 +0xf 104 // 105 tracepc = pc; // back up to CALL instruction for funcline. 106 if(n > 0 && pc > f->entry && !waspanic) 107 tracepc--; 108 if(m->throwing && gp == m->curg) 109 runtime·printf("[fp=%p] ", fp); 110 runtime·printf("%S(", f->name); 111 for(i = 0; i < f->args/sizeof(uintptr); i++) { 112 if(i != 0) 113 runtime·prints(", "); 114 runtime·printhex(((uintptr*)fp)[i]); 115 if(i >= 4) { 116 runtime·prints(", ..."); 117 break; 118 } 119 } 120 runtime·prints(")\n"); 121 runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); 122 if(pc > f->entry) 123 runtime·printf(" +%p", (uintptr)(pc - f->entry)); 124 runtime·printf("\n"); 125 } 126 n++; 127 } 128 129 waspanic = f->entry == (uintptr)runtime·sigpanic; 130 131 if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc) 132 fp += 2*sizeof(uintptr); 133 134 if(f->entry == (uintptr)runtime·newstack) 135 sawnewstack = 1; 136 137 if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·morestack && gp == m->g0 && sawnewstack) { 138 // The fact that we saw newstack means that morestack 139 // has managed to record its information in m, so we can 140 // use it to keep unwinding the stack. 141 runtime·printf("----- morestack called from goroutine %D -----\n", m->curg->goid); 142 pc = (uintptr)m->morepc; 143 sp = (byte*)m->morebuf.sp - sizeof(void*); 144 lr = (uintptr)m->morebuf.pc; 145 fp = (byte*)m->morebuf.sp; 146 sawnewstack = 0; 147 gp = m->curg; 148 stk = (Stktop*)gp->stackbase; 149 continue; 150 } 151 152 if(pcbuf == nil && fn == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) { 153 // Lessstack is running on scheduler stack. Switch to original goroutine. 154 runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid); 155 gp = m->curg; 156 stk = (Stktop*)gp->stackbase; 157 sp = (byte*)stk->gobuf.sp; 158 pc = (uintptr)stk->gobuf.pc; 159 fp = nil; 160 lr = 0; 161 continue; 162 } 163 164 // Do not unwind past the bottom of the stack. 165 if(pc == (uintptr)runtime·goexit) 166 break; 167 168 // Unwind to next frame. 169 pc = lr; 170 lr = 0; 171 sp = fp; 172 fp = nil; 173 } 174 175 // Show what created goroutine, except main goroutine (goid 1). 176 if(pcbuf == nil && fn == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil 177 && runtime·showframe(f, gp == m->curg) && gp->goid != 1) { 178 runtime·printf("created by %S\n", f->name); 179 tracepc = pc; // back up to CALL instruction for funcline. 180 if(n > 0 && pc > f->entry) 181 tracepc--; 182 runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc)); 183 if(pc > f->entry) 184 runtime·printf(" +%p", (uintptr)(pc - f->entry)); 185 runtime·printf("\n"); 186 } 187 188 return n; 189 } 190 191 void 192 runtime·traceback(byte *pc0, byte *sp, byte*, G *gp) 193 { 194 if(gp->status == Gsyscall) { 195 // Override signal registers if blocked in system call. 196 pc0 = gp->sched.pc; 197 sp = (byte*)gp->sched.sp; 198 } 199 runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100, nil, nil); 200 } 201 202 int32 203 runtime·callers(int32 skip, uintptr *pcbuf, int32 m) 204 { 205 byte *pc, *sp; 206 207 // our caller's pc, sp. 208 sp = (byte*)&skip; 209 pc = runtime·getcallerpc(&skip); 210 211 return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m, nil, nil); 212 }