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