summaryrefslogtreecommitdiff
path: root/src/runtime/traceback.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-09-12 07:46:11 -0400
committerRuss Cox <rsc@golang.org>2014-09-12 07:46:11 -0400
commit9ea01429fd02bdfe62a88d24de5fbb9d574a2f2e (patch)
tree74fa1dba900e37ddd2d333a1a90dd2290f41916f /src/runtime/traceback.go
parentb7709832debee316ddf16c56c15d7806bce63e06 (diff)
downloadgo-9ea01429fd02bdfe62a88d24de5fbb9d574a2f2e.tar.gz
runtime: stop scanning stack frames/args conservatively
The goal here is to commit fully to having precise information about stack frames. If we need information we don't have, crash instead of assuming we should scan conservatively. Since the stack copying assumes fully precise information, any crashes during garbage collection that are introduced by this CL are crashes that could have happened during stack copying instead. Those are harder to find because stacks are copied much less often than the garbage collector is invoked. In service of that goal, remove ARGSIZE macros from asm_*.s, change switchtoM to have no arguments (it doesn't have any live arguments), and add args and locals information to some frames that can call back into Go. LGTM=khr R=khr, rlh CC=golang-codereviews https://codereview.appspot.com/137540043
Diffstat (limited to 'src/runtime/traceback.go')
-rw-r--r--src/runtime/traceback.go48
1 files changed, 15 insertions, 33 deletions
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 84cb08c9e..eaf54db31 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -187,41 +187,23 @@ func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf
if usesLR {
frame.argp += ptrSize
}
- if f.args != _ArgsSizeUnknown {
- frame.arglen = uintptr(f.args)
- } else if callback != nil && (gofuncname(f) == "reflect.makeFuncStub" || gofuncname(f) == "reflect.methodValueCall") {
- // NOTE: Two calls to gofuncname on line above will be
- // collapsed to one when we pull out all the imprecise fallback code.
- arg0 := frame.sp
- if usesLR {
- arg0 += ptrSize
- }
- fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
- if fn[0] != f.entry {
- print("runtime: confused by ", gofuncname(f), "\n")
- gothrow("reflect mismatch")
- }
- bv := (*bitvector)(unsafe.Pointer(fn[1]))
- frame.arglen = uintptr(bv.n / 2 * ptrSize)
- frame.argmap = bv
- } else if flr == nil {
- frame.arglen = 0
- } else {
- i := funcarglen(flr, frame.lr)
- if i >= 0 {
- frame.arglen = uintptr(i)
- } else {
- var tmp string
- if flr != nil {
- tmp = gofuncname(flr)
- } else {
- tmp = "?"
+ frame.arglen = uintptr(f.args)
+ if callback != nil && f.args == _ArgsSizeUnknown {
+ // Extract argument bitmaps for reflect stubs from the calls they made to reflect.
+ switch gofuncname(f) {
+ case "reflect.makeFuncStub", "reflect.methodValueCall":
+ arg0 := frame.sp
+ if usesLR {
+ arg0 += ptrSize
}
- print("runtime: unknown argument frame size for ", gofuncname(f), " called from ", hex(frame.lr), " [", tmp, "]\n")
- if callback != nil {
- gothrow("invalid stack")
+ fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
+ if fn[0] != f.entry {
+ print("runtime: confused by ", gofuncname(f), "\n")
+ gothrow("reflect mismatch")
}
- frame.arglen = 0
+ bv := (*bitvector)(unsafe.Pointer(fn[1]))
+ frame.arglen = uintptr(bv.n / 2 * ptrSize)
+ frame.argmap = bv
}
}
}