diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -126,6 +126,7 @@ case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_TSTBR14: + case R_AARCH64_PLT32: return R_PLT_PC; case R_AARCH64_PREL16: case R_AARCH64_PREL32: @@ -244,7 +245,8 @@ // ELF for the ARM 64-bit architecture, section Call and Jump relocations // only permits range extension thunks for R_AARCH64_CALL26 and // R_AARCH64_JUMP26 relocation types. - if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26) + if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26 && + type != R_AARCH64_PLT32) return false; uint64_t dst = expr == R_PLT_PC ? s.getPltVA() : s.getVA(a); return !inBranchRange(type, branchAddr, dst); @@ -322,6 +324,7 @@ break; case R_AARCH64_ABS32: case R_AARCH64_PREL32: + case R_AARCH64_PLT32: checkIntUInt(loc, val, 32, rel); write32le(loc, val); break; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -556,6 +556,7 @@ case R_AARCH64_PREL64: case R_AARCH64_ADR_PREL_LO21: case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_PLT32: return p + a; } llvm_unreachable("AArch64 pc-relative relocation expected\n"); diff --git a/lld/test/ELF/aarch64-fpic-plt32.s b/lld/test/ELF/aarch64-fpic-plt32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/aarch64-fpic-plt32.s @@ -0,0 +1,19 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t2 +// RUN: llvm-objdump -s %t2 | FileCheck %s + +// Check that for an undefined symbol, the offset is taken from the PLT. + +// CHECK: Contents of section .plt: +// CHECK-NEXT: 10290 +// CHECK: Contents of section .data: +// CHECK: 30370 40fffdff +// The calculation is +// 0x10290 (foo@PLT) +// - 0x30370 (.data) +// --------- +// -0x200c0 -> 0xfffdff40 -> 0x40fffdff (little endian) + +.data + .word foo - . diff --git a/lld/test/ELF/aarch64-fpic-prel32.s b/lld/test/ELF/aarch64-fpic-prel32.s deleted file mode 100644 --- a/lld/test/ELF/aarch64-fpic-prel32.s +++ /dev/null @@ -1,9 +0,0 @@ -// REQUIRES: aarch64 -// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o -// RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s -// CHECK: relocation R_AARCH64_PREL32 cannot be used against symbol foo; recompile with -fPIC -// CHECK: >>> defined in {{.*}} -// CHECK: >>> referenced by {{.*}}:(.data+0x0) - -.data - .word foo - . diff --git a/lld/test/ELF/aarch64-prel32.s b/lld/test/ELF/aarch64-plt32.s rename from lld/test/ELF/aarch64-prel32.s rename to lld/test/ELF/aarch64-plt32.s --- a/lld/test/ELF/aarch64-prel32.s +++ b/lld/test/ELF/aarch64-plt32.s @@ -25,7 +25,7 @@ // CHECK-NEXT: 202158 ffffffff 00000080 // 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 +// OVERFLOW1: relocation R_AARCH64_PLT32 out of range: -2147483649 is not in [-2147483648, 4294967295]; references foo // RUN: not ld.lld -z max-page-size=4096 %t.o %t257.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW2 -// OVERFLOW2: relocation R_AARCH64_PREL32 out of range: 4294967296 is not in [-2147483648, 4294967295]; references foo +// OVERFLOW2: relocation R_AARCH64_PLT32 out of range: 4294967296 is not in [-2147483648, 4294967295]; references foo diff --git a/lld/test/ELF/aarch64-undefined-weak.s b/lld/test/ELF/aarch64-undefined-weak.s --- a/lld/test/ELF/aarch64-undefined-weak.s +++ b/lld/test/ELF/aarch64-undefined-weak.s @@ -27,7 +27,7 @@ adrp x0, target // R_AARCH64_LD_PREL_LO19 ldr x8, target -// R_AARCH64_PREL32 +// R_AARCH64_PLT32 .word target - . // R_AARCH64_PREL64 .xword target - . diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -399,6 +399,7 @@ case ELF::R_AARCH64_ABS64: write(isBE, TargetPtr, Value + Addend); break; + case ELF::R_AARCH64_PLT32: case ELF::R_AARCH64_PREL32: { uint64_t Result = Value + Addend - FinalAddress; assert(static_cast(Result) >= INT32_MIN && diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -129,8 +129,17 @@ return ELF::R_AARCH64_NONE; case FK_Data_2: return R_CLS(PREL16); - case FK_Data_4: - return R_CLS(PREL32); + case FK_Data_4: { + const auto &ElfSym = + llvm::cast(Target.getSymA()->getSymbol()); + if (ElfSym.isUndefined() || ElfSym.getType() == llvm::ELF::STT_FUNC) + // Even if this is undefined, the PLT relocation should be relaxed to a + // PREL32 relocation during link time if it turns out to be defined + // within the same linkage unit. + return R_CLS(PLT32); + return (ElfSym.getVisibility() == llvm::ELF::STV_HIDDEN) ? R_CLS(PREL32) + : R_CLS(PLT32); + } case FK_Data_8: if (IsILP32) { Ctx.reportError(Fixup.getLoc(), diff --git a/llvm/test/MC/AArch64/arm32-elf-relocs.s b/llvm/test/MC/AArch64/arm32-elf-relocs.s --- a/llvm/test/MC/AArch64/arm32-elf-relocs.s +++ b/llvm/test/MC/AArch64/arm32-elf-relocs.s @@ -57,7 +57,7 @@ .hword sym + 4 - . // CHECK-OBJ-ILP32: 30 R_AARCH64_P32_PREL16 sym+0x4 .word sym - . + 8 -// CHECK-OBJ-ILP32: 32 R_AARCH64_P32_PREL32 sym+0x8 +// CHECK-OBJ-ILP32: 32 R_AARCH64_P32_PLT32 sym+0x8 .hword sym // CHECK-OBJ-ILP32: 36 R_AARCH64_P32_ABS16 sym diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s --- a/llvm/test/MC/AArch64/arm64-elf-relocs.s +++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s @@ -62,7 +62,7 @@ .hword sym + 4 - . // CHECK-OBJ-LP64: 38 R_AARCH64_PREL16 sym+0x4 .word sym - . + 8 -// CHECK-OBJ-LP64: 3a R_AARCH64_PREL32 sym+0x8 +// CHECK-OBJ-LP64: 3a R_AARCH64_PLT32 sym+0x8 .xword sym-. // CHECK-OBJ-LP64: 3e R_AARCH64_PREL64 sym{{$}} @@ -305,4 +305,4 @@ // CHECK: ldr x24, :got:sym // CHECK: ldr d22, :got:sym // CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym -// CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym \ No newline at end of file +// CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym diff --git a/llvm/test/MC/AArch64/elf-reloc-plt32.s b/llvm/test/MC/AArch64/elf-reloc-plt32.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/elf-reloc-plt32.s @@ -0,0 +1,30 @@ +// RUN: llvm-mc -triple=aarch64-none-fuchsia -filetype=obj %s -o - | \ +// RUN: llvm-readobj -r | FileCheck %s + + .type func,@function + .globl func +func: + + .type obj,@object + .globl obj +obj: + + .type hidden_obj,@object + .globl hidden_obj + .hidden hidden_obj +hidden_obj: + + + .section .data +this: + .word func - this + 4 + .word undefined - this + 4 + .word obj - this + 4 + .word hidden_obj - this + 4 + +// CHECK: Relocations +// CHECK: Section (4) .rela.data +// CHECK-NEXT: 0x0 R_AARCH64_PLT32 func 0x4 +// CHECK-NEXT: 0x4 R_AARCH64_PLT32 undefined 0x8 +// CHECK-NEXT: 0x8 R_AARCH64_PLT32 obj 0xC +// CHECK-NEXT: 0xC R_AARCH64_PREL32 hidden_obj 0x10