forked from OSchip/llvm-project
[Mips] Move MipsGOTPass implementation to the separate file.
llvm-svn: 198783
This commit is contained in:
parent
d839c82ac9
commit
6e0232ce59
|
@ -1,6 +1,7 @@
|
|||
add_lld_library(lldMipsELFTarget
|
||||
MipsLinkingContext.cpp
|
||||
MipsRelocationHandler.cpp
|
||||
MipsRelocationPass.cpp
|
||||
MipsTargetHandler.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "Atoms.h"
|
||||
#include "MipsLinkingContext.h"
|
||||
#include "MipsRelocationPass.h"
|
||||
#include "MipsTargetHandler.h"
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
@ -16,151 +17,6 @@
|
|||
using namespace lld;
|
||||
using namespace lld::elf;
|
||||
|
||||
namespace {
|
||||
|
||||
// Lazy resolver
|
||||
const uint8_t mipsGot0AtomContent[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
// Module pointer
|
||||
const uint8_t mipsGotModulePointerAtomContent[] = { 0x00, 0x00, 0x00, 0x80 };
|
||||
|
||||
/// \brief Abstract base class represent MIPS GOT entries.
|
||||
class MipsGOTAtom : public GOTAtom {
|
||||
public:
|
||||
MipsGOTAtom(const File &f) : GOTAtom(f, ".got") {}
|
||||
|
||||
virtual Alignment alignment() const { return Alignment(2); }
|
||||
};
|
||||
|
||||
/// \brief MIPS GOT entry initialized by zero.
|
||||
class MipsGOT0Atom : public MipsGOTAtom {
|
||||
public:
|
||||
MipsGOT0Atom(const File &f) : MipsGOTAtom(f) {}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return llvm::makeArrayRef(mipsGot0AtomContent);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief MIPS GOT entry initialized by zero.
|
||||
class MipsGOTModulePointerAtom : public MipsGOTAtom {
|
||||
public:
|
||||
MipsGOTModulePointerAtom(const File &f) : MipsGOTAtom(f) {}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
|
||||
}
|
||||
};
|
||||
|
||||
class MipsGOTPassFile : public SimpleFile {
|
||||
public:
|
||||
MipsGOTPassFile(const ELFLinkingContext &ctx)
|
||||
: SimpleFile("MipsGOTPassFile") {
|
||||
setOrdinal(ctx.getNextOrdinalAndIncrement());
|
||||
}
|
||||
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
};
|
||||
|
||||
class MipsGOTPass : public Pass {
|
||||
public:
|
||||
MipsGOTPass(MipsLinkingContext &context)
|
||||
: _file(context), _got0(new (_file._alloc) MipsGOT0Atom(_file)),
|
||||
_got1(new (_file._alloc) MipsGOTModulePointerAtom(_file)) {
|
||||
_localGotVector.push_back(_got0);
|
||||
_localGotVector.push_back(_got1);
|
||||
}
|
||||
|
||||
virtual void perform(std::unique_ptr<MutableFile> &mf) {
|
||||
// Process all references.
|
||||
for (const auto &atom : mf->defined())
|
||||
for (const auto &ref : *atom)
|
||||
handleReference(*atom, *ref);
|
||||
|
||||
uint64_t ordinal = 0;
|
||||
|
||||
for (auto &got : _localGotVector) {
|
||||
DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding L "
|
||||
<< got->name() << "\n");
|
||||
got->setOrdinal(ordinal++);
|
||||
mf->addAtom(*got);
|
||||
}
|
||||
|
||||
for (auto &got : _globalGotVector) {
|
||||
DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding G "
|
||||
<< got->name() << "\n");
|
||||
got->setOrdinal(ordinal++);
|
||||
mf->addAtom(*got);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief Owner of all the Atoms created by this pass.
|
||||
MipsGOTPassFile _file;
|
||||
|
||||
/// \brief GOT header entries.
|
||||
GOTAtom *_got0;
|
||||
GOTAtom *_got1;
|
||||
|
||||
/// \brief Map Atoms to their GOT entries.
|
||||
llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
|
||||
|
||||
/// \brief the list of local GOT atoms.
|
||||
std::vector<GOTAtom *> _localGotVector;
|
||||
|
||||
/// \brief the list of global GOT atoms.
|
||||
std::vector<GOTAtom *> _globalGotVector;
|
||||
|
||||
/// \brief Handle a specific reference.
|
||||
void handleReference(const DefinedAtom &atom, const Reference &ref) {
|
||||
if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
|
||||
return;
|
||||
assert(ref.kindArch() == Reference::KindArch::Mips);
|
||||
switch (ref.kindValue()) {
|
||||
case R_MIPS_GOT16:
|
||||
case R_MIPS_CALL16:
|
||||
handleGOT(ref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handleGOT(const Reference &ref) {
|
||||
const_cast<Reference &>(ref).setTarget(getEntry(ref.target()));
|
||||
}
|
||||
|
||||
const GOTAtom *getEntry(const Atom *a) {
|
||||
auto got = _gotMap.find(a);
|
||||
if (got != _gotMap.end())
|
||||
return got->second;
|
||||
|
||||
const DefinedAtom *da = dyn_cast<DefinedAtom>(a);
|
||||
bool isLocal = (da && da->scope() == Atom::scopeTranslationUnit);
|
||||
|
||||
auto ga = new (_file._alloc) MipsGOT0Atom(_file);
|
||||
_gotMap[a] = ga;
|
||||
if (isLocal)
|
||||
_localGotVector.push_back(ga);
|
||||
else {
|
||||
if (da)
|
||||
ga->addReferenceELF_Mips(R_MIPS_32, 0, a, 0);
|
||||
else
|
||||
ga->addReferenceELF_Mips(R_MIPS_NONE, 0, a, 0);
|
||||
_globalGotVector.push_back(ga);
|
||||
}
|
||||
|
||||
DEBUG_WITH_TYPE("MipsGOT", {
|
||||
ga->_name = "__got_";
|
||||
ga->_name += a->name();
|
||||
llvm::dbgs() << "[ GOT ] Create " << (isLocal ? "L " : "G ") << a->name()
|
||||
<< "\n";
|
||||
});
|
||||
|
||||
return ga;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
MipsLinkingContext::MipsLinkingContext(llvm::Triple triple)
|
||||
: ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new MipsTargetHandler(*this))) {}
|
||||
|
@ -181,13 +37,8 @@ bool MipsLinkingContext::isLittleEndian() const {
|
|||
}
|
||||
|
||||
void MipsLinkingContext::addPasses(PassManager &pm) {
|
||||
switch (getOutputELFType()) {
|
||||
case llvm::ELF::ET_DYN:
|
||||
pm.add(std::unique_ptr<Pass>(new MipsGOTPass(*this)));
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unhandled output file type");
|
||||
}
|
||||
|
||||
auto pass = createMipsRelocationPass(*this);
|
||||
if (pass)
|
||||
pm.add(std::move(pass));
|
||||
ELFLinkingContext::addPasses(pm);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
//===- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.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 "MipsRelocationPass.h"
|
||||
|
||||
#include "Atoms.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace lld;
|
||||
using namespace lld::elf;
|
||||
using namespace llvm::ELF;
|
||||
|
||||
// Lazy resolver
|
||||
const uint8_t mipsGot0AtomContent[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
// Module pointer
|
||||
const uint8_t mipsGotModulePointerAtomContent[] = { 0x00, 0x00, 0x00, 0x80 };
|
||||
|
||||
/// \brief Abstract base class represent MIPS GOT entries.
|
||||
class MipsGOTAtom : public GOTAtom {
|
||||
public:
|
||||
MipsGOTAtom(const File &f) : GOTAtom(f, ".got") {}
|
||||
|
||||
virtual Alignment alignment() const { return Alignment(2); }
|
||||
};
|
||||
|
||||
/// \brief MIPS GOT entry initialized by zero.
|
||||
class MipsGOT0Atom : public MipsGOTAtom {
|
||||
public:
|
||||
MipsGOT0Atom(const File &f) : MipsGOTAtom(f) {}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return llvm::makeArrayRef(mipsGot0AtomContent);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief MIPS GOT entry initialized by zero.
|
||||
class MipsGOTModulePointerAtom : public MipsGOTAtom {
|
||||
public:
|
||||
MipsGOTModulePointerAtom(const File &f) : MipsGOTAtom(f) {}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
|
||||
}
|
||||
};
|
||||
|
||||
class MipsGOTPassFile : public SimpleFile {
|
||||
public:
|
||||
MipsGOTPassFile(const ELFLinkingContext &ctx)
|
||||
: SimpleFile("MipsGOTPassFile") {
|
||||
setOrdinal(ctx.getNextOrdinalAndIncrement());
|
||||
}
|
||||
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
};
|
||||
|
||||
class MipsGOTPass : public Pass {
|
||||
public:
|
||||
MipsGOTPass(MipsLinkingContext &context)
|
||||
: _file(context), _got0(new (_file._alloc) MipsGOT0Atom(_file)),
|
||||
_got1(new (_file._alloc) MipsGOTModulePointerAtom(_file)) {
|
||||
_localGotVector.push_back(_got0);
|
||||
_localGotVector.push_back(_got1);
|
||||
}
|
||||
|
||||
virtual void perform(std::unique_ptr<MutableFile> &mf) {
|
||||
// Process all references.
|
||||
for (const auto &atom : mf->defined())
|
||||
for (const auto &ref : *atom)
|
||||
handleReference(*atom, *ref);
|
||||
|
||||
uint64_t ordinal = 0;
|
||||
|
||||
for (auto &got : _localGotVector) {
|
||||
DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding L "
|
||||
<< got->name() << "\n");
|
||||
got->setOrdinal(ordinal++);
|
||||
mf->addAtom(*got);
|
||||
}
|
||||
|
||||
for (auto &got : _globalGotVector) {
|
||||
DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding G "
|
||||
<< got->name() << "\n");
|
||||
got->setOrdinal(ordinal++);
|
||||
mf->addAtom(*got);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief Owner of all the Atoms created by this pass.
|
||||
MipsGOTPassFile _file;
|
||||
|
||||
/// \brief GOT header entries.
|
||||
GOTAtom *_got0;
|
||||
GOTAtom *_got1;
|
||||
|
||||
/// \brief Map Atoms to their GOT entries.
|
||||
llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
|
||||
|
||||
/// \brief the list of local GOT atoms.
|
||||
std::vector<GOTAtom *> _localGotVector;
|
||||
|
||||
/// \brief the list of global GOT atoms.
|
||||
std::vector<GOTAtom *> _globalGotVector;
|
||||
|
||||
/// \brief Handle a specific reference.
|
||||
void handleReference(const DefinedAtom &atom, const Reference &ref) {
|
||||
if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
|
||||
return;
|
||||
assert(ref.kindArch() == Reference::KindArch::Mips);
|
||||
switch (ref.kindValue()) {
|
||||
case R_MIPS_GOT16:
|
||||
case R_MIPS_CALL16:
|
||||
handleGOT(ref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handleGOT(const Reference &ref) {
|
||||
const_cast<Reference &>(ref).setTarget(getEntry(ref.target()));
|
||||
}
|
||||
|
||||
const GOTAtom *getEntry(const Atom *a) {
|
||||
auto got = _gotMap.find(a);
|
||||
if (got != _gotMap.end())
|
||||
return got->second;
|
||||
|
||||
const DefinedAtom *da = dyn_cast<DefinedAtom>(a);
|
||||
bool isLocal = (da && da->scope() == Atom::scopeTranslationUnit);
|
||||
|
||||
auto ga = new (_file._alloc) MipsGOT0Atom(_file);
|
||||
_gotMap[a] = ga;
|
||||
if (isLocal)
|
||||
_localGotVector.push_back(ga);
|
||||
else {
|
||||
if (da)
|
||||
ga->addReferenceELF_Mips(R_MIPS_32, 0, a, 0);
|
||||
else
|
||||
ga->addReferenceELF_Mips(R_MIPS_NONE, 0, a, 0);
|
||||
_globalGotVector.push_back(ga);
|
||||
}
|
||||
|
||||
DEBUG_WITH_TYPE("MipsGOT", {
|
||||
ga->_name = "__got_";
|
||||
ga->_name += a->name();
|
||||
llvm::dbgs() << "[ GOT ] Create " << (isLocal ? "L " : "G ") << a->name()
|
||||
<< "\n";
|
||||
});
|
||||
|
||||
return ga;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
std::unique_ptr<Pass>
|
||||
lld::elf::createMipsRelocationPass(MipsLinkingContext &ctx) {
|
||||
switch (ctx.getOutputELFType()) {
|
||||
case llvm::ELF::ET_EXEC:
|
||||
case llvm::ELF::ET_DYN:
|
||||
return std::unique_ptr<Pass>(new MipsGOTPass(ctx));
|
||||
case llvm::ELF::ET_REL:
|
||||
return std::unique_ptr<Pass>();
|
||||
default:
|
||||
llvm_unreachable("Unhandled output file type");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//===- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.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_RELOCATION_PASS_H
|
||||
#define LLD_READER_WRITER_ELF_MIPS_RELOCATION_PASS_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace lld {
|
||||
class Pass;
|
||||
|
||||
namespace elf {
|
||||
class MipsLinkingContext;
|
||||
|
||||
std::unique_ptr<Pass> createMipsRelocationPass(MipsLinkingContext &ctx);
|
||||
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue