//===- OutputFormatOptions.cpp --------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include <mcld/OutputFormatOptions.h> #include <mcld/Module.h> #include <mcld/Support/MsgHandling.h> namespace { llvm::cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> > ArgOutputFilename("o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename")); llvm::cl::alias AliasOutputFilename("output", llvm::cl::desc("alias for -o"), llvm::cl::aliasopt(ArgOutputFilename)); llvm::cl::opt<mcld::LinkerConfig::CodeGenType> ArgFileType("filetype", llvm::cl::init(mcld::LinkerConfig::Exec), llvm::cl::desc("Choose a file type\n" "(not all types are supported by all targets):"), llvm::cl::values( clEnumValN(mcld::LinkerConfig::Object, "obj", "Emit a relocatable object ('.o') file"), clEnumValN(mcld::LinkerConfig::DynObj, "dso", "Emit an dynamic shared object ('.so') file"), clEnumValN(mcld::LinkerConfig::Exec, "exe", "Emit an executable ('.exe') file"), clEnumValN(mcld::LinkerConfig::Binary, "bin", "Emit a binary file"), clEnumValN(mcld::LinkerConfig::External, "null", "Emit nothing for performance testing"), clEnumValEnd)); llvm::cl::opt<mcld::LinkerConfig::CodeGenType> ArgOFormat("oformat", llvm::cl::value_desc("Format"), llvm::cl::desc("set output format"), llvm::cl::init(mcld::LinkerConfig::Unknown), llvm::cl::values( clEnumValN(mcld::LinkerConfig::Binary, "binary", "generate binary machine code."), clEnumValEnd)); llvm::cl::opt<bool> ArgShared("shared", llvm::cl::ZeroOrMore, llvm::cl::desc("Create a shared library."), llvm::cl::init(false)); llvm::cl::alias ArgSharedAlias("Bshareable", llvm::cl::desc("alias for -shared"), llvm::cl::aliasopt(ArgShared)); llvm::cl::opt<bool> ArgPIE("pie", llvm::cl::desc("Emit a position-independent executable file"), llvm::cl::init(false)); llvm::cl::opt<bool> ArgRelocatable("relocatable", llvm::cl::desc("Generate relocatable output"), llvm::cl::init(false)); llvm::cl::alias ArgRelocatableAlias("r", llvm::cl::desc("alias for --relocatable"), llvm::cl::aliasopt(ArgRelocatable)); llvm::cl::opt<mcld::Input::Type> ArgFormat("b", llvm::cl::value_desc("Format"), llvm::cl::desc("set input format"), llvm::cl::init(mcld::Input::Unknown), llvm::cl::values( clEnumValN(mcld::Input::Binary, "binary", "read in binary machine code."), clEnumValEnd)); llvm::cl::alias ArgFormatAlias("format", llvm::cl::desc("alias for -b"), llvm::cl::aliasopt(ArgFormat)); llvm::cl::opt<bool> ArgStripDebug("strip-debug", llvm::cl::desc("Omit debugger symbol information from the output file."), llvm::cl::init(false)); llvm::cl::alias ArgStripDebugAlias("S", llvm::cl::desc("alias for --strip-debug"), llvm::cl::aliasopt(ArgStripDebug)); llvm::cl::opt<bool> ArgStripAll("strip-all", llvm::cl::desc("Omit all symbol information from the output file."), llvm::cl::init(false)); llvm::cl::alias ArgStripAllAlias("s", llvm::cl::desc("alias for --strip-all"), llvm::cl::aliasopt(ArgStripAll)); llvm::cl::opt<bool> ArgDiscardAll("discard-all", llvm::cl::desc("Delete all local symbols."), llvm::cl::init(false)); llvm::cl::alias ArgDiscardAllAlias("x", llvm::cl::desc("alias for --discard-all"), llvm::cl::aliasopt(ArgDiscardAll)); llvm::cl::opt<bool> ArgDiscardLocals("discard-locals", llvm::cl::desc("Delete all temporary local symbols."), llvm::cl::init(false)); llvm::cl::alias ArgDiscardLocalsAlias("X", llvm::cl::desc("alias for --discard-locals"), llvm::cl::aliasopt(ArgDiscardLocals)); llvm::cl::opt<bool> ArgEhFrameHdr("eh-frame-hdr", llvm::cl::ZeroOrMore, llvm::cl::desc("Request creation of \".eh_frame_hdr\" section and\n" "ELF \"PT_GNU_EH_FRAME\" segment header."), llvm::cl::init(false)); llvm::cl::opt<bool> ArgNMagic("nmagic", llvm::cl::desc("Do not page align data"), llvm::cl::init(false)); llvm::cl::alias ArgNMagicAlias("n", llvm::cl::desc("alias for --nmagic"), llvm::cl::aliasopt(ArgNMagic)); llvm::cl::opt<bool> ArgOMagic("omagic", llvm::cl::desc("Do not page align data, do not make text readonly"), llvm::cl::init(false)); llvm::cl::alias ArgOMagicAlias("N", llvm::cl::desc("alias for --omagic"), llvm::cl::aliasopt(ArgOMagic)); llvm::cl::opt<mcld::GeneralOptions::HashStyle> ArgHashStyle("hash-style", llvm::cl::init(mcld::GeneralOptions::SystemV), llvm::cl::desc("Set the type of linker's hash table(s)."), llvm::cl::values( clEnumValN(mcld::GeneralOptions::SystemV, "sysv", "classic ELF .hash section"), clEnumValN(mcld::GeneralOptions::GNU, "gnu", "new style GNU .gnu.hash section"), clEnumValN(mcld::GeneralOptions::Both, "both", "both the classic ELF and new style GNU hash tables"), clEnumValEnd)); llvm::cl::opt<bool> ArgNoWarnMismatch("no-warn-mismatch", llvm::cl::desc("Allow linking together mismatched input files."), llvm::cl::init(false)); // Not supported yet { llvm::cl::opt<bool> ArgExportDynamic("export-dynamic", llvm::cl::desc("Export all dynamic symbols"), llvm::cl::init(false)); llvm::cl::alias ArgExportDynamicAlias("E", llvm::cl::desc("alias for --export-dynamic"), llvm::cl::aliasopt(ArgExportDynamic)); llvm::cl::opt<std::string> ArgBuildID("build-id", llvm::cl::desc("Request creation of \".note.gnu.build-id\" ELF note section."), llvm::cl::value_desc("style"), llvm::cl::ValueOptional); llvm::cl::list<std::string> ArgExcludeLIBS("exclude-libs", llvm::cl::CommaSeparated, llvm::cl::desc("Exclude libraries from automatic export"), llvm::cl::value_desc("lib1,lib2,...")); // } Not supported yet } // anonymous namespace using namespace mcld; //===----------------------------------------------------------------------===// // OutputFormatOptions //===----------------------------------------------------------------------===// OutputFormatOptions::OutputFormatOptions() : m_OutputFilename(ArgOutputFilename), m_FileType(ArgFileType), m_OFormat(ArgOFormat), m_Shared(ArgShared), m_PIE(ArgPIE), m_Relocatable(ArgRelocatable), m_Format(ArgFormat), m_StripDebug(ArgStripDebug), m_StripAll(ArgStripAll), m_DiscardAll(ArgDiscardAll), m_DiscardLocals(ArgDiscardLocals), m_EhFrameHdr(ArgEhFrameHdr), m_NMagic(ArgNMagic), m_OMagic(ArgOMagic), m_HashStyle(ArgHashStyle), m_ExportDynamic(ArgExportDynamic), m_BuildID(ArgBuildID), m_ExcludeLIBS(ArgExcludeLIBS), m_NoWarnMismatch(ArgNoWarnMismatch) { } bool OutputFormatOptions::parse(mcld::Module& pModule, LinkerConfig& pConfig) { if (!parseOutput(pModule, pConfig)) { mcld::unreachable(mcld::diag::unrecognized_output_file) << pModule.name(); return false; } if (mcld::Input::Binary == m_Format) pConfig.options().setBinaryInput(); pConfig.options().setStripDebug(m_StripDebug || m_StripAll); if (m_StripAll) pConfig.options().setStripSymbols(mcld::GeneralOptions::StripAllSymbols); else if (m_DiscardAll) pConfig.options().setStripSymbols(mcld::GeneralOptions::StripLocals); else if (m_DiscardLocals) pConfig.options().setStripSymbols(mcld::GeneralOptions::StripTemporaries); else pConfig.options().setStripSymbols(mcld::GeneralOptions::KeepAllSymbols); pConfig.options().setEhFrameHdr(m_EhFrameHdr); pConfig.options().setPIE(m_PIE); pConfig.options().setNMagic(m_NMagic); pConfig.options().setOMagic(m_OMagic); pConfig.options().setHashStyle(m_HashStyle); pConfig.options().setExportDynamic(m_ExportDynamic); // --exclude-libs llvm::cl::list<std::string>::iterator exclude, excludeEnd = m_ExcludeLIBS.end(); for (exclude = m_ExcludeLIBS.begin(); exclude != excludeEnd; ++exclude) { pConfig.options().excludeLIBS().insert(*exclude); } if (m_NoWarnMismatch) pConfig.options().setWarnMismatch(false); else pConfig.options().setWarnMismatch(true); // build-id // exclude-libs return true; } /// configure the output filename bool OutputFormatOptions::parseOutput(Module& pModule, LinkerConfig& pConfig) { if (true == m_Shared || true == m_PIE) { // -shared or -pie m_FileType = mcld::LinkerConfig::DynObj; } else if (true == m_Relocatable) { // partial linking m_FileType = mcld::LinkerConfig::Object; } else if (mcld::LinkerConfig::Binary == m_OFormat) { // binary output m_FileType = mcld::LinkerConfig::Binary; } pConfig.setCodeGenType(m_FileType); std::string output_filename(m_OutputFilename.native()); if (m_OutputFilename.empty()) { if (llvm::Triple::Win32 == pConfig.targets().triple().getOS()) { output_filename.assign("_out"); switch (m_FileType) { case mcld::LinkerConfig::Object: { output_filename += ".obj"; break; } case mcld::LinkerConfig::DynObj: { output_filename += ".dll"; break; } case mcld::LinkerConfig::Exec: { output_filename += ".exe"; break; } case mcld::LinkerConfig::External: break; default: { return false; break; } } // switch } else { if (mcld::LinkerConfig::Object == m_FileType || mcld::LinkerConfig::DynObj == m_FileType || mcld::LinkerConfig::Exec == m_FileType || mcld::LinkerConfig::External == m_FileType) { output_filename.assign("a.out"); } else { return false; } } } // end of if empty m_OutputFilename pModule.setName(output_filename); return true; }