diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 28 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 90 | ||||
-rw-r--r-- | lld/ELF/Writer.h | 61 |
3 files changed, 88 insertions, 91 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 99646305865..ab4fc2ec998 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -7,8 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "Driver.h" #include "Config.h" +#include "Driver.h" +#include "InputFiles.h" +#include "SymbolTable.h" #include "Writer.h" #include "llvm/ADT/STLExtras.h" @@ -116,25 +118,17 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { // Write the result. ObjectFileBase &FirstObj = *Symtab.ObjectFiles[0]; switch (FirstObj.kind()) { - case InputFile::Object32LEKind: { - Writer<object::ELF32LE> Out(&Symtab); - Out.write(Config->OutputFile); + case InputFile::Object32LEKind: + writeResult<object::ELF32LE>(&Symtab, Config->OutputFile); return; - } - case InputFile::Object32BEKind: { - Writer<object::ELF32BE> Out(&Symtab); - Out.write(Config->OutputFile); + case InputFile::Object32BEKind: + writeResult<object::ELF32BE>(&Symtab, Config->OutputFile); return; - } - case InputFile::Object64LEKind: { - Writer<object::ELF64LE> Out(&Symtab); - Out.write(Config->OutputFile); + case InputFile::Object64LEKind: + writeResult<object::ELF64LE>(&Symtab, Config->OutputFile); return; - } - case InputFile::Object64BEKind: { - Writer<object::ELF64BE> Out(&Symtab); - Out.write(Config->OutputFile); + case InputFile::Object64BEKind: + writeResult<object::ELF64BE>(&Symtab, Config->OutputFile); return; } - } } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 63dfec3d793..b7bfd462210 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -7,10 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "Writer.h" #include "Chunks.h" #include "Driver.h" +#include "SymbolTable.h" +#include "Writer.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/FileOutputBuffer.h" using namespace llvm; using namespace llvm::ELF; @@ -21,13 +23,77 @@ using namespace lld::elf2; static const int PageSize = 4096; +namespace { +// The writer writes a SymbolTable result to a file. +template <class ELFT> class Writer { +public: + typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; + Writer(SymbolTable *T, StringRef S) : Symtab(T), OutputPath(S) {} + void run(); + +private: + void createSections(); + void assignAddresses(); + void openFile(StringRef OutputPath); + void writeHeader(); + void writeSections(); + + SymbolTable *Symtab; + StringRef OutputPath; + std::unique_ptr<llvm::FileOutputBuffer> Buffer; + llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc; + std::vector<OutputSection *> OutputSections; + + uint64_t FileSize; + uint64_t SizeOfHeaders; + uintX_t SectionHeaderOff; + + std::vector<std::unique_ptr<Chunk>> Chunks; +}; +} // anonymous namespace + +namespace lld { +namespace elf2 { + +// OutputSection represents a section in an output file. It's a +// container of chunks. OutputSection and Chunk are 1:N relationship. +// Chunks cannot belong to more than one OutputSections. The writer +// creates multiple OutputSections and assign them unique, +// non-overlapping file offsets and VAs. +class OutputSection { +public: + OutputSection(StringRef Name) : Name(Name), Header({}) {} + void setVA(uint64_t); + void setFileOffset(uint64_t); + template <class ELFT> void addSectionChunk(SectionChunk<ELFT> *C); + std::vector<Chunk *> &getChunks() { return Chunks; } + template <class ELFT> + void writeHeaderTo(llvm::object::Elf_Shdr_Impl<ELFT> *SHdr); + + // Returns the size of the section in the output file. + uint64_t getSize() { return Header.sh_size; } + +private: + StringRef Name; + llvm::ELF::Elf64_Shdr Header; + std::vector<Chunk *> Chunks; +}; + template <class ELFT> -Writer<ELFT>::Writer(SymbolTable *Symtab) - : Symtab(Symtab) {} -template <class ELFT> Writer<ELFT>::~Writer() {} +void writeResult(SymbolTable *Symtab, StringRef Path) { + Writer<ELFT>(Symtab, Path).run(); +} + +template void writeResult<ELF32LE>(SymbolTable *, StringRef); +template void writeResult<ELF32BE>(SymbolTable *, StringRef); +template void writeResult<ELF64LE>(SymbolTable *, StringRef); +template void writeResult<ELF64BE>(SymbolTable *, StringRef); + +} // namespace elf2 +} // namespace lld // The main function of the writer. -template <class ELFT> void Writer<ELFT>::write(StringRef OutputPath) { +template <class ELFT> void Writer<ELFT>::run() { createSections(); assignAddresses(); openFile(OutputPath); @@ -171,17 +237,3 @@ template <class ELFT> void Writer<ELFT>::writeSections() { C->writeTo(Buf); } } - -namespace lld { -namespace elf2 { -template class Writer<ELF32LE>; -template class Writer<ELF32BE>; -template class Writer<ELF64LE>; -template class Writer<ELF64BE>; - -template void OutputSection::addSectionChunk<ELF32LE>(SectionChunk<ELF32LE> *); -template void OutputSection::addSectionChunk<ELF32BE>(SectionChunk<ELF32BE> *); -template void OutputSection::addSectionChunk<ELF64LE>(SectionChunk<ELF64LE> *); -template void OutputSection::addSectionChunk<ELF64BE>(SectionChunk<ELF64BE> *); -} -} diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h index 1feb68bdf4b..5302d6bf3a3 100644 --- a/lld/ELF/Writer.h +++ b/lld/ELF/Writer.h @@ -10,65 +10,16 @@ #ifndef LLD_ELF_WRITER_H #define LLD_ELF_WRITER_H -#include "Chunks.h" -#include "SymbolTable.h" -#include "llvm/Support/FileOutputBuffer.h" - namespace lld { namespace elf2 { -// OutputSection represents a section in an output file. It's a -// container of chunks. OutputSection and Chunk are 1:N relationship. -// Chunks cannot belong to more than one OutputSections. The writer -// creates multiple OutputSections and assign them unique, -// non-overlapping file offsets and VAs. -class OutputSection { -public: - OutputSection(StringRef Name) : Name(Name), Header({}) {} - void setVA(uint64_t); - void setFileOffset(uint64_t); - template <class ELFT> void addSectionChunk(SectionChunk<ELFT> *C); - std::vector<Chunk *> &getChunks() { return Chunks; } - template <class ELFT> - void writeHeaderTo(llvm::object::Elf_Shdr_Impl<ELFT> *SHdr); - - // Returns the size of the section in the output file. - uint64_t getSize() { return Header.sh_size; } - -private: - StringRef Name; - llvm::ELF::Elf64_Shdr Header; - std::vector<Chunk *> Chunks; -}; - -// The writer writes a SymbolTable result to a file. -template <class ELFT> class Writer { -public: - typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; - - explicit Writer(SymbolTable *Symtab); - ~Writer(); - void write(StringRef Path); - -private: - void createSections(); - void assignAddresses(); - void openFile(StringRef OutputPath); - void writeHeader(); - void writeSections(); - - SymbolTable *Symtab; - std::unique_ptr<llvm::FileOutputBuffer> Buffer; - llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc; - std::vector<OutputSection *> OutputSections; - uint64_t FileSize; - uint64_t SizeOfHeaders; - uintX_t SectionHeaderOff; +class OutputSection; +class SymbolTable; - std::vector<std::unique_ptr<Chunk>> Chunks; -}; +template <class ELFT> +void writeResult(SymbolTable *Symtab, StringRef Path); -} // namespace elf2 -} // namespace lld +} +} #endif |