Skip to content

Commit

Permalink
[AArch64][ELF] Add support for PLT decoding with BTI instructions pre…
Browse files Browse the repository at this point in the history
…sent

Arm Architecture v8.5a introduces Branch Target Identification (BTI). When
enabled all indirect branches must target a bti instruction of the
appropriate form. As PLT sequences may sometimes be the target of an
indirect branch and PLT[0] always is, a static linker may need to generate
PLT sequences that contain "bti c" as the first instruction. In effect:
bti     c
adrp    x16, page offset to .got.plt
...
Instead of:
adrp    x16, page offset to .got.plt
...
At present the PLT decoding assumes the adrp will always be the first
instruction. This patch adds support for a single "bti c" to prefix it. A
test binary has been uploaded with such a PLT sequence. A forthcoming LLD
patch will make heavy use of the PLT decoding code.

Differential Revision: https://reviews.llvm.org/D62598

llvm-svn: 362523
  • Loading branch information
smithp35 committed Jun 4, 2019
1 parent 8e8ddaa commit f15e3d8
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
10 changes: 9 additions & 1 deletion llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
Expand Up @@ -333,12 +333,20 @@ class AArch64MCInstrAnalysis : public MCInstrAnalysis {
for (uint64_t Byte = 0, End = PltContents.size(); Byte + 7 < End;
Byte += 4) {
uint32_t Insn = support::endian::read32le(PltContents.data() + Byte);
uint64_t Off = 0;
// Check for optional bti c that prefixes adrp in BTI enabled entries
if (Insn == 0xd503245f) {
Off = 4;
Insn = support::endian::read32le(PltContents.data() + Byte + Off);
}
// Check for adrp.
if ((Insn & 0x9f000000) != 0x90000000)
continue;
Off += 4;
uint64_t Imm = (((PltSectionVA + Byte) >> 12) << 12) +
(((Insn >> 29) & 3) << 12) + (((Insn >> 5) & 0x3ffff) << 14);
uint32_t Insn2 = support::endian::read32le(PltContents.data() + Byte + 4);
uint32_t Insn2 =
support::endian::read32le(PltContents.data() + Byte + Off);
// Check for: ldr Xt, [Xn, #pimm].
if (Insn2 >> 22 == 0x3e5) {
Imm += ((Insn2 >> 10) & 0xfff) << 3;
Expand Down
57 changes: 56 additions & 1 deletion llvm/test/tools/llvm-objdump/AArch64/plt.test
@@ -1,5 +1,60 @@
// RUN: llvm-objdump -d %p/Inputs/cfi.elf-aarch64 | FileCheck %s
# RUN: llvm-objdump -d %p/Inputs/cfi.elf-aarch64 | FileCheck %s

# CHECK: Disassembly of section .plt:
# CHECK: __cfi_slowpath@plt:
# CHECK-NEXT: adrp x16, {{.*}}
# CHECK: bl {{.*}} <__cfi_slowpath@plt>

# RUN: yaml2obj %s -o %t.aarch64
# RUN: llvm-objdump -d -mattr=+bti %t.aarch64 | \
# RUN: FileCheck --check-prefix=CHECK-BTI %s
# CHECK-BTI: bl {{.*}} <f1@plt>
# CHECK-BTI: bl {{.*}} <f2@plt>
# CHECK-BTI: Disassembly of section .plt:
# CHECK-BTI: f1@plt:
# CHECK-BTI-NEXT: bti c
# CHECK-BTI-NEXT: adrp x16, {{.*}}
# CHECK-BTI: f2@plt:
# CHECK-BTI-NEXT: bti c
# CHECK-BTI-NEXT: adrp x16, {{.*}}

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_AARCH64
Sections:
- Name: .rela.plt
Type: SHT_RELA
Flags: [ SHF_ALLOC ]
EntSize: 0x0000000000000018
Info: .got.plt
Relocations:
- Offset: 0x0000000000230018
Symbol: f1
Type: R_AARCH64_JUMP_SLOT
- Offset: 0x0000000000230020
Symbol: f2
Type: R_AARCH64_JUMP_SLOT
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x0000000000210000
Content: 0C00009411000094C0035FD6
- Name: .plt
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x0000000000210010
Content: 5F2403D5F07BBFA910010090110A40F91042009120021FD61F2003D51F2003D55F2403D510010090110E40F9106200919F2103D520021FD65F2403D510010090111240F9108200919F2103D520021FD6
- Name: .got.plt
Type: SHT_PROGBITS
Content: '000000000000000000000000000000000000000000000000100021000000000010002100000000001000210000000000'
Symbols:
- Name: f1
Type: STT_FUNC
Binding: STB_GLOBAL
- Name: f2
Type: STT_FUNC
Binding: STB_GLOBAL
...

0 comments on commit f15e3d8

Please sign in to comment.