GroupReader.cpp revision f33f6de54db174aa679a4b6d1e040d37e95541c0
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                            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