]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: export specialized variants of runtime._type to debug_info
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>
Sat, 18 Mar 2017 14:09:40 +0000 (15:09 +0100)
committerIan Lance Taylor <iant@golang.org>
Wed, 12 Apr 2017 13:25:45 +0000 (13:25 +0000)
The reflect package can be used to create new types at runtime, these
types will have runtime._type entries describing them but no entry in
debug_info (obviously).

A debugger that wanted to print the value of variables with such types
will have to read the runtime._type directly, however the
"specializations" of runtime._type (runtime.slicetype, runtime.maptype,
etc) are not exported to debug_info, besides runtime.interfacetype.

All those types (i.e. runtime.slicetype, runtime.maptype, etc) should
be exported to debug_info so that debuggers don't have to hard-code
their description.

Fixes #19602

Change-Id: I086d523a4421a4ed964e16bc3c2274319a98b45b
Reviewed-on: https://go-review.googlesource.com/38350
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>

src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/dwarf_test.go [new file with mode: 0644]

index 696a80bcdc9c18b1df84d677a93bcfd238dca57d..744e2153a35649879e23e3034abe9f60e9aede59 100644 (file)
@@ -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 (file)
index 0000000..53a5a06
--- /dev/null
@@ -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
+}