]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: enforce larger alignment on split ppc64 text sections
authorPaul E. Murphy <murp@ibm.com>
Mon, 5 Apr 2021 18:40:48 +0000 (13:40 -0500)
committerLynn Boger <laboger@linux.vnet.ibm.com>
Tue, 27 Apr 2021 11:55:52 +0000 (11:55 +0000)
When laying out, we lazily increase the alignment for text sections
as symbols are found requiring more. This works if the start of
the virtual address (VA) for the section is greater than or equal
to the alignment required by any symbols placed in this section.

The minimum alignment of the section is only known after all
symbols are placed. The starting VA of this section is adjusted
upwards in ld.(*Link).address to meet the requested alignment.

This is a problem if the starting VA of the text section is not
already aligned. This can happen when the final symbol placed
into the previous section results in an insufficiently aligned
start VA of the next text section.

To workaround this, additional text sections are split, and both
the starting VA, and alignment of the section are aligned up to
match the known worst case alignment.

64B is chosen as the worst case alignment for all ppc64 targets,
as it will respect PCALIGN and eventually prefixed instructions
which will be introduced in the future.

Likewise, the xcoff size calculations need to be improved to
handle padding bytes when function symbols have been aligned.
This is done by tracking the largest valid VA offset encountered
when placing symbols.

Change-Id: Iefef09a1ee7c963fb8dfce2288a084a95cb77fca
Reviewed-on: https://go-review.googlesource.com/c/go/+/307431
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/xcoff.go

index b909526de8d478284ae624d58ca55b7c6adb9cd2..a135fe8fd2679aeb5b59c1f0067782c0418e6979 100644 (file)
@@ -2298,12 +2298,23 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
                }
 
                if va-sect.Vaddr+funcsize+maxSizeTrampolinesPPC64(ldr, s, isTramp) > textSizelimit {
+                       // Align the next text section to the worst case function alignment likely
+                       // to be encountered when processing function symbols. The start address
+                       // is rounded against the final alignment of the text section later on in
+                       // (*Link).address. This may happen due to usage of PCALIGN directives
+                       // larger than Funcalign, or usage of ISA 3.1 prefixed instructions
+                       // (see ISA 3.1 Book I 1.9).
+                       const ppc64maxFuncalign = 64
+                       va = uint64(Rnd(int64(va), ppc64maxFuncalign))
+
                        // Set the length for the previous text section
                        sect.Length = va - sect.Vaddr
 
                        // Create new section, set the starting Vaddr
                        sect = addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05)
+
                        sect.Vaddr = va
+                       sect.Align = ppc64maxFuncalign
                        ldr.SetSymSect(s, sect)
 
                        // Create a symbol for the start of the secondary text sections
@@ -2316,6 +2327,7 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
                                ntext.SetType(sym.STEXT)
                                ntext.SetSize(int64(MINFUNC))
                                ntext.SetOnList(true)
+                               ntext.SetAlign(ppc64maxFuncalign)
                                ctxt.tramps = append(ctxt.tramps, ntext.Sym())
 
                                ntext.SetValue(int64(va))
index d412c6966bc3bc0e5ea09f4694d02200c15cbe3a..12bd23f7e57e1d9410d3c2309ab1938c2b8d3bc9 100644 (file)
@@ -28,8 +28,11 @@ const (
        // Total amount of space to reserve at the start of the file
        // for File Header, Auxiliary Header, and Section Headers.
        // May waste some.
-       XCOFFHDRRESERVE       = FILHSZ_64 + AOUTHSZ_EXEC64 + SCNHSZ_64*23
-       XCOFFSECTALIGN  int64 = 32 // base on dump -o
+       XCOFFHDRRESERVE = FILHSZ_64 + AOUTHSZ_EXEC64 + SCNHSZ_64*23
+
+       // base on dump -o, then rounded from 32B to 64B to
+       // match worst case elf text section alignment on ppc64.
+       XCOFFSECTALIGN int64 = 64
 
        // XCOFF binaries should normally have all its sections position-independent.
        // However, this is not yet possible for .text because of some R_ADDR relocations
@@ -555,11 +558,12 @@ func Xcoffinit(ctxt *Link) {
 
 // type records C_FILE information needed for genasmsym in XCOFF.
 type xcoffSymSrcFile struct {
-       name       string
-       file       *XcoffSymEnt64   // Symbol of this C_FILE
-       csectAux   *XcoffAuxCSect64 // Symbol for the current .csect
-       csectSymNb uint64           // Symbol number for the current .csect
-       csectSize  int64
+       name         string
+       file         *XcoffSymEnt64   // Symbol of this C_FILE
+       csectAux     *XcoffAuxCSect64 // Symbol for the current .csect
+       csectSymNb   uint64           // Symbol number for the current .csect
+       csectVAStart int64
+       csectVAEnd   int64
 }
 
 var (
@@ -746,7 +750,8 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
        f.addSymbol(aux)
 
        currSymSrcFile.csectAux = aux
-       currSymSrcFile.csectSize = 0
+       currSymSrcFile.csectVAStart = int64(firstEntry)
+       currSymSrcFile.csectVAEnd = int64(firstEntry)
 }
 
 // Update values for the previous package.
@@ -768,8 +773,9 @@ func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
 
        // update csect scnlen in this auxiliary entry
        aux := currSymSrcFile.csectAux
-       aux.Xscnlenlo = uint32(currSymSrcFile.csectSize & 0xFFFFFFFF)
-       aux.Xscnlenhi = uint32(currSymSrcFile.csectSize >> 32)
+       csectSize := currSymSrcFile.csectVAEnd - currSymSrcFile.csectVAStart
+       aux.Xscnlenlo = uint32(csectSize & 0xFFFFFFFF)
+       aux.Xscnlenhi = uint32(csectSize >> 32)
 }
 
 // Write symbol representing a .text function.
@@ -832,8 +838,13 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x loader.Sym) []xcoffSym {
        ldr.SetSymDynid(x, int32(xfile.symbolCount))
        syms = append(syms, s)
 
-       // Update current csect size
-       currSymSrcFile.csectSize += ldr.SymSize(x)
+       // Keep track of the section size by tracking the VA range. Individual
+       // alignment differences may introduce a few extra bytes of padding
+       // which are not fully accounted for by ldr.SymSize(x).
+       sv := ldr.SymValue(x) + ldr.SymSize(x)
+       if currSymSrcFile.csectVAEnd < sv {
+               currSymSrcFile.csectVAEnd = sv
+       }
 
        // create auxiliary entries
        a2 := &XcoffAuxFcn64{
@@ -1549,7 +1560,7 @@ func (f *xcoffFile) writeFileHeader(ctxt *Link) {
                f.xahdr.Otoc = uint64(ldr.SymValue(toc))
                f.xahdr.Osntoc = f.getXCOFFscnum(ldr.SymSect(toc))
 
-               f.xahdr.Oalgntext = int16(logBase2(int(Funcalign)))
+               f.xahdr.Oalgntext = int16(logBase2(int(XCOFFSECTALIGN)))
                f.xahdr.Oalgndata = 0x5
 
                binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)