[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:
Rui Ueyama 2013-06-16 17:14:58 +00:00
parent a97f12e00a
commit e96044a370
14 changed files with 78 additions and 46 deletions

View File

@ -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

View File

@ -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");

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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:

View File

@ -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;

View File

@ -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; }

View File

@ -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();

View File

@ -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:

View File

@ -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();

View File

@ -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;