mirror of
https://github.com/golang/go
synced 2024-11-23 20:50:04 -07:00
cmd/compile: adjust inlined DW_AT_call_line by //line
insertInlCall mistakenly uses the absolute line number of the call rather than the relative line number (adjusted by //line). Switch to the correct line number. The call filename was already correct. Fixes #58648 Change-Id: Id8d1848895233e972d8cfe9c5789a88e62d06556 Reviewed-on: https://go-review.googlesource.com/c/go/+/470876 Reviewed-by: Than McIntosh <thanm@google.com> Run-TryBot: Michael Pratt <mpratt@google.com> Auto-Submit: Michael Pratt <mpratt@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
778a60c103
commit
f60a2a9c94
@ -273,13 +273,13 @@ func insertInlCall(dwcalls *dwarf.InlCalls, inlIdx int, imap map[int]int) int {
|
||||
// Create new entry for this inline
|
||||
inlinedFn := base.Ctxt.InlTree.InlinedFunction(inlIdx)
|
||||
callXPos := base.Ctxt.InlTree.CallPos(inlIdx)
|
||||
callPos := base.Ctxt.PosTable.Pos(callXPos)
|
||||
callFileSym := base.Ctxt.Lookup(callPos.Base().SymFilename())
|
||||
absFnSym := base.Ctxt.DwFixups.AbsFuncDwarfSym(inlinedFn)
|
||||
pb := base.Ctxt.PosTable.Pos(callXPos).Base()
|
||||
callFileSym := base.Ctxt.Lookup(pb.SymFilename())
|
||||
ic := dwarf.InlCall{
|
||||
InlIndex: inlIdx,
|
||||
CallFile: callFileSym,
|
||||
CallLine: uint32(callXPos.Line()),
|
||||
CallLine: uint32(callPos.RelLine()),
|
||||
AbsFunSym: absFnSym,
|
||||
Root: parCallIdx == -1,
|
||||
}
|
||||
|
@ -530,91 +530,113 @@ func inlined() int {
|
||||
return notinlined()
|
||||
}
|
||||
|
||||
%s
|
||||
func main() {
|
||||
x := inlined()
|
||||
G = x
|
||||
}
|
||||
`
|
||||
// Note: this is a build with "-l=4", as opposed to "-l -N". The
|
||||
// test is intended to verify DWARF that is only generated when
|
||||
// the inliner is active. We're only going to look at the DWARF for
|
||||
// main.main, however, hence we build with "-gcflags=-l=4" as opposed
|
||||
// to "-gcflags=all=-l=4".
|
||||
d, ex := gobuildAndExamine(t, prog, OptInl4)
|
||||
|
||||
const (
|
||||
callFile = "test.go" // basename
|
||||
callLine = 16
|
||||
)
|
||||
|
||||
maindie := findSubprogramDIE(t, ex, "main.main")
|
||||
|
||||
// Walk main's children and pick out the inlined subroutines
|
||||
mainIdx := ex.IdxFromOffset(maindie.Offset)
|
||||
childDies := ex.Children(mainIdx)
|
||||
found := false
|
||||
for _, child := range childDies {
|
||||
if child.Tag != dwarf.TagInlinedSubroutine {
|
||||
continue
|
||||
}
|
||||
|
||||
// Found an inlined subroutine.
|
||||
if found {
|
||||
t.Fatalf("Found multiple inlined subroutines, expect only one")
|
||||
}
|
||||
found = true
|
||||
|
||||
// Locate abstract origin.
|
||||
ooff, originOK := child.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
|
||||
if !originOK {
|
||||
t.Fatalf("no abstract origin attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
originDIE := ex.EntryFromOffset(ooff)
|
||||
if originDIE == nil {
|
||||
t.Fatalf("can't locate origin DIE at off %v", ooff)
|
||||
}
|
||||
|
||||
// Name should check out.
|
||||
name, ok := originDIE.Val(dwarf.AttrName).(string)
|
||||
if !ok {
|
||||
t.Fatalf("no name attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
if name != "main.inlined" {
|
||||
t.Fatalf("expected inlined routine %s got %s", "main.cand", name)
|
||||
}
|
||||
|
||||
// Verify that the call_file attribute for the inlined
|
||||
// instance is ok. In this case it should match the file
|
||||
// for the main routine. To do this we need to locate the
|
||||
// compilation unit DIE that encloses what we're looking
|
||||
// at; this can be done with the examiner.
|
||||
cf, cfOK := child.Val(dwarf.AttrCallFile).(int64)
|
||||
if !cfOK {
|
||||
t.Fatalf("no call_file attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
file, err := ex.FileRef(d, mainIdx, cf)
|
||||
if err != nil {
|
||||
t.Errorf("FileRef: %v", err)
|
||||
continue
|
||||
}
|
||||
base := filepath.Base(file)
|
||||
if base != callFile {
|
||||
t.Errorf("bad call_file attribute, found '%s', want '%s'",
|
||||
file, callFile)
|
||||
}
|
||||
|
||||
// Verify that the call_line attribute for the inlined
|
||||
// instance is ok.
|
||||
cl, clOK := child.Val(dwarf.AttrCallLine).(int64)
|
||||
if !clOK {
|
||||
t.Fatalf("no call_line attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
if cl != callLine {
|
||||
t.Errorf("bad call_line attribute, found %d, want %d", cl, callLine)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prog string
|
||||
file string // basename
|
||||
line int64
|
||||
}{
|
||||
{
|
||||
name: "normal",
|
||||
prog: fmt.Sprintf(prog, ""),
|
||||
file: "test.go",
|
||||
line: 17,
|
||||
},
|
||||
{
|
||||
name: "line-directive",
|
||||
prog: fmt.Sprintf(prog, "//line /foobar.go:200"),
|
||||
file: "foobar.go",
|
||||
line: 201,
|
||||
},
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("not enough inlined subroutines found in main.main")
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Note: this is a build with "-l=4", as opposed to "-l -N". The
|
||||
// test is intended to verify DWARF that is only generated when
|
||||
// the inliner is active. We're only going to look at the DWARF for
|
||||
// main.main, however, hence we build with "-gcflags=-l=4" as opposed
|
||||
// to "-gcflags=all=-l=4".
|
||||
d, ex := gobuildAndExamine(t, tc.prog, OptInl4)
|
||||
|
||||
maindie := findSubprogramDIE(t, ex, "main.main")
|
||||
|
||||
// Walk main's children and pick out the inlined subroutines
|
||||
mainIdx := ex.IdxFromOffset(maindie.Offset)
|
||||
childDies := ex.Children(mainIdx)
|
||||
found := false
|
||||
for _, child := range childDies {
|
||||
if child.Tag != dwarf.TagInlinedSubroutine {
|
||||
continue
|
||||
}
|
||||
|
||||
// Found an inlined subroutine.
|
||||
if found {
|
||||
t.Fatalf("Found multiple inlined subroutines, expect only one")
|
||||
}
|
||||
found = true
|
||||
|
||||
// Locate abstract origin.
|
||||
ooff, originOK := child.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
|
||||
if !originOK {
|
||||
t.Fatalf("no abstract origin attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
originDIE := ex.EntryFromOffset(ooff)
|
||||
if originDIE == nil {
|
||||
t.Fatalf("can't locate origin DIE at off %v", ooff)
|
||||
}
|
||||
|
||||
// Name should check out.
|
||||
name, ok := originDIE.Val(dwarf.AttrName).(string)
|
||||
if !ok {
|
||||
t.Fatalf("no name attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
if name != "main.inlined" {
|
||||
t.Fatalf("expected inlined routine %s got %s", "main.cand", name)
|
||||
}
|
||||
|
||||
// Verify that the call_file attribute for the inlined
|
||||
// instance is ok. In this case it should match the file
|
||||
// for the main routine. To do this we need to locate the
|
||||
// compilation unit DIE that encloses what we're looking
|
||||
// at; this can be done with the examiner.
|
||||
cf, cfOK := child.Val(dwarf.AttrCallFile).(int64)
|
||||
if !cfOK {
|
||||
t.Fatalf("no call_file attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
file, err := ex.FileRef(d, mainIdx, cf)
|
||||
if err != nil {
|
||||
t.Errorf("FileRef: %v", err)
|
||||
continue
|
||||
}
|
||||
base := filepath.Base(file)
|
||||
if base != tc.file {
|
||||
t.Errorf("bad call_file attribute, found '%s', want '%s'",
|
||||
file, tc.file)
|
||||
}
|
||||
|
||||
// Verify that the call_line attribute for the inlined
|
||||
// instance is ok.
|
||||
cl, clOK := child.Val(dwarf.AttrCallLine).(int64)
|
||||
if !clOK {
|
||||
t.Fatalf("no call_line attr for inlined subroutine at offset %v", child.Offset)
|
||||
}
|
||||
if cl != tc.line {
|
||||
t.Errorf("bad call_line attribute, found %d, want %d", cl, tc.line)
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("not enough inlined subroutines found in main.main")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user