From 03a5e0c874c6725444fa282e80a48b3170b64d9c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 17 May 2019 03:05:07 +0000 Subject: [PATCH] [AArch64] Support .reloc *, R_AARCH64_NONE, * Summary: This can be used to create references among sections. When --gc-sections is used, the referenced section will be retained if the origin section is retained. Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D61973 llvm-svn: 360981 --- .../MCTargetDesc/AArch64AsmBackend.cpp | 18 +++++++++++-- .../MCTargetDesc/AArch64ELFObjectWriter.cpp | 2 ++ llvm/test/MC/AArch64/reloc-directive.s | 25 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 llvm/test/MC/AArch64/reloc-directive.s diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index b50659aec2d15..df94c3187eb85 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -41,6 +41,8 @@ class AArch64AsmBackend : public MCAsmBackend { return AArch64::NumTargetFixupKinds; } + Optional getFixupKind(StringRef Name) const override; + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = { // This table *must* be in the order that the fixup_* kinds are defined @@ -103,6 +105,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { default: llvm_unreachable("Unknown fixup kind!"); + case FK_NONE: case AArch64::fixup_aarch64_tlsdesc_call: return 0; @@ -304,6 +307,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, if (Value & 0x3) Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); return (Value >> 2) & 0x3ffffff; + case FK_NONE: case FK_Data_1: case FK_Data_2: case FK_Data_4: @@ -314,6 +318,12 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, } } +Optional AArch64AsmBackend::getFixupKind(StringRef Name) const { + if (TheTriple.isOSBinFormatELF() && Name == "R_AARCH64_NONE") + return FK_NONE; + return MCAsmBackend::getFixupKind(Name); +} + /// getFixupKindContainereSizeInBytes - The number of bytes of the /// container involved in big endian or 0 if the item is little endian unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const { @@ -445,6 +455,10 @@ bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) { + unsigned Kind = Fixup.getKind(); + if (Kind == FK_NONE) + return true; + // The ADRP instruction adds some multiple of 0x1000 to the current PC & // ~0xfff. This means that the required offset to reach a symbol can vary by // up to one step depending on where the ADRP is in memory. For example: @@ -457,14 +471,14 @@ bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm, // same page as the ADRP and the instruction should encode 0x0. Assuming the // section isn't 0x1000-aligned, we therefore need to delegate this decision // to the linker -- a relocation! - if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21) + if (Kind == AArch64::fixup_aarch64_pcrel_adrp_imm21) return true; AArch64MCExpr::VariantKind RefKind = static_cast(Target.getRefKind()); AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind); // LDR GOT relocations need a relocation - if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_ldr_pcrel_imm19 && + if (Kind == AArch64::fixup_aarch64_ldr_pcrel_imm19 && SymLoc == AArch64MCExpr::VK_GOT) return true; return false; diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index d7361809e6d37..c871e2c62eac8 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -185,6 +185,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, if (IsILP32 && isNonILP32reloc(Fixup, RefKind, Ctx)) return ELF::R_AARCH64_NONE; switch ((unsigned)Fixup.getKind()) { + case FK_NONE: + return ELF::R_AARCH64_NONE; case FK_Data_1: Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported"); return ELF::R_AARCH64_NONE; diff --git a/llvm/test/MC/AArch64/reloc-directive.s b/llvm/test/MC/AArch64/reloc-directive.s new file mode 100644 index 0000000000000..e10a90a5216be --- /dev/null +++ b/llvm/test/MC/AArch64/reloc-directive.s @@ -0,0 +1,25 @@ +# RUN: llvm-mc -triple=aarch64-linux-musl %s | FileCheck --check-prefix=PRINT %s + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-musl %s | llvm-readobj -r | FileCheck %s + +# PRINT: .reloc 8, R_AARCH64_NONE, .data +# PRINT: .reloc 4, R_AARCH64_NONE, foo+4 +# PRINT: .reloc 0, R_AARCH64_NONE, 8 +.text + ret + nop + nop + .reloc 8, R_AARCH64_NONE, .data + .reloc 4, R_AARCH64_NONE, foo+4 + .reloc 0, R_AARCH64_NONE, 8 + +.data +.globl foo +foo: + .word 0 + .word 0 + .word 0 + +# CHECK: 0x8 R_AARCH64_NONE .data 0x0 +# CHECK-NEXT: 0x4 R_AARCH64_NONE foo 0x4 +# CHECK-NEXT: 0x0 R_AARCH64_NONE - 0x8