]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: write ELF relocations in mmap on all architectures
authorCherry Zhang <cherryyz@google.com>
Sat, 4 Jul 2020 22:14:08 +0000 (18:14 -0400)
committerCherry Zhang <cherryyz@google.com>
Mon, 6 Jul 2020 19:58:23 +0000 (19:58 +0000)
In CL 240399 we changed to precompute the size for ELF relocation
records and use mmap to write them, but we left architectures
where elfreloc1 write non-fixed number of bytes. This CL handles
those architectures. When a Go relocation will turn into multiple
ELF relocations, in relocsym we account this difference and add
it to the size calculation. So when emitting ELF relocations, we
know the number of ELF relocations to be emitted.

Change-Id: I6732ab674b442f4618405e5412a77f6e4a3315d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/241079
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
15 files changed:
src/cmd/link/internal/amd64/asm.go
src/cmd/link/internal/arm/asm.go
src/cmd/link/internal/arm64/asm.go
src/cmd/link/internal/arm64/obj.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/mips/asm.go
src/cmd/link/internal/mips64/asm.go
src/cmd/link/internal/ppc64/asm.go
src/cmd/link/internal/ppc64/obj.go
src/cmd/link/internal/riscv64/asm.go
src/cmd/link/internal/s390x/asm.go
src/cmd/link/internal/x86/asm.go
src/cmd/link/internal/x86/obj.go

index 609daef078425817c8985735b04b13b988dbf78d..f9474860c01ab92e9f389c2486e63291b7ddf6eb 100644 (file)
@@ -550,8 +550,8 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
        return true
 }
 
-func archreloc(*ld.Target, *loader.Loader, *ld.ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, bool, bool) {
-       return -1, false, false
+func archreloc(*ld.Target, *loader.Loader, *ld.ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, int, bool) {
+       return -1, 0, false
 }
 
 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
index a75dc9525fd737b74c26574002df489d9fab257e..64e06b33aa16d03aafa87bc782f6228b0f9766cf 100644 (file)
@@ -528,7 +528,7 @@ func gentrampdyn(arch *sys.Arch, tramp *loader.SymbolBuilder, target loader.Sym,
        tramp.AddReloc(r)
 }
 
-func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
        rs := r.Sym()
        rs = ldr.ResolveABIAlias(rs)
        if target.IsExternal() {
@@ -549,14 +549,14 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                                ldr.Errorf(s, "direct call too far %d", rr.Xadd/4)
                        }
 
-                       return int64(braddoff(int32(0xff000000&uint32(r.Add())), int32(0xffffff&uint32(rr.Xadd/4)))), true, true
+                       return int64(braddoff(int32(0xff000000&uint32(r.Add())), int32(0xffffff&uint32(rr.Xadd/4)))), 1, true
                }
 
-               return -1, false, false
+               return -1, 0, false
        }
 
        const isOk = true
-       const noExtReloc = false
+       const noExtReloc = 0
        switch r.Type() {
        // The following three arch specific relocations are only for generation of
        // Linux/ARM ELF's PLT entry (3 assembler instruction)
@@ -579,7 +579,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                return int64(braddoff(int32(0xff000000&uint32(r.Add())), int32(0xffffff&t))), noExtReloc, isOk
        }
 
-       return val, false, false
+       return val, 0, false
 }
 
 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
index 4928d3eb2a499693f02c9f03c64ac6807aa95601..bbd53825b663f5a807aa966ea0f5b276cf129240 100644 (file)
@@ -441,18 +441,20 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy
        return true
 }
 
