[lld] r329004 - [PPC64] Write plt stubs for ElfV2 abi
Sean Fertile via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 2 12:17:12 PDT 2018
Author: sfertile
Date: Mon Apr 2 12:17:12 2018
New Revision: 329004
URL: http://llvm.org/viewvc/llvm-project?rev=329004&view=rev
Log:
[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
Added:
lld/trunk/test/ELF/Inputs/shared-ppc64le.s
lld/trunk/test/ELF/ppc64le-plt-stub.s
Modified:
lld/trunk/ELF/Arch/PPC64.cpp
Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=329004&r1=329003&r2=329004&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Mon Apr 2 12:17:12 2018
@@ -157,20 +157,37 @@ void PPC64::writePlt(uint8_t *Buf, uint6
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 at ha
- write32(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X at 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 at plt@to at ha
+ write32(Buf + 8, 0xe98c0000 | applyPPCLo(Off)); // ld r12,X at plt@toc at 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 at ha
+ write32(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X at 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) {
Added: lld/trunk/test/ELF/Inputs/shared-ppc64le.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/shared-ppc64le.s?rev=329004&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/shared-ppc64le.s (added)
+++ lld/trunk/test/ELF/Inputs/shared-ppc64le.s Mon Apr 2 12:17:12 2018
@@ -0,0 +1,14 @@
+ .text
+ .abiversion 2
+ .globl foo
+ .p2align 4
+ .type foo, at function
+
+foo:
+.Lfunc_begin0:
+ li 3, 55
+ blr
+ .long 0
+ .quad 0
+.Lfunc_end0:
+ .size foo, .Lfunc_end0-.Lfunc_begin0
Added: lld/trunk/test/ELF/ppc64le-plt-stub.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64le-plt-stub.s?rev=329004&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64le-plt-stub.s (added)
+++ lld/trunk/test/ELF/ppc64le-plt-stub.s Mon Apr 2 12:17:12 2018
@@ -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, at function
+_start:
+.Lfunc_begin0:
+.Lfunc_gep0:
+ addis 2, 12, .TOC.-.Lfunc_gep0 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep0 at 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
More information about the llvm-commits
mailing list