[Mips] Move member function definitions to cpp files

No functional changes.

llvm-svn: 238310
This commit is contained in:
Simon Atanasyan 2015-05-27 11:56:15 +00:00
parent 729dcfb7ee
commit 06eccbea9d
15 changed files with 1008 additions and 773 deletions

View File

@ -1,11 +1,14 @@
add_llvm_library(lldMipsELFTarget
MipsCtorsOrderPass.cpp
MipsELFFile.cpp
MipsELFFlagsMerger.cpp
MipsELFWriters.cpp
MipsLinkingContext.cpp
MipsRelocationHandler.cpp
MipsRelocationPass.cpp
MipsTargetHandler32EL.cpp
MipsTargetHandler64EL.cpp
MipsSectionChunks.cpp
MipsTargetHandler.cpp
MipsTargetLayout.cpp
LINK_LIBS
lldELF
lldReaderWriter

View File

@ -1,117 +0,0 @@
//===- lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h ---------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_LIBRARY_WRITER_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_LIBRARY_WRITER_H
#include "DynamicLibraryWriter.h"
#include "MipsDynamicTable.h"
#include "MipsELFWriters.h"
#include "MipsLinkingContext.h"
#include "MipsSectionChunks.h"
namespace lld {
namespace elf {
template <typename ELFT> class MipsSymbolTable;
template <typename ELFT> class MipsDynamicSymbolTable;
template <typename ELFT> class MipsTargetLayout;
template <class ELFT>
class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
public:
MipsDynamicLibraryWriter(MipsLinkingContext &ctx,
MipsTargetLayout<ELFT> &layout);
protected:
// Add any runtime files and their atoms to the output
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
void finalizeDefaultAtomValues() override;
void createDefaultSections() override;
std::error_code setELFHeader() override {
DynamicLibraryWriter<ELFT>::setELFHeader();
_writeHelper.setELFHeader(*this->_elfHeader);
return std::error_code();
}
unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable() override;
unique_bump_ptr<DynamicSymbolTable<ELFT>> createDynamicSymbolTable() override;
private:
MipsELFWriter<ELFT> _writeHelper;
MipsTargetLayout<ELFT> &_targetLayout;
unique_bump_ptr<Section<ELFT>> _reginfo;
};
template <class ELFT>
MipsDynamicLibraryWriter<ELFT>::MipsDynamicLibraryWriter(
MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
: DynamicLibraryWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
_targetLayout(layout) {}
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
result.push_back(_writeHelper.createRuntimeFile());
}
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
// Finalize the atom values that are part of the parent.
DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
_writeHelper.finalizeMipsRuntimeAtomValues();
}
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::createDefaultSections() {
DynamicLibraryWriter<ELFT>::createDefaultSections();
const auto &ctx = static_cast<const MipsLinkingContext &>(this->_ctx);
const auto &mask = ctx.getMergedReginfoMask();
if (!mask.hasValue())
return;
if (ELFT::Is64Bits)
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc) MipsOptionsSection<ELFT>(ctx, _targetLayout, *mask));
else
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc) MipsReginfoSection<ELFT>(ctx, _targetLayout, *mask));
this->_layout.addSection(_reginfo.get());
}
template <class ELFT>
unique_bump_ptr<SymbolTable<ELFT>>
MipsDynamicLibraryWriter<ELFT>::createSymbolTable() {
return unique_bump_ptr<SymbolTable<ELFT>>(
new (this->_alloc) MipsSymbolTable<ELFT>(this->_ctx));
}
/// \brief create dynamic table
template <class ELFT>
unique_bump_ptr<DynamicTable<ELFT>>
MipsDynamicLibraryWriter<ELFT>::createDynamicTable() {
return unique_bump_ptr<DynamicTable<ELFT>>(
new (this->_alloc) MipsDynamicTable<ELFT>(this->_ctx, _targetLayout));
}
/// \brief create dynamic symbol table
template <class ELFT>
unique_bump_ptr<DynamicSymbolTable<ELFT>>
MipsDynamicLibraryWriter<ELFT>::createDynamicSymbolTable() {
return unique_bump_ptr<DynamicSymbolTable<ELFT>>(
new (this->_alloc)
MipsDynamicSymbolTable<ELFT>(this->_ctx, _targetLayout));
}
} // namespace elf
} // namespace lld
#endif

View File

