GroupReader.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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
18using namespace mcld;
19
20GroupReader::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
31GroupReader::~GroupReader()
32{
33}
34
35bool 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.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