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
32using namespace mcld;
33using namespace llvm;
34
35//===----------------------------------------------------------------------===//
36// Forward declarations
37char SectLinker::m_ID = 0;
38static bool CompareOption(const PositionDependentOption* X,
39                          const PositionDependentOption* Y);
40
41//===----------------------------------------------------------------------===//
42// SectLinker
43SectLinker::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
54SectLinker::~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
70bool 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
85bool 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
172bool SectLinker::runOnMachineFunction(MachineFunction& pF)
173{
174  // basically, linkers do nothing during function is generated.
175  return false;
176}
177
178void 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
228void 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
399static bool CompareOption(const PositionDependentOption* X,
400                          const PositionDependentOption* Y)
401{
402  return (X->position() < Y->position());
403}
404
405