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 
GroupReader(Module & pModule,ObjectReader & pObjectReader,DynObjReader & pDynObjReader,ArchiveReader & pArchiveReader,BinaryReader & pBinaryReader)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 
~GroupReader()34 GroupReader::~GroupReader() {
35 }
36 
readGroup(Module::input_iterator pRoot,Module::input_iterator pEnd,InputBuilder & pBuilder,const LinkerConfig & pConfig)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