diff options
Diffstat (limited to 'llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp')
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 132 |
1 files changed, 16 insertions, 116 deletions
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index ce763367e29..f933962d664 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -21,17 +21,6 @@ using namespace llvm; namespace { - struct RelEntry { - RelEntry(const ELFRelocationEntry &R, const MCSymbol *S, int64_t O) : - Reloc(R), Sym(S), Offset(O) {} - ELFRelocationEntry Reloc; - const MCSymbol *Sym; - int64_t Offset; - }; - - typedef std::list<RelEntry> RelLs; - typedef RelLs::iterator RelLsIter; - class MipsELFObjectWriter : public MCELFObjectTargetWriter { public: MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, @@ -41,13 +30,7 @@ namespace { unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; - virtual void sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs); + bool needsRelocateWithSymbol(unsigned Type) const override; }; } @@ -59,21 +42,6 @@ MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, MipsELFObjectWriter::~MipsELFObjectWriter() {} -const MCSymbol *MipsELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - assert(Target.getSymA() && "SymA cannot be 0."); - const MCSymbol &Sym = Target.getSymA()->getSymbol().AliasedSymbol(); - - if (Sym.getSection().getKind().isMergeableCString() || - Sym.getSection().getKind().isMergeableConst()) - return &Sym; - - return NULL; -} - unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { @@ -229,91 +197,23 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, return Type; } -// Return true if R is either a GOT16 against a local symbol or HI16. -static bool NeedsMatchingLo(const MCAssembler &Asm, const RelEntry &R) { - if (!R.Sym) - return false; - - MCSymbolData &SD = Asm.getSymbolData(R.Sym->AliasedSymbol()); - - return ((R.Reloc.Type == ELF::R_MIPS_GOT16) && !SD.isExternal()) || - (R.Reloc.Type == ELF::R_MIPS_HI16); -} - -static bool HasMatchingLo(const MCAssembler &Asm, RelLsIter I, RelLsIter Last) { - if (I == Last) +bool +MipsELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const { + // FIXME: This is extremelly conservative. This really needs to use a + // whitelist with a clear explanation for why each realocation needs to + // point to the symbol, not to the section. + switch (Type) { + default: + return true; + + case ELF::R_MIPS_26: + case ELF::R_MIPS_LO16: + case ELF::R_MIPS_HI16: + case ELF::R_MIPS_32: + case ELF::R_MIPS_64: + case ELF::R_MIPS_GPREL16: return false; - - RelLsIter Hi = I++; - - return (I->Reloc.Type == ELF::R_MIPS_LO16) && (Hi->Sym == I->Sym) && - (Hi->Offset == I->Offset); -} - -static bool HasSameSymbol(const RelEntry &R0, const RelEntry &R1) { - return R0.Sym == R1.Sym; -} - -static int CompareOffset(const RelEntry &R0, const RelEntry &R1) { - return (R0.Offset > R1.Offset) ? 1 : ((R0.Offset == R1.Offset) ? 0 : -1); -} - -void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs) { - // Call the default function first. Relocations are sorted in descending - // order of r_offset. - MCELFObjectTargetWriter::sortRelocs(Asm, Relocs); - - RelLs RelocLs; - std::vector<RelLsIter> Unmatched; - - // Fill RelocLs. Traverse Relocs backwards so that relocations in RelocLs - // are in ascending order of r_offset. - for (std::vector<ELFRelocationEntry>::reverse_iterator R = Relocs.rbegin(); - R != Relocs.rend(); ++R) { - std::pair<const MCSymbolRefExpr*, int64_t> P = - MipsGetSymAndOffset(*R->Fixup); - RelocLs.push_back(RelEntry(*R, P.first ? &P.first->getSymbol() : 0, - P.second)); } - - // Get list of unmatched HI16 and GOT16. - for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) - if (NeedsMatchingLo(Asm, *R) && !HasMatchingLo(Asm, R, --RelocLs.end())) - Unmatched.push_back(R); - - // Insert unmatched HI16 and GOT16 immediately before their matching LO16. - for (std::vector<RelLsIter>::iterator U = Unmatched.begin(); - U != Unmatched.end(); ++U) { - RelLsIter LoPos = RelocLs.end(), HiPos = *U; - bool MatchedLo = false; - - for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) { - if ((R->Reloc.Type == ELF::R_MIPS_LO16) && HasSameSymbol(*HiPos, *R) && - (CompareOffset(*R, *HiPos) >= 0) && - ((LoPos == RelocLs.end()) || ((CompareOffset(*R, *LoPos) < 0)) || - (!MatchedLo && !CompareOffset(*R, *LoPos)))) - LoPos = R; - - MatchedLo = NeedsMatchingLo(Asm, *R) && - HasMatchingLo(Asm, R, --RelocLs.end()); - } - - // If a matching LoPos was found, move HiPos and insert it before LoPos. - // Make the offsets of HiPos and LoPos match. - if (LoPos != RelocLs.end()) { - HiPos->Offset = LoPos->Offset; - RelocLs.insert(LoPos, *HiPos); - RelocLs.erase(HiPos); - } - } - - // Put the sorted list back in reverse order. - assert(Relocs.size() == RelocLs.size()); - unsigned I = RelocLs.size(); - - for (RelLsIter R = RelocLs.begin(); R != RelocLs.end(); ++R) - Relocs[--I] = R->Reloc; } MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, |

