GroupReader.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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
20namespace mcld {
21
22GroupReader::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
34GroupReader::~GroupReader() {
35}
36
37bool 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