return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref)
}
-func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol {
- for ; die != nil; die = die.Link {
- syms = putdie(linkctxt, ctxt, syms, die)
- }
- syms[len(syms)-1].AddUint8(0)
-
- return syms
-}
-
func dtolsym(s dwarf.Sym) *sym.Symbol {
if s == nil {
return nil
dwarf.Uleb128put(ctxt, s, int64(die.Abbrev))
dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr)
if dwarf.HasChildren(die) {
- return putdies(linkctxt, ctxt, syms, die.Child)
+ for die := die.Child; die != nil; die = die.Link {
+ syms = putdie(linkctxt, ctxt, syms, die)
+ }
+ syms[len(syms)-1].AddUint8(0)
}
return syms
}
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
)
-func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevsym *sym.Symbol) []*sym.Symbol {
+func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevsym *sym.Symbol, pubNames, pubTypes *pubWriter) []*sym.Symbol {
infosec := ctxt.Syms.Lookup(".debug_info", 0)
infosec.Type = sym.SDWARFINFO
infosec.Attr |= sym.AttrReachable
continue
}
+ pubNames.beginCompUnit(compunit)
+ pubTypes.beginCompUnit(compunit)
+
// Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above.
if u.consts != nil {
cu = append(cu, u.consts)
}
- cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
var cusize int64
for _, child := range cu {
cusize += child.Size
}
+
+ for die := compunit.Child; die != nil; die = die.Link {
+ l := len(cu)
+ lastSymSz := cu[l-1].Size
+ cu = putdie(ctxt, dwarfctxt, cu, die)
+ if ispubname(die) {
+ pubNames.add(die, cusize)
+ }
+ if ispubtype(die) {
+ pubTypes.add(die, cusize)
+ }
+ if lastSymSz != cu[l-1].Size {
+ // putdie will sometimes append directly to the last symbol of the list
+ cusize = cusize - lastSymSz + cu[l-1].Size
+ }
+ for _, child := range cu[l:] {
+ cusize += child.Size
+ }
+ }
+ cu[len(cu)-1].AddUint8(0) // closes compilation unit DIE
+ cusize++
+
// Save size for AIX symbol table.
if ctxt.HeadType == objabi.Haix {
saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize))
cusize -= 4 // exclude the length field.
s.SetUint32(ctxt.Arch, 0, uint32(cusize))
}
- // Leave a breadcrumb for writepub. This does not
- // appear in the DWARF output.
- newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0)
+ pubNames.endCompUnit(compunit, uint32(cusize)+4)
+ pubTypes.endCompUnit(compunit, uint32(cusize)+4)
syms = append(syms, cu...)
}
return syms
return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE
}
-func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*sym.Symbol) []*sym.Symbol {
+type pubWriter struct {
+ ctxt *Link
+ s *sym.Symbol
+ sname string
+
+ sectionstart int64
+ culengthOff int64
+}
+
+func newPubWriter(ctxt *Link, sname string) *pubWriter {
s := ctxt.Syms.Lookup(sname, 0)
s.Type = sym.SDWARFSECT
- syms = append(syms, s)
-
- for _, u := range ctxt.compUnits {
- if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil {
- continue
- }
- compunit := u.dwinfo
- sectionstart := s.Size
- culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
+ return &pubWriter{ctxt: ctxt, s: s, sname: sname}
+}
- // Write .debug_pubnames/types Header (sec 6.1.1)
- createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later.
- s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F)
- addDwarfAddrRef(ctxt, s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
- addDwarfAddrField(ctxt, s, uint64(culength)) // debug_info_length
+func (pw *pubWriter) beginCompUnit(compunit *dwarf.DWDie) {
+ pw.sectionstart = pw.s.Size
- for die := compunit.Child; die != nil; die = die.Link {
- if !ispub(die) {
- continue
- }
- dwa := getattr(die, dwarf.DW_AT_name)
- name := dwa.Data.(string)
- if die.Sym == nil {
- fmt.Println("Missing sym for ", name)
- }
- addDwarfAddrRef(ctxt, s, dtolsym(die.Sym))
- Addstring(s, name)
- }
+ // Write .debug_pubnames/types Header (sec 6.1.1)
+ createUnitLength(pw.ctxt, pw.s, 0) // unit_length (*), will be filled in later.
+ pw.s.AddUint16(pw.ctxt.Arch, 2) // dwarf version (appendix F)
+ addDwarfAddrRef(pw.ctxt, pw.s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
+ pw.culengthOff = pw.s.Size
+ addDwarfAddrField(pw.ctxt, pw.s, uint64(0)) // debug_info_length, will be filled in later.
- addDwarfAddrField(ctxt, s, 0) // Null offset
+}
- // On AIX, save the current size of this compilation unit.
- if ctxt.HeadType == objabi.Haix {
- saveDwsectCUSize(sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(s.Size-sectionstart))
- }
- if isDwarf64(ctxt) {
- s.SetUint(ctxt.Arch, sectionstart+4, uint64(s.Size-sectionstart)-12) // exclude the length field.
- } else {
- s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
- }
+func (pw *pubWriter) add(die *dwarf.DWDie, offset int64) {
+ dwa := getattr(die, dwarf.DW_AT_name)
+ name := dwa.Data.(string)
+ if die.Sym == nil {
+ fmt.Println("Missing sym for ", name)
}
+ addDwarfAddrField(pw.ctxt, pw.s, uint64(offset))
+ Addstring(pw.s, name)
+}
- return syms
+func (pw *pubWriter) endCompUnit(compunit *dwarf.DWDie, culength uint32) {
+ addDwarfAddrField(pw.ctxt, pw.s, 0) // Null offset
+
+ // On AIX, save the current size of this compilation unit.
+ if pw.ctxt.HeadType == objabi.Haix {
+ saveDwsectCUSize(pw.sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(pw.s.Size-pw.sectionstart))
+ }
+ if isDwarf64(pw.ctxt) {
+ pw.s.SetUint(pw.ctxt.Arch, pw.sectionstart+4, uint64(pw.s.Size-pw.sectionstart)-12) // exclude the length field.
+ pw.s.SetUint(pw.ctxt.Arch, pw.culengthOff, uint64(culength))
+ } else {
+ pw.s.SetUint32(pw.ctxt.Arch, pw.sectionstart, uint32(pw.s.Size-pw.sectionstart)-4) // exclude the length field.
+ pw.s.SetUint32(pw.ctxt.Arch, pw.culengthOff, culength)
+ }
}
func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
reversetree(&dwtypes.Child)
movetomodule(ctxt, &dwtypes)
+ pubNames := newPubWriter(ctxt, ".debug_pubnames")
+ pubTypes := newPubWriter(ctxt, ".debug_pubtypes")
+
// Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
- // (but we need to generate dies before writepub)
- infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev)
+ infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev, pubNames, pubTypes)
syms = writeframes(ctxt, syms)
- syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
- syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
+ syms = append(syms, pubNames.s, pubTypes.s)
syms = writegdbscript(ctxt, syms)
// Now we're done writing SDWARFSECT symbols, so we can write
// other SDWARF* symbols.