summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsELFFile.h')
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFile.h291
1 files changed, 43 insertions, 248 deletions
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFFile.h b/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
index 7381c7e977bf..934934b539cc 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
@@ -12,42 +12,7 @@
#include "ELFReader.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationHandler.h"
-
-namespace llvm {
-namespace object {
-
-template <class ELFT>
-struct Elf_RegInfo;
-
-template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
-struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> {
- LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
- Elf_Word ri_gprmask; // bit-mask of used general registers
- Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
- Elf_Addr ri_gp_value; // gp register value
-};
-
-template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
-struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> {
- LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
- Elf_Word ri_gprmask; // bit-mask of used general registers
- Elf_Word ri_pad; // unused padding field
- Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
- Elf_Addr ri_gp_value; // gp register value
-};
-
-template <class ELFT> struct Elf_Mips_Options {
- LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment,
- ELFT::Is64Bits)
- uint8_t kind; // Determines interpretation of variable part of descriptor
- uint8_t size; // Byte size of descriptor, including this header
- Elf_Half section; // Section header index of section affected,
- // or 0 for global options
- Elf_Word info; // Kind-specific information
-};
-
-} // end namespace object.
-} // end namespace llvm.
+#include "llvm/ADT/STLExtras.h"
namespace lld {
namespace elf {
@@ -64,50 +29,21 @@ public:
StringRef sectionName, const Elf_Sym *symbol,
const Elf_Shdr *section, ArrayRef<uint8_t> contentData,
unsigned int referenceStart, unsigned int referenceEnd,
- std::vector<ELFReference<ELFT> *> &referenceList)
- : ELFDefinedAtom<ELFT>(file, symbolName, sectionName, symbol, section,
- contentData, referenceStart, referenceEnd,
- referenceList) {}
+ std::vector<ELFReference<ELFT> *> &referenceList);
- const MipsELFFile<ELFT>& file() const override {
- return static_cast<const MipsELFFile<ELFT> &>(this->_owningFile);
- }
+ const MipsELFFile<ELFT>& file() const override;
+ DefinedAtom::CodeModel codeModel() const override;
- DefinedAtom::CodeModel codeModel() const override {
- switch (this->_symbol->st_other & llvm::ELF::STO_MIPS_MIPS16) {
- case llvm::ELF::STO_MIPS_MIPS16:
- return DefinedAtom::codeMips16;
- case llvm::ELF::STO_MIPS_PIC:
- return DefinedAtom::codeMipsPIC;
- case llvm::ELF::STO_MIPS_MICROMIPS:
- return DefinedAtom::codeMipsMicro;
- case llvm::ELF::STO_MIPS_MICROMIPS | llvm::ELF::STO_MIPS_PIC:
- return DefinedAtom::codeMipsMicroPIC;
- default:
- return DefinedAtom::codeNA;
- }
- }
+ bool isPIC() const;
};
template <class ELFT> class MipsELFReference : public ELFReference<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:
- MipsELFReference(uint64_t symValue, const Elf_Rela &rel)
- : ELFReference<ELFT>(
- &rel, rel.r_offset - symValue, Reference::KindArch::Mips,
- rel.getType(_isMips64EL) & 0xff, rel.getSymbol(_isMips64EL)),
- _tag(uint32_t(rel.getType(_isMips64EL)) >> 8) {}
-
- MipsELFReference(uint64_t symValue, const Elf_Rel &rel)
- : ELFReference<ELFT>(rel.r_offset - symValue, Reference::KindArch::Mips,
- rel.getType(_isMips64EL) & 0xff,
- rel.getSymbol(_isMips64EL)),
- _tag(uint32_t(rel.getType(_isMips64EL)) >> 8) {}
+ MipsELFReference(uint64_t symValue, const Elf_Rela &rel);
+ MipsELFReference(uint64_t symValue, const Elf_Rel &rel);
uint32_t tag() const override { return _tag; }
void setTag(uint32_t tag) { _tag = tag; }
@@ -118,211 +54,70 @@ private:
template <class ELFT> class MipsELFFile : public ELFFile<ELFT> {
public:
- MipsELFFile(std::unique_ptr<MemoryBuffer> mb, MipsLinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
+ MipsELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
- static ErrorOr<std::unique_ptr<MipsELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, MipsLinkingContext &ctx) {
- return std::unique_ptr<MipsELFFile<ELFT>>(
- new MipsELFFile<ELFT>(std::move(mb), ctx));
- }
-
- bool isPIC() const {
- return this->_objFile->getHeader()->e_flags & llvm::ELF::EF_MIPS_PIC;
- }
+ bool isPIC() const;
/// \brief gp register value stored in the .reginfo section.
- int64_t getGP0() const { return _gp0 ? *_gp0 : 0; }
+ int64_t getGP0() const { return _gp0; }
/// \brief .tdata section address plus fixed offset.
- uint64_t getTPOffset() const { return *_tpOff; }
- uint64_t getDTPOffset() const { return *_dtpOff; }
+ uint64_t getTPOffset() const { return _tpOff; }
+ uint64_t getDTPOffset() const { return _dtpOff; }
protected:
- std::error_code doParse() override {
- if (std::error_code ec = ELFFile<ELFT>::doParse())
- return ec;
- // Retrieve some auxiliary data like GP value, TLS section address etc
- // from the object file.
- return readAuxData();
- }
+ std::error_code doParse() override;
private:
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela_Iter Elf_Rela_Iter;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
enum { TP_OFFSET = 0x7000, DTP_OFFSET = 0x8000 };
- static const bool _isMips64EL =
- ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
-
- llvm::Optional<int64_t> _gp0;
- llvm::Optional<uint64_t> _tpOff;
- llvm::Optional<uint64_t> _dtpOff;
+ int64_t _gp0 = 0;
+ uint64_t _tpOff = 0;
+ uint64_t _dtpOff = 0;
- ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(
- StringRef symName, StringRef sectionName, const Elf_Sym *sym,
- const Elf_Shdr *sectionHdr, ArrayRef<uint8_t> contentData,
- unsigned int referenceStart, unsigned int referenceEnd,
- std::vector<ELFReference<ELFT> *> &referenceList) override {
- return new (this->_readerStorage) MipsELFDefinedAtom<ELFT>(
- *this, symName, sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- }
-
- const Elf_Shdr *findSectionByType(uint64_t type) {
- for (const Elf_Shdr &section : this->_objFile->sections())
- if (section.sh_type == type)
- return &section;
- return nullptr;
- }
-
- const Elf_Shdr *findSectionByFlags(uint64_t flags) {
- for (const Elf_Shdr &section : this->_objFile->sections())
- if (section.sh_flags & flags)
- return &section;
- return nullptr;
- }
-
- std::error_code readAuxData() {
- using namespace llvm::ELF;
- if (const Elf_Shdr *sec = findSectionByFlags(SHF_TLS)) {
- _tpOff = sec->sh_addr + TP_OFFSET;
- _dtpOff = sec->sh_addr + DTP_OFFSET;
- }
-
- typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
- typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
-
- if (const Elf_Shdr *sec = findSectionByType(SHT_MIPS_OPTIONS)) {
- auto contents = this->getSectionContents(sec);
- if (std::error_code ec = contents.getError())
- return ec;
-
- ArrayRef<uint8_t> raw = contents.get();
- while (!raw.empty()) {
- if (raw.size() < sizeof(Elf_Mips_Options))
- return make_dynamic_error_code(
- StringRef("Invalid size of MIPS_OPTIONS section"));
-
- const auto *opt = reinterpret_cast<const Elf_Mips_Options *>(raw.data());
- if (opt->kind == ODK_REGINFO) {
- _gp0 = reinterpret_cast<const Elf_RegInfo *>(opt + 1)->ri_gp_value;
- break;
- }
- raw = raw.slice(opt->size);
- }
- } else if (const Elf_Shdr *sec = findSectionByType(SHT_MIPS_REGINFO)) {
- auto contents = this->getSectionContents(sec);
- if (std::error_code ec = contents.getError())
- return ec;
-
- ArrayRef<uint8_t> raw = contents.get();
- if (raw.size() != sizeof(Elf_RegInfo))
- return make_dynamic_error_code(
- StringRef("Invalid size of MIPS_REGINFO section"));
-
- _gp0 = reinterpret_cast<const Elf_RegInfo *>(raw.data())->ri_gp_value;
- }
- return std::error_code();
- }
+ ELFDefinedAtom<ELFT> *
+ createDefinedAtom(StringRef symName, StringRef sectionName,
+ const Elf_Sym *sym, const Elf_Shdr *sectionHdr,
+ ArrayRef<uint8_t> contentData, unsigned int referenceStart,
+ unsigned int referenceEnd,
+ std::vector<ELFReference<ELFT> *> &referenceList) override;
void createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> content,
- range<Elf_Rela_Iter> rels) override {
- const auto value = this->getSymbolValue(symbol);
- for (const auto &rel : rels) {
- if (rel.r_offset < value || value + content.size() <= rel.r_offset)
- continue;
- auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, rel);
- this->addReferenceToSymbol(r, symbol);
- this->_references.push_back(r);
- }
- }
-
+ range<const Elf_Rela *> rels) override;
void createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> symContent,
ArrayRef<uint8_t> secContent,
- range<Elf_Rel_Iter> rels) override {
- const auto value = this->getSymbolValue(symbol);
- for (Elf_Rel_Iter rit = rels.begin(), eit = rels.end(); rit != eit; ++rit) {
- if (rit->r_offset < value || value + symContent.size() <= rit->r_offset)
- continue;
+ const Elf_Shdr *RelSec) override;
- auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, *rit);
- this->addReferenceToSymbol(r, symbol);
- this->_references.push_back(r);
+ const Elf_Shdr *findSectionByType(uint64_t type) const;
+ const Elf_Shdr *findSectionByFlags(uint64_t flags) const;
- auto addend = readAddend(*rit, secContent);
- auto pairRelType = getPairRelocation(*rit);
- if (pairRelType != llvm::ELF::R_MIPS_NONE) {
- addend <<= 16;
- auto mit = findMatchingRelocation(pairRelType, rit, eit);
- if (mit != eit)
- addend += int16_t(readAddend(*mit, secContent));
- else
- // FIXME (simon): Show detailed warning.
- llvm::errs() << "lld warning: cannot matching LO16 relocation\n";
- }
- this->_references.back()->setAddend(addend);
- }
- }
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+ typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+ typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
- Reference::Addend readAddend(const Elf_Rel &ri,
- const ArrayRef<uint8_t> content) const {
- const auto &rh =
- this->_ctx.template getTargetHandler<ELFT>().getRelocationHandler();
- return static_cast<const MipsRelocationHandler &>(rh)
- .readAddend(getPrimaryType(ri), content.data() + ri.r_offset);
- }
+ ErrorOr<const Elf_Mips_RegInfo *> findRegInfoSec() const;
+ ErrorOr<const Elf_Mips_ABIFlags*> findAbiFlagsSec() const;
- uint32_t getPairRelocation(const Elf_Rel &rel) const {
- switch (getPrimaryType(rel)) {
- case llvm::ELF::R_MIPS_HI16:
- return llvm::ELF::R_MIPS_LO16;
- case llvm::ELF::R_MIPS_PCHI16:
- return llvm::ELF::R_MIPS_PCLO16;
- case llvm::ELF::R_MIPS_GOT16:
- if (isLocalBinding(rel))
- return llvm::ELF::R_MIPS_LO16;
- break;
- case llvm::ELF::R_MICROMIPS_HI16:
- return llvm::ELF::R_MICROMIPS_LO16;
- case llvm::ELF::R_MICROMIPS_GOT16:
- if (isLocalBinding(rel))
- return llvm::ELF::R_MICROMIPS_LO16;
- break;
- default:
- // Nothing to do.
- break;
- }
- return llvm::ELF::R_MIPS_NONE;
- }
+ std::error_code readAuxData();
- Elf_Rel_Iter findMatchingRelocation(uint32_t pairRelType, Elf_Rel_Iter rit,
- Elf_Rel_Iter eit) const {
- return std::find_if(rit, eit, [&](const Elf_Rel &rel) {
- return getPrimaryType(rel) == pairRelType &&
- rel.getSymbol(_isMips64EL) == rit->getSymbol(_isMips64EL);
- });
- }
+ Reference::Addend readAddend(const Elf_Rel &ri,
+ const ArrayRef<uint8_t> content) const;
- static uint8_t getPrimaryType(const Elf_Rel &rel) {
- return rel.getType(_isMips64EL) & 0xff;
- }
- bool isLocalBinding(const Elf_Rel &rel) const {
- return this->_objFile->getSymbol(rel.getSymbol(_isMips64EL))
- ->getBinding() == llvm::ELF::STB_LOCAL;
- }
-};
+ uint32_t getPairRelocation(const Elf_Shdr *Symtab, const Elf_Rel &rel) const;
-template <class ELFT> class MipsDynamicFile : public DynamicFile<ELFT> {
-public:
- MipsDynamicFile(const MipsLinkingContext &context, StringRef name)
- : DynamicFile<ELFT>(context, name) {}
+ const Elf_Rel *findMatchingRelocation(uint32_t pairRelType,
+ const Elf_Rel *rit,
+ const Elf_Rel *eit) const;
+
+ bool isLocalBinding(const Elf_Shdr *Symtab, const Elf_Rel &rel) const;
};
} // elf