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/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