Home | History | Annotate | Download | only in lib
      1 //===- PositionalOptions.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/PositionalOptions.h>
     10 #include <mcld/LinkerConfig.h>
     11 #include <mcld/LinkerScript.h>
     12 #include <mcld/MC/InputAction.h>
     13 #include <mcld/MC/CommandAction.h>
     14 #include <mcld/MC/FileAction.h>
     15 #include <mcld/Support/MsgHandling.h>
     16 
     17 namespace {
     18 
     19 //===----------------------------------------------------------------------===//
     20 // Normal input files
     21 //===----------------------------------------------------------------------===//
     22 llvm::cl::list<mcld::sys::fs::Path> ArgInputObjectFiles(llvm::cl::Positional,
     23   llvm::cl::desc("[input object files]"),
     24   llvm::cl::ZeroOrMore);
     25 
     26 // --script is an alias, but cl::alias doesn't work correctly with cl::list.
     27 llvm::cl::list<std::string> ArgLinkerScript("T",
     28   llvm::cl::ZeroOrMore,
     29   llvm::cl::desc("Linker script"),
     30   llvm::cl::value_desc("file"));
     31 
     32 //===----------------------------------------------------------------------===//
     33 // Namespecs
     34 //===----------------------------------------------------------------------===//
     35 llvm::cl::list<std::string> ArgNameSpecList("l",
     36   llvm::cl::ZeroOrMore,
     37   llvm::cl::desc("Add the archive or object file specified by namespec to\n"
     38                  "the list of files to link."),
     39   llvm::cl::value_desc("namespec"),
     40   llvm::cl::Prefix);
     41 
     42 llvm::cl::alias ArgNameSpecListAlias("library",
     43   llvm::cl::desc("alias for -l"),
     44   llvm::cl::aliasopt(ArgNameSpecList));
     45 
     46 //===----------------------------------------------------------------------===//
     47 // Attributes
     48 //===----------------------------------------------------------------------===//
     49 llvm::cl::list<bool> ArgWholeArchiveList("whole-archive",
     50   llvm::cl::ValueDisallowed,
     51   llvm::cl::desc("For each archive mentioned on the command line after\n"
     52                  "the --whole-archive option, include all object files\n"
     53                  "in the archive."));
     54 
     55 llvm::cl::list<bool> ArgNoWholeArchiveList("no-whole-archive",
     56   llvm::cl::ValueDisallowed,
     57   llvm::cl::desc("Turn off the effect of the --whole-archive option for\n"
     58                  "subsequent archive files."));
     59 
     60 llvm::cl::list<bool> ArgAsNeededList("as-needed",
     61   llvm::cl::ValueDisallowed,
     62   llvm::cl::desc("This option affects ELF DT_NEEDED tags for dynamic\n"
     63                  "libraries mentioned on the command line after the\n"
     64                  "--as-needed option."));
     65 
     66 llvm::cl::list<bool> ArgNoAsNeededList("no-as-needed",
     67   llvm::cl::ValueDisallowed,
     68   llvm::cl::desc("Turn off the effect of the --as-needed option for\n"
     69                  "subsequent dynamic libraries"));
     70 
     71 llvm::cl::list<bool> ArgAddNeededList("add-needed",
     72   llvm::cl::ValueDisallowed,
     73   llvm::cl::desc("--add-needed causes DT_NEEDED tags are always\n"
     74                  "emitted for those libraries from DT_NEEDED tags.\n"
     75                  "This is the default behavior."));
     76 
     77 llvm::cl::list<bool> ArgNoAddNeededList("no-add-needed",
     78   llvm::cl::ValueDisallowed,
     79   llvm::cl::desc("--no-add-needed causes DT_NEEDED tags will never be\n"
     80                  "emitted for those libraries from DT_NEEDED tags"));
     81 
     82 llvm::cl::list<bool> ArgBDynamicList("Bdynamic",
     83   llvm::cl::ValueDisallowed,
     84   llvm::cl::desc("Link against dynamic library"));
     85 
     86 llvm::cl::alias ArgBDynamicListAlias1("dy",
     87   llvm::cl::desc("alias for --Bdynamic"),
     88   llvm::cl::aliasopt(ArgBDynamicList));
     89 
     90 llvm::cl::alias ArgBDynamicListAlias2("call_shared",
     91   llvm::cl::desc("alias for --Bdynamic"),
     92   llvm::cl::aliasopt(ArgBDynamicList));
     93 
     94 llvm::cl::list<bool> ArgBStaticList("Bstatic",
     95   llvm::cl::ValueDisallowed,
     96   llvm::cl::desc("Link against static library"));
     97 
     98 llvm::cl::alias ArgBStaticListAlias1("dn",
     99   llvm::cl::desc("alias for --Bstatic"),
    100   llvm::cl::aliasopt(ArgBStaticList));
    101 
    102 llvm::cl::alias ArgBStaticListAlias2("static",
    103   llvm::cl::desc("alias for --Bstatic"),
    104   llvm::cl::aliasopt(ArgBStaticList));
    105 
    106 llvm::cl::alias ArgBStaticListAlias3("non_shared",
    107   llvm::cl::desc("alias for --Bstatic"),
    108   llvm::cl::aliasopt(ArgBStaticList));
    109 
    110 //===----------------------------------------------------------------------===//
    111 // Groups
    112 //===----------------------------------------------------------------------===//
    113 llvm::cl::list<bool> ArgStartGroupList("start-group",
    114   llvm::cl::ValueDisallowed,
    115   llvm::cl::desc("start to record a group of archives"));
    116 
    117 llvm::cl::alias ArgStartGroupListAlias("(",
    118   llvm::cl::desc("alias for --start-group"),
    119   llvm::cl::aliasopt(ArgStartGroupList));
    120 
    121 llvm::cl::list<bool> ArgEndGroupList("end-group",
    122   llvm::cl::ValueDisallowed,
    123   llvm::cl::desc("stop recording a group of archives"));
    124 
    125 llvm::cl::alias ArgEndGroupListAlias(")",
    126   llvm::cl::desc("alias for --end-group"),
    127   llvm::cl::aliasopt(ArgEndGroupList));
    128 
    129 //===----------------------------------------------------------------------===//
    130 // --defsym
    131 //===----------------------------------------------------------------------===//
    132 llvm::cl::list<std::string> ArgDefSymList("defsym",
    133   llvm::cl::ZeroOrMore,
    134   llvm::cl::desc("Define a symbol"),
    135   llvm::cl::value_desc("symbol=expression"));
    136 
    137 //===----------------------------------------------------------------------===//
    138 // Help Functions
    139 //===----------------------------------------------------------------------===//
    140 inline bool
    141 CompareAction(const mcld::InputAction* X, const mcld::InputAction* Y)
    142 {
    143   return (X->position() < Y->position());
    144 }
    145 
    146 } // anonymous namespace
    147 
    148 using namespace mcld;
    149 
    150 //===----------------------------------------------------------------------===//
    151 // PositionalOptions
    152 //===----------------------------------------------------------------------===//
    153 PositionalOptions::PositionalOptions()
    154   : m_InputObjectFiles(ArgInputObjectFiles),
    155     m_LinkerScript(ArgLinkerScript),
    156     m_NameSpecList(ArgNameSpecList),
    157     m_WholeArchiveList(ArgWholeArchiveList),
    158     m_NoWholeArchiveList(ArgNoWholeArchiveList),
    159     m_AsNeededList(ArgAsNeededList),
    160     m_NoAsNeededList(ArgNoAsNeededList),
    161     m_AddNeededList(ArgAddNeededList),
    162     m_NoAddNeededList(ArgNoAddNeededList),
    163     m_BDynamicList(ArgBDynamicList),
    164     m_BStaticList(ArgBStaticList),
    165     m_StartGroupList(ArgStartGroupList),
    166     m_EndGroupList(ArgEndGroupList),
    167     m_DefSymList(ArgDefSymList) {
    168 }
    169 
    170 size_t PositionalOptions::numOfActions() const
    171 {
    172   return m_InputObjectFiles.size() +
    173          m_LinkerScript.size() +
    174          m_NameSpecList.size() +
    175          m_WholeArchiveList.size() +
    176          m_NoWholeArchiveList.size() +
    177          m_AsNeededList.size() +
    178          m_NoAsNeededList.size() +
    179          m_AddNeededList.size() +
    180          m_NoAddNeededList.size() +
    181          m_BDynamicList.size() +
    182          m_BStaticList.size() +
    183          m_StartGroupList.size() +
    184          m_EndGroupList.size() +
    185          m_DefSymList.size();
    186 }
    187 
    188 size_t PositionalOptions::numOfInputs() const
    189 {
    190   return (m_InputObjectFiles.size() +
    191           m_LinkerScript.size() +
    192           m_NameSpecList.size());
    193 }
    194 
    195 bool PositionalOptions::parse(std::vector<InputAction*>& pActions,
    196                               const LinkerConfig& pConfig,
    197                               const LinkerScript& pScript)
    198 {
    199   if (0 == numOfInputs()) {
    200     fatal(diag::err_no_inputs);
    201     return false;
    202   }
    203 
    204   pActions.reserve(numOfActions());
    205 
    206   // -T/--script
    207   // FIXME:
    208   llvm::cl::list<std::string>::iterator sp;
    209   llvm::cl::list<std::string>::iterator spEnd = m_LinkerScript.end();
    210   for (sp = m_LinkerScript.begin(); sp != spEnd; ++sp) {
    211     pActions.push_back(new ScriptAction(0x0,
    212                                        *sp,
    213                                        ScriptFile::LDScript,
    214                                        pScript.directories()));
    215     pActions.push_back(new ContextAction(0x0));
    216     pActions.push_back(new MemoryAreaAction(0x0, FileHandle::ReadOnly));
    217   }
    218 
    219   // --defsym
    220   llvm::cl::list<std::string>::iterator defsym, dsBegin, dsEnd;
    221   dsBegin = m_DefSymList.begin();
    222   dsEnd = m_DefSymList.end();
    223   for (defsym = dsBegin; defsym != dsEnd; ++defsym) {
    224     unsigned int pos = m_DefSymList.getPosition(defsym - dsBegin);
    225     pActions.push_back(new DefSymAction(pos, *defsym));
    226   }
    227 
    228   // set input
    229   llvm::cl::list<mcld::sys::fs::Path>::iterator input, inBegin, inEnd;
    230   inBegin = m_InputObjectFiles.begin();
    231   inEnd = m_InputObjectFiles.end();
    232   for (input = inBegin; input != inEnd; ++input) {
    233     unsigned int pos = m_InputObjectFiles.getPosition(input - inBegin);
    234     pActions.push_back(new InputFileAction(pos, *input));
    235     pActions.push_back(new ContextAction(pos));
    236     pActions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
    237   }
    238 
    239   // set -l[namespec]
    240   llvm::cl::list<std::string>::iterator namespec, nsBegin, nsEnd;
    241   nsBegin = m_NameSpecList.begin();
    242   nsEnd = m_NameSpecList.end();
    243   for (namespec = nsBegin; namespec != nsEnd; ++namespec) {
    244     unsigned int pos = m_NameSpecList.getPosition(namespec - nsBegin);
    245     pActions.push_back(new NamespecAction(pos, *namespec,
    246                                           pScript.directories()));
    247     pActions.push_back(new ContextAction(pos));
    248     pActions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
    249   }
    250 
    251   // set --whole-archive
    252   llvm::cl::list<bool>::iterator attr, attrBegin, attrEnd;
    253   attrBegin = m_WholeArchiveList.begin();
    254   attrEnd   = m_WholeArchiveList.end();
    255   for (attr = attrBegin; attr != attrEnd; ++attr) {
    256     unsigned int pos = m_WholeArchiveList.getPosition(attr - attrBegin);
    257     pActions.push_back(new WholeArchiveAction(pos));
    258   }
    259 
    260   // set --no-whole-archive
    261   attrBegin = m_NoWholeArchiveList.begin();
    262   attrEnd   = m_NoWholeArchiveList.end();
    263   for (attr = attrBegin; attr != attrEnd; ++attr) {
    264     unsigned int pos = m_NoWholeArchiveList.getPosition(attr - attrBegin);
    265     pActions.push_back(new NoWholeArchiveAction(pos));
    266   }
    267 
    268   // set --as-needed
    269   attrBegin = m_AsNeededList.begin();
    270   attrEnd   = m_AsNeededList.end();
    271   for (attr = attrBegin; attr != attrEnd; ++attr) {
    272     unsigned int pos = m_AsNeededList.getPosition(attr - attrBegin);
    273     pActions.push_back(new AsNeededAction(pos));
    274   }
    275 
    276   // set --no-as-needed
    277   attrBegin = m_NoAsNeededList.begin();
    278   attrEnd   = m_NoAsNeededList.end();
    279   for (attr = attrBegin; attr != attrEnd; ++attr) {
    280     unsigned int pos = m_NoAsNeededList.getPosition(attr - attrBegin);
    281     pActions.push_back(new NoAsNeededAction(pos));
    282   }
    283 
    284   // set --add--needed
    285   attrBegin = m_AddNeededList.begin();
    286   attrEnd   = m_AddNeededList.end();
    287   for (attr = attrBegin; attr != attrEnd; ++attr) {
    288     unsigned int pos = m_AddNeededList.getPosition(attr - attrBegin);
    289     pActions.push_back(new AddNeededAction(pos));
    290   }
    291 
    292   // set --no-add--needed
    293   attrBegin = m_NoAddNeededList.begin();
    294   attrEnd   = m_NoAddNeededList.end();
    295   for (attr = attrBegin; attr != attrEnd; ++attr) {
    296     unsigned int pos = m_NoAddNeededList.getPosition(attr - attrBegin);
    297     pActions.push_back(new NoAddNeededAction(pos));
    298   }
    299 
    300   // set --Bdynamic
    301   attrBegin = m_BDynamicList.begin();
    302   attrEnd   = m_BDynamicList.end();
    303   for (attr = attrBegin; attr != attrEnd; ++attr) {
    304     unsigned int pos = m_BDynamicList.getPosition(attr - attrBegin);
    305     pActions.push_back(new BDynamicAction(pos));
    306   }
    307 
    308   // set --Bstatic
    309   attrBegin = m_BStaticList.begin();
    310   attrEnd   = m_BStaticList.end();
    311   for (attr = attrBegin; attr != attrEnd; ++attr) {
    312     unsigned int pos = m_BStaticList.getPosition(attr - attrBegin);
    313     pActions.push_back(new BStaticAction(pos));
    314   }
    315 
    316   // set --start-group
    317   llvm::cl::list<bool>::iterator group, gsBegin, gsEnd;
    318   gsBegin = m_StartGroupList.begin();
    319   gsEnd   = m_StartGroupList.end();
    320   for (group = gsBegin; group != gsEnd; ++group) {
    321     unsigned int pos = m_StartGroupList.getPosition(group - gsBegin);
    322     pActions.push_back(new StartGroupAction(pos));
    323   }
    324 
    325   // set --end-group
    326   gsBegin = m_EndGroupList.begin();
    327   gsEnd   = m_EndGroupList.end();
    328   for (group = gsBegin; group != gsEnd; ++group) {
    329     unsigned int pos = m_EndGroupList.getPosition(group - gsBegin);
    330     pActions.push_back(new EndGroupAction(pos));
    331   }
    332 
    333   // stable sort
    334   std::stable_sort(pActions.begin(), pActions.end(), CompareAction);
    335 
    336   return true;
    337 }
    338 
    339