blob: bb3901010634f7c6d449a2aa6a41e7f2a357e1c7 [file] [log] [blame]
//===- lib/ReaderWriter/ELF/OutputELFWriter.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_OUTPUT_WRITER_H
#define LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
#include "ELFFile.h"
#include "TargetLayout.h"
#include "lld/Core/Writer.h"
#include "llvm/ADT/StringSet.h"
namespace lld {
class ELFLinkingContext;
namespace elf {
using namespace llvm;
using namespace llvm::object;
// OutputELFWriter Class
//
/// \brief This acts as the base class for all the ELF writers that are output
/// for emitting an ELF output file. This class also acts as a common class for
/// creating static and dynamic executables. All the function in this class
/// can be overridden and an appropriate writer be created
template<class ELFT>
class OutputELFWriter : public ELFWriter {
public:
typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
typedef Elf_Sym_Impl<ELFT> Elf_Sym;
typedef Elf_Dyn_Impl<ELFT> Elf_Dyn;
OutputELFWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout);
protected:
// build the sections that need to be created
virtual void createDefaultSections();
// Build all the output sections
void buildChunks(const File &file) override;
// Build the output file
virtual std::error_code buildOutput(const File &file);
// Setup the ELF header.
virtual std::error_code setELFHeader();
// Write the file to the path specified
std::error_code writeFile(const File &File, StringRef path) override;
// Write to the output file.
virtual std::error_code writeOutput(const File &file, StringRef path);
// Get the size of the output file that the linker would emit.
virtual uint64_t outputFileSize() const;
// Build the atom to address map, this has to be called
// before applying relocations
virtual void buildAtomToAddressMap(const File &file);
// Build the symbol table for static linking
virtual void buildStaticSymbolTable(const File &file);
// Build the dynamic symbol table for dynamic linking
virtual void buildDynamicSymbolTable(const File &file);
// Build the section header table
virtual void buildSectionHeaderTable();
// Assign sections that have no segments such as the symbol table,
// section header table, string table etc
virtual void assignSectionsWithNoSegments();
// Add any runtime files and their atoms to the output
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
// Finalize the default atom values
virtual void finalizeDefaultAtomValues();
// This is called by the write section to apply relocations
uint64_t addressOfAtom(const Atom *atom) override {
auto addr = _atomToAddressMap.find(atom);
return addr == _atomToAddressMap.end() ? 0 : addr->second;
}
// This is a hook for creating default dynamic entries
virtual void createDefaultDynamicEntries() {}
/// \brief Create symbol table.
virtual unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable();
/// \brief create dynamic table.
virtual unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable();
/// \brief create dynamic symbol table.
virtual unique_bump_ptr<DynamicSymbolTable<ELFT>>
createDynamicSymbolTable();
/// \brief Create entry in the dynamic symbols table for this atom.
virtual bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const {
return _layout.isReferencedByDefinedAtom(sla);
}
/// \brief Create DT_NEEDED dynamic tage for the shared library.
virtual bool isNeededTagRequired(const SharedLibraryAtom *sla) const {
return false;
}
/// \brief Process undefined symbols that left after resolution step.
virtual void processUndefinedSymbol(StringRef symName,
RuntimeFile<ELFT> &file) const;
/// \brief Assign addresses to atoms marking section's start and end.
void updateScopeAtomValues(StringRef sym, StringRef sec);
llvm::BumpPtrAllocator _alloc;
ELFLinkingContext &_ctx;
TargetHandler &_targetHandler;
typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress;
AtomToAddress _atomToAddressMap;
TargetLayout<ELFT> &_layout;
unique_bump_ptr<ELFHeader<ELFT>> _elfHeader;
unique_bump_ptr<ProgramHeader<ELFT>> _programHeader;
unique_bump_ptr<SymbolTable<ELFT>> _symtab;
unique_bump_ptr<StringTable<ELFT>> _strtab;
unique_bump_ptr<StringTable<ELFT>> _shstrtab;
unique_bump_ptr<SectionHeader<ELFT>> _shdrtab;
unique_bump_ptr<EHFrameHeader<ELFT>> _ehFrameHeader;
/// \name Dynamic sections.
/// @{
unique_bump_ptr<DynamicTable<ELFT>> _dynamicTable;
unique_bump_ptr<DynamicSymbolTable<ELFT>> _dynamicSymbolTable;
unique_bump_ptr<StringTable<ELFT>> _dynamicStringTable;
unique_bump_ptr<HashSection<ELFT>> _hashTable;
llvm::StringSet<> _soNeeded;
/// @}
private:
static StringRef maybeGetSOName(Node *node);
void updateScopeAtomValues(StringRef start, StringRef end, StringRef sec);
};
} // namespace elf
} // namespace lld
#endif // LLD_READER_WRITER_ELF_OUTPUT_WRITER_H