cmd/link: enable DWARF with external linker on aix/ppc64

In order to allow DWARF with ld, the symbol table is adapted.
In internal linkmode, each package is considered as a .FILE. However,
current version of ld is crashing on a few programs because of
relocations between DWARF symbols. Considering all packages as part of
one .FILE seems to bypass this bug.
As it might be fixed in a future release, the size of each package
in DWARF sections is still retrieved and can be used when it's fixed.
Moreover, it's improving internal linkmode which should have done it
anyway.

Change-Id: If3d023fe118b24b9f0f46d201a4849eee8d5e333
Reviewed-on: https://go-review.googlesource.com/c/go/+/164006
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Clément Chigot 2019-02-20 16:29:00 +01:00 committed by Ian Lance Taylor
parent b37b35edd7
commit 3cf89e509b
3 changed files with 95 additions and 21 deletions

View file

@ -1773,6 +1773,12 @@ func (ctxt *Link) dodata() {
s.Value = int64(uint64(datsize) - sect.Vaddr)
s.Attr |= sym.AttrLocal
datsize += s.Size
if ctxt.HeadType == objabi.Haix && curType == sym.SDWARFLOC {
// Update the size of .debug_loc for this symbol's
// package.
addDwsectCUSize(".debug_loc", s.File, uint64(s.Size))
}
}
sect.Length = uint64(datsize) - sect.Vaddr
checkdatsize(ctxt, datsize, curType)

View file

