GroupReader.cpp revision f7ac0f19a1c8d0ad14bcf6456ce368b830fea886
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
19using namespace mcld;
20
21GroupReader::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
34GroupReader::~GroupReader()
35{
36}
37
38bool 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