-func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (int64, bool, bool) {
-       const extRelocNeeded = true
-       const extRelocNotNeeded = false
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (int64, int, bool) {
+       const noExtReloc = 0
        const isOk = true
 
        rs := ldr.ResolveABIAlias(r.Sym())
 
        if target.IsExternal() {
-               switch r.Type() {
+               nExtReloc := 0
+               switch rt := r.Type(); rt {
                default:
                case objabi.R_ARM64_GOTPCREL,
                        objabi.R_ADDRARM64:
+                       nExtReloc = 2 // need two ELF relocations. see elfreloc1
+
                        // set up addend for eventual relocation via outer symbol.
                        rs, off := ld.FoldSubSymbolOffset(ldr, rs)
                        rr.Xadd = r.Add() + off
@@ -494,13 +496,17 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                                }
                        }
 
-                       return val, extRelocNeeded, isOk
+                       return val, nExtReloc, isOk
                case objabi.R_CALLARM64,
                        objabi.R_ARM64_TLS_LE,
                        objabi.R_ARM64_TLS_IE:
+                       nExtReloc = 1
+                       if rt == objabi.R_ARM64_TLS_IE {
+                               nExtReloc = 2 // need two ELF relocations. see elfreloc1
+                       }
                        rr.Xsym = rs
                        rr.Xadd = r.Add()
-                       return val, extRelocNeeded, isOk
+                       return val, nExtReloc, isOk
                }
        }
 
@@ -526,9 +532,9 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
 
                // when laid out, the instruction order must always be o1, o2.
                if target.IsBigEndian() {
-                       return int64(o0)<<32 | int64(o1), extRelocNotNeeded, true
+                       return int64(o0)<<32 | int64(o1), noExtReloc, true
                }
-               return int64(o1)<<32 | int64(o0), extRelocNotNeeded, true
+               return int64(o1)<<32 | int64(o0), noExtReloc, true
 
        case objabi.R_ARM64_TLS_LE:
                if target.IsDarwin() {
@@ -540,7 +546,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                if v < 0 || v >= 32678 {
                        ldr.Errorf(s, "TLS offset out of range %d", v)
                }
-               return val | (v << 5), extRelocNeeded, true
+               return val | (v << 5), noExtReloc, true
 
        case objabi.R_ARM64_TLS_IE:
                if target.IsPIE() && target.IsElf() {
@@ -579,9 +585,9 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
 
                        // when laid out, the instruction order must always be o0, o1.
                        if target.IsBigEndian() {
-                               return int64(o0)<<32 | int64(o1), extRelocNotNeeded, isOk
+                               return int64(o0)<<32 | int64(o1), noExtReloc, isOk
                        }
-                       return int64(o1)<<32 | int64(o0), extRelocNotNeeded, isOk
+                       return int64(o1)<<32 | int64(o0), noExtReloc, isOk
                } else {
                        log.Fatalf("cannot handle R_ARM64_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
                }
@@ -596,7 +602,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                if t >= 1<<27 || t < -1<<27 {
                        ldr.Errorf(s, "program too large, call relocation distance = %d", t)
                }
-               return val | ((t >> 2) & 0x03ffffff), extRelocNotNeeded, true
+               return val | ((t >> 2) & 0x03ffffff), noExtReloc, true
 
        case objabi.R_ARM64_GOT:
                sData := ldr.Data(s)
@@ -609,7 +615,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                        }
                        var o0 uint32
                        o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
-                       return val | int64(o0), extRelocNotNeeded, isOk
+                       return val | int64(o0), noExtReloc, isOk
                } else if sData[r.Off()+3] == 0xf9 {
                        // R_AARCH64_LD64_GOT_LO12_NC
                        // patch instruction: ldr
@@ -619,7 +625,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                        }
                        var o1 uint32
                        o1 |= uint32(t&0xfff) << (10 - 3)
-                       return val | int64(uint64(o1)), extRelocNotNeeded, isOk
+                       return val | int64(uint64(o1)), noExtReloc, isOk
                } else {
                        ldr.Errorf(s, "unsupported instruction for %v R_GOTARM64", sData[r.Off():r.Off()+4])
                }
