From 7605a9a009b5fa3bdac07e3131c8d82f6d08feb7 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 8 Feb 2021 08:55:28 -0800 Subject: [PATCH] [ELF] Support aarch64_be This patch adds * Big-endian values for `R_AARCH64_{ABS,PREL}{16,32,64}` and `R_AARCH64_PLT32` * aarch64elfb & aarch64linuxb BFD emulations * elf64-bigaarch64 output format (bfdname) Link: https://github.com/ClangBuiltLinux/linux/issues/1288 Differential Revision: https://reviews.llvm.org/D96188 --- lld/ELF/Arch/AArch64.cpp | 10 +++++----- lld/ELF/Driver.cpp | 1 + lld/ELF/InputFiles.cpp | 1 + lld/ELF/ScriptParser.cpp | 1 + lld/test/ELF/aarch64-abs16.s | 5 +++++ lld/test/ELF/aarch64-abs32.s | 5 +++++ lld/test/ELF/aarch64-data-relocs.s | 7 +++++++ lld/test/ELF/aarch64-gnu-ifunc-plt.s | 14 ++++++++++++++ lld/test/ELF/aarch64-prel16.s | 4 ++++ lld/test/ELF/aarch64-prel32.s | 5 +++++ lld/test/ELF/aarch64-reloc-plt32.s | 9 +++++++-- lld/test/ELF/emulation-aarch64.s | 12 ++++++++++++ lld/test/ELF/lto/aarch64.ll | 33 +++++++++++++++++++++++++++++++++ 13 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 lld/test/ELF/lto/aarch64.ll diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 6fa860e..58da44a 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -195,7 +195,7 @@ RelType AArch64::getDynRel(RelType type) const { } void AArch64::writeGotPlt(uint8_t *buf, const Symbol &) const { - write64le(buf, in.plt->getVA()); + write64(buf, in.plt->getVA()); } void AArch64::writePltHeader(uint8_t *buf) const { @@ -323,20 +323,20 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, case R_AARCH64_ABS16: case R_AARCH64_PREL16: checkIntUInt(loc, val, 16, rel); - write16le(loc, val); + write16(loc, val); break; case R_AARCH64_ABS32: case R_AARCH64_PREL32: checkIntUInt(loc, val, 32, rel); - write32le(loc, val); + write32(loc, val); break; case R_AARCH64_PLT32: checkInt(loc, val, 32, rel); - write32le(loc, val); + write32(loc, val); break; case R_AARCH64_ABS64: case R_AARCH64_PREL64: - write64le(loc, val); + write64(loc, val); break; case R_AARCH64_ADD_ABS_LO12_NC: or32AArch64Imm(loc, val); diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index dce0a9c..09c2c17 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -146,6 +146,7 @@ static std::tuple parseEmulation(StringRef emul) { StringSwitch>(s) .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec", {ELF64LEKind, EM_AARCH64}) + .Cases("aarch64elfb", "aarch64linuxb", {ELF64BEKind, EM_AARCH64}) .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM}) .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 0f6afad..caca4bc 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1608,6 +1608,7 @@ static ELFKind getBitcodeELFKind(const Triple &t) { static uint16_t getBitcodeMachineKind(StringRef path, const Triple &t) { switch (t.getArch()) { case Triple::aarch64: + case Triple::aarch64_be: return EM_AARCH64; case Triple::amdgcn: case Triple::r600: diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index b81812d..3af6383 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -412,6 +412,7 @@ static std::pair parseBfdName(StringRef s) { .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf64-bigaarch64", {ELF64BEKind, EM_AARCH64}) .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC}) .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) diff --git a/lld/test/ELF/aarch64-abs16.s b/lld/test/ELF/aarch64-abs16.s index a0abe0f..5304921 100644 --- a/lld/test/ELF/aarch64-abs16.s +++ b/lld/test/ELF/aarch64-abs16.s @@ -3,6 +3,8 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs255.s -o %t255.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs256.s -o %t256.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs257.s -o %t257.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/abs256.s -o %t256.be.o .globl _start _start: @@ -12,6 +14,8 @@ _start: // RUN: ld.lld %t.o %t256.o -o %t // RUN: llvm-objdump -s --section=.data %t | FileCheck %s --check-prefixes=CHECK,LE +// RUN: ld.lld %t.be.o %t256.be.o -o %t.be +// RUN: llvm-objdump -s --section=.data %t.be | FileCheck %s --check-prefixes=CHECK,BE // CHECK: Contents of section .data: // 220158: S = 0x100, A = 0xfeff @@ -19,6 +23,7 @@ _start: // 22015c: S = 0x100, A = -0x8100 // S + A = 0x8000 // LE-NEXT: 220158 ffff0080 +// BE-NEXT: 220158 ffff8000 // RUN: not ld.lld %t.o %t255.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 // OVERFLOW1: relocation R_AARCH64_ABS16 out of range: -32769 is not in [-32768, 65535]; references foo diff --git a/lld/test/ELF/aarch64-abs32.s b/lld/test/ELF/aarch64-abs32.s index 42a7ca8..8bbacd9 100644 --- a/lld/test/ELF/aarch64-abs32.s +++ b/lld/test/ELF/aarch64-abs32.s @@ -3,6 +3,8 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs255.s -o %t255.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs256.s -o %t256.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs257.s -o %t257.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/abs256.s -o %t256.be.o .globl _start _start: @@ -12,6 +14,8 @@ _start: // RUN: ld.lld %t.o %t256.o -o %t // RUN: llvm-objdump -s --section=.data %t | FileCheck %s --check-prefixes=CHECK,LE +// RUN: ld.lld %t.be.o %t256.be.o -o %t.be +// RUN: llvm-objdump -s --section=.data %t.be | FileCheck %s --check-prefixes=CHECK,BE // CHECK: Contents of section .data: // 220158: S = 0x100, A = 0xfffffeff @@ -19,6 +23,7 @@ _start: // 22015c: S = 0x100, A = -0x80000100 // S + A = 0x80000000 // LE-NEXT: 220158 ffffffff 00000080 +// BE-NEXT: 220158 ffffffff 80000000 // RUN: not ld.lld %t.o %t255.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 // OVERFLOW1: relocation R_AARCH64_ABS32 out of range: -2147483649 is not in [-2147483648, 4294967295]; references foo diff --git a/lld/test/ELF/aarch64-data-relocs.s b/lld/test/ELF/aarch64-data-relocs.s index aa55cce..438740c 100644 --- a/lld/test/ELF/aarch64-data-relocs.s +++ b/lld/test/ELF/aarch64-data-relocs.s @@ -4,6 +4,11 @@ // RUN: ld.lld %t.o %t256.o -o %t // RUN: llvm-objdump -s %t | FileCheck %s --check-prefixes=CHECK,LE +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/abs256.s -o %t256.be.o +// RUN: ld.lld %t.be.o %t256.be.o -o %t.be +// RUN: llvm-objdump -s %t.be | FileCheck %s --check-prefixes=CHECK,BE + .globl _start _start: .section .R_AARCH64_ABS64, "ax",@progbits @@ -13,6 +18,7 @@ _start: // S + A = 0x124 // CHECK: Contents of section .R_AARCH64_ABS64: // LE-NEXT: 210120 24010000 00000000 +// BE-NEXT: 210120 00000000 00000124 .section .R_AARCH64_PREL64, "ax",@progbits .xword foo - . + 0x24 @@ -20,3 +26,4 @@ _start: // S + A - P = 0x100 + 0x24 - 0x210128 = 0xffffffffffdefffc // CHECK: Contents of section .R_AARCH64_PREL64: // LE-NEXT: 210128 fcffdeff ffffffff +// BE-NEXT: 210128 ffffffff ffdefffc diff --git a/lld/test/ELF/aarch64-gnu-ifunc-plt.s b/lld/test/ELF/aarch64-gnu-ifunc-plt.s index fdd8e6e..31b4942 100644 --- a/lld/test/ELF/aarch64-gnu-ifunc-plt.s +++ b/lld/test/ELF/aarch64-gnu-ifunc-plt.s @@ -7,6 +7,14 @@ // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT // RUN: llvm-readobj --dynamic-table -r %tout | FileCheck %s +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/shared2.s -o %t1.be.o +// RUN: ld.lld %t1.be.o --shared --soname=t.so -o %t.be.so +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +// RUN: ld.lld --hash-style=sysv %t.be.so %t.be.o -o %t.be +// RUN: llvm-objdump -d --no-show-raw-insn %t.be | FileCheck %s --check-prefix=DISASM +// RUN: llvm-objdump -s %t.be | FileCheck %s --check-prefix=GOTPLT_BE +// RUN: llvm-readobj --dynamic-table -r %t.be | FileCheck %s + // Check that the PLTRELSZ tag does not include the IRELATIVE relocations // CHECK: DynamicSection [ // CHECK: 0x0000000000000008 RELASZ 48 (bytes) @@ -31,6 +39,12 @@ // GOTPLT-NEXT: 230460 f0022100 00000000 00000000 00000000 // GOTPLT-NEXT: 230470 00000000 00000000 +// GOTPLT_BE: Contents of section .got.plt: +// GOTPLT_BE-NEXT: 230440 00000000 00000000 00000000 00000000 +// GOTPLT_BE-NEXT: 230450 00000000 00000000 00000000 002102f0 +// GOTPLT_BE-NEXT: 230460 00000000 002102f0 00000000 00000000 +// GOTPLT_BE-NEXT: 230470 00000000 00000000 + // Check that a PLT header is written and the ifunc entries appear last // DISASM: Disassembly of section .text: // DISASM-EMPTY: diff --git a/lld/test/ELF/aarch64-prel16.s b/lld/test/ELF/aarch64-prel16.s index cdebd2d..a18f079 100644 --- a/lld/test/ELF/aarch64-prel16.s +++ b/lld/test/ELF/aarch64-prel16.s @@ -3,6 +3,8 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs255.s -o %t255.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs256.s -o %t256.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs257.s -o %t257.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/abs256.s -o %t256.be.o .globl _start _start: @@ -16,6 +18,8 @@ _start: // if it is already fixed. Then, update addends accordingly. // RUN: ld.lld -z max-page-size=4096 %t.o %t256.o -o %t // RUN: llvm-objdump -s --section=.data %t | FileCheck %s --check-prefixes=CHECK,LE +// RUN: ld.lld -z max-page-size=4096 %t.be.o %t256.be.o -o %t.be +// RUN: llvm-objdump -s --section=.data %t.be | FileCheck %s --check-prefixes=CHECK,BE // CHECK: Contents of section .data: // 202158: S = 0x100, A = 0x212157, P = 0x202158 diff --git a/lld/test/ELF/aarch64-prel32.s b/lld/test/ELF/aarch64-prel32.s index 0fd72b9..ce9f059 100644 --- a/lld/test/ELF/aarch64-prel32.s +++ b/lld/test/ELF/aarch64-prel32.s @@ -3,6 +3,8 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs255.s -o %t255.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs256.s -o %t256.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs257.s -o %t257.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/abs256.s -o %t256.be.o .globl _start _start: @@ -16,6 +18,8 @@ _start: // if it is already fixed. Then, update addends accordingly. // RUN: ld.lld -z max-page-size=4096 %t.o %t256.o -o %t // RUN: llvm-objdump -s --section=.data %t | FileCheck %s --check-prefixes=CHECK,LE +// RUN: ld.lld -z max-page-size=4096 %t.be.o %t256.be.o -o %t.be +// RUN: llvm-objdump -s --section=.data %t.be | FileCheck %s --check-prefixes=CHECK,BE // CHECK: Contents of section .data: // 202158: S = 0x100, A = 0x100202057, P = 0x202158 @@ -23,6 +27,7 @@ _start: // 20215c: S = 0x100, A = -0x7fdfdfa4, P = 0x20215c // S + A - P = 0x80000000 // LE-NEXT: 202158 ffffffff 00000080 +// BE-NEXT: 202158 ffffffff 80000000 // RUN: not ld.lld -z max-page-size=4096 %t.o %t255.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 // OVERFLOW1: relocation R_AARCH64_PREL32 out of range: -2147483649 is not in [-2147483648, 4294967295]; references foo diff --git a/lld/test/ELF/aarch64-reloc-plt32.s b/lld/test/ELF/aarch64-reloc-plt32.s index a746756..2e56dfd 100644 --- a/lld/test/ELF/aarch64-reloc-plt32.s +++ b/lld/test/ELF/aarch64-reloc-plt32.s @@ -3,11 +3,15 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs255.s -o %t255.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs256.s -o %t256.o // RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs257.s -o %t257.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/abs256.s -o %t256.be.o /// Check for overflow with a R_AACH64_PLT32 relocation. // RUN: ld.lld -z max-page-size=4096 %t.o %t256.o -o %t2 -// RUN: llvm-objdump -s --section=.data %t2 | FileCheck %s +// RUN: llvm-objdump -s --section=.data %t2 | FileCheck %s --check-prefixes=CHECK,LE +// RUN: ld.lld -z max-page-size=4096 %t.be.o %t256.be.o -o %t2.be +// RUN: llvm-objdump -s --section=.data %t2.be | FileCheck %s --check-prefixes=CHECK,BE // CHECK: Contents of section .data: /// 202158: S = 0x100, A = 0x80202057, P = 0x202158 @@ -16,7 +20,8 @@ /// S + A - P = 0x80000000 /// 202160: S = 0x100, A = 0, P = 0x202160 /// S + A - P = 0xffdfdfa0 -// CHECK-NEXT: 202158 ffffff7f 00000080 a0dfdfff +// LE-NEXT: 202158 ffffff7f 00000080 a0dfdfff +// BE-NEXT: 202158 7fffffff 80000000 ffdfdfa0 // RUN: not ld.lld -z max-page-size=4096 %t.o %t255.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 // OVERFLOW1: relocation R_AARCH64_PLT32 out of range: -2147483649 is not in [-2147483648, 2147483647]; references foo diff --git a/lld/test/ELF/emulation-aarch64.s b/lld/test/ELF/emulation-aarch64.s index f7956f4..e5ba733 100644 --- a/lld/test/ELF/emulation-aarch64.s +++ b/lld/test/ELF/emulation-aarch64.s @@ -12,11 +12,23 @@ # RUN: ld.lld -m aarch64_elf64_le_vec %t.o -o %taosp # RUN: llvm-readobj --file-headers %taosp | FileCheck --check-prefixes=AARCH64,LE %s +# RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o +# RUN: ld.lld %t.be.o -o %t +# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefixes=AARCH64,BE %s +# RUN: ld.lld -m aarch64linuxb %t.be.o -o %t1.be +# RUN: llvm-readobj --file-headers %t1.be | FileCheck --check-prefixes=AARCH64,BE %s +# RUN: ld.lld -m aarch64elfb %t.be.o -o %t2.be +# RUN: llvm-readobj --file-headers %t2.be | FileCheck --check-prefixes=AARCH64,BE %s +# RUN: echo 'OUTPUT_FORMAT(elf64-bigaarch64)' > %t.script +# RUN: ld.lld %t.script %t.be.o -o %t3.be +# RUN: llvm-readobj --file-headers %t3.be | FileCheck --check-prefixes=AARCH64,BE %s + # AARCH64: ElfHeader { # AARCH64-NEXT: Ident { # AARCH64-NEXT: Magic: (7F 45 4C 46) # AARCH64-NEXT: Class: 64-bit (0x2) # LE-NEXT: DataEncoding: LittleEndian (0x1) +# BE-NEXT: DataEncoding: BigEndian (0x2) # AARCH64-NEXT: FileVersion: 1 # AARCH64-NEXT: OS/ABI: SystemV (0x0) # AARCH64-NEXT: ABIVersion: 0 diff --git a/lld/test/ELF/lto/aarch64.ll b/lld/test/ELF/lto/aarch64.ll new file mode 100644 index 0000000..a6f6cee --- /dev/null +++ b/lld/test/ELF/lto/aarch64.ll @@ -0,0 +1,33 @@ +; REQUIRES: aarch64 +;; Test we can infer the e_machine value EM_AARCH64 from a bitcode file. + +; RUN: split-file %s %t +; RUN: llvm-as %t/le.s -o %t/le.o +; RUN: ld.lld %t/le.o -o %t/le +; RUN: llvm-readobj -h %t/le | FileCheck %s --check-prefixes=CHECK,LE + +; RUN: llvm-as %t/be.s -o %t/be.o +; RUN: ld.lld %t/be.o -o %t/be +; RUN: llvm-readobj -h %t/be | FileCheck %s --check-prefixes=CHECK,BE + +; LE: DataEncoding: LittleEndian +; BE: DataEncoding: BigEndian +; CHECK: Machine: EM_AARCH64 + +;--- le.s +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-gnu" + +define void @_start() { +entry: + ret void +} + +;--- be.s +target datalayout = "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64_be-unknown-linux-gnu" + +define void @_start() { +entry: + ret void +} -- 2.7.4