diff --git a/llvm/test/Support/check-default-options.txt b/llvm/test/Support/check-default-options.txt --- a/llvm/test/Support/check-default-options.txt +++ b/llvm/test/Support/check-default-options.txt @@ -1,9 +1,7 @@ -# RUN: llvm-objdump --help-hidden %t | FileCheck --check-prefix=CHECK-OBJDUMP %s # RUN: llvm-readobj --help-hidden %t | FileCheck --check-prefix=CHECK-READOBJ %s # RUN: llvm-tblgen --help-hidden %t | FileCheck --check-prefix=CHECK-TBLGEN %s # RUN: llvm-opt-report --help-hidden %t | FileCheck --check-prefix=CHECK-OPT-RPT %s -# CHECK-OBJDUMP: -h - Alias for --section-headers # CHECK-READOBJ: -h - Alias for --file-headers # CHECK-TBLGEN: -h - Alias for --help # CHECK-OPT-RPT: -h - Alias for --help diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test --- a/llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test @@ -83,7 +83,7 @@ ; RUN: not llvm-objdump --prefix %p --prefix-strip '-1' --source %t-missing-prefix.o 2>&1 | \ ; RUN: FileCheck %s --check-prefix=CHECK-INVALID-PREFIX-STRIP -DOPTION='-1' -; CHECK-INVALID-PREFIX-STRIP: llvm-objdump{{.*}}: for the --prefix-strip option: '[[OPTION]]' value invalid for uint argument! +; CHECK-INVALID-PREFIX-STRIP: {{.*}}llvm-objdump{{.*}}: error: --prefix-strip: expected a non-negative integer, but got '[[OPTION]]' ;; Test text value --prefix-strip. Reports an error. diff --git a/llvm/test/tools/llvm-objdump/help.test b/llvm/test/tools/llvm-objdump/help.test --- a/llvm/test/tools/llvm-objdump/help.test +++ b/llvm/test/tools/llvm-objdump/help.test @@ -1,6 +1,14 @@ RUN: llvm-objdump --help | FileCheck %s +RUN: llvm-objdump --help-hidden | FileCheck --check-prefix=HIDDEN %s CHECK: OVERVIEW: llvm object file dumper CHECK: USAGE: llvm-objdump{{(.exe)?}} [options] {{$}} -CHECK: OPTIONS: +CHECK: Generic Options: +CHECK-NOT: {{ -w }} CHECK: @FILE + +HIDDEN: OVERVIEW: llvm object file dumper +HIDDEN: USAGE: llvm-objdump{{(.exe)?}} [options] {{$}} +HIDDEN: Generic Options: +HIDDEN: {{ -w }} +HIDDEN: @FILE diff --git a/llvm/test/tools/llvm-objdump/section-filter.test b/llvm/test/tools/llvm-objdump/section-filter.test --- a/llvm/test/tools/llvm-objdump/section-filter.test +++ b/llvm/test/tools/llvm-objdump/section-filter.test @@ -2,7 +2,7 @@ ## We test the LMA here too, because the code at the time of writing uses the ## value of --section when looking up section LMAs. # RUN: yaml2obj %s --docnum=1 -o %t.h.elf -# RUN: llvm-objdump -h %t.h.elf -j=.text --section=.bss \ +# RUN: llvm-objdump -h %t.h.elf -j.text --section=.bss \ # RUN: | FileCheck %s --check-prefix=SHDRS --implicit-check-not=.data --implicit-check-not=.text2 # SHDRS: Name Size VMA LMA @@ -92,10 +92,9 @@ Content: '666f6f626172' # "foobar" ## Test that the -j alias can be used flexibly. Create a baseline and ensure -## all other combinations are identical. +## all other combinations compatible with POSIX are identical. # RUN: llvm-objdump %t.h.elf -h -s --section .symtab > %t.full # RUN: llvm-objdump %t.h.elf -h -s -j .symtab > %t.1 -# RUN: llvm-objdump %t.h.elf -h -s -j=.symtab > %t.2 # RUN: llvm-objdump %t.h.elf -h -s -j.symtab > %t.3 # RUN: llvm-objdump %t.h.elf -hsj .symtab > %t.4 # RUN: llvm-objdump %t.h.elf -hsj=.symtab > %t.5 diff --git a/llvm/tools/llvm-objdump/CMakeLists.txt b/llvm/tools/llvm-objdump/CMakeLists.txt --- a/llvm/tools/llvm-objdump/CMakeLists.txt +++ b/llvm/tools/llvm-objdump/CMakeLists.txt @@ -9,10 +9,15 @@ MC MCDisassembler Object + Option Support Symbolize ) +set(LLVM_TARGET_DEFINITIONS ObjdumpOpts.td) +tablegen(LLVM ObjdumpOpts.inc -gen-opt-parser-defs) +add_public_tablegen_target(ObjdumpOptsTableGen) + add_llvm_tool(llvm-objdump llvm-objdump.cpp COFFDump.cpp @@ -20,6 +25,8 @@ MachODump.cpp WasmDump.cpp XCOFFDump.cpp + DEPENDS + ObjdumpOptsTableGen ) if(HAVE_LIBXAR) diff --git a/llvm/tools/llvm-objdump/MachODump.h b/llvm/tools/llvm-objdump/MachODump.h --- a/llvm/tools/llvm-objdump/MachODump.h +++ b/llvm/tools/llvm-objdump/MachODump.h @@ -24,25 +24,31 @@ class RelocationRef; } // namespace object +namespace opt { +class InputArgList; +} // namespace opt + namespace objdump { +void parseMachOOptions(const llvm::opt::InputArgList &InputArgs); + // MachO specific options extern cl::OptionCategory MachOCat; -extern cl::opt Bind; -extern cl::opt DataInCode; -extern cl::opt DylibsUsed; -extern cl::opt DylibId; -extern cl::opt ExportsTrie; -extern cl::opt FirstPrivateHeader; -extern cl::opt FunctionStarts; -extern cl::opt IndirectSymbols; -extern cl::opt InfoPlist; -extern cl::opt LazyBind; -extern cl::opt LinkOptHints; -extern cl::opt ObjcMetaData; -extern cl::opt Rebase; -extern cl::opt UniversalHeaders; -extern cl::opt WeakBind; +extern bool Bind; +extern bool DataInCode; +extern bool DylibsUsed; +extern bool DylibId; +extern bool ExportsTrie; +extern bool FirstPrivateHeader; +extern bool FunctionStarts; +extern bool IndirectSymbols; +extern bool InfoPlist; +extern bool LazyBind; +extern bool LinkOptHints; +extern bool ObjcMetaData; +extern bool Rebase; +extern bool UniversalHeaders; +extern bool WeakBind; Error getMachORelocationValueString(const object::MachOObjectFile *Obj, const object::RelocationRef &RelRef, diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -12,6 +12,7 @@ #include "MachODump.h" +#include "ObjdumpOptID.h" #include "llvm-objdump.h" #include "llvm-c/Disassembler.h" #include "llvm/ADT/STLExtras.h" @@ -34,8 +35,8 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" +#include "llvm/Option/ArgList.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Format.h" @@ -62,131 +63,61 @@ using namespace llvm::object; using namespace llvm::objdump; -cl::OptionCategory objdump::MachOCat("llvm-objdump MachO Specific Options"); - -cl::opt objdump::FirstPrivateHeader( - "private-header", - cl::desc("Display only the first format specific file header"), - cl::cat(MachOCat)); - -cl::opt objdump::ExportsTrie("exports-trie", - cl::desc("Display mach-o exported symbols"), - cl::cat(MachOCat)); - -cl::opt objdump::Rebase("rebase", - cl::desc("Display mach-o rebasing info"), - cl::cat(MachOCat)); - -cl::opt objdump::Bind("bind", cl::desc("Display mach-o binding info"), - cl::cat(MachOCat)); - -cl::opt objdump::LazyBind("lazy-bind", - cl::desc("Display mach-o lazy binding info"), - cl::cat(MachOCat)); - -cl::opt objdump::WeakBind("weak-bind", - cl::desc("Display mach-o weak binding info"), - cl::cat(MachOCat)); - -static cl::opt - UseDbg("g", cl::Grouping, - cl::desc("Print line information from debug info if available"), - cl::cat(MachOCat)); - -static cl::opt DSYMFile("dsym", - cl::desc("Use .dSYM file for debug info"), - cl::cat(MachOCat)); - -static cl::opt FullLeadingAddr("full-leading-addr", - cl::desc("Print full leading address"), - cl::cat(MachOCat)); - -static cl::opt NoLeadingHeaders("no-leading-headers", - cl::desc("Print no leading headers"), - cl::cat(MachOCat)); - -cl::opt objdump::UniversalHeaders( - "universal-headers", - cl::desc("Print Mach-O universal headers (requires --macho)"), - cl::cat(MachOCat)); - -static cl::opt ArchiveMemberOffsets( - "archive-member-offsets", - cl::desc("Print the offset to each archive member for Mach-O archives " - "(requires --macho and --archive-headers)"), - cl::cat(MachOCat)); - -cl::opt objdump::IndirectSymbols( - "indirect-symbols", - cl::desc( - "Print indirect symbol table for Mach-O objects (requires --macho)"), - cl::cat(MachOCat)); - -cl::opt objdump::DataInCode( - "data-in-code", - cl::desc( - "Print the data in code table for Mach-O objects (requires --macho)"), - cl::cat(MachOCat)); - -cl::opt - objdump::FunctionStarts("function-starts", - cl::desc("Print the function starts table for " - "Mach-O objects (requires --macho)"), - cl::cat(MachOCat)); - -cl::opt - objdump::LinkOptHints("link-opt-hints", - cl::desc("Print the linker optimization hints for " - "Mach-O objects (requires --macho)"), - cl::cat(MachOCat)); - -cl::opt - objdump::InfoPlist("info-plist", - cl::desc("Print the info plist section as strings for " - "Mach-O objects (requires --macho)"), - cl::cat(MachOCat)); - -cl::opt - objdump::DylibsUsed("dylibs-used", - cl::desc("Print the shared libraries used for linked " - "Mach-O files (requires --macho)"), - cl::cat(MachOCat)); - -cl::opt objdump::DylibId("dylib-id", - cl::desc("Print the shared library's id for the " - "dylib Mach-O file (requires --macho)"), - cl::cat(MachOCat)); - -static cl::opt - NonVerbose("non-verbose", - cl::desc("Print the info for Mach-O objects in non-verbose or " - "numeric form (requires --macho)"), - cl::cat(MachOCat)); - -cl::opt - objdump::ObjcMetaData("objc-meta-data", - cl::desc("Print the Objective-C runtime meta data " - "for Mach-O files (requires --macho)"), - cl::cat(MachOCat)); - -static cl::opt DisSymName( - "dis-symname", - cl::desc("disassemble just this symbol's instructions (requires --macho)"), - cl::cat(MachOCat)); - -static cl::opt NoSymbolicOperands( - "no-symbolic-operands", - cl::desc("do not symbolic operands when disassembling (requires --macho)"), - cl::cat(MachOCat)); - -static cl::list - ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), - cl::ZeroOrMore, cl::cat(MachOCat)); +bool objdump::FirstPrivateHeader; +bool objdump::ExportsTrie; +bool objdump::Rebase; +bool objdump::Bind; +bool objdump::LazyBind; +bool objdump::WeakBind; +static bool UseDbg; +static std::string DSYMFile; +static bool FullLeadingAddr; +static bool NoLeadingHeaders; +bool objdump::UniversalHeaders; +static bool ArchiveMemberOffsets; +bool objdump::IndirectSymbols; +bool objdump::DataInCode; +bool objdump::FunctionStarts; +bool objdump::LinkOptHints; +bool objdump::InfoPlist; +bool objdump::DylibsUsed; +bool objdump::DylibId; +static bool NonVerbose; +bool objdump::ObjcMetaData; +static std::string DisSymName; +static bool NoSymbolicOperands; +static std::vector ArchFlags; static bool ArchAll = false; - static std::string ThumbTripleName; +void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) { + FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header); + ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie); + Rebase = InputArgs.hasArg(OBJDUMP_rebase); + Bind = InputArgs.hasArg(OBJDUMP_bind); + LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind); + WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind); + UseDbg = InputArgs.hasArg(OBJDUMP_g); + DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str(); + FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr); + NoLeadingHeaders = InputArgs.hasArg(OBJDUMP_no_leading_headers); + UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers); + ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets); + IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols); + DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code); + FunctionStarts = InputArgs.hasArg(OBJDUMP_function_starts); + LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints); + InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist); + DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used); + DylibId = InputArgs.hasArg(OBJDUMP_dylib_id); + NonVerbose = InputArgs.hasArg(OBJDUMP_non_verbose); + ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data); + DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str(); + NoSymbolicOperands = InputArgs.hasArg(OBJDUMP_no_symbolic_operands); + ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ); +} + static const Target *GetTarget(const MachOObjectFile *MachOObj, const char **McpuDefault, const Target **ThumbTarget) { diff --git a/llvm/tools/llvm-objdump/ObjdumpOptID.h b/llvm/tools/llvm-objdump/ObjdumpOptID.h new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-objdump/ObjdumpOptID.h @@ -0,0 +1,13 @@ +#ifndef LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H +#define LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H + +enum ID { + OBJDUMP_INVALID = 0, // This is not an option ID. +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + OBJDUMP_##ID, +#include "ObjdumpOpts.inc" +#undef OPTION +}; + +#endif // LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td @@ -0,0 +1,398 @@ +include "llvm/Option/OptParser.td" + +def grp_generic : OptionGroup<"kind">, HelpText<"Generic Options">; + +def help : Flag<["--"], "help">, + HelpText<"Display available options (--help-hidden for more)">, + Group; + +def help_hidden : Flag<["--"], "help-hidden">, + Flags<[HelpHidden]>, + HelpText<"Display all available options">, + Group; + +def version : Flag<["--"], "version">, + HelpText<"Display the version of this program">, + Group; + + + +def grp_objdump : OptionGroup<"objdump">, HelpText<"llvm-objdump Options">; + +def adjust_vma_EQ : Joined<["--"], "adjust-vma=">, + MetaVarName<"offset">, + HelpText<"Increase the displayed address by the specified offset">, + Group; + +def all_headers : Flag<["--"], "all-headers">, + HelpText<"Display all available header information">, + Group; +def : Flag<["-"], "x">, Alias, HelpText<"Alias for --all-headers">, + Group; + +def arch_name_EQ : Joined<["--"], "arch-name=">, + HelpText<"Target arch to disassemble for, " + "see --version for available targets">, + Group; + +def archive_headers : Flag<["--"], "archive-headers">, + HelpText<"Display archive header information">, + Group; +def : Flag<["-"], "a">, Alias, + HelpText<"Alias for --archive-headers">, + Group; + +def demangle : Flag<["--"], "demangle">, HelpText<"Demangle symbol names">, + Group; +def : Flag<["-"], "C">, Alias, HelpText<"Alias for --demangle">, + Group; + +def disassemble : Flag<["--"], "disassemble">, + HelpText<"Display assembler mnemonics for the machine instructions">, + Group; +def : Flag<["-"], "d">, Alias, HelpText<"Alias for --disassemble">, + Group; + +def disassemble_all : Flag<["--"], "disassemble-all">, + HelpText<"Display assembler mnemonics for the machine instructions">, + Group; +def : Flag<["-"], "D">, Alias, + HelpText<"Alias for --disassemble-all">, + Group; + +def symbol_description : Flag<["--"], "symbol-description">, + HelpText<"Add symbol description for disassembly. This " + "option is for XCOFF files only.">, + Group; + +def disassemble_symbols_EQ : Joined<["--"], "disassemble-symbols=">, + HelpText<"List of symbols to disassemble. " + "Accept demangled names when --demangle is " + "specified, otherwise accept mangled names">, + Group; + +def disassemble_zeroes : Flag<["--"], "disassemble-zeroes">, + HelpText<"Do not skip blocks of zeroes when disassembling">, + Group; +def : Flag<["-"], "z">, Alias, + HelpText<"Alias for --disassemble-zeroes">, + Group; + +def disassembler_options_EQ : Joined<["--"], "disassembler-options=">, + MetaVarName<"options">, + HelpText<"Pass target specific disassembler options">, + Group; +def : JoinedOrSeparate<["-"], "M">, Alias, + HelpText<"Alias for --disassembler-options=">, + Group; + +def dynamic_reloc : Flag<["--"], "dynamic-reloc">, + HelpText<"Display the dynamic relocation entries in the file">, + Group; +def : Flag<["-"], "R">, Alias, + HelpText<"Alias for --dynamic-reloc">, + Group; + +def dwarf_EQ : Joined<["--"], "dwarf=">, + HelpText<"Dump of dwarf debug sections">, Values<"frames">, + Group; + +def fault_map_section : Flag<["--"], "fault-map-section">, + HelpText<"Display contents of faultmap section">, + Group; + +def file_headers : Flag<["--"], "file-headers">, + HelpText<"Display the contents of the overall file header">, + Group; +def : Flag<["-"], "f">, Alias, + HelpText<"Alias for --file-headers">, + Group; + +def full_contents : Flag<["--"], "full-contents">, + HelpText<"Display the content of each section">, + Group; +def : Flag<["-"], "s">, Alias, + HelpText<"Alias for --full-contents">, + Group; + +def line_numbers : Flag<["--"], "line-numbers">, + HelpText<"Display source line numbers with " + "disassembly. Implies disassemble object">, + Group; +def : Flag<["-"], "l">, Alias, + HelpText<"Alias for --line-numbers">, + Group; + +def macho : Flag<["--"], "macho">, + HelpText<"Use MachO specific object file parser">, + Group; +def : Flag<["-"], "m">, Alias, HelpText<"Alias for --macho">, + Group; + +def mcpu_EQ : Joined<["--"], "mcpu=">, + MetaVarName<"cpu-name">, + HelpText<"Target a specific cpu type (--mcpu=help for details)">, + Group; + +def mattr_EQ : Joined<["--"], "mattr=">, + MetaVarName<"a1,+a2,-a3,...">, + HelpText<"Target specific attributes (--mattr=help for details)">, + Group; + +def no_show_raw_insn : Flag<["--"], "no-show-raw-insn">, + HelpText<"When disassembling instructions, " + "do not print the instruction bytes.">, + Group; + +def no_leading_addr : Flag<["--"], "no-leading-addr">, + HelpText<"Print no leading address">, + Group; + +def raw_clang_ast : Flag<["--"], "raw-clang-ast">, + HelpText<"Dump the raw binary contents of the clang AST section">, + Group; + +def reloc : Flag<["--"], "reloc">, + HelpText<"Display the relocation entries in the file">, + Group; +def : Flag<["-"], "r">, Alias, HelpText<"Alias for --reloc">, + Group; + +def print_imm_hex : Flag<["--"], "print-imm-hex">, + HelpText<"Use hex format for immediate values">, + Group; + +def no_print_imm_hex : Flag<["--"], "no-print-imm-hex">, + HelpText<"Do not use hex format for immediate values (default)">, + Group; +def : Flag<["--"], "print-imm-hex=false">, Alias, + Group; + +def private_headers : Flag<["--"], "private-headers">, + HelpText<"Display format specific file headers">, + Group; +def : Flag<["-"], "p">, Alias, + HelpText<"Alias for --private-headers">, + Group; + +def section_EQ : Joined<["--"], "section=">, + HelpText<"Operate on the specified sections only. " + "With --macho dump segment,section">, + Group; +def : Separate<["--"], "section">, Alias, + Group; +def : JoinedOrSeparate<["-"], "j">, Alias, + HelpText<"Alias for --section">, + Group; + +def section_headers : Flag<["--"], "section-headers">, + HelpText<"Display summaries of the headers for each section.">, + Group; +def : Flag<["--"], "headers">, Alias, + HelpText<"Alias for --section-headers">, + Group; +def : Flag<["-"], "h">, Alias, + HelpText<"Alias for --section-headers">, + Group; + +def show_lma : Flag<["--"], "show-lma">, + HelpText<"Display LMA column when dumping ELF section headers">, + Group; + +def source : Flag<["--"], "source">, + HelpText<"Display source inlined with disassembly. Implies disassemble object">, + Group; +def : Flag<["-"], "S">, Alias, HelpText<"Alias for --source">, + Group; + +def start_address_EQ : Joined<["--"], "start-address=">, + MetaVarName<"address">, + HelpText<"Disassemble beginning at address">, + Group; +def stop_address_EQ : Joined<["--"], "stop-address=">, + MetaVarName<"address">, + HelpText<"Stop disassembly at address">, + Group; + +def syms : Flag<["--"], "syms">, + HelpText<"Display the symbol table">, + Group; +def : Flag<["-"], "t">, Alias, HelpText<"Alias for --syms">, + Group; + +def symbolize_operands : Flag<["--"], "symbolize-operands">, + HelpText<"Symbolize instruction operands when disassembling">, + Group; + +def dynamic_syms : Flag<["--"], "dynamic-syms">, + HelpText<"Display the contents of the dynamic symbol table">, + Group; +def : Flag<["-"], "T">, Alias, + HelpText<"Alias for --dynamic-syms">, + Group; + +def triple_EQ : Joined<["--"], "triple=">, + HelpText<"Target triple to disassemble for, " + "see --version for available targets">, + Group; +def : Separate<["--"], "triple">, + Alias, + Group; + +def unwind_info : Flag<["--"], "unwind-info">, + HelpText<"Display unwind information">, + Group; +def : Flag<["-"], "u">, Alias, + HelpText<"Alias for --unwind-info">, + Group; + +def wide : Flag<["--"], "wide">, + HelpText<"Ignored for compatibility with GNU objdump">, + Group; +def : Flag<["-"], "w">, Alias, + Group; + +def prefix : Separate<["--"], "prefix">, + HelpText<"Add prefix to absolute paths">, + Group; + +def prefix_strip : Separate<["--"], "prefix-strip">, + HelpText<"Strip out initial directories from absolute " + "paths. No effect without --prefix">, + Group; + +def debug_vars_EQ : Joined<["--"], "debug-vars=">, + Values<"unicode,ascii">, + Group; +def : Flag<["--"], "debug-vars">, + HelpText<"Print the locations (in registers or memory) of " + "source-level variables alongside disassembly">, + Alias, AliasArgs<["unicode"]>, + Group; + +def debug_vars_indent_EQ : Joined<["--"], "debug-vars-indent=">, + HelpText<"Distance to indent the source-level variable display, " + "relative to the start of the disassembly">, + Group; + +def x86_asm_syntax_att : Flag<["--"], "x86-asm-syntax=att">, + HelpText<"Emit AT&T-style disassembly">, + Group; + +def x86_asm_syntax_intel : Flag<["--"], "x86-asm-syntax=intel">, + HelpText<"Emit Intel-style disassembly">, + Group; + + + +def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-objdump MachO Specific Options">; + +def private_header : Flag<["--"], "private-header">, + HelpText<"Display only the first format specific file header">, + Group; + +def exports_trie : Flag<["--"], "exports-trie">, + HelpText<"Display mach-o exported symbols">, + Group; + +def rebase : Flag<["--"], "rebase">, + HelpText<"Display mach-o rebasing info">, + Group; + +def bind : Flag<["--"], "bind">, + HelpText<"Display mach-o binding info">, + Group; + +def lazy_bind : Flag<["--"], "lazy-bind">, + HelpText<"Display mach-o lazy binding info">, + Group; + +def weak_bind : Flag<["--"], "weak-bind">, + HelpText<"Display mach-o weak binding info">, + Group; + +def g : Flag<["-"], "g">, + HelpText<"Print line information from debug info if available">, + Group; + +def dsym_EQ : Joined<["--"], "dsym=">, + HelpText<"Use .dSYM file for debug info">, + Group; +def : Separate<["--"], "dsym">, + Alias, + Group; + +def full_leading_addr : Flag<["--"], "full-leading-addr">, + HelpText<"Print full leading address">, + Group; + +def no_leading_headers : Flag<["--"], "no-leading-headers">, + HelpText<"Print no leading headers">, + Group; + +def universal_headers : Flag<["--"], "universal-headers">, + HelpText<"Print Mach-O universal headers (requires --macho)">, + Group; + +def archive_member_offsets : Flag<["--"], "archive-member-offsets">, + HelpText<"Print the offset to each archive member for Mach-O archives " + "(requires --macho and --archive-headers)">, + Group; + +def indirect_symbols : Flag<["--"], "indirect-symbols">, + HelpText<"Print indirect symbol table for Mach-O objects (requires --macho)">, + Group; + +def data_in_code : Flag<["--"], "data-in-code">, + HelpText<"Print the data in code table for Mach-O objects (requires --macho)">, + Group; + +def function_starts : Flag<["--"], "function-starts">, + HelpText<"Print the function starts table for " + "Mach-O objects (requires --macho)">, + Group; + +def link_opt_hints : Flag<["--"], "link-opt-hints">, + HelpText<"Print the linker optimization hints for " + "Mach-O objects (requires --macho)">, + Group; + +def info_plist : Flag<["--"], "info-plist">, + HelpText<"Print the info plist section as strings for " + "Mach-O objects (requires --macho)">, + Group; + +def dylibs_used : Flag<["--"], "dylibs-used">, + HelpText<"Print the shared libraries used for linked " + "Mach-O files (requires --macho)">, + Group; + +def dylib_id : Flag<["--"], "dylib-id">, + HelpText<"Print the shared library's id for the " + "dylib Mach-O file (requires --macho)">, + Group; + +def non_verbose : Flag<["--"], "non-verbose">, + HelpText<"Print the info for Mach-O objects in non-verbose or " + "numeric form (requires --macho)">, + Group; + +def objc_meta_data : Flag<["--"], "objc-meta-data">, + HelpText<"Print the Objective-C runtime meta data " + "for Mach-O files (requires --macho)">, + Group; + +def dis_symname : Separate<["--"], "dis-symname">, + HelpText<"disassemble just this symbol's instructions (requires --macho)">, + Group; + +def no_symbolic_operands : Flag<["--"], "no-symbolic-operands">, + HelpText<"do not symbolic operands when disassembling (requires --macho)">, + Group; + +def arch_EQ : Joined<["--"], "arch=">, + HelpText<"architecture(s) from a Mach-O file to dump">, + Group; +def : Separate<["--"], "arch">, + Alias, + Group; diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -13,7 +13,6 @@ #include "llvm/DebugInfo/DIContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/Object/Archive.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -31,27 +30,27 @@ namespace objdump { -extern cl::opt ArchiveHeaders; -extern cl::opt Demangle; -extern cl::opt Disassemble; -extern cl::opt DisassembleAll; -extern cl::opt DwarfDumpType; -extern cl::list FilterSections; -extern cl::list MAttrs; -extern cl::opt MCPU; -extern cl::opt NoShowRawInsn; -extern cl::opt NoLeadingAddr; -extern cl::opt Prefix; -extern cl::opt PrefixStrip; -extern cl::opt PrintImmHex; -extern cl::opt PrivateHeaders; -extern cl::opt Relocations; -extern cl::opt SectionHeaders; -extern cl::opt SectionContents; -extern cl::opt SymbolDescription; -extern cl::opt SymbolTable; -extern cl::opt TripleName; -extern cl::opt UnwindInfo; +extern bool ArchiveHeaders; +extern bool Demangle; +extern bool Disassemble; +extern bool DisassembleAll; +extern DIDumpType DwarfDumpType; +extern std::vector FilterSections; +extern std::vector MAttrs; +extern std::string MCPU; +extern bool NoShowRawInsn; +extern bool NoLeadingAddr; +extern std::string Prefix; +extern uint32_t PrefixStrip; +extern bool PrintImmHex; +extern bool PrivateHeaders; +extern bool Relocations; +extern bool SectionHeaders; +extern bool SectionContents; +extern bool SymbolDescription; +extern bool SymbolTable; +extern std::string TripleName; +extern bool UnwindInfo; extern StringSet<> FoundSectionSet; diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -19,13 +19,14 @@ #include "COFFDump.h" #include "ELFDump.h" #include "MachODump.h" +#include "ObjdumpOptID.h" #include "WasmDump.h" #include "XCOFFDump.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Triple.h" @@ -54,8 +55,10 @@ #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/Wasm.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" @@ -81,313 +84,96 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::objdump; +using namespace llvm::opt; + +namespace { + +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#include "ObjdumpOpts.inc" +#undef PREFIX + +static constexpr opt::OptTable::Info ObjdumpInfoTable[] = { +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, \ + METAVAR, OBJDUMP_##ID, opt::Option::KIND##Class, \ + PARAM, FLAGS, OBJDUMP_##GROUP, \ + OBJDUMP_##ALIAS, ALIASARGS, VALUES}, +#include "ObjdumpOpts.inc" +#undef OPTION +}; + +class ObjdumpOptTable : public opt::OptTable { +public: + ObjdumpOptTable() : OptTable(ObjdumpInfoTable) {} + + void PrintObjdumpHelp(StringRef Argv0, bool ShowHidden = false) const { + Argv0 = sys::path::filename(Argv0); + PrintHelp(outs(), (Argv0 + " [options] ").str().c_str(), + "llvm object file dumper", ShowHidden, ShowHidden); + // TODO Replace this with OptTable API once it adds extrahelp support. + outs() << "\nPass @FILE as argument to read options from FILE.\n"; + } +}; + +} // namespace #define DEBUG_TYPE "objdump" -static cl::OptionCategory ObjdumpCat("llvm-objdump Options"); - -static cl::opt AdjustVMA( - "adjust-vma", - cl::desc("Increase the displayed address by the specified offset"), - cl::value_desc("offset"), cl::init(0), cl::cat(ObjdumpCat)); - -static cl::opt - AllHeaders("all-headers", - cl::desc("Display all available header information"), - cl::cat(ObjdumpCat)); -static cl::alias AllHeadersShort("x", cl::desc("Alias for --all-headers"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(AllHeaders)); - -static cl::opt - ArchName("arch-name", - cl::desc("Target arch to disassemble for, " - "see --version for available targets"), - cl::cat(ObjdumpCat)); - -cl::opt - objdump::ArchiveHeaders("archive-headers", - cl::desc("Display archive header information"), - cl::cat(ObjdumpCat)); -static cl::alias ArchiveHeadersShort("a", - cl::desc("Alias for --archive-headers"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(ArchiveHeaders)); - -cl::opt objdump::Demangle("demangle", cl::desc("Demangle symbols names"), - cl::init(false), cl::cat(ObjdumpCat)); -static cl::alias DemangleShort("C", cl::desc("Alias for --demangle"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(Demangle)); - -cl::opt objdump::Disassemble( - "disassemble", - cl::desc("Display assembler mnemonics for the machine instructions"), - cl::cat(ObjdumpCat)); -static cl::alias DisassembleShort("d", cl::desc("Alias for --disassemble"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(Disassemble)); - -cl::opt objdump::DisassembleAll( - "disassemble-all", - cl::desc("Display assembler mnemonics for the machine instructions"), - cl::cat(ObjdumpCat)); -static cl::alias DisassembleAllShort("D", - cl::desc("Alias for --disassemble-all"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(DisassembleAll)); - -cl::opt objdump::SymbolDescription( - "symbol-description", - cl::desc("Add symbol description for disassembly. This " - "option is for XCOFF files only"), - cl::init(false), cl::cat(ObjdumpCat)); - -static cl::list - DisassembleSymbols("disassemble-symbols", cl::CommaSeparated, - cl::desc("List of symbols to disassemble. " - "Accept demangled names when --demangle is " - "specified, otherwise accept mangled names"), - cl::cat(ObjdumpCat)); - -static cl::opt DisassembleZeroes( - "disassemble-zeroes", - cl::desc("Do not skip blocks of zeroes when disassembling"), - cl::cat(ObjdumpCat)); -static cl::alias - DisassembleZeroesShort("z", cl::desc("Alias for --disassemble-zeroes"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(DisassembleZeroes)); - -static cl::list - DisassemblerOptions("disassembler-options", - cl::desc("Pass target specific disassembler options"), - cl::value_desc("options"), cl::CommaSeparated, - cl::cat(ObjdumpCat)); -static cl::alias - DisassemblerOptionsShort("M", cl::desc("Alias for --disassembler-options"), - cl::NotHidden, cl::Grouping, cl::Prefix, - cl::CommaSeparated, - cl::aliasopt(DisassemblerOptions)); - -cl::opt objdump::DwarfDumpType( - "dwarf", cl::init(DIDT_Null), cl::desc("Dump of dwarf debug sections:"), - cl::values(clEnumValN(DIDT_DebugFrame, "frames", ".debug_frame")), - cl::cat(ObjdumpCat)); - -static cl::opt DynamicRelocations( - "dynamic-reloc", - cl::desc("Display the dynamic relocation entries in the file"), - cl::cat(ObjdumpCat)); -static cl::alias DynamicRelocationShort("R", - cl::desc("Alias for --dynamic-reloc"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(DynamicRelocations)); - -static cl::opt - FaultMapSection("fault-map-section", - cl::desc("Display contents of faultmap section"), - cl::cat(ObjdumpCat)); - -static cl::opt - FileHeaders("file-headers", - cl::desc("Display the contents of the overall file header"), - cl::cat(ObjdumpCat)); -static cl::alias FileHeadersShort("f", cl::desc("Alias for --file-headers"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(FileHeaders)); - -cl::opt - objdump::SectionContents("full-contents", - cl::desc("Display the content of each section"), - cl::cat(ObjdumpCat)); -static cl::alias SectionContentsShort("s", - cl::desc("Alias for --full-contents"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(SectionContents)); - -static cl::list InputFilenames(cl::Positional, - cl::desc(""), - cl::ZeroOrMore, - cl::cat(ObjdumpCat)); - -static cl::opt - PrintLines("line-numbers", - cl::desc("Display source line numbers with " - "disassembly. Implies disassemble object"), - cl::cat(ObjdumpCat)); -static cl::alias PrintLinesShort("l", cl::desc("Alias for --line-numbers"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(PrintLines)); - -static cl::opt MachOOpt("macho", - cl::desc("Use MachO specific object file parser"), - cl::cat(ObjdumpCat)); -static cl::alias MachOm("m", cl::desc("Alias for --macho"), cl::NotHidden, - cl::Grouping, cl::aliasopt(MachOOpt)); - -cl::opt objdump::MCPU( - "mcpu", cl::desc("Target a specific cpu type (--mcpu=help for details)"), - cl::value_desc("cpu-name"), cl::init(""), cl::cat(ObjdumpCat)); - -cl::list objdump::MAttrs( - "mattr", cl::CommaSeparated, - cl::desc("Target specific attributes (--mattr=help for details)"), - cl::value_desc("a1,+a2,-a3,..."), cl::cat(ObjdumpCat)); - -cl::opt objdump::NoShowRawInsn( - "no-show-raw-insn", - cl::desc( - "When disassembling instructions, do not print the instruction bytes."), - cl::cat(ObjdumpCat)); - -cl::opt objdump::NoLeadingAddr("no-leading-addr", - cl::desc("Print no leading address"), - cl::cat(ObjdumpCat)); - -static cl::opt RawClangAST( - "raw-clang-ast", - cl::desc("Dump the raw binary contents of the clang AST section"), - cl::cat(ObjdumpCat)); - -cl::opt - objdump::Relocations("reloc", - cl::desc("Display the relocation entries in the file"), - cl::cat(ObjdumpCat)); -static cl::alias RelocationsShort("r", cl::desc("Alias for --reloc"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(Relocations)); - -cl::opt - objdump::PrintImmHex("print-imm-hex", - cl::desc("Use hex format for immediate values"), - cl::cat(ObjdumpCat)); - -cl::opt - objdump::PrivateHeaders("private-headers", - cl::desc("Display format specific file headers"), - cl::cat(ObjdumpCat)); -static cl::alias PrivateHeadersShort("p", - cl::desc("Alias for --private-headers"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(PrivateHeaders)); - -cl::list - objdump::FilterSections("section", - cl::desc("Operate on the specified sections only. " - "With --macho dump segment,section"), - cl::cat(ObjdumpCat)); -static cl::alias FilterSectionsj("j", cl::desc("Alias for --section"), - cl::NotHidden, cl::Grouping, cl::Prefix, - cl::aliasopt(FilterSections)); - -cl::opt objdump::SectionHeaders( - "section-headers", - cl::desc("Display summaries of the headers for each section."), - cl::cat(ObjdumpCat)); -static cl::alias SectionHeadersShort("headers", - cl::desc("Alias for --section-headers"), - cl::NotHidden, - cl::aliasopt(SectionHeaders)); -static cl::alias SectionHeadersShorter("h", - cl::desc("Alias for --section-headers"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(SectionHeaders)); - -static cl::opt - ShowLMA("show-lma", - cl::desc("Display LMA column when dumping ELF section headers"), - cl::cat(ObjdumpCat)); - -static cl::opt PrintSource( - "source", - cl::desc( - "Display source inlined with disassembly. Implies disassemble object"), - cl::cat(ObjdumpCat)); -static cl::alias PrintSourceShort("S", cl::desc("Alias for --source"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(PrintSource)); - -static cl::opt - StartAddress("start-address", cl::desc("Disassemble beginning at address"), - cl::value_desc("address"), cl::init(0), cl::cat(ObjdumpCat)); -static cl::opt StopAddress("stop-address", - cl::desc("Stop disassembly at address"), - cl::value_desc("address"), - cl::init(UINT64_MAX), cl::cat(ObjdumpCat)); - -cl::opt objdump::SymbolTable("syms", cl::desc("Display the symbol table"), - cl::cat(ObjdumpCat)); -static cl::alias SymbolTableShort("t", cl::desc("Alias for --syms"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(SymbolTable)); - -static cl::opt SymbolizeOperands( - "symbolize-operands", - cl::desc("Symbolize instruction operands when disassembling"), - cl::cat(ObjdumpCat)); - -static cl::opt DynamicSymbolTable( - "dynamic-syms", - cl::desc("Display the contents of the dynamic symbol table"), - cl::cat(ObjdumpCat)); -static cl::alias DynamicSymbolTableShort("T", - cl::desc("Alias for --dynamic-syms"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(DynamicSymbolTable)); - -cl::opt - objdump::TripleName("triple", - cl::desc("Target triple to disassemble for, see " - "--version for available targets"), - cl::cat(ObjdumpCat)); - -cl::opt objdump::UnwindInfo("unwind-info", - cl::desc("Display unwind information"), - cl::cat(ObjdumpCat)); -static cl::alias UnwindInfoShort("u", cl::desc("Alias for --unwind-info"), - cl::NotHidden, cl::Grouping, - cl::aliasopt(UnwindInfo)); - -static cl::opt - Wide("wide", cl::desc("Ignored for compatibility with GNU objdump"), - cl::cat(ObjdumpCat)); -static cl::alias WideShort("w", cl::Grouping, cl::aliasopt(Wide)); - -cl::opt objdump::Prefix("prefix", - cl::desc("Add prefix to absolute paths"), - cl::cat(ObjdumpCat)); - -cl::opt - objdump::PrefixStrip("prefix-strip", - cl::desc("Strip out initial directories from absolute " - "paths. No effect without --prefix"), - cl::init(0), cl::cat(ObjdumpCat)); +static uint64_t AdjustVMA; +static bool AllHeaders; +static std::string ArchName; +bool objdump::ArchiveHeaders; +bool objdump::Demangle; +bool objdump::Disassemble; +bool objdump::DisassembleAll; +bool objdump::SymbolDescription; +static std::vector DisassembleSymbols; +static bool DisassembleZeroes; +static std::vector DisassemblerOptions; +DIDumpType objdump::DwarfDumpType; +static bool DynamicRelocations; +static bool FaultMapSection; +static bool FileHeaders; +bool objdump::SectionContents; +static std::vector InputFilenames; +static bool PrintLines; +static bool MachOOpt; +std::string objdump::MCPU; +std::vector objdump::MAttrs; +bool objdump::NoShowRawInsn; +bool objdump::NoLeadingAddr; +static bool RawClangAST; +bool objdump::Relocations; +bool objdump::PrintImmHex; +bool objdump::PrivateHeaders; +std::vector objdump::FilterSections; +bool objdump::SectionHeaders; +static bool ShowLMA; +static bool PrintSource; + +static uint64_t StartAddress; +static bool HasStartAddressFlag; +static uint64_t StopAddress = UINT64_MAX; +static bool HasStopAddressFlag; + +bool objdump::SymbolTable; +static bool SymbolizeOperands; +static bool DynamicSymbolTable; +std::string objdump::TripleName; +bool objdump::UnwindInfo; +static bool Wide; +std::string objdump::Prefix; +uint32_t objdump::PrefixStrip; enum DebugVarsFormat { DVDisabled, DVUnicode, DVASCII, }; +static DebugVarsFormat DbgVariables = DVDisabled; -static cl::opt DbgVariables( - "debug-vars", cl::init(DVDisabled), - cl::desc("Print the locations (in registers or memory) of " - "source-level variables alongside disassembly"), - cl::ValueOptional, - cl::values(clEnumValN(DVUnicode, "", "unicode"), - clEnumValN(DVUnicode, "unicode", "unicode"), - clEnumValN(DVASCII, "ascii", "unicode")), - cl::cat(ObjdumpCat)); - -static cl::opt - DbgIndent("debug-vars-indent", cl::init(40), - cl::desc("Distance to indent the source-level variable display, " - "relative to the start of the disassembly"), - cl::cat(ObjdumpCat)); - -static cl::extrahelp - HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); +static int DbgIndent = 40; static StringSet<> DisasmSymbolSet; StringSet<> objdump::FoundSectionSet; @@ -2829,11 +2615,11 @@ return; } - if (StartAddress.getNumOccurrences() == 0) + if (!HasStartAddressFlag) reportWarning("no section has address less than 0x" + Twine::utohexstr(Stop) + " specified by --stop-address", Obj->getFileName()); - else if (StopAddress.getNumOccurrences() == 0) + else if (!HasStopAddressFlag) reportWarning("no section has address greater than or equal to 0x" + Twine::utohexstr(Start) + " specified by --start-address", Obj->getFileName()); @@ -2856,7 +2642,7 @@ outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n\n"; } - if (StartAddress.getNumOccurrences() || StopAddress.getNumOccurrences()) + if (HasStartAddressFlag || HasStopAddressFlag) checkForInvalidStartStopAddress(O, StartAddress, StopAddress); // Note: the order here matches GNU objdump for compatability. @@ -2976,28 +2762,156 @@ reportError(errorCodeToError(object_error::invalid_file_type), file); } +template +static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID, + T &Value) { + if (const opt::Arg *A = InputArgs.getLastArg(ID)) { + StringRef V(A->getValue()); + if (!llvm::to_integer(V, Value, 0)) { + reportCmdLineError(A->getSpelling() + + ": expected a non-negative integer, but got '" + V + + "'"); + } + } +} + +static std::vector +commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) { + std::vector Values; + for (StringRef Value : InputArgs.getAllArgValues(ID)) { + llvm::SmallVector SplitValues; + llvm::SplitString(Value, SplitValues, ","); + for (StringRef SplitValue : SplitValues) + Values.push_back(SplitValue.str()); + } + return Values; +} + +static void parseOptions(const llvm::opt::InputArgList &InputArgs) { + parseIntArg(InputArgs, OBJDUMP_adjust_vma_EQ, AdjustVMA); + AllHeaders = InputArgs.hasArg(OBJDUMP_all_headers); + ArchName = InputArgs.getLastArgValue(OBJDUMP_arch_name_EQ).str(); + ArchiveHeaders = InputArgs.hasArg(OBJDUMP_archive_headers); + Demangle = InputArgs.hasArg(OBJDUMP_demangle); + Disassemble = InputArgs.hasArg(OBJDUMP_disassemble); + DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all); + SymbolDescription = InputArgs.hasArg(OBJDUMP_symbol_description); + DisassembleSymbols = + commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ); + DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes); + DisassemblerOptions = + commaSeparatedValues(InputArgs, OBJDUMP_disassembler_options_EQ); + if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_dwarf_EQ)) { + DwarfDumpType = + StringSwitch(A->getValue()).Case("frames", DIDT_DebugFrame); + } + DynamicRelocations = InputArgs.hasArg(OBJDUMP_dynamic_reloc); + FaultMapSection = InputArgs.hasArg(OBJDUMP_fault_map_section); + FileHeaders = InputArgs.hasArg(OBJDUMP_file_headers); + SectionContents = InputArgs.hasArg(OBJDUMP_full_contents); + PrintLines = InputArgs.hasArg(OBJDUMP_line_numbers); + InputFilenames = InputArgs.getAllArgValues(OBJDUMP_INPUT); + MachOOpt = InputArgs.hasArg(OBJDUMP_macho); + MCPU = InputArgs.getLastArgValue(OBJDUMP_mcpu_EQ).str(); + MAttrs = commaSeparatedValues(InputArgs, OBJDUMP_mattr_EQ); + NoShowRawInsn = InputArgs.hasArg(OBJDUMP_no_show_raw_insn); + NoLeadingAddr = InputArgs.hasArg(OBJDUMP_no_leading_addr); + RawClangAST = InputArgs.hasArg(OBJDUMP_raw_clang_ast); + Relocations = InputArgs.hasArg(OBJDUMP_reloc); + PrintImmHex = + InputArgs.hasFlag(OBJDUMP_print_imm_hex, OBJDUMP_no_print_imm_hex, false); + PrivateHeaders = InputArgs.hasArg(OBJDUMP_private_headers); + FilterSections = InputArgs.getAllArgValues(OBJDUMP_section_EQ); + SectionHeaders = InputArgs.hasArg(OBJDUMP_section_headers); + ShowLMA = InputArgs.hasArg(OBJDUMP_show_lma); + PrintSource = InputArgs.hasArg(OBJDUMP_source); + parseIntArg(InputArgs, OBJDUMP_start_address_EQ, StartAddress); + HasStartAddressFlag = InputArgs.hasArg(OBJDUMP_start_address_EQ); + parseIntArg(InputArgs, OBJDUMP_stop_address_EQ, StopAddress); + HasStopAddressFlag = InputArgs.hasArg(OBJDUMP_stop_address_EQ); + SymbolTable = InputArgs.hasArg(OBJDUMP_syms); + SymbolizeOperands = InputArgs.hasArg(OBJDUMP_symbolize_operands); + DynamicSymbolTable = InputArgs.hasArg(OBJDUMP_dynamic_syms); + TripleName = InputArgs.getLastArgValue(OBJDUMP_triple_EQ).str(); + UnwindInfo = InputArgs.hasArg(OBJDUMP_unwind_info); + Wide = InputArgs.hasArg(OBJDUMP_wide); + Prefix = InputArgs.getLastArgValue(OBJDUMP_prefix).str(); + parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip); + if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) { + DbgVariables = StringSwitch(A->getValue()) + .Case("ascii", DVASCII) + .Case("unicode", DVUnicode); + } + parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent); + + parseMachOOptions(InputArgs); + + // Handle options that get forwarded to cl::opt<>s in libraries. + // FIXME: Depending on https://reviews.llvm.org/D84191#inline-946075 , + // hopefully remove this again. + std::vector LLVMArgs; + LLVMArgs.push_back("llvm-objdump (LLVM option parsing)"); + if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_x86_asm_syntax_att, + OBJDUMP_x86_asm_syntax_intel)) { + switch (A->getOption().getID()) { + case OBJDUMP_x86_asm_syntax_att: + LLVMArgs.push_back("--x86-asm-syntax=att"); + break; + case OBJDUMP_x86_asm_syntax_intel: + LLVMArgs.push_back("--x86-asm-syntax=intel"); + break; + } + } + LLVMArgs.push_back(nullptr); + llvm::cl::ParseCommandLineOptions(LLVMArgs.size() - 1, LLVMArgs.data()); +} + int main(int argc, char **argv) { using namespace llvm; InitLLVM X(argc, argv); - const cl::OptionCategory *OptionFilters[] = {&ObjdumpCat, &MachOCat}; - cl::HideUnrelatedOptions(OptionFilters); + + ToolName = argv[0]; + + ObjdumpOptTable T; + T.setGroupedShortOptions(true); + + bool HasError = false; + BumpPtrAllocator A; + StringSaver Saver(A); + opt::InputArgList InputArgs = + T.parseArgs(argc, argv, OBJDUMP_UNKNOWN, Saver, [&](StringRef Msg) { + errs() << "error: " << Msg << '\n'; + HasError = true; + }); + if (HasError) + exit(1); + + if (InputArgs.size() == 0 || InputArgs.hasArg(OBJDUMP_help)) { + T.PrintObjdumpHelp(ToolName); + return 0; + } + if (InputArgs.hasArg(OBJDUMP_help_hidden)) { + T.PrintObjdumpHelp(ToolName, /*show_hidden=*/true); + return 0; + } // Initialize targets and assembly printers/parsers. InitializeAllTargetInfos(); InitializeAllTargetMCs(); InitializeAllDisassemblers(); - // Register the target printer for --version. - cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + if (InputArgs.hasArg(OBJDUMP_version)) { + cl::PrintVersionMessage(); + outs() << '\n'; + TargetRegistry::printRegisteredTargetsForVersion(outs()); + exit(0); + } - cl::ParseCommandLineOptions(argc, argv, "llvm object file dumper\n", nullptr, - /*EnvVar=*/nullptr, - /*LongOptionsUseDoubleDash=*/true); + parseOptions(InputArgs); if (StartAddress >= StopAddress) reportCmdLineError("start address should be less than stop address"); - ToolName = argv[0]; // Defaults to a.out if no filenames specified. if (InputFilenames.empty()) @@ -3024,7 +2938,7 @@ FirstPrivateHeader || FunctionStarts || IndirectSymbols || InfoPlist || LazyBind || LinkOptHints || ObjcMetaData || Rebase || UniversalHeaders || WeakBind || !FilterSections.empty()))) { - cl::PrintHelpMessage(); + T.PrintObjdumpHelp(ToolName); return 2; } diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn @@ -1,6 +1,12 @@ import("//llvm/tools/binutils_symlinks.gni") +import("//llvm/utils/TableGen/tablegen.gni") import("//llvm/utils/gn/build/symlink_or_copy.gni") +tablegen("ObjdumpOpts") { + visibility = [ ":llvm-objdump" ] + args = [ "-gen-opt-parser-defs" ] +} + if (llvm_install_binutils_symlinks) { symlink_or_copy("objdump") { deps = [ ":llvm-objdump" ] @@ -19,6 +25,7 @@ executable("llvm-objdump") { deps = [ + ":ObjdumpOpts", "//llvm/include/llvm/Config:config", "//llvm/lib/CodeGen", "//llvm/lib/DebugInfo/DWARF", @@ -28,6 +35,7 @@ "//llvm/lib/MC", "//llvm/lib/MC/MCDisassembler", "//llvm/lib/Object", + "//llvm/lib/Option", "//llvm/lib/Support", "//llvm/lib/Target:AllTargetsDescs", "//llvm/lib/Target:AllTargetsDisassemblers",