@ -0,0 +1,284 @@
//===- lib/ReaderWriter/ELF/MipsELFFile.cpp -------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MipsELFFile.h"
namespace lld {
namespace elf {
template <class ELFT>
MipsELFDefinedAtom<ELFT>::MipsELFDefinedAtom(
const MipsELFFile<ELFT> &file, StringRef symbolName, 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) {}
template <class ELFT>
const MipsELFFile<ELFT> &MipsELFDefinedAtom<ELFT>::file() const {
return static_cast<const MipsELFFile<ELFT> &>(this->_owningFile);
}
template <class ELFT>
DefinedAtom::CodeModel MipsELFDefinedAtom<ELFT>::codeModel() const {
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;
}
}
template class MipsELFDefinedAtom<ELF32LE>;
template class MipsELFDefinedAtom<ELF64LE>;
template <class ELFT> static bool isMips64EL() {
return ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
}
template <class ELFT, bool isRela>
static uint32_t
extractTag(const llvm::object::Elf_Rel_Impl<ELFT, isRela> &rel) {
return (rel.getType(isMips64EL<ELFT>()) & 0xffffff00) >> 8;
}
template <class ELFT>
MipsELFReference<ELFT>::MipsELFReference(uint64_t symValue, const Elf_Rela &rel)
: ELFReference<ELFT>(&rel, rel.r_offset - symValue,
Reference::KindArch::Mips,
rel.getType(isMips64EL<ELFT>()) & 0xff,
rel.getSymbol(isMips64EL<ELFT>())),
_tag(extractTag(rel)) {}
template <class ELFT>
MipsELFReference<ELFT>::MipsELFReference(uint64_t symValue, const Elf_Rel &rel)
: ELFReference<ELFT>(rel.r_offset - symValue, Reference::KindArch::Mips,
rel.getType(isMips64EL<ELFT>()) & 0xff,
rel.getSymbol(isMips64EL<ELFT>())),
_tag(extractTag(rel)) {}
template class MipsELFReference<ELF32LE>;
template class MipsELFReference<ELF64LE>;
template <class ELFT>
MipsELFFile<ELFT>::MipsELFFile(std::unique_ptr<MemoryBuffer> mb,
ELFLinkingContext &ctx)
: ELFFile<ELFT>(std::move(mb), ctx) {}
template <class ELFT> bool MipsELFFile<ELFT>::isPIC() const {
return this->_objFile->getHeader()->e_flags & llvm::ELF::EF_MIPS_PIC;
}
template <class ELFT> std::error_code MipsELFFile<ELFT>::doParse() {
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();
}
template <class ELFT>
ELFDefinedAtom<ELFT> *MipsELFFile<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) {
return new (this->_readerStorage) MipsELFDefinedAtom<ELFT>(
*this, symName, sectionName, sym, sectionHdr, contentData, referenceStart,
referenceEnd, referenceList);
}
template <class ELFT>
const typename MipsELFFile<ELFT>::Elf_Shdr *
MipsELFFile<ELFT>::findSectionByType(uint64_t type) const {
for (const Elf_Shdr &section : this->_objFile->sections())
if (section.sh_type == type)
return &section;
return nullptr;
}
template <class ELFT>
const typename MipsELFFile<ELFT>::Elf_Shdr *
MipsELFFile<ELFT>::findSectionByFlags(uint64_t flags) const {
for (const Elf_Shdr &section : this->_objFile->sections())
if (section.sh_flags & flags)
return &section;
return nullptr;
}
template <class ELFT>
ErrorOr<const typename MipsELFFile<ELFT>::Elf_Mips_RegInfo *>
MipsELFFile<ELFT>::findRegInfoSec() const {
using namespace llvm::ELF;
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)
return &opt->getRegInfo();
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_Mips_RegInfo))
return make_dynamic_error_code(
StringRef("Invalid size of MIPS_REGINFO section"));
return reinterpret_cast<const Elf_Mips_RegInfo *>(raw.data());
}
return nullptr;
}
template <class ELFT> std::error_code MipsELFFile<ELFT>::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;
}
auto &ctx = static_cast<MipsLinkingContext &>(this->_ctx);
ErrorOr<const Elf_Mips_RegInfo *> regInfoSec = findRegInfoSec();
if (auto ec = regInfoSec.getError())
return ec;
if (const Elf_Mips_RegInfo *regInfo = regInfoSec.get()) {
ctx.mergeReginfoMask(*regInfo);
_gp0 = regInfo->ri_gp_value;
}
const Elf_Ehdr *hdr = this->_objFile->getHeader();
if (std::error_code ec = ctx.mergeElfFlags(hdr->e_flags))
return ec;
return std::error_code();
}
template <class ELFT>
void MipsELFFile<ELFT>::createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> content,
range<Elf_Rela_Iter> rels) {
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);
}
}
template <class ELFT>
void MipsELFFile<ELFT>::createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> symContent,
ArrayRef<uint8_t> secContent,
range<Elf_Rel_Iter> rels) {
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;
auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, *rit);
this->addReferenceToSymbol(r, symbol);
this->_references.push_back(r);
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);
}
}
template <class ELFT>
static uint8_t
getPrimaryType(const llvm::object::Elf_Rel_Impl<ELFT, false> &rel) {
return rel.getType(isMips64EL<ELFT>()) & 0xff;
}
template <class ELFT>
Reference::Addend
MipsELFFile<ELFT>::readAddend(const Elf_Rel &ri,
const ArrayRef<uint8_t> content) const {
return readMipsRelocAddend(getPrimaryType(ri), content.data() + ri.r_offset);
}
template <class ELFT>
uint32_t MipsELFFile<ELFT>::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;
}
template <class ELFT>
typename MipsELFFile<ELFT>::Elf_Rel_Iter
MipsELFFile<ELFT>::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<ELFT>()) ==
rit->getSymbol(isMips64EL<ELFT>());
});
}
template <class ELFT>
bool MipsELFFile<ELFT>::isLocalBinding(const Elf_Rel &rel) const {
return this->_objFile->getSymbol(rel.getSymbol(isMips64EL<ELFT>()))
->getBinding() == llvm::ELF::STB_LOCAL;
}
template class MipsELFFile<ELF32LE>;
template class MipsELFFile<ELF64LE>;
} // elf
} // lld

View File

@ -30,70 +30,32 @@ 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);
}
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;
}
}
const MipsELFFile<ELFT>& file() const override;
DefinedAtom::CodeModel codeModel() const override;
};
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(extractTag(rel)) {}
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(extractTag(rel)) {}
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; }
private:
uint32_t _tag;
template <class R> static uint32_t extractTag(const R &rel) {
return (rel.getType(_isMips64EL) & 0xffffff00) >> 8;
}
};
template <class ELFT> class MipsELFFile : public ELFFile<ELFT> {
public:
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
: ELFFile<ELFT>(std::move(mb), ctx) {}
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &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; }
@ -103,13 +65,7 @@ public:
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;
@ -120,9 +76,6 @@ private:
enum { TP_OFFSET = 0x7000, DTP_OFFSET = 0x8000 };
static const bool _isMips64EL =
ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
int64_t _gp0 = 0;
uint64_t _tpOff = 0;
uint64_t _dtpOff = 0;
@ -132,173 +85,36 @@ private:
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);
}
std::vector<ELFReference<ELFT> *> &referenceList) override;
const Elf_Shdr *findSectionByType(uint64_t type) const {
for (const Elf_Shdr &section : this->_objFile->sections())
if (section.sh_type == type)
return &section;
return nullptr;
}
void createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> content,
range<Elf_Rela_Iter> rels) override;
void createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> symContent,
ArrayRef<uint8_t> secContent,
range<Elf_Rel_Iter> rels) override;
const Elf_Shdr *findSectionByFlags(uint64_t flags) const {
for (const Elf_Shdr &section : this->_objFile->sections())
if (section.sh_flags & flags)
return &section;
return nullptr;
}
const Elf_Shdr *findSectionByType(uint64_t type) const;
const Elf_Shdr *findSectionByFlags(uint64_t flags) const;
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;
ErrorOr<const Elf_Mips_RegInfo *> findRegInfoSec() const {
using namespace llvm::ELF;
if (const Elf_Shdr *sec = findSectionByType(SHT_MIPS_OPTIONS)) {
auto contents = this->getSectionContents(sec);
if (std::error_code ec = contents.getError())
return ec;
ErrorOr<const Elf_Mips_RegInfo *> findRegInfoSec() const;
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)
return &opt->getRegInfo();
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_Mips_RegInfo))
return make_dynamic_error_code(
StringRef("Invalid size of MIPS_REGINFO section"));
return reinterpret_cast<const Elf_Mips_RegInfo *>(raw.data());
}
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;
}
auto &ctx = static_cast<MipsLinkingContext &>(this->_ctx);
ErrorOr<const Elf_Mips_RegInfo *> regInfoSec = findRegInfoSec();
if (auto ec = regInfoSec.getError())
return ec;
if (const Elf_Mips_RegInfo *regInfo = regInfoSec.get()) {
ctx.mergeReginfoMask(*regInfo);
_gp0 = regInfo->ri_gp_value;
}
const Elf_Ehdr *hdr = this->_objFile->getHeader();
if (std::error_code ec = ctx.mergeElfFlags(hdr->e_flags))
return ec;
return std::error_code();
}
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);
}
}
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;
auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, *rit);
this->addReferenceToSymbol(r, symbol);
this->_references.push_back(r);
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);
}
}
std::error_code readAuxData();
Reference::Addend readAddend(const Elf_Rel &ri,
const ArrayRef<uint8_t> content) const {
return readMipsRelocAddend(getPrimaryType(ri),
content.data() + ri.r_offset);
}
const ArrayRef<uint8_t> content) 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;
}
uint32_t getPairRelocation(const Elf_Rel &rel) const;
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);
});
}
Elf_Rel_Iter eit) 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;
}
bool isLocalBinding(const Elf_Rel &rel) const;
};
} // elf

View File

