forked from OSchip/llvm-project
[PPC64] Write plt stubs for ElfV2 abi
Add the default version of a plt stub for the V2 Elf abi. Differential Revision: https://reviews.llvm.org/D44850 llvm-svn: 329004
This commit is contained in:
parent
bee4b5894a
commit
af95629deb
|
@ -157,20 +157,37 @@ void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
|
|||
unsigned RelOff) const {
|
||||
uint64_t Off = GotPltEntryAddr - getPPC64TocBase();
|
||||
|
||||
// FIXME: What we should do, in theory, is get the offset of the function
|
||||
// descriptor in the .opd section, and use that as the offset from %r2 (the
|
||||
// TOC-base pointer). Instead, we have the GOT-entry offset, and that will
|
||||
// be a pointer to the function descriptor in the .opd section. Using
|
||||
// this scheme is simpler, but requires an extra indirection per PLT dispatch.
|
||||
|
||||
write32(Buf, 0xf8410028); // std %r2, 40(%r1)
|
||||
write32(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
|
||||
write32(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
|
||||
write32(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
|
||||
write32(Buf + 16, 0x7d6903a6); // mtctr %r11
|
||||
write32(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
|
||||
write32(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
|
||||
write32(Buf + 28, 0x4e800420); // bctr
|
||||
if (Config->EKind == ELF64LEKind) {
|
||||
// The most-common form of the plt stub. This assumes that the toc-pointer
|
||||
// register is properly initalized, and that the stub must save the toc
|
||||
// pointer value to the stack-save slot reserved for it (sp + 24).
|
||||
// There are 2 other variants but we don't have to emit those until we add
|
||||
// support for R_PPC64_REL24_NOTOC and R_PPC64_TOCSAVE relocations.
|
||||
// We are missing a super simple optimization, where if the upper 16 bits of
|
||||
// the offset are zero, then we can omit the addis instruction, and load
|
||||
// r2 + lo-offset directly into r12. I decided to leave this out in the
|
||||
// spirit of keeping it simple until we can link actual non-trivial
|
||||
// programs.
|
||||
write32(Buf + 0, 0xf8410018); // std r2,24(r1)
|
||||
write32(Buf + 4, 0x3d820000 | applyPPCHa(Off)); // addis r12,r2, X@plt@to@ha
|
||||
write32(Buf + 8, 0xe98c0000 | applyPPCLo(Off)); // ld r12,X@plt@toc@l(r12)
|
||||
write32(Buf + 12, 0x7d8903a6); // mtctr r12
|
||||
write32(Buf + 16, 0x4e800420); // bctr
|
||||
} else {
|
||||
// FIXME: What we should do, in theory, is get the offset of the function
|
||||
// descriptor in the .opd section, and use that as the offset from %r2 (the
|
||||
// TOC-base pointer). Instead, we have the GOT-entry offset, and that will
|
||||
// be a pointer to the function descriptor in the .opd section. Using
|
||||
// this scheme is simpler, but requires an extra indirection per PLT dispatch.
|
||||
write32(Buf, 0xf8410028); // std %r2, 40(%r1)
|
||||
write32(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
|
||||
write32(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
|
||||
write32(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
|
||||
write32(Buf + 16, 0x7d6903a6); // mtctr %r11
|
||||
write32(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
|
||||
write32(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
|
||||
write32(Buf + 28, 0x4e800420); // bctr
|
||||
}
|
||||
}
|
||||
|
||||
static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
.text
|
||||
.abiversion 2
|
||||
.globl foo
|
||||
.p2align 4
|
||||
.type foo,@function
|
||||
|
||||
foo:
|
||||
.Lfunc_begin0:
|
||||
li 3, 55
|
||||
blr
|
||||
.long 0
|
||||
.quad 0
|
||||
.Lfunc_end0:
|
||||
.size foo, .Lfunc_end0-.Lfunc_begin0
|
|
@ -0,0 +1,37 @@
|
|||
// REQUIRES: ppc
|
||||
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
|
||||
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64le.s -o %t2.o
|
||||
// RUN: ld.lld -shared %t2.o -o %t2.so
|
||||
// RUN: ld.lld %t.o %t2.so -o %t
|
||||
// RUN: llvm-objdump -d %t | FileCheck %s
|
||||
|
||||
// CHECK: Disassembly of section .text:
|
||||
// CHECK: _start:
|
||||
// CHECK: bl .+24
|
||||
.text
|
||||
.abiversion 2
|
||||
.globl _start
|
||||
.p2align 4
|
||||
.type _start,@function
|
||||
_start:
|
||||
.Lfunc_begin0:
|
||||
.Lfunc_gep0:
|
||||
addis 2, 12, .TOC.-.Lfunc_gep0@ha
|
||||
addi 2, 2, .TOC.-.Lfunc_gep0@l
|
||||
.Lfunc_lep0:
|
||||
.localentry _start, .Lfunc_lep0-.Lfunc_gep0
|
||||
bl foo
|
||||
nop
|
||||
li 0, 1
|
||||
sc
|
||||
.size _start, .-.Lfunc_begin0
|
||||
|
||||
|
||||
|
||||
// CHECK: Disassembly of section .plt:
|
||||
// CHECK: .plt:
|
||||
// CHECK-NEXT: 18 00 41 f8 std 2, 24(1)
|
||||
// CHECK-NEXT: fe ff 82 3d addis 12, 2, -2
|
||||
// CHECK-NEXT: 48 7f 8c e9 ld 12, 32584(12)
|
||||
// CHECK-NEXT: a6 03 89 7d mtctr 12
|
||||
// CHECK: 20 04 80 4e bctr
|
Loading…
Reference in New Issue