[lld] r197342 - Linking of shared libraries for MIPS little-endian 32-bit target.
Simon Atanasyan
simon at atanasyan.com
Sun Dec 15 04:57:29 PST 2013
Author: atanasyan
Date: Sun Dec 15 06:57:28 2013
New Revision: 197342
URL: http://llvm.org/viewvc/llvm-project?rev=197342&view=rev
Log:
Linking of shared libraries for MIPS little-endian 32-bit target.
The following are the most significant peculiarities of MIPS target:
- MIPS ABI requires some special tags in the dynamic table.
- GOT consists of two parts local and global. The local part contains
entries refer locally visible symbols. The global part contains entries
refer global symbols.
- Entries in the .dynsym section which have corresponded entries in the
GOT should be:
* Emitted at the end of .dynsym section
* Sorted accordingly to theirs GOT counterparts
- There are "paired" relocations. One or more R_MIPS_HI16 and R_MIPS_GOT16
relocations should be followed by R_MIPS_LO16 relocation. To calculate
result of R_MIPS_HI16 and R_MIPS_GOT16 relocations we need to combine
addends from these relocations and paired R_MIPS_LO16 relocation.
The patch reviewed by Michael Spencer, Shankar Easwaran, Rui Ueyama.
http://llvm-reviews.chandlerc.com/D2156
Added:
lld/trunk/lib/ReaderWriter/ELF/Mips/
lld/trunk/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTarget.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
lld/trunk/test/elf/Mips/
lld/trunk/test/elf/Mips/Inputs/
lld/trunk/test/elf/Mips/Inputs/dynobj.c
lld/trunk/test/elf/Mips/Inputs/dynobj.o
lld/trunk/test/elf/Mips/dynlib-dynamic.test
lld/trunk/test/elf/Mips/dynlib-dynsym.test
lld/trunk/test/elf/Mips/dynlib-fileheader.test
lld/trunk/test/elf/Mips/dynlib-gotsym.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h
lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h
lld/trunk/lib/ReaderWriter/ELF/Targets.h
lld/trunk/test/elf/phdr.test
Modified: lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt Sun Dec 15 06:57:28 2013
@@ -7,6 +7,7 @@ add_lld_library(lldELF
target_link_libraries(lldELF
lldHexagonELFTarget
+ lldMipsELFTarget
lldPPCELFTarget
lldPasses
lldReaderWriter
Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h Sun Dec 15 06:57:28 2013
@@ -58,6 +58,24 @@ public:
/// \brief allocate Commons, some architectures may move small common
/// symbols over to small data, this would also be used
void allocateCommons() {}
+
+ /// \brief create dynamic table
+ LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable() {
+ return LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>)(
+ new (_alloc) DynamicTable<ELFT>(
+ this->_context, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
+ }
+
+ /// \brief create dynamic symbol table
+ LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) createDynamicSymbolTable() {
+ return LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>)(
+ new (_alloc) DynamicSymbolTable<ELFT>(
+ this->_context, ".dynsym",
+ DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
+ }
+
+private:
+ llvm::BumpPtrAllocator _alloc;
};
} // end namespace elf
} // end namespace lld
Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Sun Dec 15 06:57:28 2013
@@ -67,6 +67,8 @@ uint16_t ELFLinkingContext::getOutputMac
return llvm::ELF::EM_X86_64;
case llvm::Triple::hexagon:
return llvm::ELF::EM_HEXAGON;
+ case llvm::Triple::mipsel:
+ return llvm::ELF::EM_MIPS;
case llvm::Triple::ppc:
return llvm::ELF::EM_PPC;
default:
@@ -124,6 +126,9 @@ ELFLinkingContext::create(llvm::Triple t
case llvm::Triple::hexagon:
return std::unique_ptr<ELFLinkingContext>(
new lld::elf::HexagonLinkingContext(triple));
+ case llvm::Triple::mipsel:
+ return std::unique_ptr<ELFLinkingContext>(
+ new lld::elf::MipsLinkingContext(triple));
case llvm::Triple::ppc:
return std::unique_ptr<ELFLinkingContext>(
new lld::elf::PPCLinkingContext(triple));
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/CMakeLists.txt?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/CMakeLists.txt Sun Dec 15 06:57:28 2013
@@ -0,0 +1,9 @@
+add_lld_library(lldMipsELFTarget
+ MipsLinkingContext.cpp
+ MipsRelocationHandler.cpp
+ MipsTargetHandler.cpp
+ )
+
+target_link_libraries(lldMipsELFTarget
+ lldCore
+ )
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp Sun Dec 15 06:57:28 2013
@@ -0,0 +1,230 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp -------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Atoms.h"
+#include "MipsLinkingContext.h"
+#include "MipsTargetHandler.h"
+
+#include "llvm/ADT/StringSwitch.h"
+
+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(ctx, "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) {
+ switch (ref.kind()) {
+ 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->addReference(R_MIPS_32, 0, a, 0);
+ else
+ ga->addReference(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))) {}
+
+MipsTargetLayout<Mips32ElELFType> &MipsLinkingContext::getTargetLayout() {
+ auto &layout = getTargetHandler<Mips32ElELFType>().targetLayout();
+ return static_cast<MipsTargetLayout<Mips32ElELFType> &>(layout);
+}
+
+const MipsTargetLayout<Mips32ElELFType> &
+MipsLinkingContext::getTargetLayout() const {
+ auto &layout = getTargetHandler<Mips32ElELFType>().targetLayout();
+ return static_cast<MipsTargetLayout<Mips32ElELFType> &>(layout);
+}
+
+bool MipsLinkingContext::isLittleEndian() const {
+ return Mips32ElELFType::TargetEndianness == llvm::support::little;
+}
+
+#undef LLD_CASE
+#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
+
+ErrorOr<Reference::Kind>
+MipsLinkingContext::relocKindFromString(StringRef str) const {
+ int32_t ret = llvm::StringSwitch<int32_t>(str)
+ LLD_CASE(R_MIPS_NONE)
+ LLD_CASE(R_MIPS_32)
+ LLD_CASE(R_MIPS_HI16)
+ LLD_CASE(R_MIPS_LO16)
+ LLD_CASE(R_MIPS_GOT16)
+ LLD_CASE(R_MIPS_CALL16)
+ LLD_CASE(R_MIPS_JALR)
+ .Default(-1);
+
+ if (ret == -1)
+ return make_error_code(YamlReaderError::illegal_value);
+ return ret;
+}
+
+#undef LLD_CASE
+#define LLD_CASE(name) \
+ case llvm::ELF::name: \
+ return std::string(#name);
+
+ErrorOr<std::string>
+MipsLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
+ switch (kind) {
+ LLD_CASE(R_MIPS_NONE)
+ LLD_CASE(R_MIPS_32)
+ LLD_CASE(R_MIPS_HI16)
+ LLD_CASE(R_MIPS_LO16)
+ LLD_CASE(R_MIPS_GOT16)
+ LLD_CASE(R_MIPS_CALL16)
+ LLD_CASE(R_MIPS_JALR)
+ }
+
+ return make_error_code(YamlReaderError::illegal_value);
+}
+
+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");
+ }
+
+ ELFLinkingContext::addPasses(pm);
+}
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h Sun Dec 15 06:57:28 2013
@@ -0,0 +1,38 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsLinkingContext.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_LINKING_CONTEXT_H
+#define LLD_READER_WRITER_ELF_MIPS_LINKING_CONTEXT_H
+
+#include "lld/ReaderWriter/ELFLinkingContext.h"
+
+namespace lld {
+namespace elf {
+
+typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ElELFType;
+
+template <class ELFType> class MipsTargetLayout;
+
+class MipsLinkingContext LLVM_FINAL : public ELFLinkingContext {
+public:
+ MipsLinkingContext(llvm::Triple triple);
+
+ MipsTargetLayout<Mips32ElELFType> &getTargetLayout();
+ const MipsTargetLayout<Mips32ElELFType> &getTargetLayout() const;
+
+ // ELFLinkingContext
+ virtual bool isLittleEndian() const;
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
+ virtual void addPasses(PassManager &pm);
+};
+
+} // elf
+} // lld
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Sun Dec 15 06:57:28 2013
@@ -0,0 +1,189 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp ----------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsTargetHandler.h"
+#include "MipsLinkingContext.h"
+#include "MipsRelocationHandler.h"
+
+#include "lld/ReaderWriter/RelocationHelperFunctions.h"
+
+using namespace lld;
+using namespace elf;
+using namespace llvm::ELF;
+
+namespace {
+
+inline void applyReloc(uint8_t *location, uint32_t result) {
+ auto target = reinterpret_cast<llvm::support::ulittle32_t *>(location);
+ *target = result | *target;
+}
+
+/// \brief Calculate AHL value combines addends from 'hi' and 'lo' relocations.
+inline int64_t calcAHL(int64_t AHI, int64_t ALO) {
+ AHI &= 0xffff;
+ ALO &= 0xffff;
+ return (AHI << 16) + (int16_t)ALO;
+}
+
+/// \brief R_MIPS_32
+/// local/external: word32 S + A (truncate)
+void reloc32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
+ uint32_t result = (uint32_t)(S + A);
+ applyReloc(location, result);
+}
+
+/// \brief R_MIPS_HI16
+/// local/external: hi16 (AHL + S) - (short)(AHL + S) (truncate)
+/// _gp_disp : hi16 (AHL + GP - P) - (short)(AHL + GP - P) (verify)
+void relocHi16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
+ uint64_t GP, bool isGPDisp) {
+ int32_t result = 0;
+
+ if (isGPDisp)
+ result = (AHL + GP - P) - (int16_t)(AHL + GP - P);
+ else
+ result = (AHL + S) - (int16_t)(AHL + S);
+
+ result = lld::scatterBits<uint32_t>(result >> 16, 0xffff);
+ applyReloc(location, result);
+}
+
+/// \brief R_MIPS_LO16
+/// local/external: lo16 AHL + S (truncate)
+/// _gp_disp : lo16 AHL + GP - P + 4 (verify)
+void relocLo16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
+ uint64_t GP, bool isGPDisp) {
+ int32_t result = 0;
+
+ if (isGPDisp)
+ result = AHL + GP - P + 4;
+ else
+ result = AHL + S;
+
+ result = lld::scatterBits<uint32_t>(result, 0xffff);
+ applyReloc(location, result);
+}
+
+/// \brief R_MIPS_GOT16
+/// local/external: rel16 G (verify)
+void relocGOT16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
+ uint64_t GP) {
+ // FIXME (simon): for local sym put high 16 bit of AHL to the GOT
+ int32_t G = (int32_t)(S - GP);
+ int32_t result = lld::scatterBits<uint32_t>(G, 0xffff);
+ applyReloc(location, result);
+}
+
+/// \brief R_MIPS_CALL16
+/// external: rel16 G (verify)
+void relocCall16(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
+ uint64_t GP) {
+ int32_t G = (int32_t)(S - GP);
+ int32_t result = lld::scatterBits<uint32_t>(G, 0xffff);
+ applyReloc(location, result);
+}
+
+} // end anon namespace
+
+MipsTargetRelocationHandler::MipsTargetRelocationHandler(
+ const MipsLinkingContext &context, const MipsTargetHandler &handler)
+ : _context(context), _targetHandler(handler) {}
+
+void
+MipsTargetRelocationHandler::savePairedRelocation(const lld::AtomLayout &atom,
+ const Reference &ref) const {
+ auto pi = _pairedRelocations.find(&atom);
+ if (pi == _pairedRelocations.end())
+ pi = _pairedRelocations.emplace(&atom, PairedRelocationsT()).first;
+
+ pi->second.push_back(&ref);
+}
+
+void MipsTargetRelocationHandler::applyPairedRelocations(
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
+ int64_t loAddend) const {
+ auto pi = _pairedRelocations.find(&atom);
+ if (pi == _pairedRelocations.end())
+ return;
+
+ for (auto ri : pi->second) {
+ uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
+ uint8_t *location = atomContent + ri->offsetInAtom();
+ uint64_t targetVAddress = writer.addressOfAtom(ri->target());
+ uint64_t relocVAddress = atom._virtualAddr + ri->offsetInAtom();
+
+ int64_t ahl = calcAHL(ri->addend(), loAddend);
+
+ switch (ri->kind()) {
+ case R_MIPS_HI16:
+ relocHi16(location, relocVAddress, targetVAddress, ahl,
+ _targetHandler.getGPDispSymAddr(),
+ ri->target()->name() == "_gp_disp");
+ break;
+ case R_MIPS_GOT16:
+ relocGOT16(location, relocVAddress, targetVAddress, ahl,
+ _targetHandler.getGPDispSymAddr());
+ break;
+ default:
+ llvm_unreachable("Unknown type of paired relocation.");
+ }
+ }
+
+ _pairedRelocations.erase(pi);
+}
+
+error_code MipsTargetRelocationHandler::applyRelocation(
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
+ const Reference &ref) const {
+ uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
+ uint8_t *location = atomContent + ref.offsetInAtom();
+ uint64_t targetVAddress = writer.addressOfAtom(ref.target());
+ uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+
+ switch (ref.kind()) {
+ case R_MIPS_NONE:
+ break;
+ case R_MIPS_32:
+ reloc32(location, relocVAddress, targetVAddress, ref.addend());
+ break;
+ case R_MIPS_HI16:
+ savePairedRelocation(atom, ref);
+ break;
+ case R_MIPS_LO16:
+ relocLo16(location, relocVAddress, targetVAddress, calcAHL(0, ref.addend()),
+ _targetHandler.getGPDispSymAddr(),
+ ref.target()->name() == "_gp_disp");
+ applyPairedRelocations(writer, buf, atom, ref.addend());
+ break;
+ case R_MIPS_GOT16:
+ savePairedRelocation(atom, ref);
+ break;
+ case R_MIPS_CALL16:
+ relocCall16(location, relocVAddress, targetVAddress, ref.addend(),
+ _targetHandler.getGPDispSymAddr());
+ break;
+ case R_MIPS_JALR:
+ // We do not do JALR optimization now.
+ break;
+ case lld::Reference::kindLayoutAfter:
+ case lld::Reference::kindLayoutBefore:
+ case lld::Reference::kindInGroup:
+ break;
+ default: {
+ std::string str;
+ llvm::raw_string_ostream s(str);
+ auto name = _context.stringFromRelocKind(ref.kind());
+ s << "Unhandled relocation: "
+ << (name ? *name : "<unknown>") << " (" << ref.kind() << ")";
+ llvm_unreachable(s.str().c_str());
+ }
+ }
+
+ return error_code::success();
+}
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h Sun Dec 15 06:57:28 2013
@@ -0,0 +1,49 @@
+//===- lld/ReaderWriter/ELF/Mips/MipsRelocationHandler.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_HANDLER_H
+#define LLD_READER_WRITER_ELF_MIPS_RELOCATION_HANDLER_H
+
+#include "MipsLinkingContext.h"
+
+namespace lld {
+namespace elf {
+
+class MipsTargetHandler;
+
+class MipsTargetRelocationHandler LLVM_FINAL
+ : public TargetRelocationHandler<Mips32ElELFType> {
+public:
+ MipsTargetRelocationHandler(const MipsLinkingContext &context,
+ const MipsTargetHandler &handler);
+
+ virtual error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
+ const lld::AtomLayout &,
+ const Reference &) const;
+
+private:
+ const MipsLinkingContext &_context;
+ const MipsTargetHandler &_targetHandler;
+
+ typedef std::vector<const Reference *> PairedRelocationsT;
+ typedef std::unordered_map<const lld::AtomLayout *, PairedRelocationsT>
+ PairedRelocationMapT;
+
+ mutable PairedRelocationMapT _pairedRelocations;
+
+ void savePairedRelocation(const lld::AtomLayout &atom,
+ const Reference &ref) const;
+ void applyPairedRelocations(ELFWriter &writer, llvm::FileOutputBuffer &buf,
+ const lld::AtomLayout &atom,
+ int64_t loAddend) const;
+};
+
+} // elf
+} // lld
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h Sun Dec 15 06:57:28 2013
@@ -0,0 +1,80 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.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_SECTION_CHUNKS_H
+#define LLD_READER_WRITER_ELF_MIPS_SECTION_CHUNKS_H
+
+namespace lld {
+namespace elf {
+
+template <typename ELFT> class MipsTargetLayout;
+class MipsLinkingContext;
+
+/// \brief Handle Mips GOT section
+template <class ELFType> class MipsGOTSection : public AtomSection<ELFType> {
+public:
+ MipsGOTSection(const MipsLinkingContext &context)
+ : AtomSection<ELFType>(context, ".got", DefinedAtom::typeGOT,
+ DefinedAtom::permRW_,
+ MipsTargetLayout<ELFType>::ORDER_GOT),
+ _globalCount(0) {
+ this->_flags |= SHF_MIPS_GPREL;
+ this->_align2 = 4;
+ }
+
+ /// \brief Number of local GOT entries.
+ std::size_t getLocalCount() const {
+ return this->_atoms.size() - _globalCount;
+ }
+
+ /// \brief Number of global GOT entries.
+ std::size_t getGlobalCount() const { return _globalCount; }
+
+ /// \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);
+
+ if (ia != _posMap.end() && ib != _posMap.end())
+ return ia->second < ib->second;
+
+ return ia == _posMap.end() && ib != _posMap.end();
+ }
+
+ virtual const lld::AtomLayout &appendAtom(const Atom *atom) {
+ const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
+
+ const Atom *ta = nullptr;
+ for (const auto &r : *da) {
+ if (r->kind() == llvm::ELF::R_MIPS_32 ||
+ r->kind() == llvm::ELF::R_MIPS_NONE) {
+ ta = r->target();
+ break;
+ }
+ }
+
+ if (ta) {
+ _posMap[ta] = _posMap.size();
+ ++_globalCount;
+ }
+
+ return AtomSection<ELFType>::appendAtom(atom);
+ }
+
+private:
+ /// \brief Number of global GOT entries.
+ std::size_t _globalCount;
+
+ /// \brief Map Atoms to their GOT entry index.
+ llvm::DenseMap<const Atom *, std::size_t> _posMap;
+};
+
+} // elf
+} // lld
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTarget.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTarget.h?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTarget.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTarget.h Sun Dec 15 06:57:28 2013
@@ -0,0 +1,10 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsTarget.h -----------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsLinkingContext.h"
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp Sun Dec 15 06:57:28 2013
@@ -0,0 +1,175 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp --------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "File.h"
+#include "MipsLinkingContext.h"
+#include "MipsTargetHandler.h"
+
+using namespace lld;
+using namespace elf;
+
+namespace {
+
+class MipsDynamicSymbolTable : public DynamicSymbolTable<Mips32ElELFType> {
+public:
+ MipsDynamicSymbolTable(const MipsLinkingContext &context)
+ : DynamicSymbolTable<Mips32ElELFType>(
+ context, ".dynsym",
+ DefaultLayout<Mips32ElELFType>::ORDER_DYNAMIC_SYMBOLS),
+ _layout(context.getTargetLayout()) {}
+
+ virtual void sortSymbols() {
+ std::stable_sort(_symbolTable.begin(), _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 _layout.getGOTSection().compare(A._atom, B._atom);
+ });
+ }
+
+private:
+ const MipsTargetLayout<Mips32ElELFType> &_layout;
+};
+
+class MipsDynamicTable : public DynamicTable<Mips32ElELFType> {
+public:
+ MipsDynamicTable(MipsLinkingContext &context)
+ : DynamicTable<Mips32ElELFType>(
+ context, ".dynamic", DefaultLayout<Mips32ElELFType>::ORDER_DYNAMIC),
+ _layout(context.getTargetLayout()) {}
+
+ virtual void createDefaultEntries() {
+ DynamicTable<Mips32ElELFType>::createDefaultEntries();
+
+ Elf_Dyn dyn;
+
+ // Version id for the Runtime Linker Interface.
+ dyn.d_un.d_val = 1;
+ dyn.d_tag = DT_MIPS_RLD_VERSION;
+ addEntry(dyn);
+
+ // MIPS flags.
+ dyn.d_un.d_val = RHF_NOTPOT;
+ dyn.d_tag = DT_MIPS_FLAGS;
+ addEntry(dyn);
+
+ // The base address of the segment.
+ dyn.d_un.d_ptr = 0;
+ dyn.d_tag = DT_MIPS_BASE_ADDRESS;
+ addEntry(dyn);
+
+ // Number of local global offset table entries.
+ dyn.d_un.d_val = 0;
+ dyn.d_tag = DT_MIPS_LOCAL_GOTNO;
+ _dt_localgot = addEntry(dyn);
+
+ // Number of entries in the .dynsym section.
+ dyn.d_un.d_val = 0;
+ dyn.d_tag = DT_MIPS_SYMTABNO;
+ _dt_symtabno = addEntry(dyn);
+
+ // The index of the first dynamic symbol table entry that corresponds
+ // to an entry in the global offset table.
+ dyn.d_un.d_val = 0;
+ dyn.d_tag = DT_MIPS_GOTSYM;
+ _dt_gotsym = addEntry(dyn);
+
+ // Address of the .got section.
+ dyn.d_un.d_val = 0;
+ dyn.d_tag = DT_PLTGOT;
+ _dt_pltgot = addEntry(dyn);
+ }
+
+ virtual void updateDynamicTable() {
+ DynamicTable<Mips32ElELFType>::updateDynamicTable();
+
+ auto &got = _layout.getGOTSection();
+
+ _entries[_dt_symtabno].d_un.d_val = getSymbolTable()->size();
+ _entries[_dt_gotsym].d_un.d_val =
+ getSymbolTable()->size() - got.getGlobalCount();
+ _entries[_dt_localgot].d_un.d_val = got.getLocalCount();
+ _entries[_dt_pltgot].d_un.d_ptr =
+ _layout.findOutputSection(".got")->virtualAddr();
+ }
+
+private:
+ MipsTargetLayout<Mips32ElELFType> &_layout;
+
+ std::size_t _dt_symtabno;
+ std::size_t _dt_localgot;
+ std::size_t _dt_gotsym;
+ std::size_t _dt_pltgot;
+};
+}
+
+MipsTargetHandler::MipsTargetHandler(MipsLinkingContext &context)
+ : DefaultTargetHandler(context), _targetLayout(context),
+ _relocationHandler(context, *this) {}
+
+uint64_t MipsTargetHandler::getGPDispSymAddr() const {
+ return _gpDispSymAtom ? _gpDispSymAtom->_virtualAddr : 0;
+}
+
+MipsTargetLayout<Mips32ElELFType> &MipsTargetHandler::targetLayout() {
+ return _targetLayout;
+}
+
+const MipsTargetRelocationHandler &
+MipsTargetHandler::getRelocationHandler() const {
+ return _relocationHandler;
+}
+
+LLD_UNIQUE_BUMP_PTR(DynamicTable<Mips32ElELFType>)
+MipsTargetHandler::createDynamicTable() {
+ return LLD_UNIQUE_BUMP_PTR(DynamicTable<Mips32ElELFType>)(
+ new (_alloc) MipsDynamicTable(
+ static_cast<MipsLinkingContext &>(_context)));
+}
+
+LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<Mips32ElELFType>)
+MipsTargetHandler::createDynamicSymbolTable() {
+ return LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<Mips32ElELFType>)(
+ new (_alloc) MipsDynamicSymbolTable(
+ static_cast<MipsLinkingContext &>(_context)));
+}
+
+bool MipsTargetHandler::createImplicitFiles(
+ std::vector<std::unique_ptr<File>> &result) {
+ typedef CRuntimeFile<Mips32ElELFType> RFile;
+ auto file = std::unique_ptr<RFile>(new RFile(_context, "MIPS runtime file"));
+
+ if (_context.isDynamic()) {
+ file->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
+ file->addAbsoluteAtom("_gp_disp");
+ }
+ result.push_back(std::move(file));
+ return true;
+}
+
+void MipsTargetHandler::finalizeSymbolValues() {
+ DefaultTargetHandler<Mips32ElELFType>::finalizeSymbolValues();
+
+ if (_context.isDynamic()) {
+ auto gotSection = _targetLayout.findOutputSection(".got");
+
+ auto gotAtomIter = _targetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
+ assert(gotAtomIter != _targetLayout.absoluteAtoms().end());
+ _gotSymAtom = (*gotAtomIter);
+ _gotSymAtom->_virtualAddr = gotSection ? gotSection->virtualAddr() : 0;
+
+ auto gpDispAtomIter = _targetLayout.findAbsoluteAtom("_gp_disp");
+ assert(gpDispAtomIter != _targetLayout.absoluteAtoms().end());
+ _gpDispSymAtom = (*gpDispAtomIter);
+ _gpDispSymAtom->_virtualAddr =
+ gotSection ? gotSection->virtualAddr() + 0x7FF0 : 0;
+ }
+}
Added: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h?rev=197342&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h Sun Dec 15 06:57:28 2013
@@ -0,0 +1,74 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler.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_TARGET_HANDLER_H
+#define LLD_READER_WRITER_ELF_MIPS_TARGET_HANDLER_H
+
+#include "DefaultTargetHandler.h"
+#include "MipsLinkingContext.h"
+#include "MipsRelocationHandler.h"
+#include "MipsSectionChunks.h"
+#include "TargetLayout.h"
+
+namespace lld {
+namespace elf {
+
+/// \brief TargetLayout for Mips
+template <class ELFType>
+class MipsTargetLayout LLVM_FINAL : public TargetLayout<ELFType> {
+public:
+ MipsTargetLayout(const MipsLinkingContext &ctx)
+ : TargetLayout<ELFType>(ctx),
+ _gotSection(new (_alloc) MipsGOTSection<ELFType>(ctx)) {}
+
+ const MipsGOTSection<ELFType> &getGOTSection() const { return *_gotSection; }
+
+ virtual AtomSection<ELFType> *
+ createSection(StringRef name, int32_t type,
+ DefinedAtom::ContentPermissions permissions,
+ Layout::SectionOrder order) {
+ if (type == DefinedAtom::typeGOT)
+ return _gotSection;
+ return DefaultLayout<ELFType>::createSection(name, type, permissions,
+ order);
+ }
+
+private:
+ llvm::BumpPtrAllocator _alloc;
+ MipsGOTSection<ELFType> *_gotSection;
+};
+
+/// \brief TargetHandler for Mips
+class MipsTargetHandler LLVM_FINAL
+ : public DefaultTargetHandler<Mips32ElELFType> {
+public:
+ MipsTargetHandler(MipsLinkingContext &targetInfo);
+
+ uint64_t getGPDispSymAddr() const;
+
+ virtual MipsTargetLayout<Mips32ElELFType> &targetLayout();
+ virtual const MipsTargetRelocationHandler &getRelocationHandler() const;
+ virtual LLD_UNIQUE_BUMP_PTR(DynamicTable<Mips32ElELFType>)
+ createDynamicTable();
+ virtual LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<Mips32ElELFType>)
+ createDynamicSymbolTable();
+ virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &result);
+ virtual void finalizeSymbolValues();
+
+private:
+ llvm::BumpPtrAllocator _alloc;
+ MipsTargetLayout<Mips32ElELFType> _targetLayout;
+ MipsTargetRelocationHandler _relocationHandler;
+ AtomLayout *_gotSymAtom;
+ AtomLayout *_gpDispSymAtom;
+};
+
+} // end namespace elf
+} // end namespace lld
+
+#endif
Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Sun Dec 15 06:57:28 2013
@@ -286,12 +286,10 @@ template <class ELFT> void OutputELFWrit
}
if (_context.isDynamic()) {
- _dynamicTable.reset(new (_alloc) DynamicTable<ELFT>(
- _context, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
+ _dynamicTable = std::move(_targetHandler.createDynamicTable());
_dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
_context, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true));
- _dynamicSymbolTable.reset(new (_alloc) DynamicSymbolTable<ELFT>(
- _context, ".dynsym", DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
+ _dynamicSymbolTable = std::move(_targetHandler.createDynamicSymbolTable());
_hashTable.reset(new (_alloc) HashSection<ELFT>(
_context, ".hash", DefaultLayout<ELFT>::ORDER_HASH));
// Set the hash table in the dynamic symbol table so that the entries in the
Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Sun Dec 15 06:57:28 2013
@@ -607,19 +607,10 @@ template<class ELFT>
class SymbolTable : public Section<ELFT> {
typedef typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Addr
Elf_Addr;
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
- struct SymbolEntry {
- SymbolEntry(const Atom *a, const Elf_Sym &sym,
- const lld::AtomLayout *layout)
- : _atom(a), _atomLayout(layout), _symbol(sym) {}
-
- const Atom *_atom;
- const lld::AtomLayout *_atomLayout;
- Elf_Sym _symbol;
- };
public:
+ typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
+
SymbolTable(const ELFLinkingContext &context, const char *str, int32_t order);
/// \brief set the number of entries that would exist in the symbol
@@ -629,6 +620,9 @@ public:
_stringSection->setNumEntries(numEntries);
}
+ /// \brief return number of entries
+ std::size_t size() const { return _symbolTable.size(); }
+
void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0,
const lld::AtomLayout *layout = nullptr);
@@ -669,6 +663,16 @@ public:
StringTable<ELFT> *getStringTable() const { return _stringSection; }
protected:
+ struct SymbolEntry {
+ SymbolEntry(const Atom *a, const Elf_Sym &sym,
+ const lld::AtomLayout *layout)
+ : _atom(a), _atomLayout(layout), _symbol(sym) {}
+
+ const Atom *_atom;
+ const lld::AtomLayout *_atomLayout;
+ Elf_Sym _symbol;
+ };
+
llvm::BumpPtrAllocator _symbolAllocate;
StringTable<ELFT> *_stringSection;
std::vector<SymbolEntry> _symbolTable;
@@ -982,10 +986,10 @@ private:
template <class ELFT> class HashSection;
template <class ELFT> class DynamicTable : public Section<ELFT> {
+public:
typedef llvm::object::Elf_Dyn_Impl<ELFT> Elf_Dyn;
typedef std::vector<Elf_Dyn> EntriesT;
-public:
DynamicTable(const ELFLinkingContext &context, StringRef str, int32_t order)
: Section<ELFT>(context, str) {
this->setOrder(order);
@@ -1020,7 +1024,7 @@ public:
std::memcpy(dest, _entries.data(), this->_fsize);
}
- void createDefaultEntries() {
+ virtual void createDefaultEntries() {
Elf_Dyn dyn;
dyn.d_un.d_val = 0;
@@ -1074,9 +1078,13 @@ public:
_dynamicSymbolTable = dynsym;
}
+ const DynamicSymbolTable<ELFT> *getSymbolTable() const {
+ return _dynamicSymbolTable;
+ }
+
void setHashTable(HashSection<ELFT> *hsh) { _hashTable = hsh; }
- void updateDynamicTable() {
+ virtual void updateDynamicTable() {
StringTable<ELFT> *dynamicStringTable =
_dynamicSymbolTable->getStringTable();
_entries[_dt_hash].d_un.d_val = _hashTable->virtualAddr();
@@ -1104,8 +1112,10 @@ public:
}
}
-private:
+protected:
EntriesT _entries;
+
+private:
std::size_t _dt_hash;
std::size_t _dt_strtab;
std::size_t _dt_symtab;
Modified: lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h Sun Dec 15 06:57:28 2013
@@ -20,6 +20,7 @@
#include "lld/Core/LLVM.h"
#include "lld/Core/LinkingContext.h"
+#include "lld/Core/STDExtras.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "llvm/ADT/Hashing.h"
@@ -30,6 +31,8 @@
namespace lld {
namespace elf {
+template <class ELFT> class DynamicTable;
+template <class ELFT> class DynamicSymbolTable;
template <class ELFT> class ELFDefinedAtom;
template <class ELFT> class ELFReference;
class ELFWriter;
@@ -117,8 +120,15 @@ public:
/// symbols over to small data, this would also be used
virtual void allocateCommons() = 0;
+ /// \brief create dynamic table
+ virtual LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) createDynamicTable() = 0;
+
+ /// \brief create dynamic symbol table
+ virtual LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>)
+ createDynamicSymbolTable() = 0;
+
protected:
- const ELFLinkingContext &_context;
+ ELFLinkingContext &_context;
};
} // end namespace elf
} // end namespace lld
Modified: lld/trunk/lib/ReaderWriter/ELF/Targets.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Targets.h?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Targets.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Targets.h Sun Dec 15 06:57:28 2013
@@ -11,6 +11,7 @@
#define LLD_READER_WRITER_ELF_TARGETS_H
#include "Hexagon/HexagonTarget.h"
+#include "Mips/MipsTarget.h"
#include "PPC/PPCTarget.h"
#include "X86/X86Target.h"
#include "X86_64/X86_64Target.h"
Added: lld/trunk/test/elf/Mips/Inputs/dynobj.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/Inputs/dynobj.c?rev=197342&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/Inputs/dynobj.c (added)
+++ lld/trunk/test/elf/Mips/Inputs/dynobj.c Sun Dec 15 06:57:28 2013
@@ -0,0 +1,14 @@
+// clang -O0 -EL -fPIC -target mipsel-linux-gnu -c dynobj.c -o dynobj.o
+int xyz(const char *);
+int abc(const char *);
+
+int bar(void)
+{
+ return 1;
+}
+
+int foo(void)
+{
+ bar();
+ return xyz("str1") + abc("str2");
+}
Added: lld/trunk/test/elf/Mips/Inputs/dynobj.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/Inputs/dynobj.o?rev=197342&view=auto
==============================================================================
Binary files lld/trunk/test/elf/Mips/Inputs/dynobj.o (added) and lld/trunk/test/elf/Mips/Inputs/dynobj.o Sun Dec 15 06:57:28 2013 differ
Added: lld/trunk/test/elf/Mips/dynlib-dynamic.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/dynlib-dynamic.test?rev=197342&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/dynlib-dynamic.test (added)
+++ lld/trunk/test/elf/Mips/dynlib-dynamic.test Sun Dec 15 06:57:28 2013
@@ -0,0 +1,27 @@
+# Check MIPS specific tags in the dynamic table.
+RUN: lld -flavor gnu -target mipsel -shared --noinhibit-exec \
+RUN: -o %t %p/Inputs/dynobj.o
+RUN: llvm-readobj -dynamic-table %t | FileCheck %s
+
+CHECK: Format: ELF32-mips
+CHECK: Arch: mipsel
+CHECK: AddressSize: 32bit
+CHECK: LoadName:
+CHECK: DynamicSection [ (15 entries)
+CHECK: Tag Type Name/Value
+CHECK: 0x00000004 HASH 0xE0
+CHECK: 0x00000005 STRTAB 0x158
+CHECK: 0x00000006 SYMTAB 0x108
+CHECK: 0x0000000A STRSZ 17 (bytes)
+CHECK: 0x0000000B SYMENT 16 (bytes)
+CHECK: 0x0000001A FINI_ARRAY 0x0
+CHECK: 0x0000001C FINI_ARRAYSZ 0 (bytes)
+CHECK: 0x70000001 MIPS_RLD_VERSION 1
+CHECK: 0x70000005 MIPS_FLAGS 0x2
+CHECK: 0x70000006 MIPS_BASE_ADDRESS 0x0
+CHECK: 0x7000000A MIPS_LOCAL_GOTNO 4
+CHECK: 0x70000011 MIPS_SYMTABNO 5
+CHECK: 0x70000013 MIPS_GOTSYM 0x2
+CHECK: 0x00000003 PLTGOT 0x1000
+CHECK: 0x00000000 NULL 0x0
+CHECK: ]
Added: lld/trunk/test/elf/Mips/dynlib-dynsym.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/dynlib-dynsym.test?rev=197342&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/dynlib-dynsym.test (added)
+++ lld/trunk/test/elf/Mips/dynlib-dynsym.test Sun Dec 15 06:57:28 2013
@@ -0,0 +1,118 @@
+# Check sorting of .dynsym content accordingly to .got section.
+RUN: lld -flavor gnu -target mipsel -shared --noinhibit-exec \
+RUN: -o %t %p/Inputs/dynobj.o
+RUN: llvm-readobj -dyn-symbols %t | FileCheck -check-prefix=CHECK-DYN %s
+
+RUN: lld -flavor gnu -target mipsel -shared --noinhibit-exec \
+RUN: --output-filetype=yaml -o %t %p/Inputs/dynobj.o
+RUN: FileCheck -check-prefix=CHECK-GOT %s < %t
+
+CHECK-DYN: Format: ELF32-mips
+CHECK-DYN: Arch: mipsel
+CHECK-DYN: AddressSize: 32bit
+CHECK-DYN: LoadName:
+CHECK-DYN: DynamicSymbols [
+CHECK-DYN: Symbol {
+CHECK-DYN: Name: @ (0)
+CHECK-DYN: Value: 0x0
+CHECK-DYN: Size: 0
+CHECK-DYN: Binding: Local (0x0)
+CHECK-DYN: Type: None (0x0)
+CHECK-DYN: Other: 0
+CHECK-DYN: Section: (0x0)
+CHECK-DYN: }
+CHECK-DYN: Symbol {
+CHECK-DYN: Name: foo@ (5)
+CHECK-DYN: Value: 0x194
+CHECK-DYN: Size: 156
+CHECK-DYN: Binding: Global (0x1)
+CHECK-DYN: Type: Function (0x2)
+CHECK-DYN: Other: 0
+CHECK-DYN: Section: .text (0x4)
+CHECK-DYN: }
+CHECK-DYN: Symbol {
+CHECK-DYN: Name: bar@ (1)
+CHECK-DYN: Value: 0x170
+CHECK-DYN: Size: 36
+CHECK-DYN: Binding: Global (0x1)
+CHECK-DYN: Type: Function (0x2)
+CHECK-DYN: Other: 0
+CHECK-DYN: Section: .text (0x4)
+CHECK-DYN: }
+CHECK-DYN: Symbol {
+CHECK-DYN: Name: xyz@ (9)
+CHECK-DYN: Value: 0x0
+CHECK-DYN: Size: 0
+CHECK-DYN: Binding: Global (0x1)
+CHECK-DYN: Type: None (0x0)
+CHECK-DYN: Other: 0
+CHECK-DYN: Section: (0x0)
+CHECK-DYN: }
+CHECK-DYN: Symbol {
+CHECK-DYN: Name: abc@ (13)
+CHECK-DYN: Value: 0x0
+CHECK-DYN: Size: 0
+CHECK-DYN: Binding: Global (0x1)
+CHECK-DYN: Type: None (0x0)
+CHECK-DYN: Other: 0
+CHECK-DYN: Section: (0x0)
+CHECK-DYN: }
+CHECK-DYN: ]
+
+CHECK-GOT: - type: got
+CHECK-GOT: content: [ 00, 00, 00, 00 ]
+CHECK-GOT: alignment: 2^2
+CHECK-GOT: section-choice: custom-required
+CHECK-GOT: section-name: .got
+CHECK-GOT: permissions: rw-
+CHECK-GOT: - type: got
+CHECK-GOT: content: [ 00, 00, 00, 80 ]
+CHECK-GOT: alignment: 2^2
+CHECK-GOT: section-choice: custom-required
+CHECK-GOT: section-name: .got
+CHECK-GOT: permissions: rw-
+CHECK-GOT: - ref-name: L004
+CHECK-GOT: type: got
+CHECK-GOT: content: [ 00, 00, 00, 00 ]
+CHECK-GOT: alignment: 2^2
+CHECK-GOT: section-choice: custom-required
+CHECK-GOT: section-name: .got
+CHECK-GOT: permissions: rw-
+CHECK-GOT: - ref-name: L006
+CHECK-GOT: type: got
+CHECK-GOT: content: [ 00, 00, 00, 00 ]
+CHECK-GOT: alignment: 2^2
+CHECK-GOT: section-choice: custom-required
+CHECK-GOT: section-name: .got
+CHECK-GOT: permissions: rw-
+CHECK-GOT: - ref-name: L003
+CHECK-GOT: type: got
+CHECK-GOT: content: [ 00, 00, 00, 00 ]
+CHECK-GOT: alignment: 2^2
+CHECK-GOT: section-choice: custom-required
+CHECK-GOT: section-name: .got
+CHECK-GOT: permissions: rw-
+CHECK-GOT: references:
+CHECK-GOT: - kind: R_MIPS_32
+CHECK-GOT: offset: 0
+CHECK-GOT: target: bar
+CHECK-GOT: - ref-name: L005
+CHECK-GOT: type: got
+CHECK-GOT: content: [ 00, 00, 00, 00 ]
+CHECK-GOT: alignment: 2^2
+CHECK-GOT: section-choice: custom-required
+CHECK-GOT: section-name: .got
+CHECK-GOT: permissions: rw-
+CHECK-GOT: - ref-name: L007
+CHECK-GOT: type: got
+CHECK-GOT: content: [ 00, 00, 00, 00 ]
+CHECK-GOT: alignment: 2^2
+CHECK-GOT: section-choice: custom-required
+CHECK-GOT: section-name: .got
+CHECK-GOT: permissions: rw-
+CHECK-GOT: - ref-name: L002
+CHECK-GOT: alignment: 2^4
+CHECK-GOT: references:
+CHECK-GOT: - kind: layout-after
+CHECK-GOT: offset: 0
+CHECK-GOT: target: bar
Added: lld/trunk/test/elf/Mips/dynlib-fileheader.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/dynlib-fileheader.test?rev=197342&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/dynlib-fileheader.test (added)
+++ lld/trunk/test/elf/Mips/dynlib-fileheader.test Sun Dec 15 06:57:28 2013
@@ -0,0 +1,33 @@
+RUN: lld -flavor gnu -target mipsel -shared --noinhibit-exec \
+RUN: -o %t %p/Inputs/dynobj.o
+RUN: llvm-readobj -file-headers %t | FileCheck %s
+
+CHECK: Format: ELF32-mips
+CHECK: Arch: mipsel
+CHECK: AddressSize: 32bit
+CHECK: LoadName:
+CHECK: ElfHeader {
+CHECK: Ident {
+CHECK: Magic: (7F 45 4C 46)
+CHECK: Class: 32-bit (0x1)
+CHECK: DataEncoding: LittleEndian (0x1)
+CHECK: FileVersion: 1
+CHECK: OS/ABI: SystemV (0x0)
+CHECK: ABIVersion: 0
+CHECK: Unused: (00 00 00 00 00 00 00)
+CHECK: }
+CHECK: Type: SharedObject (0x3)
+CHECK: Machine: EM_MIPS (0x8)
+CHECK: Version: 1
+CHECK: Entry: 0x170
+CHECK: ProgramHeaderOffset: 0x34
+CHECK: SectionHeaderOffset: 0x21C8
+CHECK: Flags [ (0x0)
+CHECK: ]
+CHECK: HeaderSize: 52
+CHECK: ProgramHeaderEntrySize: 32
+CHECK: ProgramHeaderCount: 5
+CHECK: SectionHeaderEntrySize: 40
+CHECK: SectionHeaderCount: 16
+CHECK: StringTableSectionIndex: 13
+CHECK:}
Added: lld/trunk/test/elf/Mips/dynlib-gotsym.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/dynlib-gotsym.test?rev=197342&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/dynlib-gotsym.test (added)
+++ lld/trunk/test/elf/Mips/dynlib-gotsym.test Sun Dec 15 06:57:28 2013
@@ -0,0 +1,11 @@
+# Check _gp_disp and GOT_OFFSET_TABLE value
+RUN: lld -flavor gnu -target mipsel -shared --noinhibit-exec \
+RUN: -o %t %p/Inputs/dynobj.o
+RUN: llvm-objdump -section-headers -t %t | FileCheck %s
+
+CHECK: Idx Name Size Address Type
+CHECK: 7 .got 0000001c 0000000000001000 DATA
+
+CHECK: SYMBOL TABLE:
+CHECK: 00001000 g *ABS* 00000000 _GLOBAL_OFFSET_TABLE_
+CHECK: 00008ff0 g *ABS* 00000000 _gp_disp
Modified: lld/trunk/test/elf/phdr.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/phdr.test?rev=197342&r1=197341&r2=197342&view=diff
==============================================================================
--- lld/trunk/test/elf/phdr.test (original)
+++ lld/trunk/test/elf/phdr.test Sun Dec 15 06:57:28 2013
@@ -92,7 +92,7 @@ I386-NEXT: MemSize: 64
I386-NEXT: Flags [ (0x4)
I386-NEXT: PF_R (0x4)
I386-NEXT: ]
-I386-NEXT: Alignment: 4
+I386-NEXT: Alignment: 2
I386-NEXT: }
X86_64: LOAD off 0x0000000000000000
More information about the llvm-commits
mailing list