diff options
author | Jason W Kim <jason.w.kim.2009@gmail.com> | 2010-12-01 02:40:06 +0000 |
---|---|---|
committer | Jason W Kim <jason.w.kim.2009@gmail.com> | 2010-12-01 02:40:06 +0000 |
commit | 85fed5e0c5bc010f967948a4af6b425a5a2f2bd0 (patch) | |
tree | 339b05440d349244878383e60af94c7952bb28b4 /lib/MC/ELFObjectWriter.cpp | |
parent | 0480e28fb2a7d4e140d56c39e9705c922456585c (diff) |
ARM/MC/ELF relocation "hello world" for movw/movt.
Lifted adjustFixupValue() from Darwin for sharing w ELF.
Test added
TODO:
refactor ELFObjectWriter::RecordRelocation more.
Possibly share more code with Darwin?
Lots more relocations...
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120534 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 98 |
1 files changed, 97 insertions, 1 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 4b978368ec..47c70ec1cc 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -396,6 +396,10 @@ namespace { const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); + protected: + // Fixme: pull up to ELFObjectWriter + unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel); private: static bool isFixupKindPCRel(unsigned Kind) { switch (Kind) { @@ -1434,13 +1438,105 @@ ARMELFObjectWriter::ARMELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, ARMELFObjectWriter::~ARMELFObjectWriter() {} +unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) { + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + + if (IsPCRel) { + switch (Modifier) { + default: assert(0 && "Unimplemented Modifier"); + case MCSymbolRefExpr::VK_None: break; + } + switch ((unsigned)Fixup.getKind()) { + default: assert(0 && "Unimplemented"); + case ARM::fixup_arm_branch: return ELF::R_ARM_CALL; break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case ARM::fixup_arm_pcrel_12: + case ARM::fixup_arm_vfp_pcrel_12: + assert(0 && "Unimplemented"); break; + case ARM::fixup_arm_branch: + return ELF::R_ARM_CALL; break; + case ARM::fixup_arm_movt_hi16: + return ELF::R_ARM_MOVT_ABS; break; + case ARM::fixup_arm_movw_lo16: + return ELF::R_ARM_MOVW_ABS_NC; break; + } + } + + if (RelocNeedsGOT(Modifier)) + NeedsGOT = true; + return -1; +} + void ARMELFObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { - assert(0 && "ARMELFObjectWriter::RecordRelocation() unimplemented"); + int64_t Addend = 0; + int Index = 0; + int64_t Value = Target.getConstant(); + const MCSymbol *RelocSymbol = NULL; + + bool IsPCRel = isFixupKindPCRel(Fixup.getKind()); + if (!Target.isAbsolute()) { + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + const MCSymbol &ASymbol = Symbol.AliasedSymbol(); + RelocSymbol = SymbolToReloc(Asm, Target, *Fragment); + + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + const MCSymbol &SymbolB = RefB->getSymbol(); + MCSymbolData &SDB = Asm.getSymbolData(SymbolB); + IsPCRel = true; + MCSectionData *Sec = Fragment->getParent(); + + // Offset of the symbol in the section + int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec); + + // Ofeset of the relocation in the section + int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + Value += b - a; + } + + if (!RelocSymbol) { + MCSymbolData &SD = Asm.getSymbolData(ASymbol); + MCFragment *F = SD.getFragment(); + + Index = F->getParent()->getOrdinal() + 1; + + MCSectionData *FSD = F->getParent(); + // Offset of the symbol in the section + Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); + } else { + if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) + WeakrefUsedInReloc.insert(RelocSymbol); + else + UsedInReloc.insert(RelocSymbol); + Index = -1; + } + Addend = Value; + // Compensate for the addend on i386. + if (Is64Bit) + Value = 0; + } + + FixedValue = Value; + + // determine the type of the relocation + unsigned Type = GetRelocType(Target, Fixup, IsPCRel); + + uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + + Fixup.getOffset(); + + if (!HasRelocationAddend) Addend = 0; + ELFRelocationEntry ERE(RelocOffset, Index, Type, RelocSymbol, Addend); + Relocations[Fragment->getParent()].push_back(ERE); } //===- MBlazeELFObjectWriter -------------------------------------------===// |