mirror of
https://github.com/golang/go
synced 2024-11-24 01:50:11 -07:00
cmd/compile: emit DW_AT_decl_line
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>
This commit is contained in:
parent
3216e0cefa
commit
4a1be1e1da
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user