From 27100f389e9a4c7497185108e625b52956043ef3 Mon Sep 17 00:00:00 2001
From: Clement <clement.chigot@atos.net>
Date: Thu, 14 Feb 2019 10:02:11 -0600
Subject: [PATCH 11/24]  cmd/link: enable DWARF with external linker on
 aix/ppc64

---
 src/cmd/link/internal/ld/data.go  |  6 ++++
 src/cmd/link/internal/ld/dwarf.go | 34 +++++++++++++++---
 src/cmd/link/internal/ld/xcoff.go | 76 ++++++++++++++++++++++++++++++---------
 3 files changed, 95 insertions(+), 21 deletions(-)

diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 00f9ca65f9..df35f4d128 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -1774,6 +1774,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)
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 0b17985da5..93ddf503eb 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -1348,13 +1348,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))
+	}
+
 }
 
 /*
@@ -1506,6 +1513,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
 }
@@ -1683,11 +1694,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
 		}
@@ -1708,6 +1719,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.
@@ -1807,6 +1823,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)
 			}
 
@@ -1869,7 +1889,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.
@@ -2139,6 +2159,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
diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go
index f94f6693b5..e33f53b7e3 100644
--- a/src/cmd/link/internal/ld/xcoff.go
+++ b/src/cmd/link/internal/ld/xcoff.go
@@ -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
@@ -667,13 +667,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
@@ -685,6 +692,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
@@ -770,10 +791,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))
+				}
+			}
+
 		}
 	}
 
@@ -1125,9 +1161,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
@@ -1629,7 +1662,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
-- 
2.15.1

