5
5
// TODO/NICETOHAVE:
6
6
// - eliminate DW_CLS_ if not used
7
7
// - package info in compilation units
8
- // - assign global variables and types to their packages
8
+ // - assign types to their packages
9
9
// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
10
10
// ptype struct '[]uint8' and qualifiers need to be quoted away
11
11
// - file:line info for variables
@@ -106,15 +106,8 @@ func writeabbrev(ctxt *Link) *sym.Symbol {
106
106
return s
107
107
}
108
108
109
- /*
110
- * Root DIEs for compilation units, types and global variables.
111
- */
112
- var dwroot dwarf.DWDie
113
-
114
109
var dwtypes dwarf.DWDie
115
110
116
- var dwglobals dwarf.DWDie
117
-
118
111
func newattr (die * dwarf.DWDie , attr uint16 , cls int , value int64 , data interface {}) * dwarf.DWAttr {
119
112
a := new (dwarf.DWAttr )
120
113
a .Link = die .Attr
@@ -835,7 +828,11 @@ func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
835
828
}
836
829
837
830
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 ))
839
836
newabslocexprattr (dv , v , s )
840
837
if s .Version == 0 {
841
838
newattr (dv , dwarf .DW_AT_external , dwarf .DW_CLS_FLAG , 1 , 0 )
@@ -910,10 +907,11 @@ func calcCompUnitRanges(ctxt *Link) {
910
907
}
911
908
}
912
909
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
915
913
if die == nil {
916
- dwroot . Child .Child = parent .Child
914
+ ctxt . compUnitByPackage [ runtimelib ]. dwinfo .Child = parent .Child
917
915
return
918
916
}
919
917
for die .Link != nil {
@@ -1067,7 +1065,7 @@ func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) {
1067
1065
}
1068
1066
}
1069
1067
1070
- func writelines (ctxt * Link , unit * compilationUnit , ls * sym.Symbol ) ( dwinfo * dwarf. DWDie ) {
1068
+ func writelines (ctxt * Link , unit * compilationUnit , ls * sym.Symbol ) {
1071
1069
1072
1070
var dwarfctxt dwarf.Context = dwctxt {ctxt }
1073
1071
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
1076
1074
headerstart := int64 (- 1 )
1077
1075
headerend := int64 (- 1 )
1078
1076
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 )
1102
1078
1103
1079
// Write .debug_line Line Number Program Header (sec 6.2.4)
1104
1080
// 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
1300
1276
}
1301
1277
}
1302
1278
}
1303
-
1304
- return dwinfo
1305
1279
}
1306
1280
1307
1281
// 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
1468
1442
1469
1443
var dwarfctxt dwarf.Context = dwctxt {ctxt }
1470
1444
1471
- // Re-index per-package information by its CU die.
1472
- unitByDIE := make (map [* dwarf.DWDie ]* compilationUnit )
1473
1445
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
1478
1447
s := dtolsym (compunit .Sym )
1479
- u := unitByDIE [compunit ]
1448
+
1449
+ if len (u .lib .Textp ) == 0 && u .dwinfo .Child == nil {
1450
+ continue
1451
+ }
1480
1452
1481
1453
// Write .debug_info Compilation Unit Header (sec 7.5.1)
1482
1454
// 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
1536
1508
s .Type = sym .SDWARFSECT
1537
1509
syms = append (syms , s )
1538
1510
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
1540
1516
sectionstart := s .Size
1541
1517
culength := uint32 (getattr (compunit , dwarf .DW_AT_byte_size ).Value ) + 4
1542
1518
@@ -1671,13 +1647,10 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
1671
1647
defgotype (ctxt , lookupOrDiag (ctxt , typ ))
1672
1648
}
1673
1649
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
1676
1652
1677
1653
for _ , lib := range ctxt .Library {
1678
- if len (lib .Textp ) == 0 {
1679
- continue
1680
- }
1681
1654
unit := & compilationUnit {lib : lib }
1682
1655
if s := ctxt .Syms .ROLookup (dwarf .ConstInfoPrefix + lib .Pkg , 0 ); s != nil {
1683
1656
importInfoSymbol (ctxt , s )
@@ -1686,6 +1659,31 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
1686
1659
ctxt .compUnits = append (ctxt .compUnits , unit )
1687
1660
ctxt .compUnitByPackage [lib ] = unit
1688
1661
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
+
1689
1687
// Scan all functions in this compilation unit, create DIEs for all
1690
1688
// referenced types, create the file table for debug_line, find all
1691
1689
// referenced abstract functions.
@@ -1726,6 +1724,9 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
1726
1724
}
1727
1725
}
1728
1726
1727
+ // Create DIEs for global variables and the types they use.
1728
+ genasmsym (ctxt , defdwsymb )
1729
+
1729
1730
synthesizestringtypes (ctxt , dwtypes .Child )
1730
1731
synthesizeslicetypes (ctxt , dwtypes .Child )
1731
1732
synthesizemaptypes (ctxt , dwtypes .Child )
@@ -1758,19 +1759,19 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
1758
1759
debugRanges .Attr |= sym .AttrReachable
1759
1760
syms = append (syms , debugLine )
1760
1761
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 )
1762
1767
writepcranges (ctxt , u .dwinfo , u .lib .Textp [0 ], u .pcs , debugRanges )
1763
1768
}
1764
1769
1765
1770
// newdie adds DIEs to the *beginning* of the parent's DIE list.
1766
1771
// Now that we're done creating DIEs, reverse the trees so DIEs
1767
1772
// appear in the order they were created.
1768
- reversetree (& dwroot .Child )
1769
1773
reversetree (& dwtypes .Child )
1770
- reversetree (& dwglobals .Child )
1771
-
1772
- movetomodule (& dwtypes )
1773
- movetomodule (& dwglobals )
1774
+ movetomodule (ctxt , & dwtypes )
1774
1775
1775
1776
// Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
1776
1777
// (but we need to generate dies before writepub)
@@ -2005,5 +2006,14 @@ func (v compilationUnitByStartPC) Len() int { return len(v) }
2005
2006
func (v compilationUnitByStartPC ) Swap (i , j int ) { v [i ], v [j ] = v [j ], v [i ] }
2006
2007
2007
2008
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
+ }
2009
2019
}
0 commit comments