@ -1,4 +1,4 @@
//===- lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h -------------------===//
//===- lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp -----------------------===//
//
// The LLVM Linker
//
@ -6,43 +6,141 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_EXECUTABLE_WRITER_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_EXECUTABLE_WRITER_H
#include "ExecutableWriter.h"
#include "MipsDynamicTable.h"
#include "MipsELFWriters.h"
#include "MipsLinkingContext.h"
#include "MipsTargetHandler.h"
#include "MipsTargetLayout.h"
namespace {
class MipsDynamicAtom : public lld::elf::DynamicAtom {
public:
MipsDynamicAtom(const lld::File &f) : DynamicAtom(f) {}
ContentPermissions permissions() const override { return permR__; }
};
}
namespace lld {
namespace elf {
template <typename ELFT> class MipsTargetLayout;
template <class ELFT>
MipsELFWriter<ELFT>::MipsELFWriter(MipsLinkingContext &ctx,
MipsTargetLayout<ELFT> &targetLayout)
: _ctx(ctx), _targetLayout(targetLayout) {}
template <class ELFT>
class MipsExecutableWriter : public ExecutableWriter<ELFT> {
public:
MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout);
void MipsELFWriter<ELFT>::setELFHeader(ELFHeader<ELFT> &elfHeader) {
elfHeader.e_version(1);
elfHeader.e_ident(llvm::ELF::EI_VERSION, llvm::ELF::EV_CURRENT);
elfHeader.e_ident(llvm::ELF::EI_OSABI, llvm::ELF::ELFOSABI_NONE);
if (_targetLayout.findOutputSection(".got.plt"))
elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 1);
else
elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 0);
protected:
void buildDynamicSymbolTable(const File &file) override;
elfHeader.e_flags(_ctx.getMergedELFFlags());
}
// Add any runtime files and their atoms to the output
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
template <class ELFT>
void MipsELFWriter<ELFT>::finalizeMipsRuntimeAtomValues() {
if (!_ctx.isDynamic())
return;
void finalizeDefaultAtomValues() override;
void createDefaultSections() override;
std::error_code setELFHeader() override;
auto gotSection = _targetLayout.findOutputSection(".got");
auto got = gotSection ? gotSection->virtualAddr() : 0;
auto gp = gotSection ? got + _targetLayout.getGPOffset() : 0;
unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable() override;
unique_bump_ptr<DynamicSymbolTable<ELFT>> createDynamicSymbolTable() override;
setAtomValue("_gp", gp);
setAtomValue("_gp_disp", gp);
setAtomValue("__gnu_local_gp", gp);
}
private:
MipsELFWriter<ELFT> _writeHelper;
MipsTargetLayout<ELFT> &_targetLayout;
unique_bump_ptr<Section<ELFT>> _reginfo;
};
template <class ELFT>
std::unique_ptr<RuntimeFile<ELFT>> MipsELFWriter<ELFT>::createRuntimeFile() {
auto file = llvm::make_unique<RuntimeFile<ELFT>>(_ctx, "Mips runtime file");
if (_ctx.isDynamic()) {
file->addAbsoluteAtom("_gp");
file->addAbsoluteAtom("_gp_disp");
file->addAbsoluteAtom("__gnu_local_gp");
file->addAtom(*new (file->allocator()) MipsDynamicAtom(*file));
}
return file;
}
template <class ELFT>
void MipsELFWriter<ELFT>::setAtomValue(StringRef name, uint64_t value) {
AtomLayout *atom = _targetLayout.findAbsoluteAtom(name);
assert(atom);
atom->_virtualAddr = value;
}
template <class ELFT>
MipsDynamicLibraryWriter<ELFT>::MipsDynamicLibraryWriter(
MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
: DynamicLibraryWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
_targetLayout(layout) {}
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
result.push_back(_writeHelper.createRuntimeFile());
}
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
_writeHelper.finalizeMipsRuntimeAtomValues();
}
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::createDefaultSections() {
DynamicLibraryWriter<ELFT>::createDefaultSections();
const auto &ctx = static_cast<const MipsLinkingContext &>(this->_ctx);
const auto &mask = ctx.getMergedReginfoMask();
if (!mask.hasValue())
return;
if (ELFT::Is64Bits)
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc) MipsOptionsSection<ELFT>(ctx, _targetLayout, *mask));
else
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc) MipsReginfoSection<ELFT>(ctx, _targetLayout, *mask));
this->_layout.addSection(_reginfo.get());
}
template <class ELFT>
std::error_code MipsDynamicLibraryWriter<ELFT>::setELFHeader() {
DynamicLibraryWriter<ELFT>::setELFHeader();
_writeHelper.setELFHeader(*this->_elfHeader);
return std::error_code();
}
template <class ELFT>
unique_bump_ptr<SymbolTable<ELFT>>
MipsDynamicLibraryWriter<ELFT>::createSymbolTable() {
return unique_bump_ptr<SymbolTable<ELFT>>(
new (this->_alloc) MipsSymbolTable<ELFT>(this->_ctx));
}
template <class ELFT>
unique_bump_ptr<DynamicTable<ELFT>>
MipsDynamicLibraryWriter<ELFT>::createDynamicTable() {
return unique_bump_ptr<DynamicTable<ELFT>>(
new (this->_alloc) MipsDynamicTable<ELFT>(this->_ctx, _targetLayout));
}
template <class ELFT>
unique_bump_ptr<DynamicSymbolTable<ELFT>>
MipsDynamicLibraryWriter<ELFT>::createDynamicSymbolTable() {
return unique_bump_ptr<DynamicSymbolTable<ELFT>>(new (
this->_alloc) MipsDynamicSymbolTable<ELFT>(this->_ctx, _targetLayout));
}
template class MipsDynamicLibraryWriter<ELF32LE>;
template class MipsDynamicLibraryWriter<ELF64LE>;
template <class ELFT>
MipsExecutableWriter<ELFT>::MipsExecutableWriter(MipsLinkingContext &ctx,
@ -140,7 +238,7 @@ template <class ELFT> void MipsExecutableWriter<ELFT>::createDefaultSections() {
template <class ELFT>
unique_bump_ptr<SymbolTable<ELFT>>
MipsExecutableWriter<ELFT>::createSymbolTable() {
MipsExecutableWriter<ELFT>::createSymbolTable() {
return unique_bump_ptr<SymbolTable<ELFT>>(
new (this->_alloc) MipsSymbolTable<ELFT>(this->_ctx));
}
@ -148,7 +246,7 @@ unique_bump_ptr<SymbolTable<ELFT>>
/// \brief create dynamic table
template <class ELFT>
unique_bump_ptr<DynamicTable<ELFT>>
MipsExecutableWriter<ELFT>::createDynamicTable() {
MipsExecutableWriter<ELFT>::createDynamicTable() {
return unique_bump_ptr<DynamicTable<ELFT>>(
new (this->_alloc) MipsDynamicTable<ELFT>(this->_ctx, _targetLayout));
}
@ -156,13 +254,13 @@ unique_bump_ptr<DynamicTable<ELFT>>
/// \brief create dynamic symbol table
template <class ELFT>
unique_bump_ptr<DynamicSymbolTable<ELFT>>
MipsExecutableWriter<ELFT>::createDynamicSymbolTable() {
return unique_bump_ptr<DynamicSymbolTable<ELFT>>(
new (this->_alloc)
MipsDynamicSymbolTable<ELFT>(this->_ctx, _targetLayout));
MipsExecutableWriter<ELFT>::createDynamicSymbolTable() {
return unique_bump_ptr<DynamicSymbolTable<ELFT>>(new (
this->_alloc) MipsDynamicSymbolTable<ELFT>(this->_ctx, _targetLayout));
}
} // namespace elf
} // namespace lld
template class MipsExecutableWriter<ELF32LE>;
template class MipsExecutableWriter<ELF64LE>;
#endif
} // elf
} // lld

View File

@ -9,6 +9,8 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_WRITERS_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_WRITERS_H
#include "DynamicLibraryWriter.h"
#include "ExecutableWriter.h"
#include "MipsLinkingContext.h"
namespace lld {
@ -16,63 +18,71 @@ namespace elf {
template <class ELFT> class MipsTargetLayout;
class MipsDynamicAtom : public DynamicAtom {
public:
MipsDynamicAtom(const File &f) : DynamicAtom(f) {}
ContentPermissions permissions() const override { return permR__; }
};
template <typename ELFT> class MipsELFWriter {
public:
MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout)
: _ctx(ctx), _targetLayout(targetLayout) {}
MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout);
void setELFHeader(ELFHeader<ELFT> &elfHeader) {
elfHeader.e_version(1);
elfHeader.e_ident(llvm::ELF::EI_VERSION, llvm::ELF::EV_CURRENT);
elfHeader.e_ident(llvm::ELF::EI_OSABI, llvm::ELF::ELFOSABI_NONE);
if (_targetLayout.findOutputSection(".got.plt"))
elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 1);
else
elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 0);
void setELFHeader(ELFHeader<ELFT> &elfHeader);
elfHeader.e_flags(_ctx.getMergedELFFlags());
}
void finalizeMipsRuntimeAtomValues();
void finalizeMipsRuntimeAtomValues() {
if (!_ctx.isDynamic())
return;
auto gotSection = _targetLayout.findOutputSection(".got");
auto got = gotSection ? gotSection->virtualAddr() : 0;
auto gp = gotSection ? got + _targetLayout.getGPOffset() : 0;
setAtomValue("_gp", gp);
setAtomValue("_gp_disp", gp);
setAtomValue("__gnu_local_gp", gp);
}
std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile() {
auto file = llvm::make_unique<RuntimeFile<ELFT>>(_ctx, "Mips runtime file");
if (_ctx.isDynamic()) {
file->addAbsoluteAtom("_gp");
file->addAbsoluteAtom("_gp_disp");
file->addAbsoluteAtom("__gnu_local_gp");
file->addAtom(*new (file->allocator()) MipsDynamicAtom(*file));
}
return file;
}
std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile();
private:
MipsLinkingContext &_ctx;
MipsTargetLayout<ELFT> &_targetLayout;
void setAtomValue(StringRef name, uint64_t value) {
AtomLayout *atom = _targetLayout.findAbsoluteAtom(name);
assert(atom);
atom->_virtualAddr = value;
}
void setAtomValue(StringRef name, uint64_t value);
};
template <class ELFT>
class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
public:
MipsDynamicLibraryWriter(MipsLinkingContext &ctx,
MipsTargetLayout<ELFT> &layout);
protected:
// Add any runtime files and their atoms to the output
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
void finalizeDefaultAtomValues() override;
void createDefaultSections() override;
std::error_code setELFHeader() override;
unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable() override;
unique_bump_ptr<DynamicSymbolTable<ELFT>> createDynamicSymbolTable() override;
private:
MipsELFWriter<ELFT> _writeHelper;
MipsTargetLayout<ELFT> &_targetLayout;
unique_bump_ptr<Section<ELFT>> _reginfo;
};
template <class ELFT>
class MipsExecutableWriter : public ExecutableWriter<ELFT> {
public:
MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout);
protected:
void buildDynamicSymbolTable(const File &file) override;
// Add any runtime files and their atoms to the output
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
void finalizeDefaultAtomValues() override;
void createDefaultSections() override;
std::error_code setELFHeader() override;
unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable() override;
unique_bump_ptr<DynamicSymbolTable<ELFT>> createDynamicSymbolTable() override;
private:
MipsELFWriter<ELFT> _writeHelper;
MipsTargetLayout<ELFT> &_targetLayout;
unique_bump_ptr<Section<ELFT>> _reginfo;
};
} // elf

