github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/runtime/traceback.go (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 package runtime 6 7 import "unsafe" 8 9 // The code in this file implements stack trace walking for all architectures. 10 // The most important fact about a given architecture is whether it uses a link register. 11 // On systems with link registers, the prologue for a non-leaf function stores the 12 // incoming value of LR at the bottom of the newly allocated stack frame. 13 // On systems without link registers, the architecture pushes a return PC during 14 // the call instruction, so the return PC ends up above the stack frame. 15 // In this file, the return PC is always called LR, no matter how it was found. 16 // 17 // To date, the opposite of a link register architecture is an x86 architecture. 18 // This code may need to change if some other kind of non-link-register 19 // architecture comes along. 20 // 21 // The other important fact is the size of a pointer: on 32-bit systems the LR 22 // takes up only 4 bytes on the stack, while on 64-bit systems it takes up 8 bytes. 23 // Typically this is ptrSize. 24 // 25 // As an exception, amd64p32 has ptrSize == 4 but the CALL instruction still 26 // stores an 8-byte return PC onto the stack. To accommodate this, we use regSize 27 // as the size of the architecture-pushed return PC. 28 // 29 // usesLR is defined below. ptrSize and regSize are defined in stubs.go. 30 31 const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386" 32 33 var ( 34 // initialized in tracebackinit 35 goexitPC uintptr 36 jmpdeferPC uintptr 37 mcallPC uintptr 38 morestackPC uintptr 39 mstartPC uintptr 40 rt0_goPC uintptr 41 sigpanicPC uintptr 42 systemstack_switchPC uintptr 43 44 externalthreadhandlerp uintptr // initialized elsewhere 45 ) 46 47 func tracebackinit() { 48 // Go variable initialization happens late during runtime startup. 49 // Instead of initializing the variables above in the declarations, 50 // schedinit calls this function so that the variables are 51 // initialized and available earlier in the startup sequence. 52 goexitPC = funcPC(goexit) 53 jmpdeferPC = funcPC(jmpdefer) 54 mcallPC = funcPC(mcall) 55 morestackPC = funcPC(morestack) 56 mstartPC = funcPC(mstart) 57 rt0_goPC = funcPC(rt0_go) 58 sigpanicPC = funcPC(sigpanic) 59 systemstack_switchPC = funcPC(systemstack_switch) 60 } 61 62 // Traceback over the deferred function calls. 63 // Report them like calls that have been invoked but not started executing yet. 64 func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) { 65 var frame stkframe 66 for d := gp._defer; d != nil; d = d.link { 67 fn := d.fn 68 if fn == nil { 69 // Defer of nil function. Args don't matter. 70 frame.pc = 0 71 frame.fn = nil 72 frame.argp = 0 73 frame.arglen = 0 74 frame.argmap = nil 75 } else { 76 frame.pc = uintptr(fn.fn) 77 f := findfunc(frame.pc) 78 if f == nil { 79 print("runtime: unknown pc in defer ", hex(frame.pc), "\n") 80 throw("unknown pc") 81 } 82 frame.fn = f 83 frame.argp = uintptr(deferArgs(d)) 84 setArgInfo(&frame, f, true) 85 } 86 frame.continpc = frame.pc 87 if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) { 88 return 89 } 90 } 91 } 92 93 // Generic traceback. Handles runtime stack prints (pcbuf == nil), 94 // the runtime.Callers function (pcbuf != nil), as well as the garbage 95 // collector (callback != nil). A little clunky to merge these, but avoids 96 // duplicating the code and all its subtlety. 97 func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max int, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer, flags uint) int { 98 if goexitPC == 0 { 99 throw("gentraceback before goexitPC initialization") 100 } 101 g := getg() 102 if g == gp && g == g.m.curg { 103 // The starting sp has been passed in as a uintptr, and the caller may 104 // have other uintptr-typed stack references as well. 105 // If during one of the calls that got us here or during one of the 106 // callbacks below the stack must be grown, all these uintptr references 107 // to the stack will not be updated, and gentraceback will continue 108 // to inspect the old stack memory, which may no longer be valid. 109 // Even if all the variables were updated correctly, it is not clear that 110 // we want to expose a traceback that begins on one stack and ends 111 // on another stack. That could confuse callers quite a bit. 112 // Instead, we require that gentraceback and any other function that 113 // accepts an sp for the current goroutine (typically obtained by 114 // calling getcallersp) must not run on that goroutine's stack but 115 // instead on the g0 stack. 116 throw("gentraceback cannot trace user goroutine on its own stack") 117 } 118 gotraceback := gotraceback(nil) 119 if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) { // Signal to fetch saved values from gp. 120 if gp.syscallsp != 0 { 121 pc0 = gp.syscallpc 122 sp0 = gp.syscallsp 123 if usesLR { 124 lr0 = 0 125 } 126 } else { 127 pc0 = gp.sched.pc 128 sp0 = gp.sched.sp 129 if usesLR { 130 lr0 = gp.sched.lr 131 } 132 } 133 } 134 135 nprint := 0 136 var frame stkframe 137 frame.pc = pc0 138 frame.sp = sp0 139 if usesLR { 140 frame.lr = lr0 141 } 142 waspanic := false 143 printing := pcbuf == nil && callback == nil 144 _defer := gp._defer 145 146 for _defer != nil && uintptr(_defer.sp) == _NoArgs { 147 _defer = _defer.link 148 } 149 150 // If the PC is zero, it's likely a nil function call. 151 // Start in the caller's frame. 152 if frame.pc == 0 { 153 if usesLR { 154 frame.pc = *(*uintptr)(unsafe.Pointer(frame.sp)) 155 frame.lr = 0 156 } else { 157 frame.pc = uintptr(*(*uintreg)(unsafe.Pointer(frame.sp))) 158 frame.sp += regSize 159 } 160 } 161 162 f := findfunc(frame.pc) 163 if f == nil { 164 if callback != nil { 165 print("runtime: unknown pc ", hex(frame.pc), "\n") 166 throw("unknown pc") 167 } 168 return 0 169 } 170 frame.fn = f 171 172 n := 0 173 for n < max { 174 // Typically: 175 // pc is the PC of the running function. 176 // sp is the stack pointer at that program counter. 177 // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown. 178 // stk is the stack containing sp. 179 // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp. 180 f = frame.fn 181 182 // Found an actual function. 183 // Derive frame pointer and link register. 184 if frame.fp == 0 { 185 frame.fp = frame.sp + uintptr(funcspdelta(f, frame.pc)) 186 if !usesLR { 187 // On x86, call instruction pushes return PC before entering new function. 188 frame.fp += regSize 189 } 190 } 191 var flr *_func 192 if topofstack(f) { 193 frame.lr = 0 194 flr = nil 195 } else if usesLR && f.entry == jmpdeferPC { 196 // jmpdefer modifies SP/LR/PC non-atomically. 197 // If a profiling interrupt arrives during jmpdefer, 198 // the stack unwind may see a mismatched register set 199 // and get confused. Stop if we see PC within jmpdefer 200 // to avoid that confusion. 201 // See golang.org/issue/8153. 202 if callback != nil { 203 throw("traceback_arm: found jmpdefer when tracing with callback") 204 } 205 frame.lr = 0 206 } else { 207 if usesLR { 208 if n == 0 && frame.sp < frame.fp || frame.lr == 0 { 209 frame.lr = *(*uintptr)(unsafe.Pointer(frame.sp)) 210 } 211 } else { 212 if frame.lr == 0 { 213 frame.lr = uintptr(*(*uintreg)(unsafe.Pointer(frame.fp - regSize))) 214 } 215 } 216 flr = findfunc(frame.lr) 217 if flr == nil { 218 // This happens if you get a profiling interrupt at just the wrong time. 219 // In that context it is okay to stop early. 220 // But if callback is set, we're doing a garbage collection and must 221 // get everything, so crash loudly. 222 if callback != nil { 223 print("runtime: unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n") 224 throw("unknown caller pc") 225 } 226 } 227 } 228 229 frame.varp = frame.fp 230 if !usesLR { 231 // On x86, call instruction pushes return PC before entering new function. 232 frame.varp -= regSize 233 } 234 235 // Derive size of arguments. 236 // Most functions have a fixed-size argument block, 237 // so we can use metadata about the function f. 238 // Not all, though: there are some variadic functions 239 // in package runtime and reflect, and for those we use call-specific 240 // metadata recorded by f's caller. 241 if callback != nil || printing { 242 frame.argp = frame.fp 243 if usesLR { 244 frame.argp += ptrSize 245 } 246 setArgInfo(&frame, f, callback != nil) 247 } 248 249 // Determine frame's 'continuation PC', where it can continue. 250 // Normally this is the return address on the stack, but if sigpanic 251 // is immediately below this function on the stack, then the frame 252 // stopped executing due to a trap, and frame.pc is probably not 253 // a safe point for looking up liveness information. In this panicking case, 254 // the function either doesn't return at all (if it has no defers or if the 255 // defers do not recover) or it returns from one of the calls to 256 // deferproc a second time (if the corresponding deferred func recovers). 257 // It suffices to assume that the most recent deferproc is the one that 258 // returns; everything live at earlier deferprocs is still live at that one. 259 frame.continpc = frame.pc 260 if waspanic { 261 if _defer != nil && _defer.sp == frame.sp { 262 frame.continpc = _defer.pc 263 } else { 264 frame.continpc = 0 265 } 266 } 267 268 // Unwind our local defer stack past this frame. 269 for _defer != nil && (_defer.sp == frame.sp || _defer.sp == _NoArgs) { 270 _defer = _defer.link 271 } 272 273 if skip > 0 { 274 skip-- 275 goto skipped 276 } 277 278 if pcbuf != nil { 279 (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = frame.pc 280 } 281 if callback != nil { 282 if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) { 283 return n 284 } 285 } 286 if printing { 287 if (flags&_TraceRuntimeFrames) != 0 || showframe(f, gp) { 288 // Print during crash. 289 // main(0x1, 0x2, 0x3) 290 // /home/rsc/go/src/runtime/x.go:23 +0xf 291 // 292 tracepc := frame.pc // back up to CALL instruction for funcline. 293 if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic { 294 tracepc-- 295 } 296 print(funcname(f), "(") 297 argp := (*[100]uintptr)(unsafe.Pointer(frame.argp)) 298 for i := uintptr(0); i < frame.arglen/ptrSize; i++ { 299 if i >= 10 { 300 print(", ...") 301 break 302 } 303 if i != 0 { 304 print(", ") 305 } 306 print(hex(argp[i])) 307 } 308 print(")\n") 309 file, line := funcline(f, tracepc) 310 print("\t", file, ":", line) 311 if frame.pc > f.entry { 312 print(" +", hex(frame.pc-f.entry)) 313 } 314 if g.m.throwing > 0 && gp == g.m.curg || gotraceback >= 2 { 315 print(" fp=", hex(frame.fp), " sp=", hex(frame.sp)) 316 } 317 print("\n") 318 nprint++ 319 } 320 } 321 n++ 322 323 skipped: 324 waspanic = f.entry == sigpanicPC 325 326 // Do not unwind past the bottom of the stack. 327 if flr == nil { 328 break 329 } 330 331 // Unwind to next frame. 332 frame.fn = flr 333 frame.pc = frame.lr 334 frame.lr = 0 335 frame.sp = frame.fp 336 frame.fp = 0 337 frame.argmap = nil 338 339 // On link register architectures, sighandler saves the LR on stack 340 // before faking a call to sigpanic. 341 if usesLR && waspanic { 342 x := *(*uintptr)(unsafe.Pointer(frame.sp)) 343 frame.sp += ptrSize 344 f = findfunc(frame.pc) 345 frame.fn = f 346 if f == nil { 347 frame.pc = x 348 } else if f.frame == 0 { 349 frame.lr = x 350 } 351 } 352 } 353 354 if pcbuf == nil && callback == nil { 355 n = nprint 356 } 357 358 // If callback != nil, we're being called to gather stack information during 359 // garbage collection or stack growth. In that context, require that we used 360 // up the entire defer stack. If not, then there is a bug somewhere and the 361 // garbage collection or stack growth may not have seen the correct picture 362 // of the stack. Crash now instead of silently executing the garbage collection 363 // or stack copy incorrectly and setting up for a mysterious crash later. 364 // 365 // Note that panic != nil is okay here: there can be leftover panics, 366 // because the defers on the panic stack do not nest in frame order as 367 // they do on the defer stack. If you have: 368 // 369 // frame 1 defers d1 370 // frame 2 defers d2 371 // frame 3 defers d3 372 // frame 4 panics 373 // frame 4's panic starts running defers 374 // frame 5, running d3, defers d4 375 // frame 5 panics 376 // frame 5's panic starts running defers 377 // frame 6, running d4, garbage collects 378 // frame 6, running d2, garbage collects 379 // 380 // During the execution of d4, the panic stack is d4 -> d3, which 381 // is nested properly, and we'll treat frame 3 as resumable, because we 382 // can find d3. (And in fact frame 3 is resumable. If d4 recovers 383 // and frame 5 continues running, d3, d3 can recover and we'll 384 // resume execution in (returning from) frame 3.) 385 // 386 // During the execution of d2, however, the panic stack is d2 -> d3, 387 // which is inverted. The scan will match d2 to frame 2 but having 388 // d2 on the stack until then means it will not match d3 to frame 3. 389 // This is okay: if we're running d2, then all the defers after d2 have 390 // completed and their corresponding frames are dead. Not finding d3 391 // for frame 3 means we'll set frame 3's continpc == 0, which is correct 392 // (frame 3 is dead). At the end of the walk the panic stack can thus 393 // contain defers (d3 in this case) for dead frames. The inversion here 394 // always indicates a dead frame, and the effect of the inversion on the 395 // scan is to hide those dead frames, so the scan is still okay: 396 // what's left on the panic stack are exactly (and only) the dead frames. 397 // 398 // We require callback != nil here because only when callback != nil 399 // do we know that gentraceback is being called in a "must be correct" 400 // context as opposed to a "best effort" context. The tracebacks with 401 // callbacks only happen when everything is stopped nicely. 402 // At other times, such as when gathering a stack for a profiling signal 403 // or when printing a traceback during a crash, everything may not be 404 // stopped nicely, and the stack walk may not be able to complete. 405 // It's okay in those situations not to use up the entire defer stack: 406 // incomplete information then is still better than nothing. 407 if callback != nil && n < max && _defer != nil { 408 if _defer != nil { 409 print("runtime: g", gp.goid, ": leftover defer sp=", hex(_defer.sp), " pc=", hex(_defer.pc), "\n") 410 } 411 for _defer = gp._defer; _defer != nil; _defer = _defer.link { 412 print("\tdefer ", _defer, " sp=", hex(_defer.sp), " pc=", hex(_defer.pc), "\n") 413 } 414 throw("traceback has leftover defers") 415 } 416 417 return n 418 } 419 420 func setArgInfo(frame *stkframe, f *_func, needArgMap bool) { 421 frame.arglen = uintptr(f.args) 422 if needArgMap && f.args == _ArgsSizeUnknown { 423 // Extract argument bitmaps for reflect stubs from the calls they made to reflect. 424 switch funcname(f) { 425 case "reflect.makeFuncStub", "reflect.methodValueCall": 426 arg0 := frame.sp 427 if usesLR { 428 arg0 += ptrSize 429 } 430 fn := *(**[2]uintptr)(unsafe.Pointer(arg0)) 431 if fn[0] != f.entry { 432 print("runtime: confused by ", funcname(f), "\n") 433 throw("reflect mismatch") 434 } 435 bv := (*bitvector)(unsafe.Pointer(fn[1])) 436 frame.arglen = uintptr(bv.n / 2 * ptrSize) 437 frame.argmap = bv 438 } 439 } 440 } 441 442 func printcreatedby(gp *g) { 443 // Show what created goroutine, except main goroutine (goid 1). 444 pc := gp.gopc 445 f := findfunc(pc) 446 if f != nil && showframe(f, gp) && gp.goid != 1 { 447 print("created by ", funcname(f), "\n") 448 tracepc := pc // back up to CALL instruction for funcline. 449 if pc > f.entry { 450 tracepc -= _PCQuantum 451 } 452 file, line := funcline(f, tracepc) 453 print("\t", file, ":", line) 454 if pc > f.entry { 455 print(" +", hex(pc-f.entry)) 456 } 457 print("\n") 458 } 459 } 460 461 func traceback(pc uintptr, sp uintptr, lr uintptr, gp *g) { 462 traceback1(pc, sp, lr, gp, 0) 463 } 464 465 // tracebacktrap is like traceback but expects that the PC and SP were obtained 466 // from a trap, not from gp->sched or gp->syscallpc/gp->syscallsp or getcallerpc/getcallersp. 467 // Because they are from a trap instead of from a saved pair, 468 // the initial PC must not be rewound to the previous instruction. 469 // (All the saved pairs record a PC that is a return address, so we 470 // rewind it into the CALL instruction.) 471 func tracebacktrap(pc uintptr, sp uintptr, lr uintptr, gp *g) { 472 traceback1(pc, sp, lr, gp, _TraceTrap) 473 } 474 475 func traceback1(pc uintptr, sp uintptr, lr uintptr, gp *g, flags uint) { 476 var n int 477 if readgstatus(gp)&^_Gscan == _Gsyscall { 478 // Override registers if blocked in system call. 479 pc = gp.syscallpc 480 sp = gp.syscallsp 481 flags &^= _TraceTrap 482 } 483 // Print traceback. By default, omits runtime frames. 484 // If that means we print nothing at all, repeat forcing all frames printed. 485 n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags) 486 if n == 0 && (flags&_TraceRuntimeFrames) == 0 { 487 n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags|_TraceRuntimeFrames) 488 } 489 if n == _TracebackMaxFrames { 490 print("...additional frames elided...\n") 491 } 492 printcreatedby(gp) 493 } 494 495 func callers(skip int, pcbuf *uintptr, m int) int { 496 sp := getcallersp(unsafe.Pointer(&skip)) 497 pc := uintptr(getcallerpc(unsafe.Pointer(&skip))) 498 var n int 499 systemstack(func() { 500 n = gentraceback(pc, sp, 0, getg(), skip, pcbuf, m, nil, nil, 0) 501 }) 502 return n 503 } 504 505 func gcallers(gp *g, skip int, pcbuf *uintptr, m int) int { 506 return gentraceback(^uintptr(0), ^uintptr(0), 0, gp, skip, pcbuf, m, nil, nil, 0) 507 } 508 509 func showframe(f *_func, gp *g) bool { 510 g := getg() 511 if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig) { 512 return true 513 } 514 traceback := gotraceback(nil) 515 name := funcname(f) 516 517 // Special case: always show runtime.panic frame, so that we can 518 // see where a panic started in the middle of a stack trace. 519 // See golang.org/issue/5832. 520 if name == "runtime.panic" { 521 return true 522 } 523 524 return traceback > 1 || f != nil && contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name)) 525 } 526 527 // isExportedRuntime reports whether name is an exported runtime function. 528 // It is only for runtime functions, so ASCII A-Z is fine. 529 func isExportedRuntime(name string) bool { 530 const n = len("runtime.") 531 return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z' 532 } 533 534 var gStatusStrings = [...]string{ 535 _Gidle: "idle", 536 _Grunnable: "runnable", 537 _Grunning: "running", 538 _Gsyscall: "syscall", 539 _Gwaiting: "waiting", 540 _Gdead: "dead", 541 _Genqueue: "enqueue", 542 _Gcopystack: "copystack", 543 } 544 545 var gScanStatusStrings = [...]string{ 546 0: "scan", 547 _Grunnable: "scanrunnable", 548 _Grunning: "scanrunning", 549 _Gsyscall: "scansyscall", 550 _Gwaiting: "scanwaiting", 551 _Gdead: "scandead", 552 _Genqueue: "scanenqueue", 553 } 554 555 func goroutineheader(gp *g) { 556 gpstatus := readgstatus(gp) 557 558 // Basic string status 559 var status string 560 if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) { 561 status = gStatusStrings[gpstatus] 562 } else if gpstatus&_Gscan != 0 && 0 <= gpstatus&^_Gscan && gpstatus&^_Gscan < uint32(len(gStatusStrings)) { 563 status = gStatusStrings[gpstatus&^_Gscan] 564 } else { 565 status = "???" 566 } 567 568 // Override. 569 if (gpstatus == _Gwaiting || gpstatus == _Gscanwaiting) && gp.waitreason != "" { 570 status = gp.waitreason 571 } 572 573 // approx time the G is blocked, in minutes 574 var waitfor int64 575 gpstatus &^= _Gscan // drop the scan bit 576 if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 { 577 waitfor = (nanotime() - gp.waitsince) / 60e9 578 } 579 print("goroutine ", gp.goid, " [", status) 580 if waitfor >= 1 { 581 print(", ", waitfor, " minutes") 582 } 583 if gp.lockedm != nil { 584 print(", locked to thread") 585 } 586 print("]:\n") 587 } 588 589 func tracebackothers(me *g) { 590 level := gotraceback(nil) 591 592 // Show the current goroutine first, if we haven't already. 593 g := getg() 594 gp := g.m.curg 595 if gp != nil && gp != me { 596 print("\n") 597 goroutineheader(gp) 598 traceback(^uintptr(0), ^uintptr(0), 0, gp) 599 } 600 601 lock(&allglock) 602 for _, gp := range allgs { 603 if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || gp.issystem && level < 2 { 604 continue 605 } 606 print("\n") 607 goroutineheader(gp) 608 if readgstatus(gp)&^_Gscan == _Grunning { 609 print("\tgoroutine running on other thread; stack unavailable\n") 610 printcreatedby(gp) 611 } else { 612 traceback(^uintptr(0), ^uintptr(0), 0, gp) 613 } 614 } 615 unlock(&allglock) 616 } 617 618 // Does f mark the top of a goroutine stack? 619 func topofstack(f *_func) bool { 620 pc := f.entry 621 return pc == goexitPC || 622 pc == mstartPC || 623 pc == mcallPC || 624 pc == morestackPC || 625 pc == rt0_goPC || 626 externalthreadhandlerp != 0 && pc == externalthreadhandlerp 627 }