@@ -634,13 +640,13 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                                ldr.Errorf(s, "program too large, address relocation distance = %d", t)
                        }
                        o0 := (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
-                       return val | int64(o0), extRelocNotNeeded, isOk
+                       return val | int64(o0), noExtReloc, isOk
                } else if sData[r.Off()+3]&0x91 == 0x91 {
                        // R_AARCH64_ADD_ABS_LO12_NC
                        // patch instruction: add
                        t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
                        o1 := uint32(t&0xfff) << 10
-                       return val | int64(o1), extRelocNotNeeded, isOk
+                       return val | int64(o1), noExtReloc, isOk
                } else {
                        ldr.Errorf(s, "unsupported instruction for %v R_PCRELARM64", sData[r.Off():r.Off()+4])
                }
@@ -648,7 +654,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
        case objabi.R_ARM64_LDST8:
                t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
                o0 := uint32(t&0xfff) << 10
-               return val | int64(o0), extRelocNotNeeded, true
+               return val | int64(o0), noExtReloc, true
 
        case objabi.R_ARM64_LDST32:
                t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
@@ -656,7 +662,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                        ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST32_ABS_LO12_NC", t)
                }
                o0 := (uint32(t&0xfff) >> 2) << 10
-               return val | int64(o0), extRelocNotNeeded, true
+               return val | int64(o0), noExtReloc, true
 
        case objabi.R_ARM64_LDST64:
                t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
@@ -664,7 +670,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                        ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST64_ABS_LO12_NC", t)
                }
                o0 := (uint32(t&0xfff) >> 3) << 10
-               return val | int64(o0), extRelocNotNeeded, true
+               return val | int64(o0), noExtReloc, true
 
        case objabi.R_ARM64_LDST128:
                t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
@@ -672,10 +678,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                        ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST128_ABS_LO12_NC", t)
                }
                o0 := (uint32(t&0xfff) >> 4) << 10
-               return val | int64(o0), extRelocNotNeeded, true
+               return val | int64(o0), noExtReloc, true
        }
 
-       return val, false, false
+       return val, 0, false
 }
 
 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
index 8eeba0d6886390ce16b7be8072b87e3c41b71edb..5d07746ad589ef0539af0af85b2478cd68cbbec0 100644 (file)
@@ -51,6 +51,7 @@ func Init() (*sys.Arch, ld.Arch) {
                Archreloc:        archreloc,
                Archrelocvariant: archrelocvariant,
                Elfreloc1:        elfreloc1,
+               ElfrelocSize:     24,
                Elfsetupplt:      elfsetupplt,
                Gentext:          gentext,
                Machoreloc1:      machoreloc1,
index 7dc2c4662dde28fb8338c36a5b1350d7396ba646..a19a1451afbf4f80dab9ff9e5d31dd27a72c5c0c 100644 (file)
@@ -164,6 +164,11 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
                // relocs will require an external reloc
                extRelocs = st.preallocExtRelocSlice(relocs.Count())
        }
