Commit a14efb1b authored by Keith Randall's avatar Keith Randall Committed by Keith Randall

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: default avatarDmitry Vyukov <dvyukov@google.com>
parent 87008075
......@@ -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
}
......
......@@ -735,13 +735,15 @@ func funcname(f funcInfo) string {
return gostringnocopy(cfuncname(f))
}
func funcnameFromNameoff(f funcInfo, nameoff int32) string {
datap := f.datap
func cfuncnameFromNameoff(f funcInfo, nameoff int32) *byte {
if !f.valid() {
return ""
return nil
}
cstr := &datap.pclntable[nameoff]
return gostringnocopy(cstr)
return &f.datap.pclntable[nameoff]
}
func funcnameFromNameoff(f funcInfo, nameoff int32) string {
return gostringnocopy(cfuncnameFromNameoff(f, nameoff))
}
func funcfile(f funcInfo, fileno int32) string {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment