151 lines
5.9 KiB
Diff
151 lines
5.9 KiB
Diff
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 {
|