+       // Extra external host relocations (e.g. ELF relocations).
+       // This is the difference between number of host relocations
+       // and number of Go relocations, as one Go relocation may turn
+       // into multiple host relocations.
+       extraExtReloc := 0
        for ri := 0; ri < relocs.Count(); ri++ {
                r := relocs.At2(ri)
                off := r.Off()
@@ -261,16 +266,21 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
                        var rp *loader.ExtReloc
                        if target.IsExternal() {
                                // Don't pass &rr directly to Archreloc, which will escape rr
-                               // even if this case is not taken. Instead, as Archreloc2 will
+                               // even if this case is not taken. Instead, as Archreloc will
                                // likely return true, we speculatively add rr to extRelocs
                                // and use that space to pass to Archreloc.
                                extRelocs = append(extRelocs, rr)
                                rp = &extRelocs[len(extRelocs)-1]
                        }
-                       out, needExtReloc1, ok := thearch.Archreloc(target, ldr, syms, r, rp, s, o)
-                       if target.IsExternal() && !needExtReloc1 {
-                               // Speculation failed. Undo the append.
-                               extRelocs = extRelocs[:len(extRelocs)-1]
+                       out, nExtReloc, ok := thearch.Archreloc(target, ldr, syms, r, rp, s, o)
+                       if target.IsExternal() {
+                               if nExtReloc == 0 {
+                                       // No external relocation needed. Speculation failed. Undo the append.
+                                       extRelocs = extRelocs[:len(extRelocs)-1]
+                               } else {
+                                       // Account for the difference between host relocations and Go relocations.
+                                       extraExtReloc += nExtReloc - 1
+                               }
                        }
                        needExtReloc = false // already appended
                        if ok {
@@ -321,6 +331,9 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
                                if !target.IsAMD64() {
                                        o = r.Add()
                                }
+                               if target.Is386() {
+                                       extraExtReloc++ // need two ELF relocations on 386, see ../x86/asm.go:elfreloc1
+                               }
                                break
                        }
                        if target.IsPIE() && target.IsElf() {
@@ -452,6 +465,9 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
                                o += int64(siz)
                                break
                        }
+                       if target.Is386() && target.IsExternal() && target.IsELF {
+                               extraExtReloc++ // need two ELF relocations on 386, see ../x86/asm.go:elfreloc1
+                       }
                        fallthrough
                case objabi.R_CALL, objabi.R_PCREL:
                        if target.IsExternal() && rs != 0 && rst == sym.SUNDEFEXT {
@@ -582,7 +598,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
        if len(extRelocs) != 0 {
                st.finalizeExtRelocSlice(extRelocs)
                ldr.SetExtRelocs(s, extRelocs)
-               atomic.AddUint32(&ldr.SymSect(s).Relcount, uint32(len(extRelocs)))
+               atomic.AddUint32(&ldr.SymSect(s).Relcount, uint32(len(extRelocs)+extraExtReloc))
        }
 }
 
index 8e4b2a3fe41e9591e362c3d10f3c02077f83e3b9..5af6020cedd442491c7d658dc352db90fccb63e9 100644 (file)
@@ -1393,6 +1393,11 @@ func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym)
                        }
                }
        }
