From a5b97a846d70cd8db7f33c24f2b9159f935ce318 Mon Sep 17 00:00:00 2001 From: Lynn Boger 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 {