nim / rpms / golang

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