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
19 using namespace mcld;
20
GroupReader(Module & pModule,ObjectReader & pObjectReader,DynObjReader & pDynObjReader,ArchiveReader & pArchiveReader,BinaryReader & pBinaryReader)21 GroupReader::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
~GroupReader()34 GroupReader::~GroupReader()
35 {
36 }
37
readGroup(Module::input_iterator pRoot,InputBuilder & pBuilder,const LinkerConfig & pConfig)38 bool 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