]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: enable DWARF with external linker on aix/ppc64
authorClément Chigot <clement.chigot@atos.net>
Wed, 20 Feb 2019 15:29:00 +0000 (16:29 +0100)
committerIan Lance Taylor <iant@golang.org>
Sat, 9 Mar 2019 00:25:11 +0000 (00:25 +0000)
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>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/xcoff.go

index a48db2aeeba05e89764a8d24c6ccea2be3ad8aa1..9d160ca49b0c0cb7af01e6324f4b859c1364c8eb 100644 (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)
index 995a7e77b9ff9af715bd6ac28d22206a37640628..446fd572ac7f9c21be0b263dce8f860b08beb9df 100644 (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
index ee375bfe03ce2c67b72fdf34c563b53eeba2afb7..70be67420b1826febcf8bab96c5c311ab91ba415 100644 (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