Home | History | Annotate | Download | only in lib
      1 //===- OutputFormatOptions.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/OutputFormatOptions.h>
     10 #include <mcld/Module.h>
     11 #include <mcld/Support/MsgHandling.h>
     12 
     13 namespace {
     14 
     15 llvm::cl::opt<mcld::sys::fs::Path,
     16               false,
     17               llvm::cl::parser<mcld::sys::fs::Path> > ArgOutputFilename("o",
     18   llvm::cl::desc("Output filename"),
     19   llvm::cl::value_desc("filename"));
     20 
     21 llvm::cl::alias AliasOutputFilename("output",
     22   llvm::cl::desc("alias for -o"),
     23   llvm::cl::aliasopt(ArgOutputFilename));
     24 
     25 llvm::cl::opt<mcld::LinkerConfig::CodeGenType> ArgFileType("filetype",
     26   llvm::cl::init(mcld::LinkerConfig::Exec),
     27   llvm::cl::desc("Choose a file type\n"
     28                  "(not all types are supported by all targets):"),
     29   llvm::cl::values(
     30        clEnumValN(mcld::LinkerConfig::Object, "obj",
     31                   "Emit a relocatable object ('.o') file"),
     32        clEnumValN(mcld::LinkerConfig::DynObj, "dso",
     33                   "Emit an dynamic shared object ('.so') file"),
     34        clEnumValN(mcld::LinkerConfig::Exec, "exe",
     35                   "Emit an executable ('.exe') file"),
     36        clEnumValN(mcld::LinkerConfig::Binary, "bin",
     37                   "Emit a binary file"),
     38        clEnumValN(mcld::LinkerConfig::External, "null",
     39                   "Emit nothing for performance testing"),
     40        clEnumValEnd));
     41 
     42 llvm::cl::opt<mcld::LinkerConfig::CodeGenType> ArgOFormat("oformat",
     43   llvm::cl::value_desc("Format"),
     44   llvm::cl::desc("set output format"),
     45   llvm::cl::init(mcld::LinkerConfig::Unknown),
     46   llvm::cl::values(
     47     clEnumValN(mcld::LinkerConfig::Binary, "binary",
     48       "generate binary machine code."),
     49     clEnumValEnd));
     50 
     51 llvm::cl::opt<bool> ArgShared("shared",
     52   llvm::cl::ZeroOrMore,
     53   llvm::cl::desc("Create a shared library."),
     54   llvm::cl::init(false));
     55 
     56 llvm::cl::alias ArgSharedAlias("Bshareable",
     57   llvm::cl::desc("alias for -shared"),
     58   llvm::cl::aliasopt(ArgShared));
     59 
     60 llvm::cl::opt<bool> ArgPIE("pie",
     61   llvm::cl::desc("Emit a position-independent executable file"),
     62   llvm::cl::init(false));
     63 
     64 llvm::cl::opt<bool> ArgRelocatable("relocatable",
     65   llvm::cl::desc("Generate relocatable output"),
     66   llvm::cl::init(false));
     67 
     68 llvm::cl::alias ArgRelocatableAlias("r",
     69   llvm::cl::desc("alias for --relocatable"),
     70   llvm::cl::aliasopt(ArgRelocatable));
     71 
     72 llvm::cl::opt<mcld::Input::Type> ArgFormat("b",
     73   llvm::cl::value_desc("Format"),
     74   llvm::cl::desc("set input format"),
     75   llvm::cl::init(mcld::Input::Unknown),
     76   llvm::cl::values(
     77     clEnumValN(mcld::Input::Binary, "binary",
     78       "read in binary machine code."),
     79     clEnumValEnd));
     80 
     81 llvm::cl::alias ArgFormatAlias("format",
     82   llvm::cl::desc("alias for -b"),
     83   llvm::cl::aliasopt(ArgFormat));
     84 
     85 llvm::cl::opt<bool> ArgStripDebug("strip-debug",
     86   llvm::cl::desc("Omit debugger symbol information from the output file."),
     87   llvm::cl::init(false));
     88 
     89 llvm::cl::alias ArgStripDebugAlias("S",
     90   llvm::cl::desc("alias for --strip-debug"),
     91   llvm::cl::aliasopt(ArgStripDebug));
     92 
     93 llvm::cl::opt<bool> ArgStripAll("strip-all",
     94   llvm::cl::desc("Omit all symbol information from the output file."),
     95   llvm::cl::init(false));
     96 
     97 llvm::cl::alias ArgStripAllAlias("s",
     98   llvm::cl::desc("alias for --strip-all"),
     99   llvm::cl::aliasopt(ArgStripAll));
    100 
    101 llvm::cl::opt<bool> ArgDiscardAll("discard-all",
    102   llvm::cl::desc("Delete all local symbols."),
    103   llvm::cl::init(false));
    104 
    105 llvm::cl::alias ArgDiscardAllAlias("x",
    106   llvm::cl::desc("alias for --discard-all"),
    107   llvm::cl::aliasopt(ArgDiscardAll));
    108 
    109 llvm::cl::opt<bool> ArgDiscardLocals("discard-locals",
    110   llvm::cl::desc("Delete all temporary local symbols."),
    111   llvm::cl::init(false));
    112 
    113 llvm::cl::alias ArgDiscardLocalsAlias("X",
    114   llvm::cl::desc("alias for --discard-locals"),
    115   llvm::cl::aliasopt(ArgDiscardLocals));
    116 
    117 llvm::cl::opt<bool> ArgEhFrameHdr("eh-frame-hdr",
    118   llvm::cl::ZeroOrMore,
    119   llvm::cl::desc("Request creation of \".eh_frame_hdr\" section and\n"
    120                  "ELF \"PT_GNU_EH_FRAME\" segment header."),
    121   llvm::cl::init(false));
    122 
    123 llvm::cl::opt<bool> ArgNMagic("nmagic",
    124   llvm::cl::desc("Do not page align data"),
    125   llvm::cl::init(false));
    126 
    127 llvm::cl::alias ArgNMagicAlias("n",
    128   llvm::cl::desc("alias for --nmagic"),
    129   llvm::cl::aliasopt(ArgNMagic));
    130 
    131 llvm::cl::opt<bool> ArgOMagic("omagic",
    132   llvm::cl::desc("Do not page align data, do not make text readonly"),
    133   llvm::cl::init(false));
    134 
    135 llvm::cl::alias ArgOMagicAlias("N",
    136   llvm::cl::desc("alias for --omagic"),
    137   llvm::cl::aliasopt(ArgOMagic));
    138 
    139 llvm::cl::opt<mcld::GeneralOptions::HashStyle> ArgHashStyle("hash-style",
    140   llvm::cl::init(mcld::GeneralOptions::SystemV),
    141   llvm::cl::desc("Set the type of linker's hash table(s)."),
    142   llvm::cl::values(
    143        clEnumValN(mcld::GeneralOptions::SystemV, "sysv",
    144                  "classic ELF .hash section"),
    145        clEnumValN(mcld::GeneralOptions::GNU, "gnu",
    146                  "new style GNU .gnu.hash section"),
    147        clEnumValN(mcld::GeneralOptions::Both, "both",
    148                  "both the classic ELF and new style GNU hash tables"),
    149        clEnumValEnd));
    150 
    151 llvm::cl::opt<bool> ArgNoWarnMismatch("no-warn-mismatch",
    152   llvm::cl::desc("Allow linking together mismatched input files."),
    153   llvm::cl::init(false));
    154 
    155 // Not supported yet {
    156 llvm::cl::opt<bool> ArgExportDynamic("export-dynamic",
    157   llvm::cl::desc("Export all dynamic symbols"),
    158   llvm::cl::init(false));
    159 
    160 llvm::cl::alias ArgExportDynamicAlias("E",
    161   llvm::cl::desc("alias for --export-dynamic"),
    162   llvm::cl::aliasopt(ArgExportDynamic));
    163 
    164 llvm::cl::opt<std::string> ArgBuildID("build-id",
    165   llvm::cl::desc("Request creation of \".note.gnu.build-id\" ELF note section."),
    166   llvm::cl::value_desc("style"),
    167   llvm::cl::ValueOptional);
    168 
    169 llvm::cl::list<std::string> ArgExcludeLIBS("exclude-libs",
    170   llvm::cl::CommaSeparated,
    171   llvm::cl::desc("Exclude libraries from automatic export"),
    172   llvm::cl::value_desc("lib1,lib2,..."));
    173 
    174 // } Not supported yet
    175 
    176 } // anonymous namespace
    177 
    178 using namespace mcld;
    179 
    180 //===----------------------------------------------------------------------===//
    181 // OutputFormatOptions
    182 //===----------------------------------------------------------------------===//
    183 OutputFormatOptions::OutputFormatOptions()
    184   : m_OutputFilename(ArgOutputFilename),
    185     m_FileType(ArgFileType),
    186     m_OFormat(ArgOFormat),
    187     m_Shared(ArgShared),
    188     m_PIE(ArgPIE),
    189     m_Relocatable(ArgRelocatable),
    190     m_Format(ArgFormat),
    191     m_StripDebug(ArgStripDebug),
    192     m_StripAll(ArgStripAll),
    193     m_DiscardAll(ArgDiscardAll),
    194     m_DiscardLocals(ArgDiscardLocals),
    195     m_EhFrameHdr(ArgEhFrameHdr),
    196     m_NMagic(ArgNMagic),
    197     m_OMagic(ArgOMagic),
    198     m_HashStyle(ArgHashStyle),
    199     m_ExportDynamic(ArgExportDynamic),
    200     m_BuildID(ArgBuildID),
    201     m_ExcludeLIBS(ArgExcludeLIBS),
    202     m_NoWarnMismatch(ArgNoWarnMismatch) {
    203 }
    204 
    205 bool OutputFormatOptions::parse(mcld::Module& pModule, LinkerConfig& pConfig)
    206 {
    207   if (!parseOutput(pModule, pConfig)) {
    208     mcld::unreachable(mcld::diag::unrecognized_output_file) << pModule.name();
    209     return false;
    210   }
    211 
    212   if (mcld::Input::Binary == m_Format)
    213     pConfig.options().setBinaryInput();
    214 
    215   pConfig.options().setStripDebug(m_StripDebug || m_StripAll);
    216   if (m_StripAll)
    217     pConfig.options().setStripSymbols(mcld::GeneralOptions::StripAllSymbols);
    218   else if (m_DiscardAll)
    219     pConfig.options().setStripSymbols(mcld::GeneralOptions::StripLocals);
    220   else if (m_DiscardLocals)
    221     pConfig.options().setStripSymbols(mcld::GeneralOptions::StripTemporaries);
    222   else
    223     pConfig.options().setStripSymbols(mcld::GeneralOptions::KeepAllSymbols);
    224 
    225   pConfig.options().setEhFrameHdr(m_EhFrameHdr);
    226   pConfig.options().setPIE(m_PIE);
    227   pConfig.options().setNMagic(m_NMagic);
    228   pConfig.options().setOMagic(m_OMagic);
    229   pConfig.options().setHashStyle(m_HashStyle);
    230   pConfig.options().setExportDynamic(m_ExportDynamic);
    231 
    232   // --exclude-libs
    233   llvm::cl::list<std::string>::iterator exclude,
    234                                         excludeEnd = m_ExcludeLIBS.end();
    235   for (exclude = m_ExcludeLIBS.begin(); exclude != excludeEnd; ++exclude) {
    236     pConfig.options().excludeLIBS().insert(*exclude);
    237   }
    238 
    239   if (m_NoWarnMismatch)
    240     pConfig.options().setWarnMismatch(false);
    241   else
    242     pConfig.options().setWarnMismatch(true);
    243   // build-id
    244   // exclude-libs
    245 
    246   return true;
    247 }
    248 
    249 /// configure the output filename
    250 bool OutputFormatOptions::parseOutput(Module& pModule, LinkerConfig& pConfig)
    251 {
    252   if (true == m_Shared || true == m_PIE) {
    253     // -shared or -pie
    254     m_FileType = mcld::LinkerConfig::DynObj;
    255   }
    256   else if (true == m_Relocatable) {
    257     // partial linking
    258     m_FileType = mcld::LinkerConfig::Object;
    259   }
    260   else if (mcld::LinkerConfig::Binary == m_OFormat) {
    261     // binary output
    262     m_FileType = mcld::LinkerConfig::Binary;
    263   }
    264 
    265   pConfig.setCodeGenType(m_FileType);
    266 
    267   std::string output_filename(m_OutputFilename.native());
    268 
    269   if (m_OutputFilename.empty()) {
    270 
    271     if (llvm::Triple::Win32 == pConfig.targets().triple().getOS()) {
    272       output_filename.assign("_out");
    273       switch (m_FileType) {
    274         case mcld::LinkerConfig::Object: {
    275           output_filename += ".obj";
    276         break;
    277         }
    278         case mcld::LinkerConfig::DynObj: {
    279           output_filename += ".dll";
    280           break;
    281         }
    282         case mcld::LinkerConfig::Exec: {
    283           output_filename += ".exe";
    284           break;
    285         }
    286         case mcld::LinkerConfig::External:
    287           break;
    288         default: {
    289           return false;
    290           break;
    291         }
    292       } // switch
    293     }
    294     else {
    295       if (mcld::LinkerConfig::Object   == m_FileType ||
    296           mcld::LinkerConfig::DynObj   == m_FileType ||
    297           mcld::LinkerConfig::Exec     == m_FileType ||
    298           mcld::LinkerConfig::External == m_FileType) {
    299         output_filename.assign("a.out");
    300       }
    301       else {
    302         return false;
    303       }
    304     }
    305   } // end of if empty m_OutputFilename
    306 
    307   pModule.setName(output_filename);
    308   return true;
    309 }
    310