| //===- ObjectLinker.cpp ---------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include <mcld/Object/ObjectLinker.h> |
| |
| #include <mcld/LinkerConfig.h> |
| #include <mcld/Module.h> |
| #include <mcld/InputTree.h> |
| #include <mcld/MC/InputBuilder.h> |
| #include <mcld/LD/LDSection.h> |
| #include <mcld/LD/LDContext.h> |
| #include <mcld/LD/Archive.h> |
| #include <mcld/LD/ArchiveReader.h> |
| #include <mcld/LD/ObjectReader.h> |
| #include <mcld/LD/DynObjReader.h> |
| #include <mcld/LD/GroupReader.h> |
| #include <mcld/LD/ObjectWriter.h> |
| #include <mcld/LD/DynObjWriter.h> |
| #include <mcld/LD/ExecWriter.h> |
| #include <mcld/LD/ResolveInfo.h> |
| #include <mcld/LD/Layout.h> |
| #include <mcld/LD/RelocData.h> |
| #include <mcld/Support/RealPath.h> |
| #include <mcld/Support/MemoryArea.h> |
| #include <mcld/Support/MsgHandling.h> |
| #include <mcld/Target/TargetLDBackend.h> |
| #include <mcld/Fragment/FragmentLinker.h> |
| #include <mcld/Object/ObjectBuilder.h> |
| |
| #include <llvm/Support/Casting.h> |
| |
| using namespace llvm; |
| using namespace mcld; |
| |
| ObjectLinker::ObjectLinker(const LinkerConfig& pConfig, |
| Module& pModule, |
| InputBuilder& pInputBuilder, |
| TargetLDBackend& pLDBackend) |
| : m_Config(pConfig), |
| m_Module(pModule), |
| m_InputBuilder(pInputBuilder), |
| m_pLinker(NULL), |
| m_LDBackend(pLDBackend), |
| m_pObjectReader(NULL), |
| m_pDynObjReader(NULL), |
| m_pArchiveReader(NULL), |
| m_pObjectWriter(NULL), |
| m_pDynObjWriter(NULL), |
| m_pExecWriter(NULL), |
| m_pGroupReader(NULL) |
| { |
| // set up soname |
| if (!m_Config.options().soname().empty()) { |
| m_Module.setName(m_Config.options().soname()); |
| } |
| } |
| |
| ObjectLinker::~ObjectLinker() |
| { |
| delete m_pLinker; |
| delete m_pObjectReader; |
| delete m_pDynObjReader; |
| delete m_pArchiveReader; |
| delete m_pObjectWriter; |
| delete m_pDynObjWriter; |
| delete m_pExecWriter; |
| delete m_pGroupReader; |
| } |
| |
| /// initFragmentLinker - initialize FragmentLinker |
| /// Connect all components with FragmentLinker |
| bool ObjectLinker::initFragmentLinker() |
| { |
| if (NULL == m_pLinker) { |
| m_pLinker = new FragmentLinker(m_Config, |
| m_Module, |
| m_LDBackend); |
| } |
| |
| // initialize the readers and writers |
| // Because constructor can not be failed, we initalize all readers and |
| // writers outside the FragmentLinker constructors. |
| m_pObjectReader = m_LDBackend.createObjectReader(*m_pLinker); |
| m_pArchiveReader = m_LDBackend.createArchiveReader(m_Module); |
| m_pDynObjReader = m_LDBackend.createDynObjReader(*m_pLinker); |
| m_pObjectWriter = m_LDBackend.createObjectWriter(*m_pLinker); |
| m_pDynObjWriter = m_LDBackend.createDynObjWriter(*m_pLinker); |
| m_pExecWriter = m_LDBackend.createExecWriter(*m_pLinker); |
| m_pGroupReader = new GroupReader(m_Module, *m_pObjectReader, |
| *m_pDynObjReader, *m_pArchiveReader); |
| |
| // initialize RelocationFactory |
| m_LDBackend.initRelocFactory(*m_pLinker); |
| |
| // initialize BranchIslandFactory |
| m_LDBackend.initBRIslandFactory(); |
| |
| // initialize StubFactory |
| m_LDBackend.initStubFactory(); |
| |
| // initialize target stubs |
| m_LDBackend.initTargetStubs(*m_pLinker); |
| return true; |
| } |
| |
| /// initStdSections - initialize standard sections |
| bool ObjectLinker::initStdSections() |
| { |
| ObjectBuilder builder(m_Config, m_Module); |
| |
| // initialize standard sections |
| if (!m_LDBackend.initStdSections(builder)) |
| return false; |
| |
| // initialize target-dependent sections |
| m_LDBackend.initTargetSections(m_Module, builder); |
| |
| return true; |
| } |
| |
| void ObjectLinker::normalize() |
| { |
| // ----- set up inputs ----- // |
| Module::input_iterator input, inEnd = m_Module.input_end(); |
| for (input = m_Module.input_begin(); input!=inEnd; ++input) { |
| // is a group node |
| if (isGroup(input)) { |
| getGroupReader()->readGroup(input, m_InputBuilder, m_Config); |
| continue; |
| } |
| |
| // already got type - for example, bitcode or external OIR (object |
| // intermediate representation) |
| if ((*input)->type() == Input::Script || |
| (*input)->type() == Input::Archive || |
| (*input)->type() == Input::External) |
| continue; |
| |
| if (Input::Object == (*input)->type()) { |
| m_Module.getObjectList().push_back(*input); |
| continue; |
| } |
| |
| if (Input::DynObj == (*input)->type()) { |
| m_Module.getLibraryList().push_back(*input); |
| continue; |
| } |
| |
| // is a relocatable object file |
| if (getObjectReader()->isMyFormat(**input)) { |
| (*input)->setType(Input::Object); |
| getObjectReader()->readHeader(**input); |
| getObjectReader()->readSections(**input); |
| getObjectReader()->readSymbols(**input); |
| m_Module.getObjectList().push_back(*input); |
| } |
| // is a shared object file |
| else if (getDynObjReader()->isMyFormat(**input)) { |
| (*input)->setType(Input::DynObj); |
| getDynObjReader()->readHeader(**input); |
| getDynObjReader()->readSymbols(**input); |
| m_Module.getLibraryList().push_back(*input); |
| } |
| // is an archive |
| else if (getArchiveReader()->isMyFormat(**input)) { |
| (*input)->setType(Input::Archive); |
| Archive archive(**input, m_InputBuilder); |
| getArchiveReader()->readArchive(archive); |
| if(archive.numOfObjectMember() > 0) { |
| m_Module.getInputTree().merge<InputTree::Inclusive>(input, |
| archive.inputs()); |
| } |
| } |
| else { |
| fatal(diag::err_unrecognized_input_file) << (*input)->path() |
| << m_Config.triple().str(); |
| } |
| } // end of for |
| } |
| |
| bool ObjectLinker::linkable() const |
| { |
| // check we have input and output files |
| if (m_Module.getInputTree().empty()) { |
| error(diag::err_no_inputs); |
| return false; |
| } |
| |
| // can not mix -static with shared objects |
| Module::const_lib_iterator lib, libEnd = m_Module.lib_end(); |
| for (lib = m_Module.lib_begin(); lib != libEnd; ++lib) { |
| if((*lib)->attribute()->isStatic()) { |
| error(diag::err_mixed_shared_static_objects) |
| << (*lib)->name() << (*lib)->path(); |
| return false; |
| } |
| } |
| |
| // can not mix -r with shared objects |
| return true; |
| } |
| |
| /// readRelocations - read all relocation entries |
| /// |
| /// All symbols should be read and resolved before this function. |
| bool ObjectLinker::readRelocations() |
| { |
| // Bitcode is read by the other path. This function reads relocation sections |
| // in object files. |
| mcld::InputTree::bfs_iterator input, inEnd = m_Module.getInputTree().bfs_end(); |
| for (input=m_Module.getInputTree().bfs_begin(); input!=inEnd; ++input) { |
| if ((*input)->type() == Input::Object && (*input)->hasMemArea()) { |
| if (!getObjectReader()->readRelocations(**input)) |
| return false; |
| } |
| // ignore the other kinds of files. |
| } |
| return true; |
| } |
| |
| /// mergeSections - put allinput sections into output sections |
| bool ObjectLinker::mergeSections() |
| { |
| ObjectBuilder builder(m_Config, m_Module); |
| Module::obj_iterator obj, objEnd = m_Module.obj_end(); |
| for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) { |
| LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd(); |
| for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) { |
| switch ((*sect)->kind()) { |
| // Some *INPUT sections should not be merged. |
| case LDFileFormat::Ignore: |
| case LDFileFormat::Null: |
| case LDFileFormat::Relocation: |
| case LDFileFormat::NamePool: |
| case LDFileFormat::Group: |
| case LDFileFormat::StackNote: |
| // skip |
| continue; |
| case LDFileFormat::Target: |
| if (!m_LDBackend.mergeSection(m_Module, **sect)) { |
| error(diag::err_cannot_merge_section) << (*sect)->name() |
| << (*obj)->name(); |
| return false; |
| } |
| break; |
| case LDFileFormat::EhFrame: { |
| if (!(*sect)->hasEhFrame()) |
| continue; // skip |
| |
| if (!builder.MergeSection(**sect)) { |
| error(diag::err_cannot_merge_section) << (*sect)->name() |
| << (*obj)->name(); |
| return false; |
| } |
| break; |
| } |
| default: { |
| if (!(*sect)->hasSectionData()) |
| continue; // skip |
| |
| if (!builder.MergeSection(**sect)) { |
| error(diag::err_cannot_merge_section) << (*sect)->name() |
| << (*obj)->name(); |
| return false; |
| } |
| break; |
| } |
| } // end of switch |
| } // for each section |
| } // for each obj |
| return true; |
| } |
| |
| /// addStandardSymbols - shared object and executable files need some |
| /// standard symbols |
| /// @return if there are some input symbols with the same name to the |
| /// standard symbols, return false |
| bool ObjectLinker::addStandardSymbols() |
| { |
| // create and add section symbols for each output section |
| Module::iterator iter, iterEnd = m_Module.end(); |
| for (iter = m_Module.begin(); iter != iterEnd; ++iter) { |
| m_Module.getSectionSymbolSet().add(**iter, m_Module.getNamePool()); |
| } |
| |
| return m_LDBackend.initStandardSymbols(*m_pLinker, m_Module); |
| } |
| |
| /// addTargetSymbols - some targets, such as MIPS and ARM, need some |
| /// target-dependent symbols |
| /// @return if there are some input symbols with the same name to the |
| /// target symbols, return false |
| bool ObjectLinker::addTargetSymbols() |
| { |
| m_LDBackend.initTargetSymbols(*m_pLinker); |
| return true; |
| } |
| |
| bool ObjectLinker::scanRelocations() |
| { |
| // apply all relocations of all inputs |
| Module::obj_iterator input, inEnd = m_Module.obj_end(); |
| for (input = m_Module.obj_begin(); input != inEnd; ++input) { |
| LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); |
| for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { |
| // bypass the reloc section if |
| // 1. its section kind is changed to Ignore. (The target section is a |
| // discarded group section.) |
| // 2. it has no reloc data. (All symbols in the input relocs are in the |
| // discarded group sections) |
| if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) |
| continue; |
| RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); |
| for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { |
| Relocation* relocation = llvm::cast<Relocation>(reloc); |
| // scan relocation |
| if (LinkerConfig::Object != m_Config.codeGenType()) { |
| m_LDBackend.scanRelocation(*relocation, |
| *m_pLinker, |
| m_Module, |
| *(*rs)->getLink()); |
| } |
| else { |
| m_LDBackend.partialScanRelocation(*relocation, |
| *m_pLinker, |
| m_Module, |
| *(*rs)->getLink()); |
| } |
| } // for all relocations |
| } // for all relocation section |
| } // for all inputs |
| return true; |
| } |
| |
| /// prelayout - help backend to do some modification before layout |
| bool ObjectLinker::prelayout() |
| { |
| // finalize the section symbols, set their fragment reference and push them |
| // into output symbol table |
| Module::iterator iter, iterEnd = m_Module.end(); |
| for (iter = m_Module.begin(); iter != iterEnd; ++iter) { |
| LDSection* section = *iter; |
| if (0x0 == section->size() || LDFileFormat::Relocation == section->kind()) |
| continue; |
| m_Module.getSectionSymbolSet().finalize( |
| *section, m_Module.getSymbolTable()); |
| } |
| |
| m_LDBackend.preLayout(m_Module, *m_pLinker); |
| |
| m_LDBackend.allocateCommonSymbols(m_Module); |
| |
| /// check program interpreter - computer the name size of the runtime dyld |
| if (!m_pLinker->isStaticLink() && |
| (LinkerConfig::Exec == m_Config.codeGenType() || |
| m_Config.options().isPIE() || |
| m_Config.options().hasDyld())) |
| m_LDBackend.sizeInterp(); |
| |
| /// measure NamePools - compute the size of name pool sections |
| /// In ELF, will compute the size of.symtab, .strtab, .dynsym, .dynstr, |
| /// .hash and .shstrtab sections. |
| /// |
| /// dump all symbols and strings from FragmentLinker and build the format-dependent |
| /// hash table. |
| m_LDBackend.sizeNamePools(m_Module, m_pLinker->isStaticLink()); |
| |
| return true; |
| } |
| |
| /// layout - linearly layout all output sections and reserve some space |
| /// for GOT/PLT |
| /// Because we do not support instruction relaxing in this early version, |
| /// if there is a branch can not jump to its target, we return false |
| /// directly |
| bool ObjectLinker::layout() |
| { |
| Layout layout; |
| return layout.layout(m_Module, m_LDBackend, m_Config); |
| } |
| |
| /// prelayout - help backend to do some modification after layout |
| bool ObjectLinker::postlayout() |
| { |
| m_LDBackend.postLayout(m_Module, *m_pLinker); |
| return true; |
| } |
| |
| /// finalizeSymbolValue - finalize the resolved symbol value. |
| /// Before relocate(), after layout(), FragmentLinker should correct value of all |
| /// symbol. |
| bool ObjectLinker::finalizeSymbolValue() |
| { |
| return m_pLinker->finalizeSymbols(); |
| } |
| |
| /// relocate - applying relocation entries and create relocation |
| /// section in the output files |
| /// Create relocation section, asking TargetLDBackend to |
| /// read the relocation information into RelocationEntry |
| /// and push_back into the relocation section |
| bool ObjectLinker::relocation() |
| { |
| return m_pLinker->applyRelocations(); |
| } |
| |
| /// emitOutput - emit the output file. |
| bool ObjectLinker::emitOutput(MemoryArea& pOutput) |
| { |
| switch(m_Config.codeGenType()) { |
| case LinkerConfig::Object: |
| getObjectWriter()->writeObject(m_Module, pOutput); |
| return true; |
| case LinkerConfig::DynObj: |
| getDynObjWriter()->writeDynObj(m_Module, pOutput); |
| return true; |
| case LinkerConfig::Exec: |
| getExecWriter()->writeExecutable(m_Module, pOutput); |
| return true; |
| default: |
| fatal(diag::unrecognized_output_file) << m_Config.codeGenType(); |
| } |
| return false; |
| } |
| |
| /// postProcessing - do modification after all processes |
| bool ObjectLinker::postProcessing(MemoryArea& pOutput) |
| { |
| m_pLinker->syncRelocationResult(pOutput); |
| |
| // emit .eh_frame_hdr |
| // eh_frame_hdr should be emitted after syncRelocation, because eh_frame_hdr |
| // needs FDE PC value, which will be corrected at syncRelocation |
| m_LDBackend.postProcessing(*m_pLinker, pOutput); |
| return true; |
| } |
| |