@ -1342,13 +1342,20 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
}
// writepcranges generates the DW_AT_ranges table for compilation unit cu.
func writepcranges(ctxt *Link, cu *dwarf.DWDie, base *sym.Symbol, pcs []dwarf.Range, ranges *sym.Symbol) {
func writepcranges(ctxt *Link, unit *compilationUnit, base *sym.Symbol, pcs []dwarf.Range, ranges *sym.Symbol) {
var dwarfctxt dwarf.Context = dwctxt{ctxt}
unitLengthOffset := ranges.Size
// Create PC ranges for this CU.
newattr(cu, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, ranges.Size, ranges)
newattr(cu, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, base.Value, base)
newattr(unit.dwinfo, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, ranges.Size, ranges)
newattr(unit.dwinfo, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, base.Value, base)
dwarf.PutRanges(dwarfctxt, ranges, nil, pcs)
if ctxt.HeadType == objabi.Haix {
addDwsectCUSize(".debug_ranges", unit.lib.String(), uint64(ranges.Size-unitLengthOffset))
}
}
/*
@ -1500,6 +1507,10 @@ func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
fs.AddAddr(ctxt.Arch, s)
fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range
fs.AddBytes(deltaBuf)
if ctxt.HeadType == objabi.Haix {
addDwsectCUSize(".debug_frame", s.File, fdeLength+uint64(lengthFieldSize))
}
}
return syms
}
@ -1705,11 +1716,11 @@ func dwarfEnabled(ctxt *Link) bool {
}
if ctxt.LinkMode == LinkExternal {
// TODO(aix): enable DWARF
switch {
case ctxt.IsELF:
case ctxt.HeadType == objabi.Hdarwin:
case ctxt.HeadType == objabi.Hwindows:
case ctxt.HeadType == objabi.Haix:
default:
return false
}
@ -1730,6 +1741,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
return
}
if ctxt.HeadType == objabi.Haix {
// Initial map used to store package size for each DWARF section.
dwsectCUSize = make(map[string]uint64)
}
ctxt.compUnitByPackage = make(map[*sym.Library]*compilationUnit)
// Forctxt.Diagnostic messages.
@ -1829,6 +1845,10 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
if ctxt.HeadType == objabi.Hdarwin {
removeDwarfAddrListBaseAddress(ctxt, dsym, rangeSym, false)
}
if ctxt.HeadType == objabi.Haix {
addDwsectCUSize(".debug_ranges", unit.lib.String(), uint64(rangeSym.Size))
}
unit.rangeSyms = append(unit.rangeSyms, rangeSym)
}
@ -1891,7 +1911,7 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
continue
}
writelines(ctxt, u, debugLine)
writepcranges(ctxt, u.dwinfo, u.lib.Textp[0], u.pcs, debugRanges)
writepcranges(ctxt, u, u.lib.Textp[0], u.pcs, debugRanges)
}
// newdie adds DIEs to the *beginning* of the parent's DIE list.
@ -2162,6 +2182,10 @@ func saveDwsectCUSize(sname string, pkgname string, size uint64) {
dwsectCUSize[sname+"."+pkgname] = size
}
func addDwsectCUSize(sname string, pkgname string, size uint64) {
dwsectCUSize[sname+"."+pkgname] += size
}
// getPkgFromCUSym returns the package name for the compilation unit
// represented by s.
// The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get

View file

@ -501,7 +501,7 @@ func xcoffGetDwarfSubtype(str string) (string, uint32) {
case ".debug_pubtypes":
return ".dwpbtyp", SSUBTYP_DWPBTYP
case ".debug_ranges":
return ".dwrnge", SSUBTYP_DWRNGES
return ".dwrnges", SSUBTYP_DWRNGES
}
// never used
return "", 0
@ -661,13 +661,20 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
/* Dwarf */
for _, sect := range Segdwarf.Sections {
// Find the size of this corresponding package DWARF compilation unit.
// This size is set during DWARF generation (see dwarf.go).
dwsize := getDwsectCUSize(sect.Name, name)
// .debug_abbrev is commun to all packages and not found with the previous function
if sect.Name == ".debug_abbrev" {
s := ctxt.Syms.Lookup(sect.Name, 0)
dwsize = uint64(s.Size)
var dwsize uint64
if ctxt.LinkMode == LinkInternal {
// Find the size of this corresponding package DWARF compilation unit.
// This size is set during DWARF generation (see dwarf.go).
dwsize = getDwsectCUSize(sect.Name, name)
// .debug_abbrev is commun to all packages and not found with the previous function
if sect.Name == ".debug_abbrev" {
s := ctxt.Syms.ROLookup(sect.Name, 0)
dwsize = uint64(s.Size)
}
} else {
// There is only one .FILE with external linking.
dwsize = sect.Length
}
// get XCOFF name
@ -679,6 +686,20 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
Nscnum: f.getXCOFFscnum(sect),
Nnumaux: 1,
}
if currSymSrcFile.csectAux == nil {
// Dwarf relocations need the symbol number of .dw* symbols.
// It doesn't need to know it for each package, one is enough.
// currSymSrcFile.csectAux == nil means first package.
dws := ctxt.Syms.Lookup(sect.Name, 0)
dws.Dynid = int32(f.symbolCount)
if sect.Name == ".debug_frame" && ctxt.LinkMode != LinkExternal {
// CIE size must be added to the first package.
dwsize += 48
}
}
f.addSymbol(s)
// update the DWARF section offset in this file
@ -764,10 +785,25 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
} else {
// Current file has changed. New C_FILE, C_DWARF, etc must be generated.
if currSymSrcFile.name != x.File {
// update previous file values
xfile.updatePreviousFile(ctxt, false)
currSymSrcFile.name = x.File
f.writeSymbolNewFile(ctxt, x.File, uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
if ctxt.LinkMode == LinkInternal {
// update previous file values
xfile.updatePreviousFile(ctxt, false)
currSymSrcFile.name = x.File
f.writeSymbolNewFile(ctxt, x.File, uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
} else {
// With external linking, ld will crash if there is several
// .FILE and DWARF debugging enable, somewhere during
// the relocation phase.
// Therefore, all packages are merged under a fake .FILE
// "go_functions".
// TODO(aix); remove once ld has been fixed or the triggering
// relocation has been found and fixed.
if currSymSrcFile.name == "" {
currSymSrcFile.name = x.File
f.writeSymbolNewFile(ctxt, "go_functions", uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
}
}
}
}
@ -1119,9 +1155,6 @@ func (ctxt *Link) doxcoff() {
Exitf("-d is not available on AIX")
}
// Initial map used to store compilation unit size for each DWARF section (see dwarf.go).
dwsectCUSize = make(map[string]uint64)
// TOC
toc := ctxt.Syms.Lookup("TOC", 0)
toc.Type = sym.SXCOFFTOC
@ -1634,7 +1667,18 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
s.xcoffSect.Snreloc += n
}
// TODO(aix): DWARF relocations
dwarfLoop:
for _, sect := range Segdwarf.Sections {
for _, xcoffSect := range f.sections {
_, subtyp := xcoffGetDwarfSubtype(sect.Name)
if xcoffSect.Sflags&0xF0000 == subtyp {
xcoffSect.Srelptr = uint64(ctxt.Out.Offset())
xcoffSect.Snreloc = relocsect(sect, dwarfp, sect.Vaddr)
continue dwarfLoop
}
}
Errorf(nil, "emitRelocations: could not find %q section", sect.Name)
}
}
// xcoffCreateExportFile creates a file with exported symbols for