1 //===- GroupReader.cpp ----------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include <mcld/LD/Archive.h> 10 #include <mcld/LD/ArchiveReader.h> 11 #include <mcld/LD/DynObjReader.h> 12 #include <mcld/LD/GroupReader.h> 13 #include <mcld/LD/ObjectReader.h> 14 #include <mcld/LinkerConfig.h> 15 #include <mcld/MC/Attribute.h> 16 #include <mcld/Support/MsgHandling.h> 17 18 using namespace mcld; 19 20 GroupReader::GroupReader(Module& pModule, 21 ObjectReader& pObjectReader, 22 DynObjReader& pDynObjReader, 23 ArchiveReader& pArchiveReader) 24 : m_Module(pModule), 25 m_ObjectReader(pObjectReader), 26 m_DynObjReader(pDynObjReader), 27 m_ArchiveReader(pArchiveReader) 28 { 29 } 30 31 GroupReader::~GroupReader() 32 { 33 } 34 35 bool GroupReader::readGroup(Module::input_iterator pRoot, 36 InputBuilder& pBuilder, 37 const LinkerConfig& pConfig) 38 { 39 // record the number of total objects included in this sub-tree 40 size_t cur_obj_cnt = 0; 41 size_t last_obj_cnt = 0; 42 size_t non_ar_obj_cnt = 0; 43 44 // record the archive files in this sub-tree 45 typedef std::vector<ArchiveListEntry*> ArchiveListType; 46 ArchiveListType ar_list; 47 48 Module::input_iterator input = --pRoot; 49 50 // Since the end of a sub-tree is the same node to the end of whole tree, we 51 // take the end of the whole input tree for conventience. 52 Module::input_iterator input_end = m_Module.input_end(); 53 54 // first time read the sub-tree 55 while (input != input_end) { 56 // already got type - for example, bitcode or external OIR (object 57 // intermediate representation) 58 if ((*input)->type() == Input::Script || 59 (*input)->type() == Input::Object || 60 (*input)->type() == Input::DynObj || 61 (*input)->type() == Input::Archive || 62 (*input)->type() == Input::External) { 63 ++input; 64 continue; 65 } 66 67 // is an archive 68 if (m_ArchiveReader.isMyFormat(**input)) { 69 (*input)->setType(Input::Archive); 70 // record the Archive used by each archive node 71 Archive* ar = new Archive(**input, pBuilder); 72 ArchiveListEntry* entry = new ArchiveListEntry(*ar, input); 73 ar_list.push_back(entry); 74 // read archive 75 m_ArchiveReader.readArchive(*ar); 76 cur_obj_cnt += ar->numOfObjectMember(); 77 } 78 // is a relocatable object file 79 else if (m_ObjectReader.isMyFormat(**input)) { 80 (*input)->setType(Input::Object); 81 m_ObjectReader.readHeader(**input); 82 m_ObjectReader.readSections(**input); 83 m_ObjectReader.readSymbols(**input); 84 m_Module.getObjectList().push_back(*input); 85 ++cur_obj_cnt; 86 ++non_ar_obj_cnt; 87 } 88 // is a shared object file 89 else if (m_DynObjReader.isMyFormat(**input)) { 90 (*input)->setType(Input::DynObj); 91 m_DynObjReader.readHeader(**input); 92 m_DynObjReader.readSymbols(**input); 93 m_Module.getLibraryList().push_back(*input); 94 } 95 else { 96 fatal(diag::err_unrecognized_input_file) << (*input)->path() 97 << pConfig.targets().triple().str(); 98 } 99 ++input; 100 } 101 102 // after read in all the archives, traverse the archive list in a loop until 103 // there is no unresolved symbols added 104 ArchiveListType::iterator it = ar_list.begin(); 105 ArchiveListType::iterator end = ar_list.end(); 106 while (cur_obj_cnt != last_obj_cnt) { 107 last_obj_cnt = cur_obj_cnt; 108 cur_obj_cnt = non_ar_obj_cnt; 109 for (it = ar_list.begin(); it != end; ++it) { 110 Archive& ar = (*it)->archive; 111 // if --whole-archive is given to this archive, no need to read it again 112 if ( ar.getARFile().attribute()->isWholeArchive()) 113 continue; 114 m_ArchiveReader.readArchive(ar); 115 cur_obj_cnt += ar.numOfObjectMember(); 116 } 117 } 118 119 // after all needed member included, merge the archive sub-tree to main 120 // InputTree 121 for (it = ar_list.begin(); it != end; ++it) { 122 Archive& ar = (*it)->archive; 123 if (ar.numOfObjectMember() > 0) { 124 m_Module.getInputTree().merge<InputTree::Inclusive>((*it)->input, 125 ar.inputs()); 126 } 127 } 128 129 // cleanup ar_list 130 for (it = ar_list.begin(); it != end; ++it) { 131 delete &((*it)->archive); 132 delete (*it); 133 } 134 ar_list.clear(); 135 136 return true; 137 } 138 139