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