[ELF] Chop the ELF prefix off of most things.
llvm-svn: 173838
diff --git a/lld/lib/ReaderWriter/ELF/Writer.cpp b/lld/lib/ReaderWriter/ELF/Writer.cpp
new file mode 100644
index 0000000..2318cd8
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/Writer.cpp
@@ -0,0 +1,341 @@
+//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/Writer.h"
+
+#include "DefaultLayout.h"
+#include "ExecutableAtoms.h"
+
+#include "lld/ReaderWriter/ELFTargetInfo.h"
+
+using namespace llvm;
+using namespace llvm::object;
+namespace lld {
+namespace elf {
+template<class ELFT>
+class ExecutableWriter;
+
+//===----------------------------------------------------------------------===//
+// ExecutableWriter Class
+//===----------------------------------------------------------------------===//
+template<class ELFT>
+class ExecutableWriter : public ELFWriter {
+public:
+ typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
+ typedef Elf_Sym_Impl<ELFT> Elf_Sym;
+
+ ExecutableWriter(const ELFTargetInfo &ti);
+
+private:
+ // build the sections that need to be created
+ void buildChunks(const File &file);
+ virtual error_code writeFile(const File &File, StringRef path);
+ void buildAtomToAddressMap();
+ void buildSymbolTable ();
+ void buildSectionHeaderTable();
+ void assignSectionsWithNoSegments();
+ void addAbsoluteUndefinedSymbols(const File &File);
+ void addDefaultAtoms();
+ void addFiles(InputFiles&);
+ void finalizeDefaultAtomValues();
+
+ uint64_t addressOfAtom(const Atom *atom) {
+ return _atomToAddressMap[atom];
+ }
+
+ KindHandler *kindHandler() { return _referenceKindHandler.get(); }
+
+ void createDefaultSections();
+
+ const ELFTargetInfo &_targetInfo;
+
+ typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
+ std::unique_ptr<KindHandler> _referenceKindHandler;
+ AtomToAddress _atomToAddressMap;
+ llvm::BumpPtrAllocator _chunkAllocate;
+ DefaultLayout<ELFT> *_layout;
+ Header<ELFT> *_Header;
+ ProgramHeader<ELFT> *_programHeader;
+ SymbolTable<ELFT> * _symtab;
+ StringTable<ELFT> *_strtab;
+ StringTable<ELFT> *_shstrtab;
+ SectionHeader<ELFT> *_shdrtab;
+ CRuntimeFile<ELFT> _runtimeFile;
+};
+
+//===----------------------------------------------------------------------===//
+// ExecutableWriter
+//===----------------------------------------------------------------------===//
+template<class ELFT>
+ExecutableWriter<ELFT>::ExecutableWriter(const ELFTargetInfo &ti)
+ : _targetInfo(ti)
+ , _referenceKindHandler(KindHandler::makeHandler(
+ ti.getTriple().getArch(), ti.isLittleEndian()))
+ , _runtimeFile(ti) {
+ _layout = new DefaultLayout<ELFT>(ti);
+}
+
+template<class ELFT>
+void ExecutableWriter<ELFT>::buildChunks(const File &file){
+ for (const DefinedAtom *definedAtom : file.defined() ) {
+ _layout->addAtom(definedAtom);
+ }
+ /// Add all the absolute atoms to the layout
+ for (const AbsoluteAtom *absoluteAtom : file.absolute()) {
+ _layout->addAtom(absoluteAtom);
+ }
+}
+
+template<class ELFT>
+void ExecutableWriter<ELFT>::buildSymbolTable () {
+ for (auto sec : _layout->sections())
+ if (auto section = dyn_cast<Section<ELFT>>(sec))
+ for (const auto &atom : section->atoms())
+ _symtab->addSymbol(atom._atom, section->ordinal(), atom._virtualAddr);
+}
+
+template<class ELFT>
+void
+ExecutableWriter<ELFT>::addAbsoluteUndefinedSymbols(const File &file) {
+ // add all the absolute symbols that the layout contains to the output symbol
+ // table
+ for (auto &atom : _layout->absoluteAtoms())
+ _symtab->addSymbol(atom.absoluteAtom(), ELF::SHN_ABS, atom.value());
+ for (const UndefinedAtom *a : file.undefined())
+ _symtab->addSymbol(a, ELF::SHN_UNDEF);
+}
+
+template<class ELFT>
+void ExecutableWriter<ELFT>::buildAtomToAddressMap () {
+ for (auto sec : _layout->sections())
+ if (auto section = dyn_cast<Section<ELFT>>(sec))
+ for (const auto &atom : section->atoms())
+ _atomToAddressMap[atom._atom] = atom._virtualAddr;
+ // build the atomToAddressMap that contains absolute symbols too
+ for (auto &atom : _layout->absoluteAtoms())
+ _atomToAddressMap[atom.absoluteAtom()] = atom.value();
+}
+
+template<class ELFT>
+void ExecutableWriter<ELFT>::buildSectionHeaderTable() {
+ for (auto mergedSec : _layout->mergedSections()) {
+ if (mergedSec->kind() != Chunk<ELFT>::K_ELFSection)
+ continue;
+ if (mergedSec->hasSegment())
+ _shdrtab->appendSection(mergedSec);
+ }
+}
+
+template<class ELFT>
+void ExecutableWriter<ELFT>::assignSectionsWithNoSegments() {
+ for (auto mergedSec : _layout->mergedSections()) {
+ if (mergedSec->kind() != Chunk<ELFT>::K_ELFSection)
+ continue;
+ if (!mergedSec->hasSegment())
+ _shdrtab->appendSection(mergedSec);
+ }
+ _layout->assignOffsetsForMiscSections();
+ for (auto sec : _layout->sections())
+ if (auto section = dyn_cast<Section<ELFT>>(sec))
+ if (!DefaultLayout<ELFT>::hasOutputSegment(section))
+ _shdrtab->updateSection(section);
+}
+
+/// \brief Add absolute symbols by default. These are linker added
+/// absolute symbols
+template<class ELFT>
+void ExecutableWriter<ELFT>::addDefaultAtoms() {
+ _runtimeFile.addUndefinedAtom(_targetInfo.getEntry());
+ _runtimeFile.addAbsoluteAtom("__bss_start");
+ _runtimeFile.addAbsoluteAtom("__bss_end");
+ _runtimeFile.addAbsoluteAtom("_end");
+ _runtimeFile.addAbsoluteAtom("end");
+ _runtimeFile.addAbsoluteAtom("__init_array_start");
+ _runtimeFile.addAbsoluteAtom("__init_array_end");
+ _runtimeFile.addAbsoluteAtom("__rela_iplt_start");
+ _runtimeFile.addAbsoluteAtom("__rela_iplt_end");
+}
+
+/// \brief Hook in lld to add CRuntime file
+template<class ELFT>
+void ExecutableWriter<ELFT>::addFiles(InputFiles &inputFiles) {
+ addDefaultAtoms();
+ inputFiles.prependFile(_runtimeFile);
+}
+
+/// Finalize the value of all the absolute symbols that we
+/// created
+template<class ELFT>
+void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
+ auto bssStartAtomIter = _layout->findAbsoluteAtom("__bss_start");
+ auto bssEndAtomIter = _layout->findAbsoluteAtom("__bss_end");
+ auto underScoreEndAtomIter = _layout->findAbsoluteAtom("_end");
+ auto endAtomIter = _layout->findAbsoluteAtom("end");
+ auto initArrayStartIter = _layout->findAbsoluteAtom("__init_array_start");
+ auto initArrayEndIter = _layout->findAbsoluteAtom("__init_array_end");
+ auto realIpltStartIter = _layout->findAbsoluteAtom("__rela_iplt_start");
+ auto realIpltEndIter = _layout->findAbsoluteAtom("__rela_iplt_end");
+
+ auto startEnd = [&](typename DefaultLayout<ELFT>::AbsoluteAtomIterT start,
+ typename DefaultLayout<ELFT>::AbsoluteAtomIterT end,
+ StringRef sec) -> void {
+ auto section = _layout->findOutputSection(sec);
+ if (section) {
+ start->setValue(section->virtualAddr());
+ end->setValue(section->virtualAddr() + section->memSize());
+ } else {
+ start->setValue(0);
+ end->setValue(0);
+ }
+ };
+
+ startEnd(initArrayStartIter, initArrayEndIter, ".init_array");
+ startEnd(realIpltStartIter, realIpltEndIter, ".rela.plt");
+
+ assert(!(bssStartAtomIter == _layout->absoluteAtoms().end() ||
+ bssEndAtomIter == _layout->absoluteAtoms().end() ||
+ underScoreEndAtomIter == _layout->absoluteAtoms().end() ||
+ endAtomIter == _layout->absoluteAtoms().end()) &&
+ "Unable to find the absolute atoms that have been added by lld");
+
+ auto phe = _programHeader->findProgramHeader(
+ llvm::ELF::PT_LOAD, llvm::ELF::PF_W, llvm::ELF::PF_X);
+
+ assert(!(phe == _programHeader->end()) &&
+ "Can't find a data segment in the program header!");
+
+ bssStartAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_filesz);
+ bssEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz);
+ underScoreEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz);
+ endAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz);
+}
+
+template<class ELFT>
+error_code
+ExecutableWriter<ELFT>::writeFile(const File &file, StringRef path) {
+ buildChunks(file);
+ // Create the default sections like the symbol table, string table, and the
+ // section string table
+ createDefaultSections();
+
+ // Set the Layout
+ _layout->assignSectionsToSegments();
+ _layout->assignFileOffsets();
+ _layout->assignVirtualAddress();
+
+ // Finalize the default value of symbols that the linker adds
+ finalizeDefaultAtomValues();
+
+ // Build the Atom To Address map for applying relocations
+ buildAtomToAddressMap();
+
+ // Create symbol table and section string table
+ buildSymbolTable();
+
+ // add other symbols
+ addAbsoluteUndefinedSymbols(file);
+
+ // Finalize the layout by calling the finalize() functions
+ _layout->finalize();
+
+ // build Section Header table
+ buildSectionHeaderTable();
+
+ // assign Offsets and virtual addresses
+ // for sections with no segments
+ assignSectionsWithNoSegments();
+
+ uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
+
+ OwningPtr<FileOutputBuffer> buffer;
+ error_code ec = FileOutputBuffer::create(path,
+ totalSize, buffer,
+ FileOutputBuffer::F_executable);
+ if (ec)
+ return ec;
+
+ _Header->e_ident(ELF::EI_CLASS, _targetInfo.is64Bits() ? ELF::ELFCLASS64
+ : ELF::ELFCLASS32);
+ _Header->e_ident(ELF::EI_DATA, _targetInfo.isLittleEndian()
+ ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
+ _Header->e_ident(ELF::EI_VERSION, 1);
+ _Header->e_ident(ELF::EI_OSABI, 0);
+ _Header->e_type(_targetInfo.getOutputType());
+ _Header->e_machine(_targetInfo.getOutputMachine());
+ _Header->e_version(1);
+ _Header->e_entry(0ULL);
+ _Header->e_phoff(_programHeader->fileOffset());
+ _Header->e_shoff(_shdrtab->fileOffset());
+ _Header->e_phentsize(_programHeader->entsize());
+ _Header->e_phnum(_programHeader->numHeaders());
+ _Header->e_shentsize(_shdrtab->entsize());
+ _Header->e_shnum(_shdrtab->numHeaders());
+ _Header->e_shstrndx(_shstrtab->ordinal());
+ uint64_t virtualAddr = 0;
+ _layout->findAtomAddrByName(_targetInfo.getEntry(), virtualAddr);
+ _Header->e_entry(virtualAddr);
+
+ // HACK: We have to write out the header and program header here even though
+ // they are a member of a segment because only sections are written in the
+ // following loop.
+ _Header->write(this, *buffer);
+ _programHeader->write(this, *buffer);
+
+ for (auto section : _layout->sections())
+ section->write(this, *buffer);
+
+ return buffer->commit();
+}
+
+template<class ELFT>
+void ExecutableWriter<ELFT>::createDefaultSections() {
+ _Header = new Header<ELFT>(_targetInfo);
+ _programHeader = new ProgramHeader<ELFT>(_targetInfo);
+ _layout->setHeader(_Header);
+ _layout->setProgramHeader(_programHeader);
+
+ _symtab = new SymbolTable<
+ ELFT>(_targetInfo, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE);
+ _strtab = new StringTable<
+ ELFT>(_targetInfo, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE);
+ _shstrtab = new StringTable<ELFT>(
+ _targetInfo, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS);
+ _shdrtab = new SectionHeader<
+ ELFT>(_targetInfo, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS);
+ _layout->addSection(_symtab);
+ _layout->addSection(_strtab);
+ _layout->addSection(_shstrtab);
+ _shdrtab->setStringSection(_shstrtab);
+ _symtab->setStringSection(_strtab);
+ _layout->addSection(_shdrtab);
+}
+} // namespace elf
+
+std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &TI) {
+ using llvm::object::ELFType;
+ // Set the default layout to be the static executable layout
+ // We would set the layout to a dynamic executable layout
+ // if we came across any shared libraries in the process
+
+ if (!TI.is64Bits() && TI.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::little, 4, false>>(TI));
+ else if (TI.is64Bits() && TI.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::little, 8, true>>(TI));
+ else if (!TI.is64Bits() && !TI.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::big, 4, false>>(TI));
+ else if (TI.is64Bits() && !TI.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::big, 8, true>>(TI));
+
+ llvm_unreachable("Invalid Options!");
+}
+} // namespace lld