View File

@ -28,9 +28,9 @@ static std::unique_ptr<TargetHandler> createTarget(llvm::Triple triple,
MipsLinkingContext &ctx) {
switch (triple.getArch()) {
case llvm::Triple::mipsel:
return createMips32ELTargetHandler(ctx);
return llvm::make_unique<MipsTargetHandler<ELF32LE>>(ctx);
case llvm::Triple::mips64el:
return createMips64ELTargetHandler(ctx);
return llvm::make_unique<MipsTargetHandler<ELF64LE>>(ctx);
default:
llvm_unreachable("Unhandled arch");
}

View File

@ -0,0 +1,235 @@
//===- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp --------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MipsLinkingContext.h"
#include "MipsSectionChunks.h"
#include "MipsTargetLayout.h"
namespace lld {
namespace elf {
template <class ELFT>
MipsReginfoSection<ELFT>::MipsReginfoSection(
const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
const MipsReginfo &reginfo)
: Section<ELFT>(ctx, ".reginfo", "MipsReginfo"),
_targetLayout(targetLayout) {
this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_REGINFO);
this->_entSize = sizeof(Elf_Mips_RegInfo);
this->_fsize = sizeof(Elf_Mips_RegInfo);
this->_msize = sizeof(Elf_Mips_RegInfo);
this->_alignment = 4;
this->_type = SHT_MIPS_REGINFO;
this->_flags = SHF_ALLOC;
std::memset(&_reginfo, 0, sizeof(_reginfo));
_reginfo.ri_gprmask = reginfo._gpRegMask;
_reginfo.ri_cprmask[0] = reginfo._cpRegMask[0];
_reginfo.ri_cprmask[1] = reginfo._cpRegMask[1];
_reginfo.ri_cprmask[2] = reginfo._cpRegMask[2];
_reginfo.ri_cprmask[3] = reginfo._cpRegMask[3];
}
template <class ELFT>
void MipsReginfoSection<ELFT>::write(ELFWriter *writer,
TargetLayout<ELFT> &layout,
llvm::FileOutputBuffer &buffer) {
uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
std::memcpy(dest, &_reginfo, this->_fsize);
}
template <class ELFT> void MipsReginfoSection<ELFT>::finalize() {
_reginfo.ri_gp_value = _targetLayout.getGPAddr();
if (this->_outputSection)
this->_outputSection->setType(this->_type);
}
template class MipsReginfoSection<ELF32LE>;
template class MipsReginfoSection<ELF64LE>;
template <class ELFT>
MipsOptionsSection<ELFT>::MipsOptionsSection(
const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
const MipsReginfo &reginfo)
: Section<ELFT>(ctx, ".MIPS.options", "MipsOptions"),
_targetLayout(targetLayout) {
this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_OPTIONS);
this->_entSize = 1;
this->_alignment = 8;
this->_fsize = llvm::RoundUpToAlignment(
sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo), this->_alignment);
this->_msize = this->_fsize;
this->_type = SHT_MIPS_OPTIONS;
this->_flags = SHF_ALLOC | SHF_MIPS_NOSTRIP;
_header.kind = ODK_REGINFO;
_header.size = this->_fsize;
_header.section = 0;
_header.info = 0;
std::memset(&_reginfo, 0, sizeof(_reginfo));
_reginfo.ri_gprmask = reginfo._gpRegMask;
_reginfo.ri_cprmask[0] = reginfo._cpRegMask[0];
_reginfo.ri_cprmask[1] = reginfo._cpRegMask[1];
_reginfo.ri_cprmask[2] = reginfo._cpRegMask[2];
_reginfo.ri_cprmask[3] = reginfo._cpRegMask[3];
}
template <class ELFT>
void MipsOptionsSection<ELFT>::write(ELFWriter *writer,
TargetLayout<ELFT> &layout,
llvm::FileOutputBuffer &buffer) {
uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
std::memset(dest, 0, this->_fsize);
std::memcpy(dest, &_header, sizeof(_header));
std::memcpy(dest + sizeof(_header), &_reginfo, sizeof(_reginfo));
}
template <class ELFT> void MipsOptionsSection<ELFT>::finalize() {
_reginfo.ri_gp_value = _targetLayout.getGPAddr();
if (this->_outputSection)
this->_outputSection->setType(this->_type);
}
template class MipsOptionsSection<ELF32LE>;
template class MipsOptionsSection<ELF64LE>;
template <class ELFT>
MipsGOTSection<ELFT>::MipsGOTSection(const MipsLinkingContext &ctx)
: AtomSection<ELFT>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
MipsTargetLayout<ELFT>::ORDER_GOT),
_hasNonLocal(false), _localCount(0) {
this->_flags |= SHF_MIPS_GPREL;
this->_alignment = 4;
}
template <class ELFT>
bool MipsGOTSection<ELFT>::compare(const Atom *a, const Atom *b) const {
auto ia = _posMap.find(a);
auto ib = _posMap.find(b);
if (ia != _posMap.end() && ib != _posMap.end())
return ia->second < ib->second;
return ia == _posMap.end() && ib != _posMap.end();
}
template <class ELFT>
const AtomLayout *MipsGOTSection<ELFT>::appendAtom(const Atom *atom) {
const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
if (atom->name() == "_GLOBAL_OFFSET_TABLE_")
return AtomSection<ELFT>::appendAtom(atom);
for (const auto &r : *da) {
if (r->kindNamespace() != 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<ELFT>::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<ELFT>::appendAtom(atom);
case R_MIPS_TLS_DTPMOD32:
case R_MIPS_TLS_DTPMOD64:
_hasNonLocal = true;
break;
}
}
if (!_hasNonLocal)
++_localCount;
return AtomSection<ELFT>::appendAtom(atom);
}
template class MipsGOTSection<ELF32LE>;
template class MipsGOTSection<ELF64LE>;
template <class ELFT>
MipsPLTSection<ELFT>::MipsPLTSection(const MipsLinkingContext &ctx)
: AtomSection<ELFT>(ctx, ".plt", DefinedAtom::typeGOT, DefinedAtom::permR_X,
MipsTargetLayout<ELFT>::ORDER_PLT) {}
template <class ELFT>
const AtomLayout *MipsPLTSection<ELFT>::findPLTLayout(const Atom *plt) const {
auto it = _pltLayoutMap.find(plt);
return it != _pltLayoutMap.end() ? it->second : nullptr;
}
template <class ELFT>
const AtomLayout *MipsPLTSection<ELFT>::appendAtom(const Atom *atom) {
const auto *layout = AtomSection<ELFT>::appendAtom(atom);
const DefinedAtom *da = cast<DefinedAtom>(atom);
for (const auto &r : *da) {
if (r->kindNamespace() != Reference::KindNamespace::ELF)
continue;
assert(r->kindArch() == Reference::KindArch::Mips);
if (r->kindValue() == LLD_R_MIPS_STO_PLT) {
_pltLayoutMap[r->target()] = layout;
break;
}
}
return layout;
}
template class MipsPLTSection<ELF32LE>;
template class MipsPLTSection<ELF64LE>;
template <class ELFT> static bool isMips64EL() {
return ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
}
template <class ELFT>
MipsRelocationTable<ELFT>::MipsRelocationTable(const ELFLinkingContext &ctx,
StringRef str, int32_t order)
: RelocationTable<ELFT>(ctx, str, order) {}
template <class ELFT>
void MipsRelocationTable<ELFT>::writeRela(ELFWriter *writer, Elf_Rela &r,
const DefinedAtom &atom,
const Reference &ref) {
uint32_t rType = ref.kindValue() | (ref.tag() << 8);
r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType,
isMips64EL<ELFT>());
r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
// The addend is used only by relative relocations
if (this->_ctx.isRelativeReloc(ref))
r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
else
r.r_addend = 0;
}
template <class ELFT>
void MipsRelocationTable<ELFT>::writeRel(ELFWriter *writer, Elf_Rel &r,
const DefinedAtom &atom,
const Reference &ref) {
uint32_t rType = ref.kindValue() | (ref.tag() << 8);
r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType,
isMips64EL<ELFT>());
r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
}
template class MipsRelocationTable<ELF32LE>;
template class MipsRelocationTable<ELF64LE>;
} // elf
} // lld

