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