//===--------- lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.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_ARM_ARM_EXECUTABLE_WRITER_H #define LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H #include "ExecutableWriter.h" #include "ARMLinkingContext.h" #include "ARMTargetHandler.h" #include "ARMSymbolTable.h" namespace { const char *gotSymbol = "_GLOBAL_OFFSET_TABLE_"; } namespace lld { namespace elf { template class ARMExecutableWriter : public ExecutableWriter { public: ARMExecutableWriter(ARMLinkingContext &context, ARMTargetLayout &layout); protected: // Add any runtime files and their atoms to the output bool createImplicitFiles(std::vector> &) override; void finalizeDefaultAtomValues() override; void addDefaultAtoms() override { ExecutableWriter::addDefaultAtoms(); } /// \brief Create symbol table. unique_bump_ptr> createSymbolTable() override; void processUndefinedSymbol(StringRef symName, RuntimeFile &file) const override; // Setup the ELF header. std::error_code setELFHeader() override; private: ARMLinkingContext &_context; ARMTargetLayout &_armLayout; }; template ARMExecutableWriter::ARMExecutableWriter(ARMLinkingContext &context, ARMTargetLayout &layout) : ExecutableWriter(context, layout), _context(context), _armLayout(layout) {} template bool ARMExecutableWriter::createImplicitFiles( std::vector> &result) { ExecutableWriter::createImplicitFiles(result); return true; } template void ARMExecutableWriter::finalizeDefaultAtomValues() { // Finalize the atom values that are part of the parent. ExecutableWriter::finalizeDefaultAtomValues(); auto gotAtomIter = _armLayout.findAbsoluteAtom(gotSymbol); if (gotAtomIter != _armLayout.absoluteAtoms().end()) { auto *gotAtom = *gotAtomIter; if (auto gotpltSection = _armLayout.findOutputSection(".got.plt")) gotAtom->_virtualAddr = gotpltSection->virtualAddr(); else if (auto gotSection = _armLayout.findOutputSection(".got")) gotAtom->_virtualAddr = gotSection->virtualAddr(); else gotAtom->_virtualAddr = 0; } // TODO: resolve addresses of __exidx_start/_end atoms } template unique_bump_ptr> ARMExecutableWriter::createSymbolTable() { return unique_bump_ptr>( new (this->_alloc) ARMSymbolTable(this->_context)); } template void ARMExecutableWriter::processUndefinedSymbol( StringRef symName, RuntimeFile &file) const { if (symName == gotSymbol) { file.addAbsoluteAtom(gotSymbol); } else if (symName.startswith("__exidx")) { file.addAbsoluteAtom("__exidx_start"); file.addAbsoluteAtom("__exidx_end"); } } template std::error_code ARMExecutableWriter::setELFHeader() { if (std::error_code ec = ExecutableWriter::setELFHeader()) return ec; // Fixup entry point for Thumb code. StringRef entryName = _context.entrySymbolName(); if (const AtomLayout *al = _armLayout.findAtomLayoutByName(entryName)) { const auto *ea = dyn_cast(al->_atom); if (ea && ea->codeModel() == DefinedAtom::codeARMThumb) this->_elfHeader->e_entry(al->_virtualAddr | 0x1); } return std::error_code(); } } // namespace elf } // namespace lld #endif // LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H