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