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