//===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> #include <cstdint> #include <iterator> #include <list> #include <utility> #define DEBUG_TYPE … usingnamespacellvm; namespace { /// Holds additional information needed by the relocation ordering algorithm. struct MipsRelocationEntry { … }; class MipsELFObjectWriter : public MCELFObjectTargetWriter { … }; /// The possible results of the Predicate function used by find_best. enum FindBestPredicateResult { … }; } // end anonymous namespace /// Copy elements in the range [First, Last) to d1 when the predicate is true or /// d2 when the predicate is false. This is essentially both std::copy_if and /// std::remove_copy_if combined into a single pass. template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate> static std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last, OutputIt1 d1, OutputIt2 d2, UnaryPredicate Predicate) { … } /// Find the best match in the range [First, Last). /// /// An element matches when Predicate(X) returns FindBest_Match or /// FindBest_PerfectMatch. A value of FindBest_PerfectMatch also terminates /// the search. BetterThan(A, B) is a comparator that returns true when A is a /// better match than B. The return value is the position of the best match. /// /// This is similar to std::find_if but finds the best of multiple possible /// matches. template <class InputIt, class UnaryPredicate, class Comparator> static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate, Comparator BetterThan) { … } /// Determine the low relocation that matches the given relocation. /// If the relocation does not need a low relocation then the return value /// is ELF::R_MIPS_NONE. /// /// The relocations that need a matching low part are /// R_(MIPS|MICROMIPS|MIPS16)_HI16 for all symbols and /// R_(MIPS|MICROMIPS|MIPS16)_GOT16 for local symbols only. static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) { … } // Determine whether a relocation X is a low-part and matches the high-part R // perfectly by symbol and addend. static bool isMatchingReloc(unsigned MatchingType, const ELFRelocationEntry &R, const ELFRelocationEntry &X) { … } MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64) : … { … } unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { … } /// Sort relocation table entries by offset except where another order is /// required by the MIPS ABI. /// /// MIPS has a few relocations that have an AHL component in the expression used /// to evaluate them. This AHL component is an addend with the same number of /// bits as a symbol value but not all of our ABI's are able to supply a /// sufficiently sized addend in a single relocation. /// /// The O32 ABI for example, uses REL relocations which store the addend in the /// section data. All the relocations with AHL components affect 16-bit fields /// so the addend for a single relocation is limited to 16-bit. This ABI /// resolves the limitation by linking relocations (e.g. R_MIPS_HI16 and /// R_MIPS_LO16) and distributing the addend between the linked relocations. The /// ABI mandates that such relocations must be next to each other in a /// particular order (e.g. R_MIPS_HI16 must be immediately followed by a /// matching R_MIPS_LO16) but the rule is less strict in practice. /// /// The de facto standard is lenient in the following ways: /// - 'Immediately following' does not refer to the next relocation entry but /// the next matching relocation. /// - There may be multiple high parts relocations for one low part relocation. /// - There may be multiple low part relocations for one high part relocation. /// - The AHL addend in each part does not have to be exactly equal as long as /// the difference does not affect the carry bit from bit 15 into 16. This is /// to allow, for example, the use of %lo(foo) and %lo(foo+4) when loading /// both halves of a long long. /// /// See getMatchingLoType() for a description of which high part relocations /// match which low part relocations. One particular thing to note is that /// R_MIPS_GOT16 and similar only have AHL addends if they refer to local /// symbols. /// /// It should also be noted that this function is not affected by whether /// the symbol was kept or rewritten into a section-relative equivalent. We /// always match using the expressions from the source. void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, std::vector<ELFRelocationEntry> &Relocs) { … } bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, unsigned Type) const { … } std::unique_ptr<MCObjectTargetWriter> llvm::createMipsELFObjectWriter(const Triple &TT, bool IsN32) { … }