View File

@ -23,41 +23,14 @@ template <class ELFT> class MipsReginfoSection : public Section<ELFT> {
public:
MipsReginfoSection(const ELFLinkingContext &ctx,
MipsTargetLayout<ELFT> &targetLayout,
const MipsReginfo &reginfo)
: Section<ELFT>(ctx, ".reginfo", "MipsReginfo"),
_targetLayout(targetLayout) {
this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_REGINFO);
this->_entSize = sizeof(Elf_Mips_RegInfo);
this->_fsize = sizeof(Elf_Mips_RegInfo);
this->_msize = sizeof(Elf_Mips_RegInfo);
this->_alignment = 4;
this->_type = SHT_MIPS_REGINFO;
this->_flags = SHF_ALLOC;
std::memset(&_reginfo, 0, sizeof(_reginfo));
_reginfo.ri_gprmask = reginfo._gpRegMask;
_reginfo.ri_cprmask[0] = reginfo._cpRegMask[0];
_reginfo.ri_cprmask[1] = reginfo._cpRegMask[1];
_reginfo.ri_cprmask[2] = reginfo._cpRegMask[2];
_reginfo.ri_cprmask[3] = reginfo._cpRegMask[3];
}
const MipsReginfo &reginfo);
StringRef segmentKindToStr() const override { return "REGINFO"; }
bool hasOutputSegment() const override { return true; }
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
llvm::FileOutputBuffer &buffer) override {
uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
std::memcpy(dest, &_reginfo, this->_fsize);
}
void finalize() override {
_reginfo.ri_gp_value = _targetLayout.getGPAddr();
if (this->_outputSection)
this->_outputSection->setType(this->_type);
}
llvm::FileOutputBuffer &buffer) override;
void finalize() override;
private:
typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
@ -69,51 +42,15 @@ private:
/// \brief Handle .MIPS.options section
template <class ELFT> class MipsOptionsSection : public Section<ELFT> {
public:
typedef typename std::vector<MipsReginfo>::const_iterator mask_const_iterator;
MipsOptionsSection(const ELFLinkingContext &ctx,
MipsTargetLayout<ELFT> &targetLayout,
const MipsReginfo &reginfo)
: Section<ELFT>(ctx, ".MIPS.options", "MipsOptions"),
_targetLayout(targetLayout) {
this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_OPTIONS);
this->_entSize = 1;
this->_alignment = 8;
this->_fsize = llvm::RoundUpToAlignment(
sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo), this->_alignment);
this->_msize = this->_fsize;
this->_type = SHT_MIPS_OPTIONS;
this->_flags = SHF_ALLOC | SHF_MIPS_NOSTRIP;
_header.kind = ODK_REGINFO;
_header.size = this->_fsize;
_header.section = 0;
_header.info = 0;
std::memset(&_reginfo, 0, sizeof(_reginfo));
_reginfo.ri_gprmask = reginfo._gpRegMask;
_reginfo.ri_cprmask[0] = reginfo._cpRegMask[0];
_reginfo.ri_cprmask[1] = reginfo._cpRegMask[1];
_reginfo.ri_cprmask[2] = reginfo._cpRegMask[2];
_reginfo.ri_cprmask[3] = reginfo._cpRegMask[3];
}
const MipsReginfo &reginfo);
bool hasOutputSegment() const override { return true; }
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
llvm::FileOutputBuffer &buffer) override {
uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
std::memset(dest, 0, this->_fsize);
std::memcpy(dest, &_header, sizeof(_header));
std::memcpy(dest + sizeof(_header), &_reginfo, sizeof(_reginfo));
}
void finalize() override {
_reginfo.ri_gp_value = _targetLayout.getGPAddr();
if (this->_outputSection)
this->_outputSection->setType(this->_type);
}
llvm::FileOutputBuffer &buffer) override;
void finalize() override;
private:
typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
@ -127,14 +64,7 @@ private:
/// \brief Handle Mips GOT section
template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
public:
MipsGOTSection(const MipsLinkingContext &ctx)
: AtomSection<ELFT>(ctx, ".got", DefinedAtom::typeGOT,
DefinedAtom::permRW_,
MipsTargetLayout<ELFT>::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; }
@ -148,50 +78,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 AtomLayout *appendAtom(const Atom *atom) override {
const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
if (atom->name() == "_GLOBAL_OFFSET_TABLE_")
return AtomSection<ELFT>::appendAtom(atom);
for (const auto &r : *da) {
if (r->kindNamespace() != 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<ELFT>::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<ELFT>::appendAtom(atom);
case R_MIPS_TLS_DTPMOD32:
case R_MIPS_TLS_DTPMOD64:
_hasNonLocal = true;
break;
}
}
if (!_hasNonLocal)
++_localCount;
return AtomSection<ELFT>::appendAtom(atom);
}
const AtomLayout *appendAtom(const Atom *atom) override;
private:
/// \brief True if the GOT contains non-local entries.
@ -210,33 +99,11 @@ private:
/// \brief Handle Mips PLT section
template <class ELFT> class MipsPLTSection : public AtomSection<ELFT> {
public:
MipsPLTSection(const MipsLinkingContext &ctx)
: AtomSection<ELFT>(ctx, ".plt", DefinedAtom::typeGOT,
DefinedAtom::permR_X,
MipsTargetLayout<ELFT>::ORDER_PLT) {}
MipsPLTSection(const MipsLinkingContext &ctx);
const AtomLayout *findPLTLayout(const Atom *plt) const {
auto it = _pltLayoutMap.find(plt);
return it != _pltLayoutMap.end() ? it->second : nullptr;
}
const AtomLayout *findPLTLayout(const Atom *plt) const;
const AtomLayout *appendAtom(const Atom *atom) override {
const auto *layout = AtomSection<ELFT>::appendAtom(atom);
const DefinedAtom *da = cast<DefinedAtom>(atom);
for (const auto &r : *da) {
if (r->kindNamespace() != Reference::KindNamespace::ELF)
continue;
assert(r->kindArch() == Reference::KindArch::Mips);
if (r->kindValue() == LLD_R_MIPS_STO_PLT) {
_pltLayoutMap[r->target()] = layout;
break;
}
}
return layout;
}
const AtomLayout *appendAtom(const Atom *atom) override;
private:
/// \brief Map PLT Atoms to their layouts.
@ -247,33 +114,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 &ctx, StringRef str,
int32_t order)
: RelocationTable<ELFT>(ctx, str, order) {}
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->_ctx.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

