diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 696a80bcdc..744e2153a3 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1521,10 +1521,20 @@ func dwarfgeneratedebugsyms(ctxt *Link) { } // Needed by the prettyprinter code for interface inspection. - defgotype(ctxt, lookupOrDiag(ctxt, "type.runtime._type")) - - defgotype(ctxt, lookupOrDiag(ctxt, "type.runtime.interfacetype")) - defgotype(ctxt, lookupOrDiag(ctxt, "type.runtime.itab")) + for _, typ := range []string{ + "type.runtime._type", + "type.runtime.arraytype", + "type.runtime.chantype", + "type.runtime.functype", + "type.runtime.maptype", + "type.runtime.ptrtype", + "type.runtime.slicetype", + "type.runtime.structtype", + "type.runtime.interfacetype", + "type.runtime.itab", + "type.runtime.imethod"} { + defgotype(ctxt, lookupOrDiag(ctxt, typ)) + } genasmsym(ctxt, defdwsymb) diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go new file mode 100644 index 0000000000..53a5a0610d --- /dev/null +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -0,0 +1,90 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ld + +import ( + objfilepkg "cmd/internal/objfile" // renamed to avoid conflict with objfile function + "debug/dwarf" + "internal/testenv" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "testing" +) + +func TestRuntimeTypeDIEs(t *testing.T) { + testenv.MustHaveGoBuild(t) + dir, err := ioutil.TempDir("", "TestRuntimeTypeDIEs") + if err != nil { + t.Fatalf("could not create directory: %v", err) + } + defer os.RemoveAll(dir) + + f := gobuild(t, dir, `package main; func main() { }`) + defer f.Close() + + dwarf, err := f.DWARF() + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + + want := map[string]bool{ + "runtime._type": true, + "runtime.arraytype": true, + "runtime.chantype": true, + "runtime.functype": true, + "runtime.maptype": true, + "runtime.ptrtype": true, + "runtime.slicetype": true, + "runtime.structtype": true, + "runtime.interfacetype": true, + "runtime.itab": true, + "runtime.imethod": true, + } + + found := findTypes(t, dwarf, want) + if len(found) != len(want) { + t.Errorf("found %v, want %v", found, want) + } +} + +func findTypes(t *testing.T, dw *dwarf.Data, want map[string]bool) (found map[string]bool) { + found = make(map[string]bool) + rdr := dw.Reader() + for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() { + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + switch entry.Tag { + case dwarf.TagTypedef: + if name, ok := entry.Val(dwarf.AttrName).(string); ok && want[name] { + found[name] = true + } + } + } + return +} + +func gobuild(t *testing.T, dir string, testfile string) *objfilepkg.File { + src := filepath.Join(dir, "test.go") + dst := filepath.Join(dir, "out") + + if err := ioutil.WriteFile(src, []byte(testfile), 0666); err != nil { + t.Fatal(err) + } + + cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dst, src) + if b, err := cmd.CombinedOutput(); err != nil { + t.Logf("build: %s\n", b) + t.Fatalf("build error: %v", err) + } + + f, err := objfilepkg.Open(dst) + if err != nil { + t.Fatal(err) + } + return f +}