1
0
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:
Michael Pratt 2023-02-22 17:50:20 -05:00 committed by Gopher Robot
parent 778a60c103
commit f60a2a9c94
2 changed files with 104 additions and 82 deletions

View File

@ -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,
}

View File

@ -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")
}
})
}
}