forked from OSchip/llvm-project
154 lines
5.1 KiB
C++
154 lines
5.1 KiB
C++
//===- 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
|