1 //===- main.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/PreferenceOptions.h> 10 #include <mcld/TripleOptions.h> 11 #include <mcld/DynamicSectionOptions.h> 12 #include <mcld/OutputFormatOptions.h> 13 #include <mcld/SearchPathOptions.h> 14 #include <mcld/OptimizationOptions.h> 15 #include <mcld/SymbolOptions.h> 16 #include <mcld/TargetControlOptions.h> 17 #include <mcld/ScriptOptions.h> 18 #include <mcld/PositionalOptions.h> 19 20 #include <mcld/Module.h> 21 #include <mcld/Environment.h> 22 #include <mcld/LinkerConfig.h> 23 #include <mcld/LinkerScript.h> 24 #include <mcld/Linker.h> 25 #include <mcld/IRBuilder.h> 26 #include <mcld/MC/InputAction.h> 27 #include <mcld/Support/raw_ostream.h> 28 #include <mcld/Support/MsgHandling.h> 29 #include <llvm/Support/ManagedStatic.h> 30 #include <llvm/Support/Signals.h> 31 #include <string> 32 #include <cassert> 33 34 /// configure linker 35 static inline bool ConfigLinker(int pArgc, 36 char* pArgv[], 37 const char* pName, 38 mcld::Module& pModule, 39 mcld::LinkerScript& pScript, 40 mcld::LinkerConfig& pConfig, 41 mcld::IRBuilder& pBuilder, 42 std::vector<mcld::InputAction*>& pInputActions) 43 { 44 mcld::PreferenceOptions preference; 45 mcld::TripleOptions triple; 46 mcld::DynamicSectionOptions dynamic_section; 47 mcld::OutputFormatOptions output_format; 48 mcld::SearchPathOptions search_path; 49 mcld::OptimizationOptions optimization; 50 mcld::SymbolOptions symbol; 51 mcld::TargetControlOptions target_control; 52 mcld::ScriptOptions script; 53 mcld::PositionalOptions positional; 54 55 llvm::cl::ParseCommandLineOptions(pArgc, pArgv, pName); 56 57 if (!preference.parse(pConfig)) 58 return false; 59 60 if (!triple.parse(pArgc, pArgv, pConfig)) 61 return false; 62 63 if (!dynamic_section.parse(pConfig, pScript)) 64 return false; 65 66 if (!output_format.parse(pModule, pConfig)) 67 return false; 68 69 if (!search_path.parse(pConfig, pScript)) 70 return false; 71 72 if (!optimization.parse(pConfig)) 73 return false; 74 75 if (!symbol.parse(pConfig)) 76 return false; 77 78 if (!target_control.parse(pConfig)) 79 return false; 80 81 if (!script.parse(pScript)) 82 return false; 83 84 if (!positional.parse(pInputActions, pConfig, pScript)) 85 return false; 86 87 if (pConfig.options().soname().empty()) 88 pConfig.options().setSOName(pModule.name()); 89 90 return true; 91 } 92 93 static 94 inline bool InitializeInputs(mcld::IRBuilder& pBuilder, 95 std::vector<mcld::InputAction*>& pInputActions) 96 { 97 for (std::vector<mcld::InputAction*>::iterator action = pInputActions.begin(), 98 actionEnd = pInputActions.end(); action != actionEnd; ++action) { 99 assert(*action != NULL); 100 (*action)->activate(pBuilder.getInputBuilder()); 101 delete *action; 102 } 103 104 if (pBuilder.getInputBuilder().isInGroup()) { 105 mcld::fatal(mcld::diag::fatal_forbid_nest_group); 106 return false; 107 } 108 109 return true; 110 } 111 112 int main(int argc, char* argv[]) 113 { 114 llvm::sys::PrintStackTraceOnErrorSignal(); 115 llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 116 mcld::Initialize(); 117 118 mcld::LinkerScript script; 119 mcld::LinkerConfig config; 120 mcld::Module module(script); 121 mcld::IRBuilder builder(module, config); 122 std::vector<mcld::InputAction*> input_actions; 123 124 if (!ConfigLinker(argc, argv, "MCLinker\n", module, script, config, builder, 125 input_actions)) { 126 mcld::errs() << argv[0] 127 << ": failed to process linker options from command line!\n"; 128 return 1; 129 } 130 131 mcld::Linker linker; 132 if (!linker.emulate(script, config)) { 133 mcld::errs() << argv[0] 134 << ": failed to emulate target!\n"; 135 return 1; 136 } 137 138 // FIXME: is it possible to have a lightweight MCLinker pass? 139 if (!InitializeInputs(builder, input_actions)) { 140 mcld::errs() << argv[0] 141 << ": failed to initialize input tree!\n"; 142 return 1; 143 } 144 145 if (!linker.link(module, builder)) { 146 mcld::errs() << argv[0] 147 << ": failed to link objects!\n"; 148 return 1; 149 } 150 151 if (!linker.emit(module, module.name())) { 152 mcld::errs() << argv[0] 153 << ": failed to emit output!\n"; 154 return 1; 155 } 156 157 mcld::Finalize(); 158 159 return 0; 160 } 161