+
+       // sanity check
+       if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
+               panic("elfrelocsect: size mismatch")
+       }
 }
 
 func elfEmitReloc(ctxt *Link) {
@@ -1402,29 +1407,25 @@ func elfEmitReloc(ctxt *Link) {
 
        // Precompute the size needed for the reloc records if we can
        // Mmap the output buffer with the proper size.
-       //
-       // TODO: on some architectures, one Go relocation may turn to
-       // multiple ELF relocations, which makes the size not fixed.
-       // Handle this case better. Maybe increment the counter by the
-       // number of external reloc records in relocsym.
-       var sz, filesz int64
-       if thearch.ElfrelocSize != 0 {
-               for _, seg := range Segments {
-                       for _, sect := range seg.Sections {
-                               sect.Reloff = uint64(ctxt.Out.Offset() + sz)
-                               sect.Rellen = uint64(thearch.ElfrelocSize * sect.Relcount)
-                               sz += int64(sect.Rellen)
-                       }
+       if thearch.ElfrelocSize == 0 {
+               panic("elfEmitReloc: ELF relocation size not set")
+       }
+       var sz int64
+       for _, seg := range Segments {
+               for _, sect := range seg.Sections {
+                       sect.Reloff = uint64(ctxt.Out.Offset() + sz)
+                       sect.Rellen = uint64(thearch.ElfrelocSize * sect.Relcount)
+                       sz += int64(sect.Rellen)
                }
-               filesz = ctxt.Out.Offset() + sz
-               ctxt.Out.Mmap(uint64(filesz))
        }
+       filesz := ctxt.Out.Offset() + sz
+       ctxt.Out.Mmap(uint64(filesz))
 
        // Now emits the records.
        var relocSect func(ctxt *Link, sect *sym.Section, syms []loader.Sym)
        var wg sync.WaitGroup
        var sem chan int
-       if thearch.ElfrelocSize != 0 && ctxt.Out.isMmapped() {
+       if ctxt.Out.isMmapped() {
                // Write sections in parallel.
                sem = make(chan int, 2*runtime.GOMAXPROCS(0))
                relocSect = func(ctxt *Link, sect *sym.Section, syms []loader.Sym) {
@@ -1436,21 +1437,14 @@ func elfEmitReloc(ctxt *Link) {
                        }
                        go func() {
                                elfrelocsect(ctxt, out, sect, syms)
-                               // sanity check
-                               if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
-                                       panic("elfEmitReloc: size mismatch")
-                               }
                                wg.Done()
                                <-sem
                        }()
                }
        } else {
-               // Sizes and offsets are not precomputed, or we cannot Mmap.
-               // We have to write sequentially.
+               // We cannot Mmap. Write sequentially.
                relocSect = func(ctxt *Link, sect *sym.Section, syms []loader.Sym) {
-                       sect.Reloff = uint64(ctxt.Out.Offset()) // offset is not precomputed, so fill it in now
                        elfrelocsect(ctxt, ctxt.Out, sect, syms)
-                       sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
                }
        }
        for _, sect := range Segtext.Sections {
index 5d078d0e9925e0bc650611d5769defd1acc94ebd..a53bb45327833078829f6d94537fde16631a6e62 100644 (file)
@@ -206,11 +206,12 @@ type Arch struct {
        // containing the chunk of data to which the relocation applies, and "off"
        // is the contents of the to-be-relocated data item (from sym.P). Return
        // value is the appropriately relocated value (to be written back to the
-       // same spot in sym.P), a boolean indicating if the external relocations'
-       // been used, and a boolean indicating success/failure (a failing value
-       // indicates a fatal error).
+       // same spot in sym.P), number of external _host_ relocations needed (i.e.
+       // ELF/Mach-O/etc. relocations, not Go relocations, this must match Elfreloc1,
+       // etc.), and a boolean indicating success/failure (a failing value indicates
+       // a fatal error).
        Archreloc func(*Target, *loader.Loader, *ArchSyms, loader.Reloc2, *loader.ExtReloc,
-               loader.Sym, int64) (relocatedOffset int64, needExtReloc bool, ok bool)
+               loader.Sym, int64) (relocatedOffset int64, nExtReloc int, ok bool)
        // Archrelocvariant is a second arch-specific hook used for
        // relocation processing; it handles relocations where r.Type is
        // insufficient to describe the relocation (r.Variant !=
@@ -237,7 +238,7 @@ type Arch struct {
        Asmb2 func(*Link, *loader.Loader)
 
        Elfreloc1    func(*Link, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
-       ElfrelocSize uint32 // size of an ELF relocation record, must match Elfreloc1. Currently this can be 0, meaning that the size is not fixed (a Go reloc may turn into multiple ELF reloc).
+       ElfrelocSize uint32 // size of an ELF relocation record, must match Elfreloc1.
        Elfsetupplt  func(ctxt *Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
        Gentext      func(*Link, *loader.Loader)
        Machoreloc1  func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
index 7e1b9b3730bf7eab204651b4e8605d287917fa71..5344a72a312662ff08ee3df73abb42e1961fdc53 100644 (file)
@@ -90,13 +90,13 @@ func applyrel(arch *sys.Arch, ldr *loader.Loader, rt objabi.RelocType, off int32
        }
 }
 
-func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
        rs := r.Sym()
        rs = ldr.ResolveABIAlias(rs)
        if target.IsExternal() {
                switch r.Type() {
                default:
-                       return val, false, false
+                       return val, 0, false
 
                case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
                        // set up addend for eventual relocation via outer symbol.
@@ -107,17 +107,17 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                                ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
                        }
                        rr.Xsym = rs
-                       return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, rr.Xadd), true, true
+                       return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, rr.Xadd), 1, true
 
                case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
                        rr.Xsym = rs
                        rr.Xadd = r.Add()
-                       return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, rr.Xadd), true, true
+                       return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, rr.Xadd), 1, true
                }
        }
 
        const isOk = true
-       const noExtReloc = false
+       const noExtReloc = 0
        switch rt := r.Type(); rt {
        case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
                t := ldr.SymValue(rs) + r.Add()
@@ -144,7 +144,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
        }
 
-       return val, false, false
+       return val, 0, false
 }
 
 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
index d8760b45f5d363950ce327db019eb30d962a2bbd..73b1542c84d51dc8abf36db3d66b27ad2d01db57 100644 (file)
@@ -94,13 +94,13 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe
        return false
 }
 
