summaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
authorJason W Kim <jason.w.kim.2009@gmail.com>2011-02-07 01:11:15 +0000
committerJason W Kim <jason.w.kim.2009@gmail.com>2011-02-07 01:11:15 +0000
commit953a2a3dee46bebd70b129fd62709710f5f2b033 (patch)
tree01a5aaf6b81117295a7eaea805843178e9b59766 /lib/MC
parentf009a961caa75465999ef3bc764984d97a7da331 (diff)
downloadllvm-953a2a3dee46bebd70b129fd62709710f5f2b033.tar.gz
llvm-953a2a3dee46bebd70b129fd62709710f5f2b033.tar.bz2
llvm-953a2a3dee46bebd70b129fd62709710f5f2b033.tar.xz
Teach ARM/MC/ELF about gcc compatible reloc output to get past odd linkage
failures with relocations. The code committed is a first cut at compatibility for emitted relocations in ELF .o. Why do this? because existing ARM tools like emitting relocs symbols as explicit relocations, not as section-offset relocs. Result is that with these changes, 1) relocs are now substantially identical what to gcc outputs. 2) larger apps (including many spec2k tests) compile, cross-link, and pass Added reminder fixme to tests for future conversion to .s form. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124996 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/ELFObjectWriter.cpp48
1 files changed, 45 insertions, 3 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index bd5d048f26..0db54b5d48 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -30,6 +30,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ELF.h"
#include "llvm/Target/TargetAsmBackend.h"
+#include "llvm/ADT/StringSwitch.h"
#include "../Target/X86/X86FixupKinds.h"
#include "../Target/ARM/ARMFixupKinds.h"
@@ -189,6 +190,14 @@ namespace {
const MCValue &Target,
const MCFragment &F) const;
+ // For arch-specific emission of explicit reloc symbol
+ virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
+ const MCValue &Target,
+ const MCFragment &F,
+ bool IsBSS) const {
+ return NULL;
+ }
+
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
bool hasRelocationAddend() const {
return TargetObjectWriter->hasRelocationAddend();
@@ -401,6 +410,11 @@ namespace {
virtual void WriteEFlags();
protected:
+ virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
+ const MCValue &Target,
+ const MCFragment &F,
+ bool IsBSS) const;
+
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsPCRel, bool IsRelocWithSymbol,
int64_t Addend);
@@ -704,7 +718,7 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
const SectionKind secKind = Section.getKind();
if (secKind.isBSS())
- return NULL;
+ return ExplicitRelSym(Asm, Target, F, true);
if (secKind.isThreadLocal()) {
if (Renamed)
@@ -733,7 +747,7 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
return &Symbol;
}
- return NULL;
+ return ExplicitRelSym(Asm, Target, F, false);
}
@@ -1490,6 +1504,34 @@ void ARMELFObjectWriter::WriteEFlags() {
Write32(ELF::EF_ARM_EABIMASK & DefaultEABIVersion);
}
+// In ARM, _MergedGlobals and other most symbols get emitted directly.
+// I.e. not as an offset to a section symbol.
+// This code is a first-cut approximation of what ARM/gcc does.
+
+const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
+ const MCValue &Target,
+ const MCFragment &F,
+ bool IsBSS) const {
+ const MCSymbol &Symbol = Target.getSymA()->getSymbol();
+ bool EmitThisSym = false;
+
+ if (IsBSS) {
+ EmitThisSym = StringSwitch<bool>(Symbol.getName())
+ .Case("_MergedGlobals", true)
+ .Default(false);
+ } else {
+ EmitThisSym = StringSwitch<bool>(Symbol.getName())
+ .Case("_MergedGlobals", true)
+ .StartsWith(".L.str", true)
+ .Default(false);
+ }
+ if (EmitThisSym)
+ return &Symbol;
+ if (! Symbol.isTemporary())
+ return &Symbol;
+ return NULL;
+}
+
unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel,
@@ -1604,7 +1646,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
if (RelocNeedsGOT(Modifier))
NeedsGOT = true;
-
+
return Type;
}