From 152d14da64c2e906974822c084e2a79c1e970c1d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 27 Mar 2020 12:41:35 -0700 Subject: [PATCH] [MC][X86] Make .reloc support arbitrary relocation types Generalizes D62014 (R_386_NONE/R_X86_64_NONE). Unlike ARM (D76746) and AArch64 (D76754), we cannot delete FK_NONE from getFixupKindSize because FK_NONE is still used by R_386_TLS_DESC_CALL/R_X86_64_TLSDESC_CALL. --- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 30 +++++++++++++++---- .../X86/MCTargetDesc/X86ELFObjectWriter.cpp | 4 ++- llvm/test/MC/X86/reloc-directive-elf-32.s | 9 ++++++ llvm/test/MC/X86/reloc-directive-elf-64.s | 9 ++++++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 34c5295a66fb..9a832c1bb16d 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -646,13 +646,23 @@ void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) Optional X86AsmBackend::getFixupKind(StringRef Name) const { if (STI.getTargetTriple().isOSBinFormatELF()) { + unsigned Type; if (STI.getTargetTriple().getArch() == Triple::x86_64) { - if (Name == "R_X86_64_NONE") - return FK_NONE; + Type = llvm::StringSwitch(Name) +#define ELF_RELOC(X, Y) .Case(#X, Y) +#include "llvm/BinaryFormat/ELFRelocs/x86_64.def" +#undef ELF_RELOC + .Default(-1u); } else { - if (Name == "R_386_NONE") - return FK_NONE; + Type = llvm::StringSwitch(Name) +#define ELF_RELOC(X, Y) .Case(#X, Y) +#include "llvm/BinaryFormat/ELFRelocs/i386.def" +#undef ELF_RELOC + .Default(-1u); } + if (Type == -1u) + return None; + return static_cast(FirstLiteralRelocationKind + Type); } return MCAsmBackend::getFixupKind(Name); } @@ -670,6 +680,11 @@ const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const { {"reloc_branch_4byte_pcrel", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, }; + // Fixup kinds from .reloc directive are like R_386_NONE/R_X86_64_NONE. They + // do not require any extra processing. + if (Kind >= FirstLiteralRelocationKind) + return MCAsmBackend::getFixupKindInfo(FK_NONE); + if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); @@ -682,7 +697,7 @@ const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const { bool X86AsmBackend::shouldForceRelocation(const MCAssembler &, const MCFixup &Fixup, const MCValue &) { - return Fixup.getKind() == FK_NONE; + return Fixup.getKind() >= FirstLiteralRelocationKind; } static unsigned getFixupKindSize(unsigned Kind) { @@ -724,7 +739,10 @@ void X86AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, MutableArrayRef Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const { - unsigned Size = getFixupKindSize(Fixup.getKind()); + unsigned Kind = Fixup.getKind(); + if (Kind >= FirstLiteralRelocationKind) + return; + unsigned Size = getFixupKindSize(Kind); assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!"); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp index bd009da60851..292dd17e2f51 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp @@ -317,8 +317,10 @@ static unsigned getRelocType32(MCContext &Ctx, unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { - MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); MCFixupKind Kind = Fixup.getKind(); + if (Kind >= FirstLiteralRelocationKind) + return Kind - FirstLiteralRelocationKind; + MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); X86_64RelType Type = getType64(Kind, Modifier, IsPCRel); if (getEMachine() == ELF::EM_X86_64) return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind); diff --git a/llvm/test/MC/X86/reloc-directive-elf-32.s b/llvm/test/MC/X86/reloc-directive-elf-32.s index f6e321c94e0d..06755863e573 100644 --- a/llvm/test/MC/X86/reloc-directive-elf-32.s +++ b/llvm/test/MC/X86/reloc-directive-elf-32.s @@ -7,12 +7,18 @@ # PRINT: .reloc 2, R_386_NONE, .data # PRINT-NEXT: .reloc 1, R_386_NONE, foo+4 # PRINT-NEXT: .reloc 0, R_386_NONE, 8 +# PRINT-NEXT: .reloc 0, R_386_32, .data+2 +# PRINT-NEXT: .reloc 0, R_386_IRELATIVE, foo+3 +# PRINT-NEXT: .reloc 0, R_386_GOT32X, 5 # X86 relocations use the Elf32_Rel format. Addends are neither stored in the # relocation entries nor applied in the referenced locations. # CHECK: 0x2 R_386_NONE .data 0x0 # CHECK-NEXT: 0x1 R_386_NONE foo 0x0 # CHECK-NEXT: 0x0 R_386_NONE - 0x0 +# CHECK-NEXT: 0x0 R_386_32 .data 0x0 +# CHECK-NEXT: 0x0 R_386_IRELATIVE foo 0x0 +# CHECK-NEXT: 0x0 R_386_GOT32X - 0x0 # HEX: 0x00000000 00000000 00000000 @@ -23,6 +29,9 @@ .reloc 2, R_386_NONE, .data .reloc 1, R_386_NONE, foo+4 .reloc 0, R_386_NONE, 8 + .reloc 0, R_386_32, .data+2 + .reloc 0, R_386_IRELATIVE, foo+3 + .reloc 0, R_386_GOT32X, 5 .data .globl foo diff --git a/llvm/test/MC/X86/reloc-directive-elf-64.s b/llvm/test/MC/X86/reloc-directive-elf-64.s index e9523d72949f..30a252fcb84d 100644 --- a/llvm/test/MC/X86/reloc-directive-elf-64.s +++ b/llvm/test/MC/X86/reloc-directive-elf-64.s @@ -6,10 +6,16 @@ # PRINT: .reloc 2, R_X86_64_NONE, .data # PRINT-NEXT: .reloc 1, R_X86_64_NONE, foo+4 # PRINT-NEXT: .reloc 0, R_X86_64_NONE, 8 +# PRINT-NEXT: .reloc 0, R_X86_64_64, .data+2 +# PRINT-NEXT: .reloc 0, R_X86_64_GOTPCRELX, foo+3 +# PRINT-NEXT: .reloc 0, R_X86_64_REX_GOTPCRELX, 5 # CHECK: 0x2 R_X86_64_NONE .data 0x0 # CHECK-NEXT: 0x1 R_X86_64_NONE foo 0x4 # CHECK-NEXT: 0x0 R_X86_64_NONE - 0x8 +# CHECK-NEXT: 0x0 R_X86_64_64 .data 0x2 +# CHECK-NEXT: 0x0 R_X86_64_GOTPCRELX foo 0x3 +# CHECK-NEXT: 0x0 R_X86_64_REX_GOTPCRELX - 0x5 .text ret @@ -18,6 +24,9 @@ .reloc 2, R_X86_64_NONE, .data .reloc 1, R_X86_64_NONE, foo+4 .reloc 0, R_X86_64_NONE, 8 + .reloc 0, R_X86_64_64, .data+2 + .reloc 0, R_X86_64_GOTPCRELX, foo+3 + .reloc 0, R_X86_64_REX_GOTPCRELX, 5 .data .globl foo