• 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,Module::input_iterator pEnd,InputBuilder & pBuilder,const LinkerConfig & pConfig)38 bool GroupReader::readGroup(Module::input_iterator pRoot,
39                             Module::input_iterator pEnd,
40                             InputBuilder& pBuilder,
41                             const LinkerConfig& pConfig)
42 {
43   // record the number of total objects included in this sub-tree
44   size_t cur_obj_cnt = 0;
45   size_t last_obj_cnt = 0;
46   size_t non_ar_obj_cnt = 0;
47 
48   // record the archive files in this sub-tree
49   typedef std::vector<ArchiveListEntry*> ArchiveListType;
50   ArchiveListType ar_list;
51 
52   Module::input_iterator input = --pRoot;
53 
54   // first time read the sub-tree
55   while (input != pEnd) {
56     // already got type - for example, bitcode or external OIR (object
57     // intermediate representation)
58     if ((*input)->type() == Input::Script ||
59         (*input)->type() == Input::Archive ||
60         (*input)->type() == Input::External) {
61       ++input;
62       continue;
63     }
64 
65     if (Input::Object == (*input)->type()) {
66       m_Module.getObjectList().push_back(*input);
67       continue;
68     }
69 
70     if (Input::DynObj == (*input)->type()) {
71       m_Module.getLibraryList().push_back(*input);
72       continue;
73     }
74 
75     bool doContinue = false;
76     // is an archive
77     if (m_ArchiveReader.isMyFormat(**input, doContinue)) {
78       (*input)->setType(Input::Archive);
79       // record the Archive used by each archive node
80       Archive* ar = new Archive(**input, pBuilder);
81       ArchiveListEntry* entry = new ArchiveListEntry(*ar, input);
82       ar_list.push_back(entry);
83       // read archive
84       m_ArchiveReader.readArchive(pConfig, *ar);
85       cur_obj_cnt += ar->numOfObjectMember();
86     }
87     // read input as a binary file
88     else if (doContinue && m_BinaryReader.isMyFormat(**input, doContinue)) {
89       (*input)->setType(Input::Object);
90       m_BinaryReader.readBinary(**input);
91       m_Module.getObjectList().push_back(*input);
92     }
93     // is a relocatable object file
94     else if (doContinue && m_ObjectReader.isMyFormat(**input, doContinue)) {
95       (*input)->setType(Input::Object);
96       m_ObjectReader.readHeader(**input);
97       m_ObjectReader.readSections(**input);
98       m_ObjectReader.readSymbols(**input);
99       m_Module.getObjectList().push_back(*input);
100       ++cur_obj_cnt;
101       ++non_ar_obj_cnt;
102     }
103     // is a shared object file
104     else if (doContinue && m_DynObjReader.isMyFormat(**input, doContinue)) {
105       (*input)->setType(Input::DynObj);
106       m_DynObjReader.readHeader(**input);
107       m_DynObjReader.readSymbols(**input);
108       m_Module.getLibraryList().push_back(*input);
109     }
110     else {
111       warning(diag::warn_unrecognized_input_file) << (*input)->path()
112         << pConfig.targets().triple().str();
113     }
114     ++input;
115   }
116 
117   // after read in all the archives, traverse the archive list in a loop until
118   // there is no unresolved symbols added
119   ArchiveListType::iterator it = ar_list.begin();
120   ArchiveListType::iterator end = ar_list.end();
121   while (cur_obj_cnt != last_obj_cnt) {
122     last_obj_cnt = cur_obj_cnt;
123     cur_obj_cnt = non_ar_obj_cnt;
124     for (it = ar_list.begin(); it != end; ++it) {
125       Archive& ar = (*it)->archive;
126       // if --whole-archive is given to this archive, no need to read it again
127       if ( ar.getARFile().attribute()->isWholeArchive())
128         continue;
129       m_ArchiveReader.readArchive(pConfig, ar);
130       cur_obj_cnt += ar.numOfObjectMember();
131     }
132   }
133 
134   // after all needed member included, merge the archive sub-tree to main
135   // InputTree
136   for (it = ar_list.begin(); it != end; ++it) {
137     Archive& ar = (*it)->archive;
138     if (ar.numOfObjectMember() > 0) {
139       m_Module.getInputTree().merge<InputTree::Inclusive>((*it)->input,
140                                                           ar.inputs());
141     }
142   }
143 
144   // cleanup ar_list
145   for (it = ar_list.begin(); it != end; ++it) {
146     delete &((*it)->archive);
147     delete (*it);
148   }
149   ar_list.clear();
150 
151   return true;
152 }
153 
154