[lld] Move AtomLayout from ELF to ReaderWriter so that it can be used by non-ELF writers.
Reviewers: Bigcheese CC: llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D977 llvm-svn: 184061
This commit is contained in:
parent
a97f12e00a
commit
e96044a370
|
@ -0,0 +1,41 @@
|
|||
//===- include/lld/ReaderWriter/AtomLayout.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_LAYOUT_H
|
||||
#define LLD_READER_WRITER_LAYOUT_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace lld {
|
||||
class Atom;
|
||||
|
||||
/// AtomLayouts are used by a writer to manage physical positions of atoms.
|
||||
/// AtomLayout has two positions; one is file offset, and the other is the
|
||||
/// address when loaded into memory.
|
||||
///
|
||||
/// Construction of AtomLayouts is usually a multi-pass process. When an atom
|
||||
/// is appended to a section, we don't know the starting address of the
|
||||
/// section. Thus, we have no choice but to store the offset from the
|
||||
/// beginning of the section as AtomLayout values. After all sections starting
|
||||
/// address are fixed, AtomLayout is revisited to get the offsets updated by
|
||||
/// adding the starting addresses of the section.
|
||||
struct AtomLayout {
|
||||
AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr)
|
||||
: _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {}
|
||||
|
||||
AtomLayout() : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {}
|
||||
|
||||
const Atom *_atom;
|
||||
uint64_t _fileOffset;
|
||||
uint64_t _virtualAddr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -149,10 +149,10 @@ public:
|
|||
struct FindByName {
|
||||
const std::string _name;
|
||||
FindByName(StringRef name) : _name(name) {}
|
||||
bool operator()(const AtomLayout *j) { return j->_atom->name() == _name; }
|
||||
bool operator()(const lld::AtomLayout *j) { return j->_atom->name() == _name; }
|
||||
};
|
||||
|
||||
typedef typename std::vector<AtomLayout *>::iterator AbsoluteAtomIterT;
|
||||
typedef typename std::vector<lld::AtomLayout *>::iterator AbsoluteAtomIterT;
|
||||
|
||||
DefaultLayout(const ELFTargetInfo &ti) : _targetInfo(ti) {}
|
||||
|
||||
|
@ -177,7 +177,7 @@ public:
|
|||
static bool hasOutputSegment(Section<ELFT> *section);
|
||||
|
||||
// Adds an atom to the section
|
||||
virtual ErrorOr<const AtomLayout &> addAtom(const Atom *atom);
|
||||
virtual ErrorOr<const lld::AtomLayout &> addAtom(const Atom *atom);
|
||||
|
||||
/// \brief Find an output Section given a section name.
|
||||
MergedSections<ELFT> *findOutputSection(StringRef name) {
|
||||
|
@ -304,7 +304,7 @@ private:
|
|||
ProgramHeader<ELFT> *_programHeader;
|
||||
LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _dynamicRelocationTable;
|
||||
LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _pltRelocationTable;
|
||||
std::vector<AtomLayout *> _absoluteAtoms;
|
||||
std::vector<lld::AtomLayout *> _absoluteAtoms;
|
||||
const ELFTargetInfo &_targetInfo;
|
||||
};
|
||||
|
||||
|
@ -488,7 +488,7 @@ AtomSection<ELFT> *DefaultLayout<ELFT>::getSection(
|
|||
}
|
||||
|
||||
template <class ELFT>
|
||||
ErrorOr<const AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom) {
|
||||
ErrorOr<const lld::AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom) {
|
||||
if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
|
||||
// HACK: Ignore undefined atoms. We need to adjust the interface so that
|
||||
// undefined atoms can still be included in the output symbol table for
|
||||
|
@ -513,8 +513,8 @@ ErrorOr<const AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom) {
|
|||
} else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
|
||||
// Absolute atoms are not part of any section, they are global for the whole
|
||||
// link
|
||||
_absoluteAtoms.push_back(
|
||||
new (_allocator) AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
|
||||
_absoluteAtoms.push_back(new (_allocator)
|
||||
lld::AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
|
||||
return *_absoluteAtoms.back();
|
||||
} else {
|
||||
llvm_unreachable("Only absolute / defined atoms can be added here");
|
||||
|
|
|
@ -214,7 +214,7 @@ int relocHexGOTREL_32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
|
|||
} // end anon namespace
|
||||
|
||||
ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation(
|
||||
ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
|
||||
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();
|
||||
|
|
|
@ -30,8 +30,8 @@ public:
|
|||
: _targetInfo(ti), _targetHandler(tH), _targetLayout(layout) {}
|
||||
|
||||
virtual ErrorOr<void>
|
||||
applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &,
|
||||
const Reference &) const;
|
||||
applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &, const Reference &) const;
|
||||
private:
|
||||
const HexagonTargetInfo &_targetInfo;
|
||||
const HexagonTargetHandler &_targetHandler;
|
||||
|
|
|
@ -36,11 +36,11 @@ public:
|
|||
/// \brief Does this section have an output segment.
|
||||
virtual bool hasOutputSegment() { return true; }
|
||||
|
||||
const AtomLayout &appendAtom(const Atom *atom) {
|
||||
const lld::AtomLayout &appendAtom(const Atom *atom) {
|
||||
const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
|
||||
DefinedAtom::Alignment atomAlign = definedAtom->alignment();
|
||||
uint64_t align2 = 1u << atomAlign.powerOf2;
|
||||
this->_atoms.push_back(new (this->_alloc) AtomLayout(atom, 0, 0));
|
||||
this->_atoms.push_back(new (this->_alloc) lld::AtomLayout(atom, 0, 0));
|
||||
// Set the section alignment to the largest alignment
|
||||
// std::max doesnot support uint64_t
|
||||
if (this->_align2 < align2)
|
||||
|
@ -54,7 +54,7 @@ template <class HexagonELFType>
|
|||
void SDataSection<HexagonELFType>::doPreFlight() {
|
||||
// sort the atoms on the alignments they have been set
|
||||
std::stable_sort(this->_atoms.begin(), this->_atoms.end(),
|
||||
[](const AtomLayout * A, const AtomLayout * B) {
|
||||
[](const lld::AtomLayout * A, const lld::AtomLayout * B) {
|
||||
const DefinedAtom *definedAtomA = cast<DefinedAtom>(A->_atom);
|
||||
const DefinedAtom *definedAtomB = cast<DefinedAtom>(B->_atom);
|
||||
int64_t align2A = 1 << definedAtomA->alignment().powerOf2;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define LLD_READER_WRITER_ELF_LAYOUT_H
|
||||
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/ReaderWriter/AtomLayout.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
|
@ -21,17 +22,6 @@
|
|||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
struct AtomLayout {
|
||||
AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr)
|
||||
: _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {
|
||||
}
|
||||
|
||||
AtomLayout() : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {}
|
||||
|
||||
const Atom *_atom;
|
||||
uint64_t _fileOffset;
|
||||
uint64_t _virtualAddr;
|
||||
};
|
||||
|
||||
/// \brief The ELFLayout is an abstract class for managing the final layout for
|
||||
/// the kind of binaries(Shared Libraries / Relocatables / Executables 0
|
||||
|
@ -51,7 +41,7 @@ public:
|
|||
/// \brief Append the Atom to the layout and create appropriate sections.
|
||||
/// \returns A reference to the atom layout or an error. The atom layout will
|
||||
/// be updated as linking progresses.
|
||||
virtual ErrorOr<const AtomLayout &> addAtom(const Atom *atom) = 0;
|
||||
virtual ErrorOr<const lld::AtomLayout &> addAtom(const Atom *atom) = 0;
|
||||
/// find the Atom Address in the current layout
|
||||
virtual bool findAtomAddrByName(StringRef name, uint64_t &addr) = 0;
|
||||
/// associates a section to a segment
|
||||
|
|
|
@ -36,7 +36,7 @@ int relocB24PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
|||
} // end anon namespace
|
||||
|
||||
ErrorOr<void> PPCTargetRelocationHandler::applyRelocation(
|
||||
ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
|
||||
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();
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
PPCTargetRelocationHandler(const PPCTargetInfo &ti) : _targetInfo(ti) {}
|
||||
|
||||
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const AtomLayout &,
|
||||
const lld::AtomLayout &,
|
||||
const Reference &)const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -183,7 +183,7 @@ public:
|
|||
// \brief Append an atom to a Section. The atom gets pushed into a vector
|
||||
// contains the atom, the atom file offset, the atom virtual address
|
||||
// the atom file offset is aligned appropriately as set by the Reader
|
||||
virtual const AtomLayout &appendAtom(const Atom *atom);
|
||||
virtual const lld::AtomLayout &appendAtom(const Atom *atom);
|
||||
|
||||
/// \brief Set the virtual address of each Atom in the Section. This
|
||||
/// routine gets called after the linker fixes up the virtual address
|
||||
|
@ -233,7 +233,7 @@ public:
|
|||
}
|
||||
|
||||
/// Atom Iterators
|
||||
typedef typename std::vector<AtomLayout *>::iterator atom_iter;
|
||||
typedef typename std::vector<lld::AtomLayout *>::iterator atom_iter;
|
||||
|
||||
range<atom_iter> atoms() { return _atoms; }
|
||||
|
||||
|
@ -247,7 +247,7 @@ protected:
|
|||
llvm::BumpPtrAllocator _alloc;
|
||||
int32_t _contentType;
|
||||
int32_t _contentPermissions;
|
||||
std::vector<AtomLayout *> _atoms;
|
||||
std::vector<lld::AtomLayout *> _atoms;
|
||||
};
|
||||
|
||||
/// Align the offset to the required modulus defined by the atom alignment
|
||||
|
@ -271,7 +271,7 @@ uint64_t AtomSection<ELFT>::alignOffset(uint64_t offset,
|
|||
// contains the atom, the atom file offset, the atom virtual address
|
||||
// the atom file offset is aligned appropriately as set by the Reader
|
||||
template <class ELFT>
|
||||
const AtomLayout &AtomSection<ELFT>::appendAtom(const Atom *atom) {
|
||||
const lld::AtomLayout &AtomSection<ELFT>::appendAtom(const Atom *atom) {
|
||||
Atom::Definition atomType = atom->definition();
|
||||
const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
|
||||
|
||||
|
@ -293,7 +293,7 @@ const AtomLayout &AtomSection<ELFT>::appendAtom(const Atom *atom) {
|
|||
case DefinedAtom::typeStub:
|
||||
case DefinedAtom::typeResolver:
|
||||
case DefinedAtom::typeTLVInitialData:
|
||||
_atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0));
|
||||
_atoms.push_back(new (_alloc) lld::AtomLayout(atom, fOffset, 0));
|
||||
this->_fsize = fOffset + definedAtom->size();
|
||||
this->_msize = mOffset + definedAtom->size();
|
||||
DEBUG_WITH_TYPE("Section",
|
||||
|
@ -304,7 +304,7 @@ const AtomLayout &AtomSection<ELFT>::appendAtom(const Atom *atom) {
|
|||
case DefinedAtom::typeTLVInitialZeroFill:
|
||||
case DefinedAtom::typeZeroFill:
|
||||
case DefinedAtom::typeZeroFillFast:
|
||||
_atoms.push_back(new (_alloc) AtomLayout(atom, mOffset, 0));
|
||||
_atoms.push_back(new (_alloc) lld::AtomLayout(atom, mOffset, 0));
|
||||
this->_msize = mOffset + definedAtom->size();
|
||||
break;
|
||||
default:
|
||||
|
@ -354,7 +354,7 @@ template <class ELFT>
|
|||
void AtomSection<ELFT>::write(ELFWriter *writer,
|
||||
llvm::FileOutputBuffer &buffer) {
|
||||
uint8_t *chunkBuffer = buffer.getBufferStart();
|
||||
parallel_for_each(_atoms.begin(), _atoms.end(), [&] (AtomLayout *ai) {
|
||||
parallel_for_each(_atoms.begin(), _atoms.end(), [&] (lld::AtomLayout *ai) {
|
||||
DEBUG_WITH_TYPE("Section",
|
||||
llvm::dbgs() << "Writing atom: " << ai->_atom->name()
|
||||
<< " | " << ai->_fileOffset << "\n");
|
||||
|
@ -602,13 +602,13 @@ class SymbolTable : public Section<ELFT> {
|
|||
|
||||
struct SymbolEntry {
|
||||
SymbolEntry(const Atom *a, const Elf_Sym &sym,
|
||||
const AtomLayout *layout) : _atom(a), _symbol(sym),
|
||||
_atomLayout(layout) {}
|
||||
const lld::AtomLayout *layout)
|
||||
: _atom(a), _symbol(sym), _atomLayout(layout) {}
|
||||
SymbolEntry() : _atom(nullptr) {}
|
||||
|
||||
const Atom *_atom;
|
||||
Elf_Sym _symbol;
|
||||
const AtomLayout *_atomLayout;
|
||||
const lld::AtomLayout *_atomLayout;
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -622,7 +622,7 @@ public:
|
|||
}
|
||||
|
||||
void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0,
|
||||
const AtomLayout *layout = nullptr);
|
||||
const lld::AtomLayout *layout = nullptr);
|
||||
|
||||
/// \brief Get the symbol table index for an Atom. If it's not in the symbol
|
||||
/// table, return STN_UNDEF.
|
||||
|
@ -786,7 +786,8 @@ void SymbolTable<ELFT>::addUndefinedAtom(Elf_Sym &sym,
|
|||
/// information
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::addSymbol(const Atom *atom, int32_t sectionIndex,
|
||||
uint64_t addr, const AtomLayout *atomLayout) {
|
||||
uint64_t addr,
|
||||
const lld::AtomLayout *atomLayout) {
|
||||
Elf_Sym symbol;
|
||||
|
||||
if (atom->name().empty())
|
||||
|
@ -876,7 +877,7 @@ public:
|
|||
// dont have their addresses known until addresses have been assigned
|
||||
// so lets update the symbol values after they have got assigned
|
||||
for (auto &ste: this->_symbolTable) {
|
||||
const AtomLayout *atomLayout = ste._atomLayout;
|
||||
const lld::AtomLayout *atomLayout = ste._atomLayout;
|
||||
if (!atomLayout)
|
||||
continue;
|
||||
ste._symbol.st_value = atomLayout->_virtualAddr;
|
||||
|
|
|
@ -71,8 +71,8 @@ public:
|
|||
template <class ELFT> class TargetRelocationHandler {
|
||||
public:
|
||||
virtual ErrorOr<void>
|
||||
applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &,
|
||||
const Reference &)const = 0;
|
||||
applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &, const Reference &) const = 0;
|
||||
|
||||
virtual int64_t relocAddend(const Reference &)const { return 0; }
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ int relocPC32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
|
|||
} // end anon namespace
|
||||
|
||||
ErrorOr<void> X86TargetRelocationHandler::applyRelocation(
|
||||
ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
|
||||
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();
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
X86TargetRelocationHandler(const X86TargetInfo &ti) : _targetInfo(ti) {}
|
||||
|
||||
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const AtomLayout &,
|
||||
const lld::AtomLayout &,
|
||||
const Reference &)const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -60,7 +60,7 @@ int64_t X86_64TargetRelocationHandler::relocAddend(const Reference &ref) const {
|
|||
}
|
||||
|
||||
ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||
ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
|
||||
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();
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
: _tlsSize(0), _targetInfo(ti) {}
|
||||
|
||||
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const AtomLayout &,
|
||||
const lld::AtomLayout &,
|
||||
const Reference &) const;
|
||||
|
||||
virtual int64_t relocAddend(const Reference &) const;
|
||||
|
|
Loading…
Reference in New Issue