View File

@ -0,0 +1,155 @@
//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler32EL.cpp ----------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ELFReader.h"
#include "MipsELFFile.h"
#include "MipsELFWriters.h"
#include "MipsTargetHandler.h"
namespace lld {
namespace elf {
template <class ELFT>
MipsTargetHandler<ELFT>::MipsTargetHandler(MipsLinkingContext &ctx)
: _ctx(ctx), _targetLayout(new MipsTargetLayout<ELFT>(ctx)),
_relocationHandler(
createMipsRelocationHandler<ELFT>(ctx, *_targetLayout)) {}
template <class ELFT>
std::unique_ptr<Reader> MipsTargetHandler<ELFT>::getObjReader() {
return llvm::make_unique<ELFReader<MipsELFFile<ELFT>>>(_ctx);
}
template <class ELFT>
std::unique_ptr<Reader> MipsTargetHandler<ELFT>::getDSOReader() {
return llvm::make_unique<ELFReader<DynamicFile<ELFT>>>(_ctx);
}
template <class ELFT>
const TargetRelocationHandler &
MipsTargetHandler<ELFT>::getRelocationHandler() const {
return *_relocationHandler;
}
template <class ELFT>
std::unique_ptr<Writer> MipsTargetHandler<ELFT>::getWriter() {
switch (_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
return llvm::make_unique<MipsExecutableWriter<ELFT>>(_ctx, *_targetLayout);
case llvm::ELF::ET_DYN:
return llvm::make_unique<MipsDynamicLibraryWriter<ELFT>>(_ctx,
*_targetLayout);
case llvm::ELF::ET_REL:
llvm_unreachable("TODO: support -r mode");
default:
llvm_unreachable("unsupported output type");
}
}
template class MipsTargetHandler<ELF32LE>;
template class MipsTargetHandler<ELF64LE>;
template <class ELFT>
MipsSymbolTable<ELFT>::MipsSymbolTable(const ELFLinkingContext &ctx)
: SymbolTable<ELFT>(ctx, ".symtab",
TargetLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
template <class ELFT>
void MipsSymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
int64_t addr) {
SymbolTable<ELFT>::addDefinedAtom(sym, da, addr);
switch (da->codeModel()) {
case DefinedAtom::codeMipsMicro:
sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS;
break;
case DefinedAtom::codeMipsMicroPIC:
sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS | llvm::ELF::STO_MIPS_PIC;
break;
default:
break;
}
}
template <class ELFT> void MipsSymbolTable<ELFT>::finalize(bool sort) {
SymbolTable<ELFT>::finalize(sort);
for (auto &ste : this->_symbolTable) {
if (!ste._atom)
continue;
if (const auto *da = dyn_cast<DefinedAtom>(ste._atom)) {
if (da->codeModel() == DefinedAtom::codeMipsMicro ||
da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
// Adjust dynamic microMIPS symbol value. That allows a dynamic
// linker to recognize and handle this symbol correctly.
ste._symbol.st_value = ste._symbol.st_value | 1;
}
}
}
}
template class MipsSymbolTable<ELF32LE>;
template class MipsSymbolTable<ELF64LE>;
template <class ELFT>
MipsDynamicSymbolTable<ELFT>::MipsDynamicSymbolTable(
const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
: DynamicSymbolTable<ELFT>(ctx, layout, ".dynsym",
TargetLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS),
_targetLayout(layout) {}
template <class ELFT> void MipsDynamicSymbolTable<ELFT>::sortSymbols() {
typedef typename DynamicSymbolTable<ELFT>::SymbolEntry SymbolEntry;
std::stable_sort(this->_symbolTable.begin(), this->_symbolTable.end(),
[this](const SymbolEntry &A, const SymbolEntry &B) {
if (A._symbol.getBinding() != STB_GLOBAL &&
B._symbol.getBinding() != STB_GLOBAL)
return A._symbol.getBinding() < B._symbol.getBinding();
return _targetLayout.getGOTSection().compare(A._atom,
B._atom);
});
}
template <class ELFT> void MipsDynamicSymbolTable<ELFT>::finalize() {
DynamicSymbolTable<ELFT>::finalize();
const auto &pltSection = _targetLayout.getPLTSection();
for (auto &ste : this->_symbolTable) {
const Atom *a = ste._atom;
if (!a)
continue;
if (auto *layout = pltSection.findPLTLayout(a)) {
a = layout->_atom;
// Under some conditions a dynamic symbol table record should hold
// a symbol value of the corresponding PLT entry. For details look
// at the PLT entry creation code in the class MipsRelocationPass.
// Let's update atomLayout fields for such symbols.
assert(!ste._atomLayout);
ste._symbol.st_value = layout->_virtualAddr;
ste._symbol.st_other |= ELF::STO_MIPS_PLT;
}
if (const auto *da = dyn_cast<DefinedAtom>(a)) {
if (da->codeModel() == DefinedAtom::codeMipsMicro ||
da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
// Adjust dynamic microMIPS symbol value. That allows a dynamic
// linker to recognize and handle this symbol correctly.
ste._symbol.st_value = ste._symbol.st_value | 1;
}
}
}
}
template class MipsDynamicSymbolTable<ELF32LE>;
template class MipsDynamicSymbolTable<ELF64LE>;
}
}

View File

@ -9,10 +9,6 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
#include "ELFReader.h"
#include "MipsDynamicLibraryWriter.h"
#include "MipsELFFile.h"
#include "MipsExecutableWriter.h"
#include "MipsLinkingContext.h"
#include "MipsTargetLayout.h"
#include "TargetHandler.h"
@ -23,37 +19,12 @@ namespace elf {
/// \brief TargetHandler for Mips
template <class ELFT> class MipsTargetHandler final : public TargetHandler {
public:
MipsTargetHandler(MipsLinkingContext &ctx)
: _ctx(ctx), _targetLayout(new MipsTargetLayout<ELFT>(ctx)),
_relocationHandler(
createMipsRelocationHandler<ELFT>(ctx, *_targetLayout)) {}
MipsTargetHandler(MipsLinkingContext &ctx);
std::unique_ptr<Reader> getObjReader() override {
return llvm::make_unique<ELFReader<MipsELFFile<ELFT>>>(_ctx);
}
std::unique_ptr<Reader> getDSOReader() override {
return llvm::make_unique<ELFReader<DynamicFile<ELFT>>>(_ctx);
}
const TargetRelocationHandler &getRelocationHandler() const override {
return *_relocationHandler;
}
std::unique_ptr<Writer> getWriter() override {
switch (_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
return llvm::make_unique<MipsExecutableWriter<ELFT>>(
_ctx, *_targetLayout);
case llvm::ELF::ET_DYN:
return llvm::make_unique<MipsDynamicLibraryWriter<ELFT>>(
_ctx, *_targetLayout);
case llvm::ELF::ET_REL:
llvm_unreachable("TODO: support -r mode");
default:
llvm_unreachable("unsupported output type");
}
}
std::unique_ptr<Reader> getObjReader() override;
std::unique_ptr<Reader> getDSOReader() override;
const TargetRelocationHandler &getRelocationHandler() const override;
std::unique_ptr<Writer> getWriter() override;
private:
MipsLinkingContext &_ctx;
@ -65,105 +36,26 @@ template <class ELFT> class MipsSymbolTable : public SymbolTable<ELFT> {
public:
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
MipsSymbolTable(const ELFLinkingContext &ctx)
: SymbolTable<ELFT>(ctx, ".symtab",
TargetLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
MipsSymbolTable(const ELFLinkingContext &ctx);
void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
int64_t addr) override {
SymbolTable<ELFT>::addDefinedAtom(sym, da, addr);
switch (da->codeModel()) {
case DefinedAtom::codeMipsMicro:
sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS;
break;
case DefinedAtom::codeMipsMicroPIC:
sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS | llvm::ELF::STO_MIPS_PIC;
break;
default:
break;
}
}
void finalize(bool sort) override {
SymbolTable<ELFT>::finalize(sort);
for (auto &ste : this->_symbolTable) {
if (!ste._atom)
continue;
if (const auto *da = dyn_cast<DefinedAtom>(ste._atom)) {
if (da->codeModel() == DefinedAtom::codeMipsMicro ||
da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
// Adjust dynamic microMIPS symbol value. That allows a dynamic
// linker to recognize and handle this symbol correctly.
ste._symbol.st_value = ste._symbol.st_value | 1;
}
}
}
}
int64_t addr) override;
void finalize(bool sort) override;
};
template <class ELFT>
class MipsDynamicSymbolTable : public DynamicSymbolTable<ELFT> {
public:
MipsDynamicSymbolTable(const ELFLinkingContext &ctx,
MipsTargetLayout<ELFT> &layout)
: DynamicSymbolTable<ELFT>(ctx, layout, ".dynsym",
TargetLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS),
_targetLayout(layout) {}
MipsTargetLayout<ELFT> &layout);
void sortSymbols() override {
typedef typename DynamicSymbolTable<ELFT>::SymbolEntry SymbolEntry;
std::stable_sort(this->_symbolTable.begin(), this->_symbolTable.end(),
[this](const SymbolEntry &A, const SymbolEntry &B) {
if (A._symbol.getBinding() != STB_GLOBAL &&
B._symbol.getBinding() != STB_GLOBAL)
return A._symbol.getBinding() < B._symbol.getBinding();
return _targetLayout.getGOTSection().compare(A._atom, B._atom);
});
}
void finalize() override {
DynamicSymbolTable<ELFT>::finalize();
const auto &pltSection = _targetLayout.getPLTSection();
for (auto &ste : this->_symbolTable) {
const Atom *a = ste._atom;
if (!a)
continue;
if (auto *layout = pltSection.findPLTLayout(a)) {
a = layout->_atom;
// Under some conditions a dynamic symbol table record should hold
// a symbol value of the corresponding PLT entry. For details look
// at the PLT entry creation code in the class MipsRelocationPass.
// Let's update atomLayout fields for such symbols.
assert(!ste._atomLayout);
ste._symbol.st_value = layout->_virtualAddr;
ste._symbol.st_other |= ELF::STO_MIPS_PLT;
}
if (const auto *da = dyn_cast<DefinedAtom>(a)) {
if (da->codeModel() == DefinedAtom::codeMipsMicro ||
da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
// Adjust dynamic microMIPS symbol value. That allows a dynamic
// linker to recognize and handle this symbol correctly.
ste._symbol.st_value = ste._symbol.st_value | 1;
}
}
}
}
void sortSymbols() override;
void finalize() override;
private:
MipsTargetLayout<ELFT> &_targetLayout;
};
std::unique_ptr<TargetHandler>
createMips32ELTargetHandler(MipsLinkingContext &ctx);
std::unique_ptr<TargetHandler>
createMips64ELTargetHandler(MipsLinkingContext &ctx);
} // end namespace elf
} // end namespace lld

