Commit 9f5673d9 authored by David Chase's avatar David Chase

cmd/compile: ensure necessary types appear in .debug_info

Autotmp filtering was too aggressive and excluded types
necessary to make debuggers work properly.  Restore the
"late filter" in dwarf.go based on names to exclude autotmps,
and remove the "early filter" in pgen.go based on how the
name was introduced.  However, the updated naming scheme
with a dot prefix is retained to prevent accidental clashes
with legal Go identifier names.

Includes test (grouped with runtime gdb tests),
verified to fail without the fix.

Updates #17644.
Fixes #17830.

Change-Id: I7ec3f7230083889660236e5f6bc77ba5fe434e93
Reviewed-on: https://go-review.googlesource.com/33233
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarMatthew Dempsky <mdempsky@google.com>
parent 1e3c57c2
......@@ -427,9 +427,8 @@ func compile(fn *Node) {
}
fallthrough
case PPARAM, PPARAMOUT:
if n.IsAutoTmp() { // skip debugging info for temporaries
continue
}
// The symbol is excluded later from debugging info if its name begins ".autotmp_", but the type is still necessary.
// See bugs #17644 and #17830 and cmd/internal/dwarf/dwarf.go
p := Gins(obj.ATYPE, n, nil)
p.From.Sym = obj.Linklookup(Ctxt, n.Sym.Name, 0)
p.To.Type = obj.TYPE_MEM
......
......@@ -9,6 +9,7 @@ package dwarf
import (
"fmt"
"strings"
)
// InfoPrefix is the prefix for all the symbols containing DWARF info entries.
......@@ -576,6 +577,9 @@ func PutFunc(ctxt Context, s Sym, name string, external bool, startPC Sym, size
putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
names := make(map[string]bool)
for v := vars; v != nil; v = v.Link {
if strings.Contains(v.Name, ".autotmp_") {
continue
}
var n string
if names[v.Name] {
n = fmt.Sprintf("%s#%d", v.Name, len(names))
......
......@@ -15,6 +15,7 @@ import (
"regexp"
"runtime"
"strconv"
"strings"
"testing"
)
......@@ -275,3 +276,72 @@ func TestGdbBacktrace(t *testing.T) {
}
}
}
const autotmpTypeSource = `
package main
type astruct struct {
a, b int
}
func main() {
var iface interface{} = map[string]astruct{}
var iface2 interface{} = []astruct{}
println(iface, iface2)
}
`
// TestGdbAutotmpTypes ensures that types of autotmp variables appear in .debug_info
// See bug #17830.
func TestGdbAutotmpTypes(t *testing.T) {
t.Parallel()
checkGdbEnvironment(t)
checkGdbVersion(t)
dir, err := ioutil.TempDir("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
}
defer os.RemoveAll(dir)
// Build the source code.
src := filepath.Join(dir, "main.go")
err = ioutil.WriteFile(src, []byte(autotmpTypeSource), 0644)
if err != nil {
t.Fatalf("failed to create file: %v", err)
}
cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-N -l", "-o", "a.exe")
cmd.Dir = dir
out, err := testEnv(cmd).CombinedOutput()
if err != nil {
t.Fatalf("building source %v\n%s", err, out)
}
// Execute gdb commands.
args := []string{"-nx", "-batch",
"-ex", "set startup-with-shell off",
"-ex", "break main.main",
"-ex", "run",
"-ex", "step",
"-ex", "info types astruct",
filepath.Join(dir, "a.exe"),
}
got, _ := exec.Command("gdb", args...).CombinedOutput()
sgot := string(got)
// Check that the backtrace matches the source code.
types := []string{
"struct []main.astruct;",
"struct bucket<string,main.astruct>;",
"struct hash<string,main.astruct>;",
"struct main.astruct;",
"typedef struct hash<string,main.astruct> * map[string]main.astruct;",
}
for _, name := range types {
if !strings.Contains(sgot, name) {
t.Errorf("could not find %s in 'info typrs astruct' output", name)
t.Fatalf("gdb output:\n%v", sgot)
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment