cmd/compile: output DWARF lexical blocks for local variables

Change compiler and linker to emit DWARF lexical blocks in .debug_info
section when compiling with -N -l.

Version of debug_info is updated from DWARF v2 to DWARF v3 since
version 2 does not allow lexical blocks with discontinuous PC ranges.

Remaining open problems:
- scope information is removed from inlined functions
- variables records do not have DW_AT_start_scope attributes so a
variable will shadow other variables with the same name as soon as its
containing scope begins, even before its declaration.

Updates #6913.
Updates #12899.

Change-Id: Idc6808788512ea20e7e45bcf782453acb416fb49
Reviewed-on: https://go-review.googlesource.com/40095
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Alessandro Arzilli 2017-05-02 16:46:01 +02:00 committed by Matthew Dempsky
parent 0f0a51f1d1
commit 2ad41a3090
22 changed files with 1021 additions and 111 deletions

View file

@ -8,7 +8,6 @@
// - assign global variables and types to their packages
// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
// ptype struct '[]uint8' and qualifiers need to be quoted away
// - lexical scoping is lost, so gdb gets confused as to which 'main.i' you mean.
// - file:line info for variables
// - make strings a typedef so prettyprinters can see the underlying string type
@ -76,6 +75,7 @@ var arangessec *Symbol
var framesec *Symbol
var infosec *Symbol
var linesec *Symbol
var rangesec *Symbol
var gdbscript string
@ -1291,6 +1291,33 @@ func writeframes(ctxt *Link, syms []*Symbol) []*Symbol {
return syms
}
func writeranges(ctxt *Link, syms []*Symbol) []*Symbol {
if rangesec == nil {
rangesec = ctxt.Syms.Lookup(".debug_ranges", 0)
}
rangesec.Type = SDWARFSECT
rangesec.Attr |= AttrReachable
rangesec.R = rangesec.R[:0]
for _, s := range ctxt.Textp {
rangeSym := ctxt.Syms.Lookup(dwarf.RangePrefix+s.Name, int(s.Version))
rangeSym.Attr |= AttrReachable
rangeSym.Type = SDWARFRANGE
rangeSym.Value = rangesec.Size
rangesec.P = append(rangesec.P, rangeSym.P...)
for _, r := range rangeSym.R {
r.Off += int32(rangesec.Size)
rangesec.R = append(rangesec.R, r)
}
rangesec.Size += rangeSym.Size
}
if rangesec.Size > 0 {
// PE does not like empty sections
syms = append(syms, rangesec)
}
return syms
}
/*
* Walk DWarfDebugInfoEntries, and emit .debug_info
*/
@ -1321,7 +1348,7 @@ func writeinfo(ctxt *Link, syms []*Symbol, funcs []*Symbol) []*Symbol {
// Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above.
Adduint32(ctxt, s, 0) // unit_length (*), will be filled in later.
Adduint16(ctxt, s, 2) // dwarf version (appendix F)
Adduint16(ctxt, s, 3) // dwarf version (appendix F)
// debug_abbrev_offset (*)
adddwarfref(ctxt, s, abbrevsym, 4)
@ -1553,6 +1580,7 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
syms := writeabbrev(ctxt, nil)
syms, funcs := writelines(ctxt, syms)
syms = writeframes(ctxt, syms)
syms = writeranges(ctxt, syms)
synthesizestringtypes(ctxt, dwtypes.Child)
synthesizeslicetypes(ctxt, dwtypes.Child)
@ -1594,6 +1622,7 @@ func dwarfaddshstrings(ctxt *Link, shstrtab *Symbol) {
Addstring(shstrtab, ".debug_pubnames")
Addstring(shstrtab, ".debug_pubtypes")
Addstring(shstrtab, ".debug_gdb_scripts")
Addstring(shstrtab, ".debug_ranges")
if Linkmode == LinkExternal {
Addstring(shstrtab, elfRelType+".debug_info")
Addstring(shstrtab, elfRelType+".debug_aranges")
@ -1601,6 +1630,7 @@ func dwarfaddshstrings(ctxt *Link, shstrtab *Symbol) {
Addstring(shstrtab, elfRelType+".debug_frame")
Addstring(shstrtab, elfRelType+".debug_pubnames")
Addstring(shstrtab, elfRelType+".debug_pubtypes")
Addstring(shstrtab, elfRelType+".debug_ranges")
}
}
@ -1621,6 +1651,10 @@ func dwarfaddelfsectionsyms(ctxt *Link) {
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
sym = ctxt.Syms.Lookup(".debug_frame", 0)
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
sym = ctxt.Syms.Lookup(".debug_ranges", 0)
if sym.Sect != nil {
putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
}
}
/*