Commit 3cf89e50 authored by Clément Chigot's avatar Clément Chigot Committed by Ian Lance Taylor

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: default avatarIan Lance Taylor <iant@golang.org>
parent b37b35ed
...@@ -1773,6 +1773,12 @@ func (ctxt *Link) dodata() { ...@@ -1773,6 +1773,12 @@ func (ctxt *Link) dodata() {
s.Value = int64(uint64(datsize) - sect.Vaddr) s.Value = int64(uint64(datsize) - sect.Vaddr)
s.Attr |= sym.AttrLocal s.Attr |= sym.AttrLocal
datsize += s.Size 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 sect.Length = uint64(datsize) - sect.Vaddr
checkdatsize(ctxt, datsize, curType) checkdatsize(ctxt, datsize, curType)
......
...@@ -1342,13 +1342,20 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) { ...@@ -1342,13 +1342,20 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
} }
// writepcranges generates the DW_AT_ranges table for compilation unit cu. // 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} var dwarfctxt dwarf.Context = dwctxt{ctxt}
unitLengthOffset := ranges.Size
// Create PC ranges for this CU. // Create PC ranges for this CU.
newattr(cu, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, ranges.Size, ranges) newattr(unit.dwinfo, 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_low_pc, dwarf.DW_CLS_ADDRESS, base.Value, base)
dwarf.PutRanges(dwarfctxt, ranges, nil, pcs) 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 { ...@@ -1500,6 +1507,10 @@ func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
fs.AddAddr(ctxt.Arch, s) fs.AddAddr(ctxt.Arch, s)
fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range
fs.AddBytes(deltaBuf) fs.AddBytes(deltaBuf)
if ctxt.HeadType == objabi.Haix {
addDwsectCUSize(".debug_frame", s.File, fdeLength+uint64(lengthFieldSize))
}
} }
return syms return syms
} }
...@@ -1705,11 +1716,11 @@ func dwarfEnabled(ctxt *Link) bool { ...@@ -1705,11 +1716,11 @@ func dwarfEnabled(ctxt *Link) bool {
} }
if ctxt.LinkMode == LinkExternal { if ctxt.LinkMode == LinkExternal {
// TODO(aix): enable DWARF
switch { switch {
case ctxt.IsELF: case ctxt.IsELF:
case ctxt.HeadType == objabi.Hdarwin: case ctxt.HeadType == objabi.Hdarwin:
case ctxt.HeadType == objabi.Hwindows: case ctxt.HeadType == objabi.Hwindows:
case ctxt.HeadType == objabi.Haix:
default: default:
return false return false
} }
...@@ -1730,6 +1741,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) { ...@@ -1730,6 +1741,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
return 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) ctxt.compUnitByPackage = make(map[*sym.Library]*compilationUnit)
// Forctxt.Diagnostic messages. // Forctxt.Diagnostic messages.
...@@ -1829,6 +1845,10 @@ func dwarfGenerateDebugInfo(ctxt *Link) { ...@@ -1829,6 +1845,10 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
if ctxt.HeadType == objabi.Hdarwin { if ctxt.HeadType == objabi.Hdarwin {
removeDwarfAddrListBaseAddress(ctxt, dsym, rangeSym, false) 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) unit.rangeSyms = append(unit.rangeSyms, rangeSym)
} }
...@@ -1891,7 +1911,7 @@ func dwarfGenerateDebugSyms(ctxt *Link) { ...@@ -1891,7 +1911,7 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
continue continue
} }
writelines(ctxt, u, debugLine) 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. // newdie adds DIEs to the *beginning* of the parent's DIE list.
...@@ -2162,6 +2182,10 @@ func saveDwsectCUSize(sname string, pkgname string, size uint64) { ...@@ -2162,6 +2182,10 @@ func saveDwsectCUSize(sname string, pkgname string, size uint64) {
dwsectCUSize[sname+"."+pkgname] = size 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 // getPkgFromCUSym returns the package name for the compilation unit
// represented by s. // represented by s.
// The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get // The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get
......
...@@ -501,7 +501,7 @@ func xcoffGetDwarfSubtype(str string) (string, uint32) { ...@@ -501,7 +501,7 @@ func xcoffGetDwarfSubtype(str string) (string, uint32) {
case ".debug_pubtypes": case ".debug_pubtypes":
return ".dwpbtyp", SSUBTYP_DWPBTYP return ".dwpbtyp", SSUBTYP_DWPBTYP
case ".debug_ranges": case ".debug_ranges":
return ".dwrnge", SSUBTYP_DWRNGES return ".dwrnges", SSUBTYP_DWRNGES
} }
// never used // never used
return "", 0 return "", 0
...@@ -661,13 +661,20 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6 ...@@ -661,13 +661,20 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
/* Dwarf */ /* Dwarf */
for _, sect := range Segdwarf.Sections { for _, sect := range Segdwarf.Sections {
var dwsize uint64
if ctxt.LinkMode == LinkInternal {
// Find the size of this corresponding package DWARF compilation unit. // Find the size of this corresponding package DWARF compilation unit.
// This size is set during DWARF generation (see dwarf.go). // This size is set during DWARF generation (see dwarf.go).
dwsize := getDwsectCUSize(sect.Name, name) dwsize = getDwsectCUSize(sect.Name, name)
// .debug_abbrev is commun to all packages and not found with the previous function // .debug_abbrev is commun to all packages and not found with the previous function
if sect.Name == ".debug_abbrev" { if sect.Name == ".debug_abbrev" {
s := ctxt.Syms.Lookup(sect.Name, 0) s := ctxt.Syms.ROLookup(sect.Name, 0)
dwsize = uint64(s.Size) dwsize = uint64(s.Size)
}
} else {
// There is only one .FILE with external linking.
dwsize = sect.Length
} }
// get XCOFF name // get XCOFF name
...@@ -679,6 +686,20 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6 ...@@ -679,6 +686,20 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
Nscnum: f.getXCOFFscnum(sect), Nscnum: f.getXCOFFscnum(sect),
Nnumaux: 1, 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) f.addSymbol(s)
// update the DWARF section offset in this file // update the DWARF section offset in this file
...@@ -764,10 +785,25 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym { ...@@ -764,10 +785,25 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
} else { } else {
// Current file has changed. New C_FILE, C_DWARF, etc must be generated. // Current file has changed. New C_FILE, C_DWARF, etc must be generated.
if currSymSrcFile.name != x.File { if currSymSrcFile.name != x.File {
if ctxt.LinkMode == LinkInternal {
// update previous file values // update previous file values
xfile.updatePreviousFile(ctxt, false) xfile.updatePreviousFile(ctxt, false)
currSymSrcFile.name = x.File currSymSrcFile.name = x.File
f.writeSymbolNewFile(ctxt, x.File, uint64(x.Value), xfile.getXCOFFscnum(x.Sect)) 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() { ...@@ -1119,9 +1155,6 @@ func (ctxt *Link) doxcoff() {
Exitf("-d is not available on AIX") 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
toc := ctxt.Syms.Lookup("TOC", 0) toc := ctxt.Syms.Lookup("TOC", 0)
toc.Type = sym.SXCOFFTOC toc.Type = sym.SXCOFFTOC
...@@ -1634,7 +1667,18 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) { ...@@ -1634,7 +1667,18 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
s.xcoffSect.Snreloc += n 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 // xcoffCreateExportFile creates a file with exported symbols for
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment