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