• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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