• 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 #include <mcld/Support/FileHandle.h>
14 #include <mcld/MC/InputTree.h>
15 #include <mcld/MC/MCLDDriver.h>
16 #include <mcld/Support/FileSystem.h>
17 #include <mcld/Support/MsgHandling.h>
18 #include <mcld/Support/FileHandle.h>
19 #include <mcld/Support/raw_ostream.h>
20 #include <mcld/Support/MemoryAreaFactory.h>
21 #include <mcld/Support/DerivedPositionDependentOptions.h>
22 #include <mcld/Target/TargetLDBackend.h>
23 #include <mcld/CodeGen/SectLinker.h>
24 #include <mcld/CodeGen/SectLinkerOption.h>
25 
26 #include <llvm/Module.h>
27 
28 #include <algorithm>
29 #include <stack>
30 #include <string>
31 
32 using namespace mcld;
33 using namespace llvm;
34 
35 //===----------------------------------------------------------------------===//
36 // Forward declarations
37 char SectLinker::m_ID = 0;
38 static bool CompareOption(const PositionDependentOption* X,
39                           const PositionDependentOption* Y);
40 
41 //===----------------------------------------------------------------------===//
42 // SectLinker
SectLinker(SectLinkerOption & pOption,TargetLDBackend & pLDBackend)43 SectLinker::SectLinker(SectLinkerOption &pOption,
44                        TargetLDBackend& pLDBackend)
45   : MachineFunctionPass(m_ID),
46     m_pOption(&pOption),
47     m_pLDBackend(&pLDBackend),
48     m_pLDDriver(NULL),
49     m_pMemAreaFactory(NULL)
50 {
51   m_pMemAreaFactory = new MemoryAreaFactory(32);
52 }
53 
~SectLinker()54 SectLinker::~SectLinker()
55 {
56   delete m_pLDDriver;
57 
58   // FIXME: current implementation can not change the order of delete.
59   //
60   // Instance of TargetLDBackend was created outside and is not managed by
61   // SectLinker. It should not be destroyed here and by SectLinker. However, in
62   // order to follow the LLVM convention - that is, the pass manages all the
63   // objects it used during the processing, we destroy the object of
64   // TargetLDBackend here.
65   delete m_pLDBackend;
66 
67   delete m_pMemAreaFactory;
68 }
69 
doInitialization(Module & pM)70 bool SectLinker::doInitialization(Module &pM)
71 {
72   MCLDInfo &info = m_pOption->info();
73 
74   // ----- convert position dependent options into tree of input files  ----- //
75   PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
76   std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
77   initializeInputTree(PosDepOpts);
78   initializeInputOutput(info);
79   // Now, all input arguments are prepared well, send it into MCLDDriver
80   m_pLDDriver = new MCLDDriver(info, *m_pLDBackend, *memAreaFactory());
81 
82   return false;
83 }
84 
doFinalization(Module & pM)85 bool SectLinker::doFinalization(Module &pM)
86 {
87   const MCLDInfo &info = m_pOption->info();
88 
89   // 2. - initialize MCLinker
90   if (!m_pLDDriver->initMCLinker())
91     return true;
92 
93   // 3. - initialize output's standard sections
94   if (!m_pLDDriver->initStdSections())
95     return true;
96 
97   // 4. - normalize the input tree
98   m_pLDDriver->normalize();
99 
100   if (info.options().trace()) {
101     static int counter = 0;
102     mcld::outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
103     InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
104     for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
105       mcld::outs() << counter++ << " *  " << (*input)->name();
106       switch((*input)->type()) {
107       case Input::Archive:
108         mcld::outs() << "\tarchive\t(";
109         break;
110       case Input::Object:
111         mcld::outs() << "\tobject\t(";
112         break;
113       case Input::DynObj:
114         mcld::outs() << "\tshared\t(";
115         break;
116       case Input::Script:
117         mcld::outs() << "\tscript\t(";
118         break;
119       case Input::External:
120         mcld::outs() << "\textern\t(";
121         break;
122       default:
123         unreachable(diag::err_cannot_trace_file) << (*input)->type()
124                                                  << (*input)->name()
125                                                  << (*input)->path();
126       }
127       mcld::outs() << (*input)->path() << ")\n";
128     }
129   }
130 
131   // 5. - check if we can do static linking and if we use split-stack.
132   if (!m_pLDDriver->linkable())
133     return true;
134 
135 
136   // 6. - merge all sections
137   if (!m_pLDDriver->mergeSections())
138     return true;
139 
140   // 7. - add standard symbols and target-dependent symbols
141   // m_pLDDriver->addUndefSymbols();
142   if (!m_pLDDriver->addStandardSymbols() ||
143       !m_pLDDriver->addTargetSymbols())
144     return true;
145 
146   // 8. - read all relocation entries from input files
147   m_pLDDriver->readRelocations();
148 
149   // 9. - pre-layout
150   m_pLDDriver->prelayout();
151 
152   // 10. - linear layout
153   m_pLDDriver->layout();
154 
155   // 10.b - post-layout (create segment, instruction relaxing)
156   m_pLDDriver->postlayout();
157 
158   // 11. - finalize symbol value
159   m_pLDDriver->finalizeSymbolValue();
160 
161   // 12. - apply relocations
162   m_pLDDriver->relocation();
163 
164   // 13. - write out output
165   m_pLDDriver->emitOutput();
166 
167   // 14. - post processing
168   m_pLDDriver->postProcessing();
169   return false;
170 }
171 
runOnMachineFunction(MachineFunction & pF)172 bool SectLinker::runOnMachineFunction(MachineFunction& pF)
173 {
174   // basically, linkers do nothing during function is generated.
175   return false;
176 }
177 
initializeInputOutput(MCLDInfo & pLDInfo)178 void SectLinker::initializeInputOutput(MCLDInfo &pLDInfo)
179 {
180   // -----  initialize output file  ----- //
181   FileHandle::Permission perm;
182   if (Output::Object == pLDInfo.output().type())
183     perm = 0544;
184   else
185     perm = 0755;
186 
187   MemoryArea* out_area = memAreaFactory()->produce(pLDInfo.output().path(),
188                                                  FileHandle::ReadWrite,
189                                                  perm);
190 
191   if (!out_area->handler()->isGood()) {
192     // make sure output is openend successfully.
193     fatal(diag::err_cannot_open_output_file) << pLDInfo.output().name()
194                                              << pLDInfo.output().path();
195   }
196 
197   pLDInfo.output().setMemArea(out_area);
198   pLDInfo.output().setContext(pLDInfo.contextFactory().produce());
199 
200   // -----  initialize input files  ----- //
201   InputTree::dfs_iterator input, inEnd = pLDInfo.inputs().dfs_end();
202   for (input = pLDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
203     // already got type - for example, bitcode
204     if ((*input)->type() == Input::Script ||
205         (*input)->type() == Input::Object ||
206         (*input)->type() == Input::DynObj  ||
207         (*input)->type() == Input::Archive)
208       continue;
209 
210     MemoryArea *input_memory =
211         memAreaFactory()->produce((*input)->path(), FileHandle::ReadOnly);
212 
213     if (input_memory->handler()->isGood()) {
214       (*input)->setMemArea(input_memory);
215     }
216     else {
217       error(diag::err_cannot_open_input) << (*input)->name() << (*input)->path();
218       return;
219     }
220 
221     LDContext *input_context =
222         pLDInfo.contextFactory().produce((*input)->path());
223 
224     (*input)->setContext(input_context);
225   }
226 }
227 
initializeInputTree(const PositionDependentOptions & pPosDepOptions) const228 void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
229 {
230   if (pPosDepOptions.empty())
231     fatal(diag::err_no_inputs);
232 
233   MCLDInfo &info = m_pOption->info();
234   PositionDependentOptions::const_iterator option = pPosDepOptions.begin();
235   if (1 == pPosDepOptions.size() &&
236       ((*option)->type() != PositionDependentOption::INPUT_FILE &&
237        (*option)->type() != PositionDependentOption::NAMESPEC) &&
238        (*option)->type() != PositionDependentOption::BITCODE) {
239     // if we only have one positional options, and the option is
240     // not an input file, then emit error message.
241     fatal(diag::err_no_inputs);
242   }
243 
244   // -----  Input tree insertion algorithm  ----- //
245   //   The type of the previsou node indicates the direction of the current
246   //   insertion.
247   //
248   //     root   : the parent node who being inserted.
249   //     mover  : the direcion of current movement.
250   //
251   //   for each positional options:
252   //     insert the options in current root.
253   //     calculate the next movement
254 
255   // Initialization
256   InputTree::Mover *move = &InputTree::Downward;
257   InputTree::iterator root = info.inputs().root();
258   PositionDependentOptions::const_iterator optionEnd = pPosDepOptions.end();
259   std::stack<InputTree::iterator> returnStack;
260 
261   while (option != optionEnd ) {
262 
263     switch ((*option)->type()) {
264       /** bitcode **/
265       case PositionDependentOption::BITCODE: {
266 
267         const BitcodeOption *bitcode_option =
268             static_cast<const BitcodeOption*>(*option);
269 
270         // threat bitcode as an external IR in this version.
271         info.inputs().insert(root, *move,
272                              bitcode_option->path()->native(),
273                              *(bitcode_option->path()),
274                              Input::External);
275 
276         info.setBitcode(**root);
277 
278         // move root on the new created node.
279         move->move(root);
280 
281         // the next file is appended after bitcode file.
282         move = &InputTree::Afterward;
283         break;
284       }
285 
286       /** input object file **/
287       case PositionDependentOption::INPUT_FILE: {
288         const InputFileOption *input_file_option =
289             static_cast<const InputFileOption*>(*option);
290 
291         info.inputs().insert(root, *move,
292                              input_file_option->path()->native(),
293                              *(input_file_option->path()));
294 
295         // move root on the new created node.
296         move->move(root);
297 
298         // the next file is appended after object file.
299         move = &InputTree::Afterward;
300         break;
301       }
302 
303     /** -lnamespec **/
304     case PositionDependentOption::NAMESPEC: {
305       sys::fs::Path* path = NULL;
306       const NamespecOption *namespec_option =
307           static_cast<const NamespecOption*>(*option);
308 
309       // find out the real path of the namespec.
310       if (info.attrFactory().constraint().isSharedSystem()) {
311         // In the system with shared object support, we can find both archive
312         // and shared object.
313 
314         if (info.attrFactory().last().isStatic()) {
315           // with --static, we must search an archive.
316           path = info.options().directories().find(namespec_option->namespec(),
317                                                    Input::Archive);
318         }
319         else {
320           // otherwise, with --Bdynamic, we can find either an archive or a
321           // shared object.
322           path = info.options().directories().find(namespec_option->namespec(),
323                                                    Input::DynObj);
324         }
325       }
326       else {
327         // In the system without shared object support, we only look for an
328         // archive.
329         path = info.options().directories().find(namespec_option->namespec(),
330                                                  Input::Archive);
331       }
332 
333       if (NULL == path)
334         fatal(diag::err_cannot_find_namespec) << namespec_option->namespec();
335 
336       info.inputs().insert(root, *move,
337                            namespec_option->namespec(),
338                            *path);
339 
340       // iterate root on the new created node.
341       move->move(root);
342 
343       // the file after a namespec must be appended afterward.
344       move = &InputTree::Afterward;
345       break;
346     }
347 
348     /** start group **/
349     case PositionDependentOption::START_GROUP:
350       info.inputs().enterGroup(root, *move);
351       move->move(root);
352       returnStack.push(root);
353       move = &InputTree::Downward;
354       break;
355     /** end group **/
356     case PositionDependentOption::END_GROUP:
357       root = returnStack.top();
358       returnStack.pop();
359       move = &InputTree::Afterward;
360       break;
361     case PositionDependentOption::WHOLE_ARCHIVE:
362       info.attrFactory().last().setWholeArchive();
363       break;
364     case PositionDependentOption::NO_WHOLE_ARCHIVE:
365       info.attrFactory().last().unsetWholeArchive();
366       break;
367     case PositionDependentOption::AS_NEEDED:
368       info.attrFactory().last().setAsNeeded();
369       break;
370     case PositionDependentOption::NO_AS_NEEDED:
371       info.attrFactory().last().unsetAsNeeded();
372       break;
373     case PositionDependentOption::ADD_NEEDED:
374       info.attrFactory().last().setAddNeeded();
375       break;
376     case PositionDependentOption::NO_ADD_NEEDED:
377       info.attrFactory().last().unsetAddNeeded();
378       break;
379     case PositionDependentOption::BSTATIC:
380       info.attrFactory().last().setStatic();
381       break;
382     case PositionDependentOption::BDYNAMIC:
383       info.attrFactory().last().setDynamic();
384       break;
385     default:
386       fatal(diag::err_cannot_identify_option) << (*option)->position()
387                                               << (uint32_t)(*option)->type();
388     } // end of switch
389     ++option;
390   } // end of while
391 
392   if (!returnStack.empty()) {
393     report_fatal_error("no matched --start-group and --end-group");
394   }
395 }
396 
397 //===----------------------------------------------------------------------===//
398 // Non-member functions
CompareOption(const PositionDependentOption * X,const PositionDependentOption * Y)399 static bool CompareOption(const PositionDependentOption* X,
400                           const PositionDependentOption* Y)
401 {
402   return (X->position() < Y->position());
403 }
404 
405