summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/MC/MCAsmInfo.h6
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp24
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp6
-rw-r--r--llvm/test/MC/ELF/got-relaxed.s18
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_
OpenPOWER on IntegriCloud