• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- SectLinker.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 //
10 // This file implements the SectLinker class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include <mcld/ADT/BinTree.h>
15 #include <mcld/CodeGen/SectLinker.h>
16 #include <mcld/CodeGen/SectLinkerOption.h>
17 #include <mcld/MC/MCLDInputTree.h>
18 #include <mcld/MC/MCLDDriver.h>
19 #include <mcld/Support/DerivedPositionDependentOptions.h>
20 #include <mcld/Support/FileSystem.h>
21 #include <mcld/Target/TargetLDBackend.h>
22 
23 #include <llvm/Module.h>
24 #include <llvm/Support/ErrorHandling.h>
25 #include <llvm/Support/raw_ostream.h>
26 
27 #include <algorithm>
28 #include <stack>
29 #include <string>
30 
31 using namespace mcld;
32 using namespace llvm;
33 
34 //===----------------------------------------------------------------------===//
35 // Forward declarations
36 char SectLinker::m_ID = 0;
37 static bool CompareOption(const PositionDependentOption* X,
38                           const PositionDependentOption* Y);
39 
40 //===----------------------------------------------------------------------===//
41 // SectLinker
SectLinker(SectLinkerOption & pOption,TargetLDBackend & pLDBackend)42 SectLinker::SectLinker(SectLinkerOption &pOption,
43                        TargetLDBackend& pLDBackend)
44   : MachineFunctionPass(m_ID),
45     m_pOption(&pOption),
46     m_pLDBackend(&pLDBackend),
47     m_pLDDriver(NULL) { }
48 
~SectLinker()49 SectLinker::~SectLinker()
50 {
51   delete m_pLDDriver;
52   // FIXME: current implementation can not change the order of delete.
53   //
54   // Instance of TargetLDBackend was created outside and is not managed by
55   // SectLinker. It should not be destroyed here and by SectLinker. However, in
56   // order to follow the LLVM convention - that is, the pass manages all the
57   // objects it used during the processing, we destroy the object of
58   // TargetLDBackend here.
59   delete m_pLDBackend;
60 }
61 
doInitialization(Module & pM)62 bool SectLinker::doInitialization(Module &pM)
63 {
64   MCLDInfo &info = m_pOption->info();
65 
66   // setup the output
67   info.output().setContext(info.contextFactory().produce(info.output().path()));
68 
69   int mode = (Output::Object == info.output().type())? 0544 : 0755;
70   info.output().setMemArea(
71       info.memAreaFactory().produce(info.output().path(),
72                                     O_RDWR | O_CREAT | O_TRUNC,
73                                     mode));
74 
75   //   make sure output is openend successfully.
76   if (!info.output().hasMemArea())
77     report_fatal_error("output is not given on the command line\n");
78 
79   if (!info.output().memArea()->isGood())
80     report_fatal_error("can not open output file :"+info.output().path().native());
81 
82   // let the target override the target-specific parameters
83   addTargetOptions(pM, *m_pOption);
84 
85   // ----- convert position dependent options into tree of input files  ----- //
86   PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
87   std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
88   initializeInputTree(PosDepOpts);
89 
90   // Now, all input arguments are prepared well, send it into MCLDDriver
91   m_pLDDriver = new MCLDDriver(info, *m_pLDBackend);
92 
93   return false;
94 }
95 
doFinalization(Module & pM)96 bool SectLinker::doFinalization(Module &pM)
97 {
98   const MCLDInfo &info = m_pOption->info();
99 
100   // 3. - initialize output's standard segments and sections
101   if (!m_pLDDriver->initMCLinker())
102     return true;
103 
104   // 4. - normalize the input tree
105   m_pLDDriver->normalize();
106 
107   if (info.options().verbose()) {
108     outs() << "MCLinker (LLVM Sub-project) - ";
109     outs() << MCLDInfo::version();
110     outs() << "\n";
111   }
112 
113   if (info.options().trace()) {
114     static int counter = 0;
115     outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
116     InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
117     for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
118       outs() << counter++ << " *  " << (*input)->name();
119       switch((*input)->type()) {
120       case Input::Archive:
121         outs() << "\tarchive\t(";
122         break;
123       case Input::Object:
124         outs() << "\tobject\t(";
125         break;
126       case Input::DynObj:
127         outs() << "\tshared\t(";
128         break;
129       case Input::Script:
130         outs() << "\tscript\t(";
131         break;
132       default:
133         report_fatal_error("** Trace a unsupported file. It must be an internal bug!");
134       }
135       outs() << (*input)->path().c_str() << ")\n";
136     }
137   }
138 
139   // 5. - check if we can do static linking and if we use split-stack.
140   if (!m_pLDDriver->linkable())
141     return true;
142 
143 
144   // 6. - read all sections
145   if (!m_pLDDriver->readSections() ||
146       !m_pLDDriver->mergeSections())
147     return true;
148 
149   // 7. - read all symbol tables of input files and resolve them
150   if (!m_pLDDriver->readSymbolTables() ||
151       !m_pLDDriver->mergeSymbolTables())
152     return true;
153 
154   // 7.a - add standard symbols and target-dependent symbols
155   // m_pLDDriver->addUndefSymbols();
156   if (!m_pLDDriver->addStandardSymbols() ||
157       !m_pLDDriver->addTargetSymbols())
158     return true;
159 
160   // 8. - read all relocation entries from input files
161   m_pLDDriver->readRelocations();
162 
163   // 9. - pre-layout
164   m_pLDDriver->prelayout();
165 
166   // 10. - linear layout
167   m_pLDDriver->layout();
168 
169   // 10.b - post-layout
170   m_pLDDriver->postlayout();
171 
172   // 11. - finalize symbol value
173   m_pLDDriver->finalizeSymbolValue();
174 
175   // 12. - apply relocations
176   m_pLDDriver->relocate();
177 
178   // 13. - write out output
179   m_pLDDriver->emitOutput();
180 
181   // 14. - post processing
182   m_pLDDriver->postProcessing();
183   return false;
184 }
185 
runOnMachineFunction(MachineFunction & pF)186 bool SectLinker::runOnMachineFunction(MachineFunction& pF)
187 {
188   // basically, linkers do nothing during function is generated.
189   return false;
190 }
191 
initializeInputTree(const PositionDependentOptions & pPosDepOptions) const192 void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
193 {
194   if (pPosDepOptions.empty())
195     return;
196 
197   MCLDInfo &info = m_pOption->info();
198   PositionDependentOptions::const_iterator cur_char = pPosDepOptions.begin();
199   if (1 == pPosDepOptions.size() &&
200       ((*cur_char)->type() != PositionDependentOption::INPUT_FILE &&
201        (*cur_char)->type() != PositionDependentOption::NAMESPEC))
202     return;
203 
204   InputTree::Connector *prev_ward = &InputTree::Downward;
205 
206   std::stack<InputTree::iterator> returnStack;
207   InputTree::iterator cur_node = info.inputs().root();
208 
209   PositionDependentOptions::const_iterator charEnd = pPosDepOptions.end();
210   while (cur_char != charEnd ) {
211     switch ((*cur_char)->type()) {
212     case PositionDependentOption::BITCODE: {
213       // threat bitcode as a script in this version.
214       const BitcodeOption *bitcode_option =
215           static_cast<const BitcodeOption*>(*cur_char);
216       info.inputs().insert(cur_node,
217                            *prev_ward,
218                            bitcode_option->path()->native(),
219                            *(bitcode_option->path()),
220                            Input::Script);
221       info.setBitcode(**cur_node);
222       prev_ward->move(cur_node);
223       prev_ward = &InputTree::Afterward;
224       break;
225     }
226     case PositionDependentOption::INPUT_FILE: {
227       const InputFileOption *input_file_option =
228           static_cast<const InputFileOption*>(*cur_char);
229       info.inputs().insert(cur_node,
230                            *prev_ward,
231                            input_file_option->path()->native(),
232                            *(input_file_option->path()));
233       prev_ward->move(cur_node);
234       prev_ward = &InputTree::Afterward;
235       break;
236     }
237     case PositionDependentOption::NAMESPEC: {
238       sys::fs::Path* path = 0;
239       const NamespecOption *namespec_option =
240           static_cast<const NamespecOption*>(*cur_char);
241       if (info.attrFactory().last().isStatic()) {
242         path = info.options().directories().find(namespec_option->namespec(),
243                                                  Input::Archive);
244       }
245       else {
246         path = info.options().directories().find(namespec_option->namespec(),
247                                                  Input::DynObj);
248       }
249 
250       if (0 == path) {
251         llvm::report_fatal_error(std::string("Can't find namespec: ")+
252                                  namespec_option->namespec());
253       }
254       info.inputs().insert(cur_node,
255                            *prev_ward,
256                            namespec_option->namespec(),
257                            *path);
258       prev_ward->move(cur_node);
259       prev_ward = &InputTree::Afterward;
260       break;
261     }
262     case PositionDependentOption::START_GROUP:
263       info.inputs().enterGroup(cur_node, *prev_ward);
264       prev_ward->move(cur_node);
265       returnStack.push(cur_node);
266       prev_ward = &InputTree::Downward;
267       break;
268     case PositionDependentOption::END_GROUP:
269       cur_node = returnStack.top();
270       returnStack.pop();
271       prev_ward = &InputTree::Afterward;
272       break;
273     case PositionDependentOption::WHOLE_ARCHIVE:
274       info.attrFactory().last().setWholeArchive();
275       break;
276     case PositionDependentOption::NO_WHOLE_ARCHIVE:
277       info.attrFactory().last().unsetWholeArchive();
278       break;
279     case PositionDependentOption::AS_NEEDED:
280       info.attrFactory().last().setAsNeeded();
281       break;
282     case PositionDependentOption::NO_AS_NEEDED:
283       info.attrFactory().last().unsetAsNeeded();
284       break;
285     case PositionDependentOption::ADD_NEEDED:
286       info.attrFactory().last().setAddNeeded();
287       break;
288     case PositionDependentOption::NO_ADD_NEEDED:
289       info.attrFactory().last().unsetAddNeeded();
290       break;
291     case PositionDependentOption::BSTATIC:
292       info.attrFactory().last().setStatic();
293       break;
294     case PositionDependentOption::BDYNAMIC:
295       info.attrFactory().last().setDynamic();
296       break;
297     default:
298       report_fatal_error("can not find the type of input file");
299     }
300     ++cur_char;
301   }
302 
303   if (!returnStack.empty()) {
304     report_fatal_error("no matched --start-group and --end-group");
305   }
306 }
307 
308 //===----------------------------------------------------------------------===//
309 // Non-member functions
CompareOption(const PositionDependentOption * X,const PositionDependentOption * Y)310 static bool CompareOption(const PositionDependentOption* X,
311                           const PositionDependentOption* Y)
312 {
313   return (X->position() < Y->position());
314 }
315 
316