nim / rpms / golang

Forked from rpms/golang 5 years ago
Clone
Blob Blame History Raw
From a5b97a846d70cd8db7f33c24f2b9159f935ce318 Mon Sep 17 00:00:00 2001
From: Lynn Boger <laboger@linux.vnet.ibm.com>
Date: Tue, 13 Sep 2016 15:13:08 -0500
Subject: [PATCH] cmd/compile: large text sections on ppc64le

Additional fixes as submitted upstream.
---
 src/cmd/link/internal/ld/data.go   | 24 ++++++++++++------------
 src/cmd/link/internal/ld/lib.go    |  2 +-
 src/cmd/link/internal/ld/symtab.go |  2 +-
 src/runtime/type.go                | 28 ++++++++++++++++++----------
 4 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 58ce18c..d8e43ff 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -531,7 +531,7 @@ func relocsym(s *LSym) {
 			// The method offset tables using this relocation expect the offset to be relative
 			// to the start of the first text section, even if there are multiple.
 
-			if Linkmode == LinkExternal && r.Sym.Sect.Name == ".text" && r.Sym.Sect.Vaddr != Segtext.Vaddr {
+			if r.Sym.Sect.Name == ".text" {
 				o = Symaddr(r.Sym) - int64(Segtext.Vaddr) + r.Add
 			} else {
 				o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
@@ -1928,7 +1928,6 @@ func textaddress() {
 
 	sect.Align = int32(Funcalign)
 	Linklookup(Ctxt, "runtime.text", 0).Sect = sect
-	Linklookup(Ctxt, "runtime.etext", 0).Sect = sect
 	if HEADTYPE == obj.Hwindows {
 		Linklookup(Ctxt, ".text", 0).Sect = sect
 	}
@@ -1964,7 +1963,7 @@ func textaddress() {
 
 		// Only break at outermost syms.
 
-		if sym.Outer == nil && Iself && Linkmode == LinkExternal && SysArch.InFamily(sys.PPC64) && va-sect.Vaddr > uint64(0x1c00000) {
+		if sym.Outer == nil && Iself && Linkmode == LinkExternal && SysArch.InFamily(sys.PPC64) && va-sect.Vaddr > 0x1c00000 {
 
 			// Set the length for the previous text section
 			sect.Length = va - sect.Vaddr
@@ -1973,7 +1972,7 @@ func textaddress() {
 			sect = addsection(&Segtext, ".text", 05)
 			sect.Vaddr = va
 
-			// Create a symbol for the start and end of the secondary text section
+			// Create a symbol for the start of the secondary text section
 			Linklookup(Ctxt, fmt.Sprintf("runtime.text.%d", n), 0).Sect = sect
 			n++
 		}
@@ -2093,15 +2092,8 @@ func address() {
 		rodata = Segrodata.Sect
 	} else {
 		// Could be multiple .text sections
-		n := 1
-		for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
-			if sect.Name != ".text" {
-				break
-			}
+		for sect := Segtext.Sect.Next; sect != nil && sect.Name == ".text"; sect = sect.Next {
 			lasttext = sect
-			symname := fmt.Sprintf("runtime.text.%d", n)
-			xdefine(symname, obj.STEXT, int64(sect.Vaddr))
-			n++
 		}
 
 		rodata = lasttext.Next
@@ -2155,6 +2147,14 @@ func address() {
 
 	xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
 	xdefine("runtime.etext", obj.STEXT, int64(lasttext.Vaddr+lasttext.Length))
+
+	n := 1
+	for sect := Segtext.Sect.Next; sect != nil && sect.Name == ".text"; sect = sect.Next {
+		symname := fmt.Sprintf("runtime.text.%d", n)
+		xdefine(symname, obj.STEXT, int64(sect.Vaddr))
+		n++
+	}
+
 	if HEADTYPE == obj.Hwindows {
 		xdefine(".text", obj.STEXT, int64(text.Vaddr))
 	}
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 709e7ca..c37ef92 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1958,7 +1958,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
 	}
 	n := 0
 
-	// Generate base addresses for all text sections if there are multiple
+	// Generate base addresses for all text sections if there are multiple.
 	for sect := Segtext.Sect; sect != nil; sect = sect.Next {
 		if n == 0 {
 			n++
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 80eb33d..ec26f88 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -331,7 +331,7 @@ func textsectionmap() uint32 {
 			break
 		}
 	}
-	Symgrow(Ctxt, t, nsections*3*8)
+	Symgrow(Ctxt, t, nsections*(2*int64(SysArch.IntSize)+int64(SysArch.PtrSize)))
 
 	off := int64(0)
 	n := 0
diff --git a/src/runtime/type.go b/src/runtime/type.go
index f641adc..d4df5a9 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -259,17 +259,25 @@ func (t *_type) textOff(off textOff) unsafe.Pointer {
 	}
 	res := uintptr(0)
 
-	// Find the text section range that contains the offset to determine the section's base
-	// address.  In cases where there are multiple text sections, the base address might be
-	// relocated by the linker.
-
-	for i := 0; i < len(md.textsectmap); i++ {
-		sectaddr := md.textsectmap[i].vaddr
-		sectlen := md.textsectmap[i].length
-		if uint64(off) >= sectaddr && uint64(off) <= sectaddr+sectlen {
-			res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr)
-			break
+	// The text, or instruction stream is generated as one large buffer.  The off (offset) for a method is
+	// its offset within this buffer.  If the total text size gets too large, there can be issues on platforms like ppc64 if
+	// the target of calls are too far for the call instruction.  To resolve the large text issue, the text is split
+	// into multiple text sections to allow the linker to generate long calls when necessary.  When this happens, the vaddr
+	// for each text section is set to its offset within the text.  Each method's offset is compared against the section
+	// vaddrs and sizes to determine the containing section.  Then the section relative offset is added to the section's
+	// relocated baseaddr to compute the method addess.
+
+	if len(md.textsectmap) > 1 {
+		for i := 0; i < len(md.textsectmap); i++ {
+			sectaddr := md.textsectmap[i].vaddr
+			sectlen := md.textsectmap[i].length
+			if uint64(off) >= sectaddr && uint64(off) <= sectaddr+sectlen {
+				res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr)
+				break
+			}
 		}
+	} else {
+		res = md.text + uintptr(off)
 	}
 
 	if res > md.etext {