]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link/internal/ld: add dwarf testing helpers
authorMichael Pratt <mpratt@google.com>
Thu, 15 Dec 2022 22:17:01 +0000 (17:17 -0500)
committerGopher Robot <gobot@golang.org>
Mon, 30 Jan 2023 16:32:56 +0000 (16:32 +0000)
Many tests build a program just to analyze it with dwtest.Examiner. Add
gobuildAndExamine, a helper that returns Examiner directly to reduce
duplication in these tests.

Many tests also lookup the DIE for a specific subprogram, which includes
several verification steps. Package those up in findSubprogramDIE.

Change-Id: I72202ba289ae8389b682be525ff7e6cfbfc00ff3
Reviewed-on: https://go-review.googlesource.com/c/go/+/458196
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/link/internal/ld/dwarf_test.go

index a11541f3208ab5f672ddaf19bd1e94f028dfb36b..e3a2109445f4eccf592347b1c022df49ffa24823 100644 (file)
@@ -135,6 +135,45 @@ func gobuildTestdata(t *testing.T, tdir string, pkgDir string, gcflags string) *
        return &builtFile{f, dst}
 }
 
+// Helper to build a snippet of source for examination with dwtest.Examiner.
+func gobuildAndExamine(t *testing.T, source string, gcflags string) (*dwarf.Data, *dwtest.Examiner) {
+       dir := t.TempDir()
+
+       f := gobuild(t, dir, source, gcflags)
+       defer f.Close()
+
+       d, err := f.DWARF()
+       if err != nil {
+               t.Fatalf("error reading DWARF in program %q: %v", source, err)
+       }
+
+       rdr := d.Reader()
+       ex := &dwtest.Examiner{}
+       if err := ex.Populate(rdr); err != nil {
+               t.Fatalf("error populating DWARF examiner for program %q: %v", source, err)
+       }
+
+       return d, ex
+}
+
+func findSubprogramDIE(t *testing.T, ex *dwtest.Examiner, sym string) *dwarf.Entry {
+       dies := ex.Named(sym)
+       if len(dies) == 0 {
+               t.Fatalf("unable to locate DIE for %s", sym)
+       }
+       if len(dies) != 1 {
+               t.Fatalf("more than one %s DIE: %+v", sym, dies)
+       }
+       die := dies[0]
+
+       // Vet the DIE.
+       if die.Tag != dwarf.TagSubprogram {
+               t.Fatalf("unexpected tag %v on %s DIE", die.Tag, sym)
+       }
+
+       return die
+}
+
 func TestEmbeddedStructMarker(t *testing.T) {
        t.Parallel()
        testenv.MustHaveGoBuild(t)
@@ -341,21 +380,7 @@ func varDeclCoordsAndSubprogramDeclFile(t *testing.T, testpoint string, expectFi
        prog := fmt.Sprintf("package main\n%s\nfunc main() {\n\nvar i int\ni = i\n}\n", directive)
        const iLineOffset = 2
 
-       dir := t.TempDir()
-
-       f := gobuild(t, dir, prog, NoOpt)
-       defer f.Close()
-
-       d, err := f.DWARF()
-       if err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
-
-       rdr := d.Reader()
-       ex := dwtest.Examiner{}
-       if err := ex.Populate(rdr); err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
+       d, ex := gobuildAndExamine(t, prog, NoOpt)
 
        // Locate the main.main DIE
        mains := ex.Named("main.main")
@@ -466,44 +491,17 @@ func main() {
     G = x
 }
 `
-       dir := t.TempDir()
-
        // 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".
-       f := gobuild(t, dir, prog, OptInl4)
-       defer f.Close()
-
-       d, err := f.DWARF()
-       if err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
+       d, ex := gobuildAndExamine(t, prog, OptInl4)
 
        // The inlined subroutines we expect to visit
        expectedInl := []string{"main.cand"}
 
-       rdr := d.Reader()
-       ex := dwtest.Examiner{}
-       if err := ex.Populate(rdr); err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
-
-       // Locate the main.main DIE
-       mains := ex.Named("main.main")
-       if len(mains) == 0 {
-               t.Fatalf("unable to locate DIE for main.main")
-       }
-       if len(mains) != 1 {
-               t.Fatalf("more than one main.main DIE")
-       }
-       maindie := mains[0]
-
-       // Vet the main.main DIE
-       if maindie.Tag != dwarf.TagSubprogram {
-               t.Fatalf("unexpected tag %v on main.main DIE", maindie.Tag)
-       }
+       maindie := findSubprogramDIE(t, ex, "main.main")
 
        // Walk main's children and pick out the inlined subroutines
        mainIdx := ex.IdxFromOffset(maindie.Offset)
@@ -1334,20 +1332,12 @@ func TestIssue39757(t *testing.T) {
                t.Fatalf("error parsing DWARF: %v", err)
        }
        rdr := dw.Reader()
-       ex := dwtest.Examiner{}
+       ex := &dwtest.Examiner{}
        if err := ex.Populate(rdr); err != nil {
                t.Fatalf("error reading DWARF: %v", err)
        }
 
-       // Locate the main.main DIE
-       mains := ex.Named("main.main")
-       if len(mains) == 0 {
-               t.Fatalf("unable to locate DIE for main.main")
-       }
-       if len(mains) != 1 {
-               t.Fatalf("more than one main.main DIE")
-       }
-       maindie := mains[0]
+       maindie := findSubprogramDIE(t, ex, "main.main")
 
        // Collect the start/end PC for main.main
        lowpc := maindie.Val(dwarf.AttrLowpc).(uint64)
@@ -1556,38 +1546,12 @@ func main() {
        println(v1, v2, v3[0], v4, v5, v6)
 }
 `
-       dir := t.TempDir()
-       f := gobuild(t, dir, prog, NoOpt)
-       defer f.Close()
+       _, ex := gobuildAndExamine(t, prog, NoOpt)
 
-       d, err := f.DWARF()
-       if err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
-
-       rdr := d.Reader()
-       ex := dwtest.Examiner{}
-       if err := ex.Populate(rdr); err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
-
-       // Locate the main.ABC DIE
-       abcs := ex.Named("main.ABC")
-       if len(abcs) == 0 {
-               t.Fatalf("unable to locate DIE for main.ABC")
-       }
-       if len(abcs) != 1 {
-               t.Fatalf("more than one main.ABC DIE")
-       }
-       abcdie := abcs[0]
-
-       // Vet the DIE
-       if abcdie.Tag != dwarf.TagSubprogram {
-               t.Fatalf("unexpected tag %v on main.ABC DIE", abcdie.Tag)
-       }
+       abcdie := findSubprogramDIE(t, ex, "main.ABC")
 
        // Call a helper to collect param info.
-       found := processParams(abcdie, &ex)
+       found := processParams(abcdie, ex)
 
        // Make sure we see all of the expected params in the proper
        // order, that they have the varparam attr, and the varparam is
@@ -1788,20 +1752,7 @@ func main() {
 
 }
 `
-       dir := t.TempDir()
-       f := gobuild(t, dir, prog, DefaultOpt)
-       defer f.Close()
-
-       d, err := f.DWARF()
-       if err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
-
-       rdr := d.Reader()
-       ex := dwtest.Examiner{}
-       if err := ex.Populate(rdr); err != nil {
-               t.Fatalf("error reading DWARF: %v", err)
-       }
+       _, ex := gobuildAndExamine(t, prog, DefaultOpt)
 
        testcases := []struct {
                tag      string
@@ -1828,22 +1779,10 @@ func main() {
        for _, tc := range testcases {
                // Locate the proper DIE
                which := fmt.Sprintf("main.%s", tc.tag)
-               tcs := ex.Named(which)
-               if len(tcs) == 0 {
-                       t.Fatalf("unable to locate DIE for " + which)
-               }
-               if len(tcs) != 1 {
-                       t.Fatalf("more than one " + which + " DIE")
-               }
-               die := tcs[0]
-
-               // Vet the DIE
-               if die.Tag != dwarf.TagSubprogram {
-                       t.Fatalf("unexpected tag %v on "+which+" DIE", die.Tag)
-               }
+               die := findSubprogramDIE(t, ex, which)
 
                // Examine params for this subprogram.
-               foundParams := processParams(die, &ex)
+               foundParams := processParams(die, ex)
                if foundParams != tc.expected {
                        t.Errorf("check failed for testcase %s -- wanted:\n%s\ngot:%s\n",
                                tc.tag, tc.expected, foundParams)
@@ -1956,29 +1895,18 @@ func main() {
 `
 
        for _, opt := range []string{NoOpt, DefaultOpt} {
-               dir := t.TempDir()
-               f := gobuild(t, dir, prog, opt)
-               defer f.Close()
-               defer os.RemoveAll(dir)
-
-               d, err := f.DWARF()
-               if err != nil {
-                       t.Fatalf("error reading DWARF: %v", err)
-               }
-
-               rdr := d.Reader()
-               ex := dwtest.Examiner{}
-               if err := ex.Populate(rdr); err != nil {
-                       t.Fatalf("error reading DWARF: %v", err)
-               }
-
-               // Locate the main.zeroSizedVariable DIE
-               abcs := ex.Named("zeroSizedVariable")
-               if len(abcs) == 0 {
-                       t.Fatalf("unable to locate DIE for zeroSizedVariable")
-               }
-               if len(abcs) != 1 {
-                       t.Fatalf("more than one zeroSizedVariable DIE")
-               }
+               opt := opt
+               t.Run(opt, func(t *testing.T) {
+                       _, ex := gobuildAndExamine(t, prog, opt)
+
+                       // Locate the main.zeroSizedVariable DIE
+                       abcs := ex.Named("zeroSizedVariable")
+                       if len(abcs) == 0 {
+                               t.Fatalf("unable to locate DIE for zeroSizedVariable")
+                       }
+                       if len(abcs) != 1 {
+                               t.Fatalf("more than one zeroSizedVariable DIE")
+                       }
+               })
        }
 }