summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h')
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h174
1 files changed, 77 insertions, 97 deletions
diff --git a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
index de9390f2b3074..e545f65dc419a 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
@@ -9,23 +9,81 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
+#include "SectionChunks.h"
+
namespace lld {
namespace elf {
template <typename ELFT> class MipsTargetLayout;
class MipsLinkingContext;
+/// \brief Handle Mips .reginfo section
+template <class ELFT> class MipsReginfoSection : public Section<ELFT> {
+public:
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+ MipsReginfoSection(const ELFLinkingContext &ctx,
+ MipsTargetLayout<ELFT> &targetLayout,
+ const Elf_Mips_RegInfo &reginfo);
+
+ StringRef segmentKindToStr() const override { return "REGINFO"; }
+ bool hasOutputSegment() const override { return true; }
+
+ void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
+ llvm::FileOutputBuffer &buffer) override;
+ void finalize() override;
+
+private:
+ Elf_Mips_RegInfo _reginfo;
+ MipsTargetLayout<ELFT> &_targetLayout;
+};
+
+/// \brief Handle .MIPS.options section
+template <class ELFT> class MipsOptionsSection : public Section<ELFT> {
+public:
+ typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+ MipsOptionsSection(const ELFLinkingContext &ctx,
+ MipsTargetLayout<ELFT> &targetLayout,
+ const Elf_Mips_RegInfo &reginfo);
+
+ bool hasOutputSegment() const override { return true; }
+
+ void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
+ llvm::FileOutputBuffer &buffer) override;
+ void finalize() override;
+
+private:
+ Elf_Mips_Options _header;
+ Elf_Mips_RegInfo _reginfo;
+ MipsTargetLayout<ELFT> &_targetLayout;
+};
+
+/// \brief Handle .MIPS.abiflags section
+template <class ELFT> class MipsAbiFlagsSection : public Section<ELFT> {
+public:
+ typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
+
+ MipsAbiFlagsSection(const ELFLinkingContext &ctx,
+ MipsTargetLayout<ELFT> &targetLayout,
+ const Elf_Mips_ABIFlags &abiFlags);
+
+ bool hasOutputSegment() const override { return true; }
+
+ void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
+ llvm::FileOutputBuffer &buffer) override;
+ void finalize() override;
+
+private:
+ Elf_Mips_ABIFlags _abiFlags;
+ MipsTargetLayout<ELFT> &_targetLayout;
+};
+
/// \brief Handle Mips GOT section
-template <class ELFType> class MipsGOTSection : public AtomSection<ELFType> {
+template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
public:
- MipsGOTSection(const MipsLinkingContext &ctx)
- : AtomSection<ELFType>(ctx, ".got", DefinedAtom::typeGOT,
- DefinedAtom::permRW_,
- MipsTargetLayout<ELFType>::ORDER_GOT),
- _hasNonLocal(false), _localCount(0) {
- this->_flags |= SHF_MIPS_GPREL;
- this->_alignment = 4;
- }
+ MipsGOTSection(const MipsLinkingContext &ctx);
/// \brief Number of local GOT entries.
std::size_t getLocalCount() const { return _localCount; }
@@ -39,47 +97,9 @@ public:
}
/// \brief Compare two atoms accordingly theirs positions in the GOT.
- bool compare(const Atom *a, const Atom *b) const {
- auto ia = _posMap.find(a);
- auto ib = _posMap.find(b);
+ bool compare(const Atom *a, const Atom *b) const;
- if (ia != _posMap.end() && ib != _posMap.end())
- return ia->second < ib->second;
-
- return ia == _posMap.end() && ib != _posMap.end();
- }
-
- const lld::AtomLayout *appendAtom(const Atom *atom) override {
- const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
-
- for (const auto &r : *da) {
- if (r->kindNamespace() != lld::Reference::KindNamespace::ELF)
- continue;
- assert(r->kindArch() == Reference::KindArch::Mips);
- switch (r->kindValue()) {
- case LLD_R_MIPS_GLOBAL_GOT:
- _hasNonLocal = true;
- _posMap[r->target()] = _posMap.size();
- return AtomSection<ELFType>::appendAtom(atom);
- case R_MIPS_TLS_TPREL32:
- case R_MIPS_TLS_DTPREL32:
- case R_MIPS_TLS_TPREL64:
- case R_MIPS_TLS_DTPREL64:
- _hasNonLocal = true;
- _tlsMap[r->target()] = _tlsMap.size();
- return AtomSection<ELFType>::appendAtom(atom);
- case R_MIPS_TLS_DTPMOD32:
- case R_MIPS_TLS_DTPMOD64:
- _hasNonLocal = true;
- break;
- }
- }
-
- if (!_hasNonLocal)
- ++_localCount;
-
- return AtomSection<ELFType>::appendAtom(atom);
- }
+ const AtomLayout *appendAtom(const Atom *atom) override;
private:
/// \brief True if the GOT contains non-local entries.
@@ -96,35 +116,13 @@ private:
};
/// \brief Handle Mips PLT section
-template <class ELFType> class MipsPLTSection : public AtomSection<ELFType> {
+template <class ELFT> class MipsPLTSection : public AtomSection<ELFT> {
public:
- MipsPLTSection(const MipsLinkingContext &ctx)
- : AtomSection<ELFType>(ctx, ".plt", DefinedAtom::typeGOT,
- DefinedAtom::permR_X,
- MipsTargetLayout<ELFType>::ORDER_PLT) {}
-
- const AtomLayout *findPLTLayout(const Atom *plt) const {
- auto it = _pltLayoutMap.find(plt);
- return it != _pltLayoutMap.end() ? it->second : nullptr;
- }
-
- const lld::AtomLayout *appendAtom(const Atom *atom) override {
- const auto *layout = AtomSection<ELFType>::appendAtom(atom);
-
- const DefinedAtom *da = cast<DefinedAtom>(atom);
+ MipsPLTSection(const MipsLinkingContext &ctx);
- for (const auto &r : *da) {
- if (r->kindNamespace() != lld::Reference::KindNamespace::ELF)
- continue;
- assert(r->kindArch() == Reference::KindArch::Mips);
- if (r->kindValue() == LLD_R_MIPS_STO_PLT) {
- _pltLayoutMap[r->target()] = layout;
- break;
- }
- }
+ const AtomLayout *findPLTLayout(const Atom *plt) const;
- return layout;
- }
+ const AtomLayout *appendAtom(const Atom *atom) override;
private:
/// \brief Map PLT Atoms to their layouts.
@@ -135,33 +133,15 @@ template <class ELFT> class MipsRelocationTable : public RelocationTable<ELFT> {
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
- static const bool _isMips64EL =
- ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
-
public:
- MipsRelocationTable(const ELFLinkingContext &context, StringRef str,
- int32_t order)
- : RelocationTable<ELFT>(context, str, order) {}
+ MipsRelocationTable(const ELFLinkingContext &ctx, StringRef str,
+ int32_t order);
protected:
void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom,
- const Reference &ref) override {
- uint32_t rType = ref.kindValue() | (ref.tag() << 8);
- r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL);
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
- // The addend is used only by relative relocations
- if (this->_context.isRelativeReloc(ref))
- r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
- else
- r.r_addend = 0;
- }
-
+ const Reference &ref) override;
void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom,
- const Reference &ref) override {
- uint32_t rType = ref.kindValue() | (ref.tag() << 8);
- r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL);
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
- }
+ const Reference &ref) override;
};
} // elf