From f60a2a9c9423222b52ecb5f6463787f913195127 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 22 Feb 2023 17:50:20 -0500 Subject: [PATCH] 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 Run-TryBot: Michael Pratt Auto-Submit: Michael Pratt TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/dwarfgen/dwinl.go | 6 +- src/cmd/link/internal/ld/dwarf_test.go | 166 ++++++++++++--------- 2 files changed, 97 insertions(+), 75 deletions(-) diff --git a/src/cmd/compile/internal/dwarfgen/dwinl.go b/src/cmd/compile/internal/dwarfgen/dwinl.go index c785e064a7..99e1ce9a81 100644 --- a/src/cmd/compile/internal/dwarfgen/dwinl.go +++ b/src/cmd/compile/internal/dwarfgen/dwinl.go @@ -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, } diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 17ed44ad6a..6fac85a01d 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -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) + 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, + }, + } + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() - const ( - callFile = "test.go" // basename - callLine = 16 - ) + // 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") + 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 - } + // 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 + // 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) - } + // 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) - } + // 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_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 != callLine { - t.Errorf("bad call_line attribute, found %d, want %d", cl, callLine) - } - } - if !found { - t.Fatalf("not enough inlined subroutines found in main.main") + // 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") + } + }) } } -- 2.50.0