-func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
        rs := r.Sym()
        rs = ldr.ResolveABIAlias(rs)
        if target.IsExternal() {
                switch r.Type() {
                default:
-                       return val, false, false
+                       return val, 0, false
 
                case objabi.R_ADDRMIPS,
                        objabi.R_ADDRMIPSU:
@@ -112,19 +112,19 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                                ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
                        }
                        rr.Xsym = rs
-                       return val, true, true
+                       return val, 1, true
 
                case objabi.R_ADDRMIPSTLS,
                        objabi.R_CALLMIPS,
                        objabi.R_JMPMIPS:
                        rr.Xsym = rs
                        rr.Xadd = r.Add()
-                       return val, true, true
+                       return val, 1, true
                }
        }
 
        const isOk = true
-       const noExtReloc = false
+       const noExtReloc = 0
        switch r.Type() {
        case objabi.R_ADDRMIPS,
                objabi.R_ADDRMIPSU:
@@ -150,7 +150,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                return int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000), noExtReloc, isOk
        }
 
-       return val, false, false
+       return val, 0, false
 }
 
 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
index b8cd1c7bd30c7f50f9b6fe0e0a5cde9ed7c44fc9..7dca8703a8eaf4fcd0a9500fc291b350c3d94f9d 100644 (file)
@@ -797,30 +797,32 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta
        tramp.SetData(P)
 }
 
-func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (relocatedOffset int64, needExtReloc bool, ok bool) {
-       needExternal := false
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (relocatedOffset int64, nExtReloc int, ok bool) {
        rs := ldr.ResolveABIAlias(r.Sym())
        if target.IsExternal() {
                // On AIX, relocations (except TLS ones) must be also done to the
                // value with the current addresses.
-               switch r.Type() {
+               switch rt := r.Type(); rt {
                default:
                        if target.IsAIX() {
-                               return val, needExternal, false
+                               return val, nExtReloc, false
                        }
                case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
                        // check Outer is nil, Type is TLSBSS?
-                       needExternal = true
+                       nExtReloc = 1
+                       if rt == objabi.R_POWER_TLS_IE {
+                               nExtReloc = 2 // need two ELF relocations, see elfreloc1
+                       }
                        rr.Xadd = r.Add()
                        rr.Xsym = rs
-                       return val, needExternal, true
+                       return val, nExtReloc, true
                case objabi.R_ADDRPOWER,
                        objabi.R_ADDRPOWER_DS,
                        objabi.R_ADDRPOWER_TOCREL,
                        objabi.R_ADDRPOWER_TOCREL_DS,
                        objabi.R_ADDRPOWER_GOT,
                        objabi.R_ADDRPOWER_PCREL:
-                       needExternal = true
+                       nExtReloc = 2 // need two ELF relocations, see elfreloc1
 
                        // set up addend for eventual relocation via outer symbol.
                        rs, off := ld.FoldSubSymbolOffset(ldr, rs)
@@ -832,23 +834,23 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                        rr.Xsym = rs
 
                        if !target.IsAIX() {
-                               return val, needExternal, true
+                               return val, nExtReloc, true
                        }
                case objabi.R_CALLPOWER:
-                       needExternal = true
+                       nExtReloc = 1
                        rr.Xsym = rs
                        rr.Xadd = r.Add()
                        if !target.IsAIX() {
-                               return val, needExternal, true
+                               return val, nExtReloc, true
                        }
                }
        }
 
        switch r.Type() {
        case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
-               return archreloctoc(ldr, target, syms, r, s, val), needExternal, true
+               return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
        case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
-               return archrelocaddr(ldr, target, syms, r, s, val), needExternal, true
+               return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
        case objabi.R_CALLPOWER:
                // Bits 6 through 29 = (S + A - P) >> 2
 
@@ -862,9 +864,9 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                if int64(int32(t<<6)>>6) != t {
                        ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
                }
-               return val | int64(uint32(t)&^0xfc000003), needExternal, true
+               return val | int64(uint32(t)&^0xfc000003), nExtReloc, true
        case objabi.R_POWER_TOC: // S + A - .TOC.
-               return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), needExternal, true
+               return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
 
        case objabi.R_POWER_TLS_LE:
                // The thread pointer points 0x7000 bytes after the start of the
@@ -880,10 +882,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                if int64(int16(v)) != v {
                        ldr.Errorf(s, "TLS offset out of range %d", v)
                }
-               return (val &^ 0xffff) | (v & 0xffff), needExternal, true
+               return (val &^ 0xffff) | (v & 0xffff), nExtReloc, true
        }
 
-       return val, needExternal, false
+       return val, nExtReloc, false
 }
 
 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc2, rv sym.RelocVariant, s loader.Sym, t int64) (relocatedOffset int64) {
index 8a94f9aa237083807754c379c878baa4ea3ce26d..31823444dd1338ce2ba71fdee61861bf556543ea 100644 (file)
@@ -55,6 +55,7 @@ func Init() (*sys.Arch, ld.Arch) {
                Archreloc:        archreloc,
                Archrelocvariant: archrelocvariant,
                Elfreloc1:        elfreloc1,
+               ElfrelocSize:     24,
                Elfsetupplt:      elfsetupplt,
                Gentext:          gentext,
                Trampoline:       trampoline,
index bf8ce0c51ec6569dbfe744c29d9801651516de52..991e0b9556d41b992772b5eea816289760189824 100644 (file)
@@ -32,13 +32,13 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe
        return false
 }
 
-func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
        rs := r.Sym()
        rs = ldr.ResolveABIAlias(rs)
        switch r.Type() {
        case objabi.R_CALLRISCV:
                // Nothing to do.
-               return val, false, true
+               return val, 0, true
 
        case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
                pc := ldr.SymValue(s) + int64(r.Off())
@@ -79,10 +79,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
                auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
                second = (second &^ secondImmMask) | int64(uint32(secondImm))
 
-               return second<<32 | auipc, false, true
+               return second<<32 | auipc, 0, true
        }
 
-       return val, false, false
+       return val, 0, false
 }
 
 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
index c2d0dc2ea55fe0487b9f04eedd4ecefc66d4941d..00f946e70499edeb7c0e1b0955f63a9792cd2874 100644 (file)
@@ -367,8 +367,8 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe
        return false
 }
 
-func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
-       return val, false, false
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
+       return val, 0, false
 }
 
 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc2, rv sym.RelocVariant, s loader.Sym, t int64) int64 {
index 5e3c452c3a3f62ea94a9f3729ac23017e8731465..4d59261db987dc29fd3122f948eb4b9c72db095d 100644 (file)
@@ -411,8 +411,8 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
        return true
 }
 
-func archreloc(*ld.Target, *loader.Loader, *ld.ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, bool, bool) {
-       return -1, false, false
+func archreloc(*ld.Target, *loader.Loader, *ld.ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, int, bool) {
+       return -1, 0, false
 }
 
 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
index e1c469ca85aea42f780663a37e0084726a322c12..a19437d8e61d1c35098860579f2b21be7ebe13bc 100644 (file)
@@ -55,6 +55,7 @@ func Init() (*sys.Arch, ld.Arch) {
                Archreloc:        archreloc,
                Archrelocvariant: archrelocvariant,
                Elfreloc1:        elfreloc1,
+               ElfrelocSize:     8,
                Elfsetupplt:      elfsetupplt,
                Gentext:          gentext,
                Machoreloc1:      machoreloc1,