]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: emit DW_AT_decl_line
authorHeschi Kreinick <heschi@google.com>
Fri, 26 May 2017 19:34:56 +0000 (15:34 -0400)
committerHeschi Kreinick <heschi@google.com>
Tue, 22 Aug 2017 18:05:53 +0000 (18:05 +0000)
Some debuggers use the declaration line to avoid showing variables
before they're declared. Emit them for local variables and function
parameters.

DW_AT_decl_file would be nice too, but since its value is an index
into a table built by the linker, that's dramatically harder. In
practice, with inlining disabled it's safe to assume that all a
function's variables are declared in the same file, so this should still
be pretty useful.

Change-Id: I8105818c8940cd71bc5473ec98797cce2f3f9872
Reviewed-on: https://go-review.googlesource.com/44350
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/gc/pgen.go
src/cmd/internal/dwarf/dwarf.go
src/cmd/link/internal/ld/dwarf_test.go

index 542fd43b63117ccf0868bfe7b6fdbbeb57ba394f..3a6848598b02d3a4b69fa1611555c804443451bd 100644 (file)
@@ -397,6 +397,7 @@ func createSimpleVars(automDecls []*Node) ([]*Node, []*dwarf.Var) {
                        Abbrev:      abbrev,
                        StackOffset: int32(offs),
                        Type:        Ctxt.Lookup(typename),
+                       DeclLine:    n.Pos.Line(),
                })
        }
        return decls, vars
@@ -513,6 +514,7 @@ func createComplexVar(debugInfo *ssa.FuncDebug, n *Node, parts []varPart) *dwarf
                Abbrev:      abbrev,
                Type:        Ctxt.Lookup(typename),
                StackOffset: int32(stackOffset),
+               DeclLine:    n.Pos.Line(),
        }
 
        if Debug_locationlist != 0 {
index b0c7fb20f5199e5b37c9dfecdace022bce7c8eab..3ab036db0c5991bfc62563055bf5244a3bf36288 100644 (file)
@@ -51,6 +51,7 @@ type Var struct {
        LocationList []Location
        Scope        int32
        Type         Sym
+       DeclLine     uint
 }
 
 // A Scope represents a lexical scope. All variables declared within a
@@ -315,6 +316,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{
                DW_CHILDREN_no,
                []dwAttrForm{
                        {DW_AT_name, DW_FORM_string},
+                       {DW_AT_decl_line, DW_FORM_udata},
                        {DW_AT_location, DW_FORM_block1},
                        {DW_AT_type, DW_FORM_ref_addr},
                },
@@ -337,6 +339,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{
                DW_CHILDREN_no,
                []dwAttrForm{
                        {DW_AT_name, DW_FORM_string},
+                       {DW_AT_decl_line, DW_FORM_udata},
                        {DW_AT_location, DW_FORM_block1},
                        {DW_AT_type, DW_FORM_ref_addr},
                },
@@ -794,6 +797,7 @@ func putvar(ctxt Context, info, loc Sym, v *Var, startPC Sym, encbuf []byte) {
 
        Uleb128put(ctxt, info, int64(v.Abbrev))
        putattr(ctxt, info, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
+       putattr(ctxt, info, v.Abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
        if v.Abbrev == DW_ABRV_AUTO_LOCLIST || v.Abbrev == DW_ABRV_PARAM_LOCLIST {
                putattr(ctxt, info, v.Abbrev, DW_FORM_sec_offset, DW_CLS_PTR, int64(loc.Len()), loc)
                addLocList(ctxt, loc, startPC, v, encbuf)
index d59220bb66fcf8ab6690aa296392bae24e4d3987..00ee8a05652a866ded8ce5fce79deb81a6e4c386 100644 (file)
@@ -83,7 +83,7 @@ func gobuild(t *testing.T, dir string, testfile string) *objfilepkg.File {
                t.Fatal(err)
        }
 
-       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dst, src)
+       cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags", "-N -l", "-o", dst, src)
        if b, err := cmd.CombinedOutput(); err != nil {
                t.Logf("build: %s\n", b)
                t.Fatalf("build error: %v", err)
@@ -298,3 +298,60 @@ func main() {
                }
        }
 }
+
+func TestVarDeclCoords(t *testing.T) {
+       testenv.MustHaveGoBuild(t)
+
+       if runtime.GOOS == "plan9" {
+               t.Skip("skipping on plan9; no DWARF symbol table in executables")
+       }
+
+       const prog = `
+package main
+
+func main() {
+       var i int
+       i = i
+}
+`
+       dir, err := ioutil.TempDir("", "TestVarDeclCoords")
+       if err != nil {
+               t.Fatalf("could not create directory: %v", err)
+       }
+       defer os.RemoveAll(dir)
+
+       f := gobuild(t, dir, prog)
+
+       d, err := f.DWARF()
+       if err != nil {
+               t.Fatalf("error reading DWARF: %v", err)
+       }
+
+       rdr := d.Reader()
+       var iEntry *dwarf.Entry
+       foundMain := false
+       for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() {
+               if err != nil {
+                       t.Fatalf("error reading DWARF: %v", err)
+               }
+               if entry.Tag == dwarf.TagSubprogram && entry.Val(dwarf.AttrName).(string) == "main.main" {
+                       foundMain = true
+                       continue
+               }
+               if !foundMain {
+                       continue
+               }
+               if entry.Tag == dwarf.TagSubprogram {
+                       t.Fatalf("didn't find DW_TAG_variable for i in main.main")
+               }
+               if foundMain && entry.Tag == dwarf.TagVariable && entry.Val(dwarf.AttrName).(string) == "i" {
+                       iEntry = entry
+                       break
+               }
+       }
+
+       line := iEntry.Val(dwarf.AttrDeclLine)
+       if line == nil || line.(int64) != 5 {
+               t.Errorf("DW_AT_decl_line for i is %v, want 5", line)
+       }
+}