View File

@ -1,18 +0,0 @@
//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler32EL.cpp ----------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MipsTargetHandler.h"
using namespace lld;
using namespace lld::elf;
std::unique_ptr<TargetHandler>
lld::elf::createMips32ELTargetHandler(MipsLinkingContext &ctx) {
return llvm::make_unique<MipsTargetHandler<ELF32LE>>(ctx);
}

View File

@ -1,18 +0,0 @@
//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler64EL.cpp ----------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MipsTargetHandler.h"
using namespace lld;
using namespace lld::elf;
std::unique_ptr<TargetHandler>
lld::elf::createMips64ELTargetHandler(MipsLinkingContext &ctx) {
return llvm::make_unique<MipsTargetHandler<ELF64LE>>(ctx);
}

View File

@ -0,0 +1,83 @@
//===- lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp ---------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MipsLinkingContext.h"
#include "MipsTargetLayout.h"
namespace lld {
namespace elf {
template <class ELFT>
MipsTargetLayout<ELFT>::MipsTargetLayout(MipsLinkingContext &ctx)
: TargetLayout<ELFT>(ctx),
_gotSection(new (this->_allocator) MipsGOTSection<ELFT>(ctx)),
_pltSection(new (this->_allocator) MipsPLTSection<ELFT>(ctx)) {}
template <class ELFT>
AtomSection<ELFT> *MipsTargetLayout<ELFT>::createSection(
StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions,
typename TargetLayout<ELFT>::SectionOrder order) {
if (type == DefinedAtom::typeGOT && name == ".got")
return _gotSection;
if (type == DefinedAtom::typeStub && name == ".plt")
return _pltSection;
return TargetLayout<ELFT>::createSection(name, type, permissions, order);
}
template <class ELFT>
typename TargetLayout<ELFT>::SegmentType
MipsTargetLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
switch (section->order()) {
case ORDER_MIPS_REGINFO:
return llvm::ELF::PT_MIPS_REGINFO;
case ORDER_MIPS_OPTIONS:
return llvm::ELF::PT_LOAD;
default:
return TargetLayout<ELFT>::getSegmentType(section);
}
}
template <class ELFT> uint64_t MipsTargetLayout<ELFT>::getGPAddr() {
std::call_once(_gpOnce, [this]() {
if (AtomLayout *a = this->findAbsoluteAtom("_gp"))
_gpAddr = a->_virtualAddr;
});
return _gpAddr;
}
template <class ELFT>
typename TargetLayout<ELFT>::SectionOrder
MipsTargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType,
int32_t contentPermissions) {
if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text")))
return TargetLayout<ELFT>::ORDER_TEXT;
return TargetLayout<ELFT>::getSectionOrder(name, contentType,
contentPermissions);
}
template <class ELFT>
unique_bump_ptr<RelocationTable<ELFT>>
MipsTargetLayout<ELFT>::createRelocationTable(StringRef name, int32_t order) {
return unique_bump_ptr<RelocationTable<ELFT>>(new (
this->_allocator) MipsRelocationTable<ELFT>(this->_ctx, name, order));
}
template <class ELFT>
uint64_t MipsTargetLayout<ELFT>::getLookupSectionFlags(
const OutputSection<ELFT> *os) const {
uint64_t flags = TargetLayout<ELFT>::getLookupSectionFlags(os);
return flags & ~llvm::ELF::SHF_MIPS_NOSTRIP;
}
template class MipsTargetLayout<ELF32LE>;
template class MipsTargetLayout<ELF64LE>;
} // end namespace elf
} // end namespace lld

