mirror of
https://github.com/golang/go
synced 2024-11-11 20:20:23 -07:00
cmd/compile: clean up buggy DWARF inlined info PC ranges
Repair the code that generates PC ranges for DWARF inlined routine instances to insure that if II Y is a child of II X within the inline tree, X's ranges include the ranges from Y. This is similar to what we're already doing for DWARF scopes. Updates #33188. Change-Id: I9bb552777fcd1ae93dc01872707667ad092b1dd9 Reviewed-on: https://go-review.googlesource.com/c/go/+/248724 Run-TryBot: Than McIntosh <thanm@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com> Trust: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
01df2febf5
commit
05082c90d5
@ -8,6 +8,7 @@ import (
|
|||||||
"cmd/internal/dwarf"
|
"cmd/internal/dwarf"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -170,12 +171,32 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
|
|||||||
addRange(inlcalls.Calls, start, fnsym.Size, curii, imap)
|
addRange(inlcalls.Calls, start, fnsym.Size, curii, imap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue 33188: if II foo is a child of II bar, then ensure that
|
||||||
|
// bar's ranges include the ranges of foo (the loop above will produce
|
||||||
|
// disjoint ranges).
|
||||||
|
for k, c := range inlcalls.Calls {
|
||||||
|
if c.Root {
|
||||||
|
unifyCallRanges(inlcalls, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
if Debug_gendwarfinl != 0 {
|
if Debug_gendwarfinl != 0 {
|
||||||
dumpInlCalls(inlcalls)
|
dumpInlCalls(inlcalls)
|
||||||
dumpInlVars(dwVars)
|
dumpInlVars(dwVars)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform a consistency check on inlined routine PC ranges
|
||||||
|
// produced by unifyCallRanges above. In particular, complain in
|
||||||
|
// cases where you have A -> B -> C (e.g. C is inlined into B, and
|
||||||
|
// B is inlined into A) and the ranges for B are not enclosed
|
||||||
|
// within the ranges for A, or C within B.
|
||||||
|
for k, c := range inlcalls.Calls {
|
||||||
|
if c.Root {
|
||||||
|
checkInlCall(fnsym.Name, inlcalls, fnsym.Size, k, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return inlcalls
|
return inlcalls
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,3 +376,74 @@ func dumpInlVars(dwvars []*dwarf.Var) {
|
|||||||
Ctxt.Logf("V%d: %s CI:%d II:%d IA:%d %s\n", i, dwv.Name, dwv.ChildIndex, dwv.InlIndex-1, ia, typ)
|
Ctxt.Logf("V%d: %s CI:%d II:%d IA:%d %s\n", i, dwv.Name, dwv.ChildIndex, dwv.InlIndex-1, ia, typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rangesContains(par []dwarf.Range, rng dwarf.Range) (bool, string) {
|
||||||
|
for _, r := range par {
|
||||||
|
if rng.Start >= r.Start && rng.End <= r.End {
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg := fmt.Sprintf("range [%d,%d) not contained in {", rng.Start, rng.End)
|
||||||
|
for _, r := range par {
|
||||||
|
msg += fmt.Sprintf(" [%d,%d)", r.Start, r.End)
|
||||||
|
}
|
||||||
|
msg += " }"
|
||||||
|
return false, msg
|
||||||
|
}
|
||||||
|
|
||||||
|
func rangesContainsAll(parent, child []dwarf.Range) (bool, string) {
|
||||||
|
for _, r := range child {
|
||||||
|
c, m := rangesContains(parent, r)
|
||||||
|
if !c {
|
||||||
|
return false, m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkInlCall verifies that the PC ranges for inline info 'idx' are
|
||||||
|
// enclosed/contained within the ranges of its parent inline (or if
|
||||||
|
// this is a root/toplevel inline, checks that the ranges fall within
|
||||||
|
// the extent of the top level function). A panic is issued if a
|
||||||
|
// malformed range is found.
|
||||||
|
func checkInlCall(funcName string, inlCalls dwarf.InlCalls, funcSize int64, idx, parentIdx int) {
|
||||||
|
|
||||||
|
// Callee
|
||||||
|
ic := inlCalls.Calls[idx]
|
||||||
|
callee := Ctxt.InlTree.InlinedFunction(ic.InlIndex).Name
|
||||||
|
calleeRanges := ic.Ranges
|
||||||
|
|
||||||
|
// Caller
|
||||||
|
caller := funcName
|
||||||
|
parentRanges := []dwarf.Range{dwarf.Range{Start: int64(0), End: funcSize}}
|
||||||
|
if parentIdx != -1 {
|
||||||
|
pic := inlCalls.Calls[parentIdx]
|
||||||
|
caller = Ctxt.InlTree.InlinedFunction(pic.InlIndex).Name
|
||||||
|
parentRanges = pic.Ranges
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callee ranges contained in caller ranges?
|
||||||
|
c, m := rangesContainsAll(parentRanges, calleeRanges)
|
||||||
|
if !c {
|
||||||
|
Fatalf("** malformed inlined routine range in %s: caller %s callee %s II=%d %s\n", funcName, caller, callee, idx, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now visit kids
|
||||||
|
for _, k := range ic.Children {
|
||||||
|
checkInlCall(funcName, inlCalls, funcSize, k, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unifyCallRanges ensures that the ranges for a given inline
|
||||||
|
// transitively include all of the ranges for its child inlines.
|
||||||
|
func unifyCallRanges(inlcalls dwarf.InlCalls, idx int) {
|
||||||
|
ic := &inlcalls.Calls[idx]
|
||||||
|
for _, childIdx := range ic.Children {
|
||||||
|
// First make sure child ranges are unified.
|
||||||
|
unifyCallRanges(inlcalls, childIdx)
|
||||||
|
|
||||||
|
// Then merge child ranges into ranges for this inline.
|
||||||
|
cic := inlcalls.Calls[childIdx]
|
||||||
|
ic.Ranges = dwarf.MergeRanges(ic.Ranges, cic.Ranges)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -101,26 +101,26 @@ func EnableLogging(doit bool) {
|
|||||||
logDwarf = doit
|
logDwarf = doit
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnifyRanges merges the list of ranges of c into the list of ranges of s
|
// MergeRanges creates a new range list by merging the ranges from
|
||||||
func (s *Scope) UnifyRanges(c *Scope) {
|
// its two arguments, then returns the new list.
|
||||||
out := make([]Range, 0, len(s.Ranges)+len(c.Ranges))
|
func MergeRanges(in1, in2 []Range) []Range {
|
||||||
|
out := make([]Range, 0, len(in1)+len(in2))
|
||||||
i, j := 0, 0
|
i, j := 0, 0
|
||||||
for {
|
for {
|
||||||
var cur Range
|
var cur Range
|
||||||
if i < len(s.Ranges) && j < len(c.Ranges) {
|
if i < len(in2) && j < len(in1) {
|
||||||
if s.Ranges[i].Start < c.Ranges[j].Start {
|
if in2[i].Start < in1[j].Start {
|
||||||
cur = s.Ranges[i]
|
cur = in2[i]
|
||||||
i++
|
i++
|
||||||
} else {
|
} else {
|
||||||
cur = c.Ranges[j]
|
cur = in1[j]
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
} else if i < len(s.Ranges) {
|
} else if i < len(in2) {
|
||||||
cur = s.Ranges[i]
|
cur = in2[i]
|
||||||
i++
|
i++
|
||||||
} else if j < len(c.Ranges) {
|
} else if j < len(in1) {
|
||||||
cur = c.Ranges[j]
|
cur = in1[j]
|
||||||
j++
|
j++
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
@ -133,7 +133,12 @@ func (s *Scope) UnifyRanges(c *Scope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Ranges = out
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnifyRanges merges the ranges from 'c' into the list of ranges for 's'.
|
||||||
|
func (s *Scope) UnifyRanges(c *Scope) {
|
||||||
|
s.Ranges = MergeRanges(s.Ranges, c.Ranges)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendRange adds r to s, if r is non-empty.
|
// AppendRange adds r to s, if r is non-empty.
|
||||||
|
Loading…
Reference in New Issue
Block a user