mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: use getcallerpc for racefuncentry
Currently, when instrumenting for the race detector, the compiler inserts racefuncentry/racefuncentryfp at the entry of instrumented functions. racefuncentry takes the caller's PC. On AMD64, we synthesize a node which points to -8(FP) which is where the return address is stored. Later this node turns to a special Arg in SSA that is not really an argument. This causes problems in the new ABI work so that special node has to be special-cased. This CL changes the special node to a call to getcallerpc, which lowers to an intrinsic in SSA. This also unifies AMD64 code path and LR machine code path, as getcallerpc works on all platforms. Change-Id: I1377e140b91e0473cfcadfda221f26870c1b124d Reviewed-on: https://go-review.googlesource.com/c/go/+/297929 Trust: Cherry Zhang <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
a829114b21
commit
a22bd3dc73
6 changed files with 44 additions and 55 deletions
|
|
@ -70,6 +70,6 @@ var NoInstrumentPkgs = []string{
|
||||||
"internal/cpu",
|
"internal/cpu",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't insert racefuncenterfp/racefuncexit into the following packages.
|
// Don't insert racefuncenter/racefuncexit into the following packages.
|
||||||
// Memory accesses in the packages are either uninteresting or will cause false positives.
|
// Memory accesses in the packages are either uninteresting or will cause false positives.
|
||||||
var NoRacePkgs = []string{"sync", "sync/atomic"}
|
var NoRacePkgs = []string{"sync", "sync/atomic"}
|
||||||
|
|
|
||||||
|
|
@ -1612,18 +1612,18 @@ func needRaceCleanup(sym *AuxCall, v *Value) bool {
|
||||||
if !f.Config.Race {
|
if !f.Config.Race {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isSameCall(sym, "runtime.racefuncenter") && !isSameCall(sym, "runtime.racefuncenterfp") && !isSameCall(sym, "runtime.racefuncexit") {
|
if !isSameCall(sym, "runtime.racefuncenter") && !isSameCall(sym, "runtime.racefuncexit") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
switch v.Op {
|
switch v.Op {
|
||||||
case OpStaticCall, OpStaticLECall:
|
case OpStaticCall, OpStaticLECall:
|
||||||
// Check for racefuncenter/racefuncenterfp will encounter racefuncexit and vice versa.
|
// Check for racefuncenter will encounter racefuncexit and vice versa.
|
||||||
// Allow calls to panic*
|
// Allow calls to panic*
|
||||||
s := v.Aux.(*AuxCall).Fn.String()
|
s := v.Aux.(*AuxCall).Fn.String()
|
||||||
switch s {
|
switch s {
|
||||||
case "runtime.racefuncenter", "runtime.racefuncenterfp", "runtime.racefuncexit",
|
case "runtime.racefuncenter", "runtime.racefuncexit",
|
||||||
"runtime.panicdivide", "runtime.panicwrap",
|
"runtime.panicdivide", "runtime.panicwrap",
|
||||||
"runtime.panicshift":
|
"runtime.panicshift":
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -4564,6 +4564,9 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder {
|
||||||
if sym.Pkg == types.LocalPkg {
|
if sym.Pkg == types.LocalPkg {
|
||||||
pkg = base.Ctxt.Pkgpath
|
pkg = base.Ctxt.Pkgpath
|
||||||
}
|
}
|
||||||
|
if sym.Pkg == ir.Pkgs.Runtime {
|
||||||
|
pkg = "runtime"
|
||||||
|
}
|
||||||
if base.Flag.Race && pkg == "sync/atomic" {
|
if base.Flag.Race && pkg == "sync/atomic" {
|
||||||
// The race detector needs to be able to intercept these calls.
|
// The race detector needs to be able to intercept these calls.
|
||||||
// We can't intrinsify them.
|
// We can't intrinsify them.
|
||||||
|
|
|
||||||
|
|
@ -177,26 +177,26 @@ var runtimeDecls = [...]struct {
|
||||||
{"uint64tofloat64", funcTag, 116},
|
{"uint64tofloat64", funcTag, 116},
|
||||||
{"uint32tofloat64", funcTag, 117},
|
{"uint32tofloat64", funcTag, 117},
|
||||||
{"complex128div", funcTag, 118},
|
{"complex128div", funcTag, 118},
|
||||||
|
{"getcallerpc", funcTag, 119},
|
||||||
{"racefuncenter", funcTag, 31},
|
{"racefuncenter", funcTag, 31},
|
||||||
{"racefuncenterfp", funcTag, 9},
|
|
||||||
{"racefuncexit", funcTag, 9},
|
{"racefuncexit", funcTag, 9},
|
||||||
{"raceread", funcTag, 31},
|
{"raceread", funcTag, 31},
|
||||||
{"racewrite", funcTag, 31},
|
{"racewrite", funcTag, 31},
|
||||||
{"racereadrange", funcTag, 119},
|
{"racereadrange", funcTag, 120},
|
||||||
{"racewriterange", funcTag, 119},
|
{"racewriterange", funcTag, 120},
|
||||||
{"msanread", funcTag, 119},
|
{"msanread", funcTag, 120},
|
||||||
{"msanwrite", funcTag, 119},
|
{"msanwrite", funcTag, 120},
|
||||||
{"msanmove", funcTag, 120},
|
{"msanmove", funcTag, 121},
|
||||||
{"checkptrAlignment", funcTag, 121},
|
{"checkptrAlignment", funcTag, 122},
|
||||||
{"checkptrArithmetic", funcTag, 123},
|
{"checkptrArithmetic", funcTag, 124},
|
||||||
{"libfuzzerTraceCmp1", funcTag, 125},
|
{"libfuzzerTraceCmp1", funcTag, 126},
|
||||||
{"libfuzzerTraceCmp2", funcTag, 127},
|
{"libfuzzerTraceCmp2", funcTag, 128},
|
||||||
{"libfuzzerTraceCmp4", funcTag, 128},
|
{"libfuzzerTraceCmp4", funcTag, 129},
|
||||||
{"libfuzzerTraceCmp8", funcTag, 129},
|
{"libfuzzerTraceCmp8", funcTag, 130},
|
||||||
{"libfuzzerTraceConstCmp1", funcTag, 125},
|
{"libfuzzerTraceConstCmp1", funcTag, 126},
|
||||||
{"libfuzzerTraceConstCmp2", funcTag, 127},
|
{"libfuzzerTraceConstCmp2", funcTag, 128},
|
||||||
{"libfuzzerTraceConstCmp4", funcTag, 128},
|
{"libfuzzerTraceConstCmp4", funcTag, 129},
|
||||||
{"libfuzzerTraceConstCmp8", funcTag, 129},
|
{"libfuzzerTraceConstCmp8", funcTag, 130},
|
||||||
{"x86HasPOPCNT", varTag, 6},
|
{"x86HasPOPCNT", varTag, 6},
|
||||||
{"x86HasSSE41", varTag, 6},
|
{"x86HasSSE41", varTag, 6},
|
||||||
{"x86HasFMA", varTag, 6},
|
{"x86HasFMA", varTag, 6},
|
||||||
|
|
@ -219,7 +219,7 @@ func params(tlist ...*types.Type) []*types.Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runtimeTypes() []*types.Type {
|
func runtimeTypes() []*types.Type {
|
||||||
var typs [130]*types.Type
|
var typs [131]*types.Type
|
||||||
typs[0] = types.ByteType
|
typs[0] = types.ByteType
|
||||||
typs[1] = types.NewPtr(typs[0])
|
typs[1] = types.NewPtr(typs[0])
|
||||||
typs[2] = types.Types[types.TANY]
|
typs[2] = types.Types[types.TANY]
|
||||||
|
|
@ -339,16 +339,17 @@ func runtimeTypes() []*types.Type {
|
||||||
typs[116] = newSig(params(typs[24]), params(typs[20]))
|
typs[116] = newSig(params(typs[24]), params(typs[20]))
|
||||||
typs[117] = newSig(params(typs[65]), params(typs[20]))
|
typs[117] = newSig(params(typs[65]), params(typs[20]))
|
||||||
typs[118] = newSig(params(typs[26], typs[26]), params(typs[26]))
|
typs[118] = newSig(params(typs[26], typs[26]), params(typs[26]))
|
||||||
typs[119] = newSig(params(typs[5], typs[5]), nil)
|
typs[119] = newSig(nil, params(typs[5]))
|
||||||
typs[120] = newSig(params(typs[5], typs[5], typs[5]), nil)
|
typs[120] = newSig(params(typs[5], typs[5]), nil)
|
||||||
typs[121] = newSig(params(typs[7], typs[1], typs[5]), nil)
|
typs[121] = newSig(params(typs[5], typs[5], typs[5]), nil)
|
||||||
typs[122] = types.NewSlice(typs[7])
|
typs[122] = newSig(params(typs[7], typs[1], typs[5]), nil)
|
||||||
typs[123] = newSig(params(typs[7], typs[122]), nil)
|
typs[123] = types.NewSlice(typs[7])
|
||||||
typs[124] = types.Types[types.TUINT8]
|
typs[124] = newSig(params(typs[7], typs[123]), nil)
|
||||||
typs[125] = newSig(params(typs[124], typs[124]), nil)
|
typs[125] = types.Types[types.TUINT8]
|
||||||
typs[126] = types.Types[types.TUINT16]
|
typs[126] = newSig(params(typs[125], typs[125]), nil)
|
||||||
typs[127] = newSig(params(typs[126], typs[126]), nil)
|
typs[127] = types.Types[types.TUINT16]
|
||||||
typs[128] = newSig(params(typs[65], typs[65]), nil)
|
typs[128] = newSig(params(typs[127], typs[127]), nil)
|
||||||
typs[129] = newSig(params(typs[24], typs[24]), nil)
|
typs[129] = newSig(params(typs[65], typs[65]), nil)
|
||||||
|
typs[130] = newSig(params(typs[24], typs[24]), nil)
|
||||||
return typs[:]
|
return typs[:]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
// to update builtin.go. This is not done automatically
|
// to update builtin.go. This is not done automatically
|
||||||
// to avoid depending on having a working compiler binary.
|
// to avoid depending on having a working compiler binary.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
// +build ignore
|
// +build ignore
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
@ -224,9 +225,10 @@ func uint32tofloat64(uint32) float64
|
||||||
|
|
||||||
func complex128div(num complex128, den complex128) (quo complex128)
|
func complex128div(num complex128, den complex128) (quo complex128)
|
||||||
|
|
||||||
|
func getcallerpc() uintptr
|
||||||
|
|
||||||
// race detection
|
// race detection
|
||||||
func racefuncenter(uintptr)
|
func racefuncenter(uintptr)
|
||||||
func racefuncenterfp()
|
|
||||||
func racefuncexit()
|
func racefuncexit()
|
||||||
func raceread(uintptr)
|
func raceread(uintptr)
|
||||||
func racewrite(uintptr)
|
func racewrite(uintptr)
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,8 @@ package walk
|
||||||
import (
|
import (
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/ssagen"
|
|
||||||
"cmd/compile/internal/typecheck"
|
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
"cmd/internal/sys"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func instrument(fn *ir.Func) {
|
func instrument(fn *ir.Func) {
|
||||||
|
|
@ -26,26 +23,12 @@ func instrument(fn *ir.Func) {
|
||||||
if base.Flag.Race {
|
if base.Flag.Race {
|
||||||
lno := base.Pos
|
lno := base.Pos
|
||||||
base.Pos = src.NoXPos
|
base.Pos = src.NoXPos
|
||||||
if ssagen.Arch.LinkArch.Arch.Family != sys.AMD64 {
|
var init ir.Nodes
|
||||||
fn.Enter.Prepend(mkcallstmt("racefuncenterfp"))
|
fn.Enter.Prepend(mkcallstmt("racefuncenter", mkcall("getcallerpc", types.Types[types.TUINTPTR], &init)))
|
||||||
fn.Exit.Append(mkcallstmt("racefuncexit"))
|
if len(init) != 0 {
|
||||||
} else {
|
base.Fatalf("race walk: unexpected init for getcallerpc")
|
||||||
|
|
||||||
// nodpc is the PC of the caller as extracted by
|
|
||||||
// getcallerpc. We use -widthptr(FP) for x86.
|
|
||||||
// This only works for amd64. This will not
|
|
||||||
// work on arm or others that might support
|
|
||||||
// race in the future.
|
|
||||||
|
|
||||||
nodpc := ir.NewNameAt(src.NoXPos, typecheck.Lookup(".fp"))
|
|
||||||
nodpc.Class = ir.PPARAM
|
|
||||||
nodpc.SetUsed(true)
|
|
||||||
nodpc.SetType(types.Types[types.TUINTPTR])
|
|
||||||
nodpc.SetFrameOffset(int64(-types.PtrSize))
|
|
||||||
fn.Dcl = append(fn.Dcl, nodpc)
|
|
||||||
fn.Enter.Prepend(mkcallstmt("racefuncenter", nodpc))
|
|
||||||
fn.Exit.Append(mkcallstmt("racefuncexit"))
|
|
||||||
}
|
}
|
||||||
|
fn.Exit.Append(mkcallstmt("racefuncexit"))
|
||||||
base.Pos = lno
|
base.Pos = lno
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue