"debug/elf"
"encoding/binary"
"fmt"
+ "internal/buildcfg"
"log"
"strconv"
"strings"
)
+// The build configuration supports PC-relative instructions and relocations.
+var hasPCrel = buildcfg.GOPPC64 >= 10 && buildcfg.GOOS == "linux" && buildcfg.GOARCH == "ppc64le"
+
func genpltstub(ctxt *ld.Link, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (sym loader.Sym, firstUse bool) {
// The ppc64 ABI PLT has similar concepts to other
// architectures, but is laid out quite differently. When we
P := make([]byte, tramp.Size())
var o1, o2 uint32
+ // ELFv2 save/restore functions use R0/R12 in special ways, therefore trampolines
+ // as generated here will not always work correctly.
+ if strings.HasPrefix(ldr.SymName(target), "runtime.elf_") {
+ log.Fatalf("Internal linker does not support trampolines to ELFv2 ABI"+
+ " register save/restore function %s", ldr.SymName(target))
+ }
+
if ctxt.IsAIX() {
// On AIX, the address is retrieved with a TOC symbol.
// For internal linking, the "Linux" way might still be used.
r.SetOff(0)
r.SetSiz(8) // generates 2 relocations: HA + LO
r.SetSym(toctramp.Sym())
+ } else if hasPCrel {
+ // pla r12, addr (PCrel). This works for static or PIC, with or without a valid TOC pointer.
+ o1 = uint32(0x06100000)
+ o2 = uint32(0x39800000) // pla r12, addr
+
+ // The trampoline's position is not known yet, insert a relocation.
+ r, _ := tramp.AddRel(objabi.R_ADDRPOWER_PCREL34)
+ r.SetOff(0)
+ r.SetSiz(8) // This spans 2 words.
+ r.SetSym(target)
+ r.SetAdd(offset)
} else {
// Used for default build mode for an executable
// Address of the call target is generated using
o1 = uint32(0x3c000000) | 12<<21 // lis r12,targetaddr hi
o2 = uint32(0x38000000) | 12<<21 | 12<<16 // addi r12,r12,targetaddr lo
- // ELFv2 save/restore functions use R0/R12 in special ways, therefore trampolines
- // as generated here will not always work correctly.
- if strings.HasPrefix(ldr.SymName(target), "runtime.elf_") {
- log.Fatalf("Internal linker does not support trampolines to ELFv2 ABI"+
- " register save/restore function %s", ldr.SymName(target))
- }
-
t := ldr.SymValue(target)
if t == 0 || r2Valid(ctxt) || ctxt.IsExternal() {
// Target address is unknown, generate relocations