LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package runtime | 5 package runtime |
6 | 6 |
7 import "unsafe" | 7 import "unsafe" |
8 | 8 |
9 // The code in this file implements stack trace walking for all architectures. | 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. | 10 // The most important fact about a given architecture is whether it uses a link
register. |
(...skipping 27 matching lines...) Expand all Loading... |
38 morestackPC = funcPC(morestack) | 38 morestackPC = funcPC(morestack) |
39 mstartPC = funcPC(mstart) | 39 mstartPC = funcPC(mstart) |
40 newprocPC = funcPC(newproc) | 40 newprocPC = funcPC(newproc) |
41 newstackPC = funcPC(newstack) | 41 newstackPC = funcPC(newstack) |
42 rt0_goPC = funcPC(rt0_go) | 42 rt0_goPC = funcPC(rt0_go) |
43 sigpanicPC = funcPC(sigpanic) | 43 sigpanicPC = funcPC(sigpanic) |
44 | 44 |
45 externalthreadhandlerp uintptr // initialized elsewhere | 45 externalthreadhandlerp uintptr // initialized elsewhere |
46 ) | 46 ) |
47 | 47 |
48 // System-specific hook. See traceback_windows.go | 48 // Traceback over the deferred function calls. |
49 var systraceback func(*_func, *stkframe, *g, bool, func(*stkframe, unsafe.Pointe
r) bool, unsafe.Pointer) (changed, aborted bool) | 49 // Report them like calls that have been invoked but not started executing yet. |
| 50 func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v uns
afe.Pointer) { |
| 51 » var frame stkframe |
| 52 » for d := gp._defer; d != nil; d = d.link { |
| 53 » » fn := d.fn |
| 54 » » if fn == nil { |
| 55 » » » // Defer of nil function. Args don't matter. |
| 56 » » » frame.pc = 0 |
| 57 » » » frame.fn = nil |
| 58 » » » frame.argp = 0 |
| 59 » » » frame.arglen = 0 |
| 60 » » » frame.argmap = nil |
| 61 » » } else { |
| 62 » » » frame.pc = uintptr(fn.fn) |
| 63 » » » f := findfunc(frame.pc) |
| 64 » » » if f == nil { |
| 65 » » » » print("runtime: unknown pc in defer ", hex(frame
.pc), "\n") |
| 66 » » » » gothrow("unknown pc") |
| 67 » » » } |
| 68 » » » frame.fn = f |
| 69 » » » frame.argp = uintptr(deferArgs(d)) |
| 70 » » » setArgInfo(&frame, f, true) |
| 71 » » } |
| 72 » » frame.continpc = frame.pc |
| 73 » » if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) { |
| 74 » » » return |
| 75 » » } |
| 76 » } |
| 77 } |
50 | 78 |
51 // Generic traceback. Handles runtime stack prints (pcbuf == nil), | 79 // Generic traceback. Handles runtime stack prints (pcbuf == nil), |
52 // the runtime.Callers function (pcbuf != nil), as well as the garbage | 80 // the runtime.Callers function (pcbuf != nil), as well as the garbage |
53 // collector (callback != nil). A little clunky to merge these, but avoids | 81 // collector (callback != nil). A little clunky to merge these, but avoids |
54 // duplicating the code and all its subtlety. | 82 // duplicating the code and all its subtlety. |
55 func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf
*uintptr, max int, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Point
er, printall bool) int { | 83 func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf
*uintptr, max int, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Point
er, printall bool) int { |
56 g := getg() | 84 g := getg() |
57 gotraceback := gotraceback(nil) | 85 gotraceback := gotraceback(nil) |
58 if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) { // Signal to fetch saved v
alues from gp. | 86 if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) { // Signal to fetch saved v
alues from gp. |
59 if gp.syscallsp != 0 { | 87 if gp.syscallsp != 0 { |
(...skipping 14 matching lines...) Expand all Loading... |
74 nprint := 0 | 102 nprint := 0 |
75 var frame stkframe | 103 var frame stkframe |
76 frame.pc = pc0 | 104 frame.pc = pc0 |
77 frame.sp = sp0 | 105 frame.sp = sp0 |
78 if usesLR { | 106 if usesLR { |
79 frame.lr = lr0 | 107 frame.lr = lr0 |
80 } | 108 } |
81 waspanic := false | 109 waspanic := false |
82 wasnewproc := false | 110 wasnewproc := false |
83 printing := pcbuf == nil && callback == nil | 111 printing := pcbuf == nil && callback == nil |
84 panic := gp._panic | |
85 _defer := gp._defer | 112 _defer := gp._defer |
86 | 113 |
87 for _defer != nil && uintptr(_defer.argp) == _NoArgs { | 114 for _defer != nil && uintptr(_defer.argp) == _NoArgs { |
88 _defer = _defer.link | 115 _defer = _defer.link |
89 } | |
90 for panic != nil && panic._defer == nil { | |
91 panic = panic.link | |
92 } | 116 } |
93 | 117 |
94 // If the PC is zero, it's likely a nil function call. | 118 // If the PC is zero, it's likely a nil function call. |
95 // Start in the caller's frame. | 119 // Start in the caller's frame. |
96 if frame.pc == 0 { | 120 if frame.pc == 0 { |
97 if usesLR { | 121 if usesLR { |
98 frame.pc = *(*uintptr)(unsafe.Pointer(frame.sp)) | 122 frame.pc = *(*uintptr)(unsafe.Pointer(frame.sp)) |
99 frame.lr = 0 | 123 frame.lr = 0 |
100 } else { | 124 } else { |
101 frame.pc = uintptr(*(*uintreg)(unsafe.Pointer(frame.sp))
) | 125 frame.pc = uintptr(*(*uintreg)(unsafe.Pointer(frame.sp))
) |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 // Most functions have a fixed-size argument block, | 204 // Most functions have a fixed-size argument block, |
181 // so we can use metadata about the function f. | 205 // so we can use metadata about the function f. |
182 // Not all, though: there are some variadic functions | 206 // Not all, though: there are some variadic functions |
183 // in package runtime and reflect, and for those we use call-spe
cific | 207 // in package runtime and reflect, and for those we use call-spe
cific |
184 // metadata recorded by f's caller. | 208 // metadata recorded by f's caller. |
185 if callback != nil || printing { | 209 if callback != nil || printing { |
186 frame.argp = frame.fp | 210 frame.argp = frame.fp |
187 if usesLR { | 211 if usesLR { |
188 frame.argp += ptrSize | 212 frame.argp += ptrSize |
189 } | 213 } |
190 » » » frame.arglen = uintptr(f.args) | 214 » » » setArgInfo(&frame, f, callback != nil) |
191 » » » if callback != nil && f.args == _ArgsSizeUnknown { | |
192 » » » » // Extract argument bitmaps for reflect stubs fr
om the calls they made to reflect. | |
193 » » » » switch gofuncname(f) { | |
194 » » » » case "reflect.makeFuncStub", "reflect.methodValu
eCall": | |
195 » » » » » arg0 := frame.sp | |
196 » » » » » if usesLR { | |
197 » » » » » » arg0 += ptrSize | |
198 » » » » » } | |
199 » » » » » fn := *(**[2]uintptr)(unsafe.Pointer(arg
0)) | |
200 » » » » » if fn[0] != f.entry { | |
201 » » » » » » print("runtime: confused by ", g
ofuncname(f), "\n") | |
202 » » » » » » gothrow("reflect mismatch") | |
203 » » » » » } | |
204 » » » » » bv := (*bitvector)(unsafe.Pointer(fn[1])
) | |
205 » » » » » frame.arglen = uintptr(bv.n / 2 * ptrSiz
e) | |
206 » » » » » frame.argmap = bv | |
207 » » » » } | |
208 » » » } | |
209 } | 215 } |
210 | 216 |
211 // Determine function SP where deferproc would find its argument
s. | 217 // Determine function SP where deferproc would find its argument
s. |
212 var sparg uintptr | 218 var sparg uintptr |
213 if usesLR { | 219 if usesLR { |
214 // On link register architectures, that's the standard b
ottom-of-stack plus 1 word | 220 // On link register architectures, that's the standard b
ottom-of-stack plus 1 word |
215 // for the saved LR. If the previous frame was a direct
call to newproc/deferproc, | 221 // for the saved LR. If the previous frame was a direct
call to newproc/deferproc, |
216 // however, the SP is three words lower than normal. | 222 // however, the SP is three words lower than normal. |
217 // If the function has no frame at all - perhaps it just
started, or perhaps | 223 // If the function has no frame at all - perhaps it just
started, or perhaps |
218 // it is a leaf with no local variables - then we cannot
possibly find its | 224 // it is a leaf with no local variables - then we cannot
possibly find its |
(...skipping 20 matching lines...) Expand all Loading... |
239 // is immediately below this function on the stack, then the fra
me | 245 // is immediately below this function on the stack, then the fra
me |
240 // stopped executing due to a trap, and frame.pc is probably not | 246 // stopped executing due to a trap, and frame.pc is probably not |
241 // a safe point for looking up liveness information. In this pan
icking case, | 247 // a safe point for looking up liveness information. In this pan
icking case, |
242 // the function either doesn't return at all (if it has no defer
s or if the | 248 // the function either doesn't return at all (if it has no defer
s or if the |
243 // defers do not recover) or it returns from one of the calls to | 249 // defers do not recover) or it returns from one of the calls to |
244 // deferproc a second time (if the corresponding deferred func r
ecovers). | 250 // deferproc a second time (if the corresponding deferred func r
ecovers). |
245 // It suffices to assume that the most recent deferproc is the o
ne that | 251 // It suffices to assume that the most recent deferproc is the o
ne that |
246 // returns; everything live at earlier deferprocs is still live
at that one. | 252 // returns; everything live at earlier deferprocs is still live
at that one. |
247 frame.continpc = frame.pc | 253 frame.continpc = frame.pc |
248 if waspanic { | 254 if waspanic { |
249 » » » if panic != nil && panic._defer.argp == sparg { | 255 » » » if _defer != nil && _defer.argp == sparg { |
250 » » » » frame.continpc = panic._defer.pc | |
251 » » » } else if _defer != nil && _defer.argp == sparg { | |
252 frame.continpc = _defer.pc | 256 frame.continpc = _defer.pc |
253 } else { | 257 } else { |
254 frame.continpc = 0 | 258 frame.continpc = 0 |
255 } | 259 } |
256 } | 260 } |
257 | 261 |
258 » » // Unwind our local panic & defer stacks past this frame. | 262 » » // Unwind our local defer stack past this frame. |
259 » » for panic != nil && (panic._defer == nil || panic._defer.argp ==
sparg || panic._defer.argp == _NoArgs) { | |
260 » » » panic = panic.link | |
261 » » } | |
262 for _defer != nil && (_defer.argp == sparg || _defer.argp == _No
Args) { | 263 for _defer != nil && (_defer.argp == sparg || _defer.argp == _No
Args) { |
263 _defer = _defer.link | 264 _defer = _defer.link |
264 } | 265 } |
265 | 266 |
266 if skip > 0 { | 267 if skip > 0 { |
267 skip-- | 268 skip-- |
268 goto skipped | 269 goto skipped |
269 } | 270 } |
270 | 271 |
271 if pcbuf != nil { | 272 if pcbuf != nil { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 // callbacks only happen when everything is stopped nicely. | 397 // callbacks only happen when everything is stopped nicely. |
397 // At other times, such as when gathering a stack for a profiling signal | 398 // At other times, such as when gathering a stack for a profiling signal |
398 // or when printing a traceback during a crash, everything may not be | 399 // or when printing a traceback during a crash, everything may not be |
399 // stopped nicely, and the stack walk may not be able to complete. | 400 // stopped nicely, and the stack walk may not be able to complete. |
400 // It's okay in those situations not to use up the entire defer stack: | 401 // It's okay in those situations not to use up the entire defer stack: |
401 // incomplete information then is still better than nothing. | 402 // incomplete information then is still better than nothing. |
402 if callback != nil && n < max && _defer != nil { | 403 if callback != nil && n < max && _defer != nil { |
403 if _defer != nil { | 404 if _defer != nil { |
404 print("runtime: g", gp.goid, ": leftover defer argp=", h
ex(_defer.argp), " pc=", hex(_defer.pc), "\n") | 405 print("runtime: g", gp.goid, ": leftover defer argp=", h
ex(_defer.argp), " pc=", hex(_defer.pc), "\n") |
405 } | 406 } |
406 if panic != nil { | |
407 print("runtime: g", gp.goid, ": leftover panic argp=", h
ex(panic._defer.argp), " pc=", hex(panic._defer.pc), "\n") | |
408 } | |
409 for _defer = gp._defer; _defer != nil; _defer = _defer.link { | 407 for _defer = gp._defer; _defer != nil; _defer = _defer.link { |
410 print("\tdefer ", _defer, " argp=", hex(_defer.argp), "
pc=", hex(_defer.pc), "\n") | 408 print("\tdefer ", _defer, " argp=", hex(_defer.argp), "
pc=", hex(_defer.pc), "\n") |
411 } | 409 } |
412 » » for panic = gp._panic; panic != nil; panic = panic.link { | 410 » » gothrow("traceback has leftover defers") |
413 » » » print("\tpanic ", panic, " defer ", panic._defer) | |
414 » » » if panic._defer != nil { | |
415 » » » » print(" argp=", hex(panic._defer.argp), " pc=",
hex(panic._defer.pc)) | |
416 » » » } | |
417 » » » print("\n") | |
418 » » } | |
419 » » gothrow("traceback has leftover defers or panics") | |
420 } | 411 } |
421 | 412 |
422 return n | 413 return n |
| 414 } |
| 415 |
| 416 func setArgInfo(frame *stkframe, f *_func, needArgMap bool) { |
| 417 frame.arglen = uintptr(f.args) |
| 418 if needArgMap && f.args == _ArgsSizeUnknown { |
| 419 // Extract argument bitmaps for reflect stubs from the calls the
y made to reflect. |
| 420 switch gofuncname(f) { |
| 421 case "reflect.makeFuncStub", "reflect.methodValueCall": |
| 422 arg0 := frame.sp |
| 423 if usesLR { |
| 424 arg0 += ptrSize |
| 425 } |
| 426 fn := *(**[2]uintptr)(unsafe.Pointer(arg0)) |
| 427 if fn[0] != f.entry { |
| 428 print("runtime: confused by ", gofuncname(f), "\
n") |
| 429 gothrow("reflect mismatch") |
| 430 } |
| 431 bv := (*bitvector)(unsafe.Pointer(fn[1])) |
| 432 frame.arglen = uintptr(bv.n / 2 * ptrSize) |
| 433 frame.argmap = bv |
| 434 } |
| 435 } |
423 } | 436 } |
424 | 437 |
425 func printcreatedby(gp *g) { | 438 func printcreatedby(gp *g) { |
426 // Show what created goroutine, except main goroutine (goid 1). | 439 // Show what created goroutine, except main goroutine (goid 1). |
427 pc := gp.gopc | 440 pc := gp.gopc |
428 f := findfunc(pc) | 441 f := findfunc(pc) |
429 if f != nil && showframe(f, gp) && gp.goid != 1 { | 442 if f != nil && showframe(f, gp) && gp.goid != 1 { |
430 print("created by ", gofuncname(f), "\n") | 443 print("created by ", gofuncname(f), "\n") |
431 tracepc := pc // back up to CALL instruction for funcline. | 444 tracepc := pc // back up to CALL instruction for funcline. |
432 if pc > f.entry { | 445 if pc > f.entry { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 // Does f mark the top of a goroutine stack? | 589 // Does f mark the top of a goroutine stack? |
577 func topofstack(f *_func) bool { | 590 func topofstack(f *_func) bool { |
578 pc := f.entry | 591 pc := f.entry |
579 return pc == goexitPC || | 592 return pc == goexitPC || |
580 pc == mstartPC || | 593 pc == mstartPC || |
581 pc == mcallPC || | 594 pc == mcallPC || |
582 pc == morestackPC || | 595 pc == morestackPC || |
583 pc == rt0_goPC || | 596 pc == rt0_goPC || |
584 externalthreadhandlerp != 0 && pc == externalthreadhandlerp | 597 externalthreadhandlerp != 0 && pc == externalthreadhandlerp |
585 } | 598 } |
LEFT | RIGHT |