Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1133)

Delta Between Two Patch Sets: src/runtime/traceback.go

Issue 141490043: code review 141490043: runtime: use traceback to traverse defer structures (Closed)
Left Patch Set: diff -r c655137b930c3f839cc08f01f759ac5eb35d766f https://code.google.com/p/go/ Created 9 years, 6 months ago
Right Patch Set: diff -r 86735ca806e08b2ee073776fdddd0f7712dd788a https://code.google.com/p/go/ Created 9 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/runtime/stack_test.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(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
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
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
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
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
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
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 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b