| //===- 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::ZeroOrMore, |
| 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; |
| } |