Home | History | Annotate | Download | only in CodeGen
      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
     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 
     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 
     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 
     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 
    186 bool SectLinker::runOnMachineFunction(MachineFunction& pF)
    187 {
    188   // basically, linkers do nothing during function is generated.
    189   return false;
    190 }
    191 
    192 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
    310 static bool CompareOption(const PositionDependentOption* X,
    311                           const PositionDependentOption* Y)
    312 {
    313   return (X->position() < Y->position());
    314 }
    315 
    316