View File

@ -25,10 +25,7 @@ public:
ORDER_MIPS_OPTIONS
};
MipsTargetLayout(MipsLinkingContext &ctx)
: TargetLayout<ELFT>(ctx),
_gotSection(new (this->_allocator) MipsGOTSection<ELFT>(ctx)),
_pltSection(new (this->_allocator) MipsPLTSection<ELFT>(ctx)) {}
MipsTargetLayout(MipsLinkingContext &ctx);
const MipsGOTSection<ELFT> &getGOTSection() const { return *_gotSection; }
const MipsPLTSection<ELFT> &getPLTSection() const { return *_pltSection; }
@ -36,60 +33,26 @@ public:
AtomSection<ELFT> *
createSection(StringRef name, int32_t type,
DefinedAtom::ContentPermissions permissions,
typename TargetLayout<ELFT>::SectionOrder order) override {
if (type == DefinedAtom::typeGOT && name == ".got")
return _gotSection;
if (type == DefinedAtom::typeStub && name == ".plt")
return _pltSection;
return TargetLayout<ELFT>::createSection(name, type, permissions, order);
}
typename TargetLayout<ELFT>::SectionOrder order) override;
typename TargetLayout<ELFT>::SegmentType
getSegmentType(Section<ELFT> *section) const override {
switch (section->order()) {
case ORDER_MIPS_REGINFO:
return llvm::ELF::PT_MIPS_REGINFO;
case ORDER_MIPS_OPTIONS:
return llvm::ELF::PT_LOAD;
default:
return TargetLayout<ELFT>::getSegmentType(section);
}
}
getSegmentType(Section<ELFT> *section) const override;
/// \brief GP offset relative to .got section.
uint64_t getGPOffset() const { return 0x7FF0; }
/// \brief Get '_gp' symbol address.
uint64_t getGPAddr() {
std::call_once(_gpOnce, [this]() {
if (AtomLayout *a = this->findAbsoluteAtom("_gp"))
_gpAddr = a->_virtualAddr;
});
return _gpAddr;
}
uint64_t getGPAddr();
/// \brief Return the section order for a input section
typename TargetLayout<ELFT>::SectionOrder
getSectionOrder(StringRef name, int32_t contentType,
int32_t contentPermissions) override {
if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text")))
return TargetLayout<ELFT>::ORDER_TEXT;
return TargetLayout<ELFT>::getSectionOrder(name, contentType,
contentPermissions);
}
int32_t contentPermissions) override;
protected:
unique_bump_ptr<RelocationTable<ELFT>>
createRelocationTable(StringRef name, int32_t order) override {
return unique_bump_ptr<RelocationTable<ELFT>>(new (
this->_allocator) MipsRelocationTable<ELFT>(this->_ctx, name, order));
}
uint64_t getLookupSectionFlags(const OutputSection<ELFT> *os) const override {
uint64_t flags = TargetLayout<ELFT>::getLookupSectionFlags(os);
return flags & ~llvm::ELF::SHF_MIPS_NOSTRIP;
}
createRelocationTable(StringRef name, int32_t order) override;
uint64_t getLookupSectionFlags(const OutputSection<ELFT> *os) const override;
private:
MipsGOTSection<ELFT> *_gotSection;