diff options
| -rw-r--r-- | llvm/include/llvm/MC/MCAsmInfo.h | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp | 6 | ||||
| -rw-r--r-- | llvm/test/MC/ELF/got-relaxed.s | 18 |
4 files changed, 49 insertions, 5 deletions
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h index 3106c8c501f..737637942ff 100644 --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -363,6 +363,10 @@ protected: /// expressions as logical rather than arithmetic. bool UseLogicalShr; + // If true, emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL, on + // X86_64 ELF. + bool RelaxELFRelocations; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -568,6 +572,8 @@ public: } bool shouldUseLogicalShr() const { return UseLogicalShr; } + + bool canRelaxRelocations() const { return RelaxELFRelocations; } }; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp index 9f2d2738d1d..6fa479e4d7e 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp @@ -9,6 +9,7 @@ #include "MCTargetDesc/X86FixupKinds.h" #include "MCTargetDesc/X86MCTargetDesc.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" @@ -84,10 +85,10 @@ static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) { "32 bit reloc applied to a field with a different size"); } -static unsigned getRelocType64(MCContext &Ctx, const MCFixup &Fixup, +static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc, MCSymbolRefExpr::VariantKind Modifier, - X86_64RelType Type, bool IsPCRel) { - SMLoc Loc = Fixup.getLoc(); + X86_64RelType Type, bool IsPCRel, + unsigned Kind) { switch (Modifier) { default: llvm_unreachable("Unimplemented"); @@ -173,7 +174,19 @@ static unsigned getRelocType64(MCContext &Ctx, const MCFixup &Fixup, return ELF::R_X86_64_PLT32; case MCSymbolRefExpr::VK_GOTPCREL: checkIs32(Ctx, Loc, Type); - return ELF::R_X86_64_GOTPCREL; + // Older versions of ld.bfd/ld.gold/lld + // do not support GOTPCRELX/REX_GOTPCRELX, + // and we want to keep back-compatibility. + if (!Ctx.getAsmInfo()->canRelaxRelocations()) + return ELF::R_X86_64_GOTPCREL; + switch (Kind) { + default: + return ELF::R_X86_64_GOTPCREL; + case X86::reloc_riprel_4byte: + return ELF::R_X86_64_GOTPCRELX; + case X86::reloc_riprel_4byte_movq_load: + return ELF::R_X86_64_REX_GOTPCRELX; + } } } @@ -259,7 +272,8 @@ unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); X86_64RelType Type = getType64(Fixup.getKind(), Modifier, IsPCRel); if (getEMachine() == ELF::EM_X86_64) - return getRelocType64(Ctx, Fixup, Modifier, Type, IsPCRel); + return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, + Fixup.getKind()); assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) && "Unsupported ELF machine type."); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp index fc0b0f89e23..f5bdd2d4b7e 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp @@ -35,6 +35,10 @@ AsmWriterFlavor("x86-asm-syntax", cl::init(ATT), clEnumValEnd)); static cl::opt<bool> +RelaxELFRel("relax-relocations", cl::init(false), + cl::desc("Emit R_X86_64_GOTPCRELX instead of R_X86_64_GOTPCREL")); + +static cl::opt<bool> MarkedJTDataRegions("mark-data-regions", cl::init(false), cl::desc("Mark code section jump table data regions."), cl::Hidden); @@ -111,6 +115,8 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { // Always enable the integrated assembler by default. // Clang also enabled it when the OS is Solaris but that is redundant here. UseIntegratedAssembler = true; + + RelaxELFRelocations = RelaxELFRel; } const MCExpr * diff --git a/llvm/test/MC/ELF/got-relaxed.s b/llvm/test/MC/ELF/got-relaxed.s new file mode 100644 index 00000000000..2a9969e29c6 --- /dev/null +++ b/llvm/test/MC/ELF/got-relaxed.s @@ -0,0 +1,18 @@ +// RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -r -t | FileCheck %s + +// Test that this produces the correct relaxed relocations. + + movl foo@GOT, %eax + movl foo@GOTPCREL(%rip), %eax + movq foo@GOTPCREL(%rip), %rax + +// CHECK: Relocations [ +// CHECK: Section ({{[^ ]+}}) .rela.text { +// CHECK-NEXT: 0x{{[^ ]+}} R_X86_64_GOT32 foo 0x{{[^ ]+}} +// CHECK-NEXT: 0x{{[^ ]+}} R_X86_64_GOTPCRELX foo 0x{{[^ ]+}} +// CHECK-NEXT: 0x{{[^ ]+}} R_X86_64_REX_GOTPCRELX foo 0x{{[^ ]+}} +// CHECK-NEXT: } +// CHECK-NEXT: ] + +// CHECK: Symbols [ +// CHECK-NOT: _GLOBAL_OFFSET_TABLE_ |

