diff options
author | Keith Randall <khr@google.com> | 2019-09-16 14:38:12 -0700 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2019-09-23 16:50:00 +0000 |
commit | a14efb1be3a59dffbf4dd9121191d6d656049564 (patch) | |
tree | 495e090dede94f044caa36cd3169e76806772816 /src/runtime/race.go | |
parent | 870080752d175d5cede350486acf36213c64f35c (diff) | |
download | go-a14efb1be3a59dffbf4dd9121191d6d656049564.tar.gz go-a14efb1be3a59dffbf4dd9121191d6d656049564.zip |
runtime: allow the Go runtime to return multiple stack frames for a single PC
Upgrade the thread sanitizer to handle mid-stack inlining correctly.
We can now return multiple stack frames for each pc that the thread sanitizer
gives us to symbolize.
To fix #33309, we still need to modify the tsan library with its portion
of this fix, rebuild the .syso files on all supported archs, and check
them into runtime/race.
Update #33309
Change-Id: I340013631ffc8428043ab7efe3a41b6bf5638eaf
Reviewed-on: https://go-review.googlesource.com/c/go/+/195781
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Diffstat (limited to 'src/runtime/race.go')
-rw-r--r-- | src/runtime/race.go | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/src/runtime/race.go b/src/runtime/race.go index c41e1ba222..d2fc6a3c47 100644 --- a/src/runtime/race.go +++ b/src/runtime/race.go @@ -155,15 +155,51 @@ func racecallback(cmd uintptr, ctx unsafe.Pointer) { } } +// raceSymbolizeCode reads ctx.pc and populates the rest of *ctx with +// information about the code at that pc. +// +// The race detector has already subtracted 1 from pcs, so they point to the last +// byte of call instructions (including calls to runtime.racewrite and friends). +// +// If the incoming pc is part of an inlined function, *ctx is populated +// with information about the inlined function, and on return ctx.pc is set +// to a pc in the logically containing function. (The race detector should call this +// function again with that pc.) +// +// If the incoming pc is not part of an inlined function, the return pc is unchanged. func raceSymbolizeCode(ctx *symbolizeCodeContext) { - f := findfunc(ctx.pc)._Func() + pc := ctx.pc + fi := findfunc(pc) + f := fi._Func() if f != nil { - file, line := f.FileLine(ctx.pc) + file, line := f.FileLine(pc) if line != 0 { - ctx.fn = cfuncname(f.funcInfo()) + if inldata := funcdata(fi, _FUNCDATA_InlTree); inldata != nil { + inltree := (*[1 << 20]inlinedCall)(inldata) + for { + ix := pcdatavalue(fi, _PCDATA_InlTreeIndex, pc, nil) + if ix >= 0 { + if inltree[ix].funcID == funcID_wrapper { + // ignore wrappers + // Back up to an instruction in the "caller". + pc = f.Entry() + uintptr(inltree[ix].parentPc) + continue + } + ctx.pc = f.Entry() + uintptr(inltree[ix].parentPc) // "caller" pc + ctx.fn = cfuncnameFromNameoff(fi, inltree[ix].func_) + ctx.line = uintptr(line) + ctx.file = &bytes(file)[0] // assume NUL-terminated + ctx.off = pc - f.Entry() + ctx.res = 1 + return + } + break + } + } + ctx.fn = cfuncname(fi) ctx.line = uintptr(line) ctx.file = &bytes(file)[0] // assume NUL-terminated - ctx.off = ctx.pc - f.Entry() + ctx.off = pc - f.Entry() ctx.res = 1 return } |