diff options
author | Jason W Kim <jason.w.kim.2009@gmail.com> | 2011-02-07 01:11:15 +0000 |
---|---|---|
committer | Jason W Kim <jason.w.kim.2009@gmail.com> | 2011-02-07 01:11:15 +0000 |
commit | 953a2a3dee46bebd70b129fd62709710f5f2b033 (patch) | |
tree | 01a5aaf6b81117295a7eaea805843178e9b59766 /lib/MC | |
parent | f009a961caa75465999ef3bc764984d97a7da331 (diff) |
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.cpp | 48 |
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; } |