Skip to content

Commit 1c8943b

Browse files
aarzillithanm
authored andcommitted
cmd/link: move DIE of global variables to their compile unit
The DIEs for global variables were all assigned to the first emitted compile unit in debug_info, regardless of what it was. Move them instead to their respective compile units. Change-Id: If794fa0ba4702f5b959c6e8c16119b16e7ecf6d8 Reviewed-on: https://go-review.googlesource.com/137235 Reviewed-by: Than McIntosh <[email protected]>
1 parent 4ba4c5a commit 1c8943b

File tree

5 files changed

+88
-59
lines changed

5 files changed

+88
-59
lines changed

src/cmd/compile/internal/ssa/stmtlines_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ func TestStmtLines(t *testing.T) {
6262
if pkgname == "runtime" {
6363
continue
6464
}
65+
if e.Val(dwarf.AttrStmtList) == nil {
66+
continue
67+
}
6568
lrdr, err := dw.LineReader(e)
6669
must(err)
6770

src/cmd/internal/dwarf/dwarf.go

+13
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ const (
304304
const (
305305
DW_ABRV_NULL = iota
306306
DW_ABRV_COMPUNIT
307+
DW_ABRV_COMPUNIT_TEXTLESS
307308
DW_ABRV_FUNCTION
308309
DW_ABRV_FUNCTION_ABSTRACT
309310
DW_ABRV_FUNCTION_CONCRETE
@@ -368,6 +369,18 @@ var abbrevs = [DW_NABRV]dwAbbrev{
368369
},
369370
},
370371

372+
/* COMPUNIT_TEXTLESS */
373+
{
374+
DW_TAG_compile_unit,
375+
DW_CHILDREN_yes,
376+
[]dwAttrForm{
377+
{DW_AT_name, DW_FORM_string},
378+
{DW_AT_language, DW_FORM_data1},
379+
{DW_AT_comp_dir, DW_FORM_string},
380+
{DW_AT_producer, DW_FORM_string},
381+
},
382+
},
383+
371384
/* FUNCTION */
372385
{
373386
DW_TAG_subprogram,

src/cmd/link/dwarf_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
122122
r.SkipChildren()
123123
continue
124124
}
125+
if cu.Val(dwarf.AttrStmtList) == nil {
126+
continue
127+
}
125128
lr, err := d.LineReader(cu)
126129
if err != nil {
127130
t.Fatal(err)

src/cmd/link/internal/ld/dwarf.go

+68-58
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// TODO/NICETOHAVE:
66
// - eliminate DW_CLS_ if not used
77
// - package info in compilation units
8-
// - assign global variables and types to their packages
8+
// - assign types to their packages
99
// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
1010
// ptype struct '[]uint8' and qualifiers need to be quoted away
1111
// - file:line info for variables
@@ -106,15 +106,8 @@ func writeabbrev(ctxt *Link) *sym.Symbol {
106106
return s
107107
}
108108

109-
/*
110-
* Root DIEs for compilation units, types and global variables.
111-
*/
112-
var dwroot dwarf.DWDie
113-
114109
var dwtypes dwarf.DWDie
115110

116-
var dwglobals dwarf.DWDie
117-
118111
func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) *dwarf.DWAttr {
119112
a := new(dwarf.DWAttr)
120113
a.Link = die.Attr
@@ -835,7 +828,11 @@ func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
835828
}
836829

837830
func dwarfDefineGlobal(ctxt *Link, s *sym.Symbol, str string, v int64, gotype *sym.Symbol) {
838-
dv := newdie(ctxt, &dwglobals, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
831+
lib := s.Lib
832+
if lib == nil {
833+
lib = ctxt.LibraryByPkg["runtime"]
834+
}
835+
dv := newdie(ctxt, ctxt.compUnitByPackage[lib].dwinfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
839836
newabslocexprattr(dv, v, s)
840837
if s.Version == 0 {
841838
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
@@ -910,10 +907,11 @@ func calcCompUnitRanges(ctxt *Link) {
910907
}
911908
}
912909

913-
func movetomodule(parent *dwarf.DWDie) {
914-
die := dwroot.Child.Child
910+
func movetomodule(ctxt *Link, parent *dwarf.DWDie) {
911+
runtimelib := ctxt.LibraryByPkg["runtime"]
912+
die := ctxt.compUnitByPackage[runtimelib].dwinfo.Child
915913
if die == nil {
916-
dwroot.Child.Child = parent.Child
914+
ctxt.compUnitByPackage[runtimelib].dwinfo.Child = parent.Child
917915
return
918916
}
919917
for die.Link != nil {
@@ -1067,7 +1065,7 @@ func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) {
10671065
}
10681066
}
10691067

1070-
func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) (dwinfo *dwarf.DWDie) {
1068+
func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
10711069

10721070
var dwarfctxt dwarf.Context = dwctxt{ctxt}
10731071
is_stmt := uint8(1) // initially = recommended default_is_stmt = 1, tracks is_stmt toggles.
@@ -1076,29 +1074,7 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) (dwinfo *dwar
10761074
headerstart := int64(-1)
10771075
headerend := int64(-1)
10781076

1079-
lang := dwarf.DW_LANG_Go
1080-
1081-
dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, unit.lib.Pkg, 0)
1082-
newattr(dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(lang), 0)
1083-
newattr(dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, ls.Size, ls)
1084-
// OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
1085-
compDir := getCompilationDir()
1086-
// TODO: Make this be the actual compilation directory, not
1087-
// the linker directory. If we move CU construction into the
1088-
// compiler, this should happen naturally.
1089-
newattr(dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
1090-
producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+unit.lib.Pkg, 0)
1091-
producer := "Go cmd/compile " + objabi.Version
1092-
if len(producerExtra.P) > 0 {
1093-
// We put a semicolon before the flags to clearly
1094-
// separate them from the version, which can be long
1095-
// and have lots of weird things in it in development
1096-
// versions. We promise not to put a semicolon in the
1097-
// version, so it should be safe for readers to scan
1098-
// forward to the semicolon.
1099-
producer += "; " + string(producerExtra.P)
1100-
}
1101-
newattr(dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
1077+
newattr(unit.dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, ls.Size, ls)
11021078

11031079
// Write .debug_line Line Number Program Header (sec 6.2.4)
11041080
// Fields marked with (*) must be changed for 64-bit dwarf
@@ -1300,8 +1276,6 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) (dwinfo *dwar
13001276
}
13011277
}
13021278
}
1303-
1304-
return dwinfo
13051279
}
13061280

13071281
// writepcranges generates the DW_AT_ranges table for compilation unit cu.
@@ -1468,15 +1442,13 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
14681442

14691443
var dwarfctxt dwarf.Context = dwctxt{ctxt}
14701444

1471-
// Re-index per-package information by its CU die.
1472-
unitByDIE := make(map[*dwarf.DWDie]*compilationUnit)
14731445
for _, u := range units {
1474-
unitByDIE[u.dwinfo] = u
1475-
}
1476-
1477-
for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
1446+
compunit := u.dwinfo
14781447
s := dtolsym(compunit.Sym)
1479-
u := unitByDIE[compunit]
1448+
1449+
if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil {
1450+
continue
1451+
}
14801452

14811453
// Write .debug_info Compilation Unit Header (sec 7.5.1)
14821454
// Fields marked with (*) must be changed for 64-bit dwarf
@@ -1536,7 +1508,11 @@ func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*s
15361508
s.Type = sym.SDWARFSECT
15371509
syms = append(syms, s)
15381510

1539-
for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
1511+
for _, u := range ctxt.compUnits {
1512+
if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil {
1513+
continue
1514+
}
1515+
compunit := u.dwinfo
15401516
sectionstart := s.Size
15411517
culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
15421518

@@ -1671,13 +1647,10 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
16711647
defgotype(ctxt, lookupOrDiag(ctxt, typ))
16721648
}
16731649

1674-
// Create DIEs for global variables and the types they use.
1675-
genasmsym(ctxt, defdwsymb)
1650+
// fake root DIE for compile unit DIEs
1651+
var dwroot dwarf.DWDie
16761652

16771653
for _, lib := range ctxt.Library {
1678-
if len(lib.Textp) == 0 {
1679-
continue
1680-
}
16811654
unit := &compilationUnit{lib: lib}
16821655
if s := ctxt.Syms.ROLookup(dwarf.ConstInfoPrefix+lib.Pkg, 0); s != nil {
16831656
importInfoSymbol(ctxt, s)
@@ -1686,6 +1659,31 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
16861659
ctxt.compUnits = append(ctxt.compUnits, unit)
16871660
ctxt.compUnitByPackage[lib] = unit
16881661

1662+
unit.dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, unit.lib.Pkg, 0)
1663+
newattr(unit.dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0)
1664+
// OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
1665+
compDir := getCompilationDir()
1666+
// TODO: Make this be the actual compilation directory, not
1667+
// the linker directory. If we move CU construction into the
1668+
// compiler, this should happen naturally.
1669+
newattr(unit.dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
1670+
producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+unit.lib.Pkg, 0)
1671+
producer := "Go cmd/compile " + objabi.Version
1672+
if len(producerExtra.P) > 0 {
1673+
// We put a semicolon before the flags to clearly
1674+
// separate them from the version, which can be long
1675+
// and have lots of weird things in it in development
1676+
// versions. We promise not to put a semicolon in the
1677+
// version, so it should be safe for readers to scan
1678+
// forward to the semicolon.
1679+
producer += "; " + string(producerExtra.P)
1680+
}
1681+
newattr(unit.dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
1682+
1683+
if len(lib.Textp) == 0 {
1684+
unit.dwinfo.Abbrev = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
1685+
}
1686+
16891687
// Scan all functions in this compilation unit, create DIEs for all
16901688
// referenced types, create the file table for debug_line, find all
16911689
// referenced abstract functions.
@@ -1726,6 +1724,9 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
17261724
}
17271725
}
17281726

1727+
// Create DIEs for global variables and the types they use.
1728+
genasmsym(ctxt, defdwsymb)
1729+
17291730
synthesizestringtypes(ctxt, dwtypes.Child)
17301731
synthesizeslicetypes(ctxt, dwtypes.Child)
17311732
synthesizemaptypes(ctxt, dwtypes.Child)
@@ -1758,19 +1759,19 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
17581759
debugRanges.Attr |= sym.AttrReachable
17591760
syms = append(syms, debugLine)
17601761
for _, u := range ctxt.compUnits {
1761-
u.dwinfo = writelines(ctxt, u, debugLine)
1762+
reversetree(&u.dwinfo.Child)
1763+
if u.dwinfo.Abbrev == dwarf.DW_ABRV_COMPUNIT_TEXTLESS {
1764+
continue
1765+
}
1766+
writelines(ctxt, u, debugLine)
17621767
writepcranges(ctxt, u.dwinfo, u.lib.Textp[0], u.pcs, debugRanges)
17631768
}
17641769

17651770
// newdie adds DIEs to the *beginning* of the parent's DIE list.
17661771
// Now that we're done creating DIEs, reverse the trees so DIEs
17671772
// appear in the order they were created.
1768-
reversetree(&dwroot.Child)
17691773
reversetree(&dwtypes.Child)
1770-
reversetree(&dwglobals.Child)
1771-
1772-
movetomodule(&dwtypes)
1773-
movetomodule(&dwglobals)
1774+
movetomodule(ctxt, &dwtypes)
17741775

17751776
// Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
17761777
// (but we need to generate dies before writepub)
@@ -2005,5 +2006,14 @@ func (v compilationUnitByStartPC) Len() int { return len(v) }
20052006
func (v compilationUnitByStartPC) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
20062007

20072008
func (v compilationUnitByStartPC) Less(i, j int) bool {
2008-
return v[i].lib.Textp[0].Value < v[j].lib.Textp[0].Value
2009+
switch {
2010+
case len(v[i].lib.Textp) == 0 && len(v[j].lib.Textp) == 0:
2011+
return v[i].lib.Pkg < v[j].lib.Pkg
2012+
case len(v[i].lib.Textp) != 0 && len(v[j].lib.Textp) == 0:
2013+
return true
2014+
case len(v[i].lib.Textp) == 0 && len(v[j].lib.Textp) != 0:
2015+
return false
2016+
default:
2017+
return v[i].lib.Textp[0].Value < v[j].lib.Textp[0].Value
2018+
}
20092019
}

src/cmd/link/internal/objfile/objfile.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ func (r *objReader) readSym() {
203203

204204
overwrite:
205205
s.File = pkg
206+
s.Lib = r.lib
206207
if dupok {
207208
s.Attr |= sym.AttrDuplicateOK
208209
}
@@ -320,7 +321,6 @@ overwrite:
320321

321322
s.FuncInfo.IsStmtSym = r.syms.Lookup(dwarf.IsStmtPrefix+s.Name, int(s.Version))
322323

323-
s.Lib = r.lib
324324
if !dupok {
325325
if s.Attr.OnList() {
326326
log.Fatalf("symbol %s listed multiple times", s.Name)

0 commit comments

Comments
 (0)