| //===- GroupReader.cpp ----------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include <mcld/LD/Archive.h> |
| #include <mcld/LD/ArchiveReader.h> |
| #include <mcld/LD/DynObjReader.h> |
| #include <mcld/LD/GroupReader.h> |
| #include <mcld/LD/ObjectReader.h> |
| #include <mcld/LinkerConfig.h> |
| #include <mcld/MC/Attribute.h> |
| #include <mcld/Support/MsgHandling.h> |
| |
| using namespace mcld; |
| |
| GroupReader::GroupReader(Module& pModule, |
| ObjectReader& pObjectReader, |
| DynObjReader& pDynObjReader, |
| ArchiveReader& pArchiveReader) |
| : m_Module(pModule), |
| m_ObjectReader(pObjectReader), |
| m_DynObjReader(pDynObjReader), |
| m_ArchiveReader(pArchiveReader) |
| { |
| } |
| |
| GroupReader::~GroupReader() |
| { |
| } |
| |
| bool GroupReader::readGroup(Module::input_iterator pRoot, |
| InputBuilder& pBuilder, |
| const LinkerConfig& pConfig) |
| { |
| // record the number of total objects included in this sub-tree |
| size_t cur_obj_cnt = 0; |
| size_t last_obj_cnt = 0; |
| size_t non_ar_obj_cnt = 0; |
| |
| // record the archive files in this sub-tree |
| typedef std::vector<ArchiveListEntry*> ArchiveListType; |
| ArchiveListType ar_list; |
| |
| Module::input_iterator input = --pRoot; |
| |
| // Since the end of a sub-tree is the same node to the end of whole tree, we |
| // take the end of the whole input tree for conventience. |
| Module::input_iterator input_end = m_Module.input_end(); |
| |
| // first time read the sub-tree |
| while (input != input_end) { |
| // already got type - for example, bitcode or external OIR (object |
| // intermediate representation) |
| if ((*input)->type() == Input::Script || |
| (*input)->type() == Input::Object || |
| (*input)->type() == Input::DynObj || |
| (*input)->type() == Input::Archive || |
| (*input)->type() == Input::External) { |
| ++input; |
| continue; |
| } |
| |
| // is an archive |
| if (m_ArchiveReader.isMyFormat(**input)) { |
| (*input)->setType(Input::Archive); |
| // record the Archive used by each archive node |
| Archive* ar = new Archive(**input, pBuilder); |
| ArchiveListEntry* entry = new ArchiveListEntry(*ar, input); |
| ar_list.push_back(entry); |
| // read archive |
| m_ArchiveReader.readArchive(*ar); |
| cur_obj_cnt += ar->numOfObjectMember(); |
| } |
| // is a relocatable object file |
| else if (m_ObjectReader.isMyFormat(**input)) { |
| (*input)->setType(Input::Object); |
| m_ObjectReader.readHeader(**input); |
| m_ObjectReader.readSections(**input); |
| m_ObjectReader.readSymbols(**input); |
| m_Module.getObjectList().push_back(*input); |
| ++cur_obj_cnt; |
| ++non_ar_obj_cnt; |
| } |
| // is a shared object file |
| else if (m_DynObjReader.isMyFormat(**input)) { |
| (*input)->setType(Input::DynObj); |
| m_DynObjReader.readHeader(**input); |
| m_DynObjReader.readSymbols(**input); |
| m_Module.getLibraryList().push_back(*input); |
| } |
| else { |
| fatal(diag::err_unrecognized_input_file) << (*input)->path() |
| << pConfig.targets().triple().str(); |
| } |
| ++input; |
| } |
| |
| // after read in all the archives, traverse the archive list in a loop until |
| // there is no unresolved symbols added |
| ArchiveListType::iterator it = ar_list.begin(); |
| ArchiveListType::iterator end = ar_list.end(); |
| while (cur_obj_cnt != last_obj_cnt) { |
| last_obj_cnt = cur_obj_cnt; |
| cur_obj_cnt = non_ar_obj_cnt; |
| for (it = ar_list.begin(); it != end; ++it) { |
| Archive& ar = (*it)->archive; |
| // if --whole-archive is given to this archive, no need to read it again |
| if ( ar.getARFile().attribute()->isWholeArchive()) |
| continue; |
| m_ArchiveReader.readArchive(ar); |
| cur_obj_cnt += ar.numOfObjectMember(); |
| } |
| } |
| |
| // after all needed member included, merge the archive sub-tree to main |
| // InputTree |
| for (it = ar_list.begin(); it != end; ++it) { |
| Archive& ar = (*it)->archive; |
| if (ar.numOfObjectMember() > 0) { |
| m_Module.getInputTree().merge<InputTree::Inclusive>((*it)->input, |
| ar.inputs()); |
| } |
| } |
| |
| // cleanup ar_list |
| for (it = ar_list.begin(); it != end; ++it) { |
| delete &((*it)->archive); |
| delete (*it); |
| } |
| ar_list.clear(); |
| |
| return true; |
| } |
| |