[llvm] 1035123 - [llvm-objdump] Switch command-line parsing from llvm::cl to OptTable

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 14 17:12:39 PDT 2021


Author: Nico Weber
Date: 2021-04-14T20:12:24-04:00
New Revision: 1035123ac50db21bb2f44f78c040a823d7d064b2

URL: https://github.com/llvm/llvm-project/commit/1035123ac50db21bb2f44f78c040a823d7d064b2
DIFF: https://github.com/llvm/llvm-project/commit/1035123ac50db21bb2f44f78c040a823d7d064b2.diff

LOG: [llvm-objdump] Switch command-line parsing from llvm::cl to OptTable

This is similar to D83530, but for llvm-objdump.

The motivation is the desire to add an `llvm-otool` symlink to
llvm-objdump that behaves like macOS's `otool`, using the same
technique the at llvm-objcopy uses to behave like `strip` (etc).

This change for the most part preserves behavior. In some cases,
it increases compatibility with GNU objdump a bit. For example,
the long options now require two dashes, and the long options
taking arguments for the most part now require a `=` in front
of the value. Exceptions are flags where tests passed the
value separately, for these the separate form is kept as
an alias to the = form.

The one-letter short form args are now joined or separate
and long longer accept a =, which also matches GNU objdump.

cl::opt<>s in libraries now have to be explicitly plumbed
through. This patch does that for --x86-asm-syntax=, but
there's hope that we can remove that again.

Differential Revision: https://reviews.llvm.org/D100433

Added: 
    llvm/tools/llvm-objdump/ObjdumpOptID.h
    llvm/tools/llvm-objdump/ObjdumpOpts.td

Modified: 
    llvm/test/Support/check-default-options.txt
    llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test
    llvm/test/tools/llvm-objdump/help.test
    llvm/test/tools/llvm-objdump/section-filter.test
    llvm/tools/llvm-objdump/CMakeLists.txt
    llvm/tools/llvm-objdump/MachODump.cpp
    llvm/tools/llvm-objdump/MachODump.h
    llvm/tools/llvm-objdump/llvm-objdump.cpp
    llvm/tools/llvm-objdump/llvm-objdump.h
    llvm/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn

Removed: 
    


################################################################################
diff  --git a/llvm/test/Support/check-default-options.txt b/llvm/test/Support/check-default-options.txt
index 352471ed9ef2..46246e06210c 100644
--- 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
index c2fc95ed4f02..e26db49e6d22 100644
--- 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
index 940eea3293af..ae0bf81e040f 100644
--- 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] <input object files>{{$}}
-CHECK: OPTIONS:
+CHECK: Generic Options:
+CHECK-NOT: {{ -w }}
 CHECK: @FILE
+
+HIDDEN: OVERVIEW: llvm object file dumper
+HIDDEN: USAGE: llvm-objdump{{(.exe)?}} [options] <input object files>{{$}}
+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
index 77506320c20f..6b5c2bcf747a 100644
--- 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 @@ Sections:
     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
index a8546fd77236..5a0c855b37cd 100644
--- a/llvm/tools/llvm-objdump/CMakeLists.txt
+++ b/llvm/tools/llvm-objdump/CMakeLists.txt
@@ -9,10 +9,15 @@ set(LLVM_LINK_COMPONENTS
   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 @@ add_llvm_tool(llvm-objdump
   MachODump.cpp
   WasmDump.cpp
   XCOFFDump.cpp
+  DEPENDS
+  ObjdumpOptsTableGen
   )
 
 if(HAVE_LIBXAR)

diff  --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp
index 11d22a9cfb3d..fadb2999d209 100644
--- 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;
 using namespace llvm::object;
 using namespace llvm::objdump;
 
-cl::OptionCategory objdump::MachOCat("llvm-objdump MachO Specific Options");
-
-cl::opt<bool> objdump::FirstPrivateHeader(
-    "private-header",
-    cl::desc("Display only the first format specific file header"),
-    cl::cat(MachOCat));
-
-cl::opt<bool> objdump::ExportsTrie("exports-trie",
-                                   cl::desc("Display mach-o exported symbols"),
-                                   cl::cat(MachOCat));
-
-cl::opt<bool> objdump::Rebase("rebase",
-                              cl::desc("Display mach-o rebasing info"),
-                              cl::cat(MachOCat));
-
-cl::opt<bool> objdump::Bind("bind", cl::desc("Display mach-o binding info"),
-                            cl::cat(MachOCat));
-
-cl::opt<bool> objdump::LazyBind("lazy-bind",
-                                cl::desc("Display mach-o lazy binding info"),
-                                cl::cat(MachOCat));
-
-cl::opt<bool> objdump::WeakBind("weak-bind",
-                                cl::desc("Display mach-o weak binding info"),
-                                cl::cat(MachOCat));
-
-static cl::opt<bool>
-    UseDbg("g", cl::Grouping,
-           cl::desc("Print line information from debug info if available"),
-           cl::cat(MachOCat));
-
-static cl::opt<std::string> DSYMFile("dsym",
-                                     cl::desc("Use .dSYM file for debug info"),
-                                     cl::cat(MachOCat));
-
-static cl::opt<bool> FullLeadingAddr("full-leading-addr",
-                                     cl::desc("Print full leading address"),
-                                     cl::cat(MachOCat));
-
-static cl::opt<bool> NoLeadingHeaders("no-leading-headers",
-                                      cl::desc("Print no leading headers"),
-                                      cl::cat(MachOCat));
-
-cl::opt<bool> objdump::UniversalHeaders(
-    "universal-headers",
-    cl::desc("Print Mach-O universal headers (requires --macho)"),
-    cl::cat(MachOCat));
-
-static cl::opt<bool> 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<bool> objdump::IndirectSymbols(
-    "indirect-symbols",
-    cl::desc(
-        "Print indirect symbol table for Mach-O objects (requires --macho)"),
-    cl::cat(MachOCat));
-
-cl::opt<bool> objdump::DataInCode(
-    "data-in-code",
-    cl::desc(
-        "Print the data in code table for Mach-O objects (requires --macho)"),
-    cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::FunctionStarts("function-starts",
-                            cl::desc("Print the function starts table for "
-                                     "Mach-O objects (requires --macho)"),
-                            cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::LinkOptHints("link-opt-hints",
-                          cl::desc("Print the linker optimization hints for "
-                                   "Mach-O objects (requires --macho)"),
-                          cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::InfoPlist("info-plist",
-                       cl::desc("Print the info plist section as strings for "
-                                "Mach-O objects (requires --macho)"),
-                       cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::DylibsUsed("dylibs-used",
-                        cl::desc("Print the shared libraries used for linked "
-                                 "Mach-O files (requires --macho)"),
-                        cl::cat(MachOCat));
-
-cl::opt<bool> 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<bool>
-    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<bool>
-    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<std::string> DisSymName(
-    "dis-symname",
-    cl::desc("disassemble just this symbol's instructions (requires --macho)"),
-    cl::cat(MachOCat));
-
-static cl::opt<bool> NoSymbolicOperands(
-    "no-symbolic-operands",
-    cl::desc("do not symbolic operands when disassembling (requires --macho)"),
-    cl::cat(MachOCat));
-
-static cl::list<std::string>
-    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<std::string> 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/MachODump.h b/llvm/tools/llvm-objdump/MachODump.h
index a4cc7de0860c..447749a23e59 100644
--- a/llvm/tools/llvm-objdump/MachODump.h
+++ b/llvm/tools/llvm-objdump/MachODump.h
@@ -24,25 +24,31 @@ class ObjectFile;
 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<bool> Bind;
-extern cl::opt<bool> DataInCode;
-extern cl::opt<bool> DylibsUsed;
-extern cl::opt<bool> DylibId;
-extern cl::opt<bool> ExportsTrie;
-extern cl::opt<bool> FirstPrivateHeader;
-extern cl::opt<bool> FunctionStarts;
-extern cl::opt<bool> IndirectSymbols;
-extern cl::opt<bool> InfoPlist;
-extern cl::opt<bool> LazyBind;
-extern cl::opt<bool> LinkOptHints;
-extern cl::opt<bool> ObjcMetaData;
-extern cl::opt<bool> Rebase;
-extern cl::opt<bool> UniversalHeaders;
-extern cl::opt<bool> 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/ObjdumpOptID.h b/llvm/tools/llvm-objdump/ObjdumpOptID.h
new file mode 100644
index 000000000000..2c17f441a033
--- /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
index 000000000000..dfcb25938022
--- /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<grp_generic>;
+
+def help_hidden : Flag<["--"], "help-hidden">,
+  Flags<[HelpHidden]>,
+  HelpText<"Display all available options">,
+  Group<grp_generic>;
+
+def version : Flag<["--"], "version">,
+  HelpText<"Display the version of this program">,
+  Group<grp_generic>;
+
+
+
+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<grp_objdump>;
+
+def all_headers : Flag<["--"], "all-headers">,
+  HelpText<"Display all available header information">,
+  Group<grp_objdump>;
+def : Flag<["-"], "x">, Alias<all_headers>, HelpText<"Alias for --all-headers">,
+  Group<grp_objdump>;
+
+def arch_name_EQ : Joined<["--"], "arch-name=">,
+  HelpText<"Target arch to disassemble for, "
+            "see --version for available targets">,
+  Group<grp_objdump>;
+
+def archive_headers : Flag<["--"], "archive-headers">,
+  HelpText<"Display archive header information">,
+  Group<grp_objdump>;
+def : Flag<["-"], "a">, Alias<all_headers>,
+  HelpText<"Alias for --archive-headers">,
+  Group<grp_objdump>;
+
+def demangle : Flag<["--"], "demangle">, HelpText<"Demangle symbol names">,
+  Group<grp_objdump>;
+def : Flag<["-"], "C">, Alias<demangle>, HelpText<"Alias for --demangle">,
+  Group<grp_objdump>;
+
+def disassemble : Flag<["--"], "disassemble">,
+  HelpText<"Display assembler mnemonics for the machine instructions">,
+  Group<grp_objdump>;
+def : Flag<["-"], "d">, Alias<disassemble>, HelpText<"Alias for --disassemble">,
+  Group<grp_objdump>;
+
+def disassemble_all : Flag<["--"], "disassemble-all">,
+  HelpText<"Display assembler mnemonics for the machine instructions">,
+  Group<grp_objdump>;
+def : Flag<["-"], "D">, Alias<disassemble_all>,
+  HelpText<"Alias for --disassemble-all">,
+  Group<grp_objdump>;
+
+def symbol_description : Flag<["--"], "symbol-description">,
+  HelpText<"Add symbol description for disassembly. This "
+           "option is for XCOFF files only.">,
+  Group<grp_objdump>;
+
+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<grp_objdump>;
+
+def disassemble_zeroes : Flag<["--"], "disassemble-zeroes">,
+  HelpText<"Do not skip blocks of zeroes when disassembling">,
+  Group<grp_objdump>;
+def : Flag<["-"], "z">, Alias<disassemble_zeroes>,
+  HelpText<"Alias for --disassemble-zeroes">,
+  Group<grp_objdump>;
+
+def disassembler_options_EQ : Joined<["--"], "disassembler-options=">,
+  MetaVarName<"options">,
+  HelpText<"Pass target specific disassembler options">,
+  Group<grp_objdump>;
+def : JoinedOrSeparate<["-"], "M">, Alias<disassembler_options_EQ>,
+  HelpText<"Alias for --disassembler-options=">,
+  Group<grp_objdump>;
+
+def dynamic_reloc : Flag<["--"], "dynamic-reloc">,
+  HelpText<"Display the dynamic relocation entries in the file">,
+  Group<grp_objdump>;
+def : Flag<["-"], "R">, Alias<dynamic_reloc>,
+  HelpText<"Alias for --dynamic-reloc">,
+  Group<grp_objdump>;
+
+def dwarf_EQ : Joined<["--"], "dwarf=">,
+  HelpText<"Dump of dwarf debug sections">, Values<"frames">,
+  Group<grp_objdump>;
+
+def fault_map_section : Flag<["--"], "fault-map-section">,
+  HelpText<"Display contents of faultmap section">,
+  Group<grp_objdump>;
+
+def file_headers : Flag<["--"], "file-headers">,
+  HelpText<"Display the contents of the overall file header">,
+  Group<grp_objdump>;
+def : Flag<["-"], "f">, Alias<file_headers>,
+  HelpText<"Alias for --file-headers">,
+  Group<grp_objdump>;
+
+def full_contents : Flag<["--"], "full-contents">,
+  HelpText<"Display the content of each section">,
+  Group<grp_objdump>;
+def : Flag<["-"], "s">, Alias<full_contents>,
+  HelpText<"Alias for --full-contents">,
+  Group<grp_objdump>;
+
+def line_numbers : Flag<["--"], "line-numbers">,
+  HelpText<"Display source line numbers with "
+            "disassembly. Implies disassemble object">,
+  Group<grp_objdump>;
+def : Flag<["-"], "l">, Alias<line_numbers>,
+  HelpText<"Alias for --line-numbers">,
+  Group<grp_objdump>;
+
+def macho : Flag<["--"], "macho">,
+  HelpText<"Use MachO specific object file parser">,
+  Group<grp_objdump>;
+def : Flag<["-"], "m">, Alias<macho>, HelpText<"Alias for --macho">,
+  Group<grp_objdump>;
+
+def mcpu_EQ : Joined<["--"], "mcpu=">,
+  MetaVarName<"cpu-name">,
+  HelpText<"Target a specific cpu type (--mcpu=help for details)">,
+  Group<grp_objdump>;
+
+def mattr_EQ : Joined<["--"], "mattr=">,
+  MetaVarName<"a1,+a2,-a3,...">,
+  HelpText<"Target specific attributes (--mattr=help for details)">,
+  Group<grp_objdump>;
+
+def no_show_raw_insn : Flag<["--"], "no-show-raw-insn">,
+  HelpText<"When disassembling instructions, "
+           "do not print the instruction bytes.">,
+  Group<grp_objdump>;
+
+def no_leading_addr : Flag<["--"], "no-leading-addr">,
+  HelpText<"Print no leading address">,
+  Group<grp_objdump>;
+
+def raw_clang_ast : Flag<["--"], "raw-clang-ast">,
+  HelpText<"Dump the raw binary contents of the clang AST section">,
+  Group<grp_objdump>;
+
+def reloc : Flag<["--"], "reloc">,
+  HelpText<"Display the relocation entries in the file">,
+  Group<grp_objdump>;
+def : Flag<["-"], "r">, Alias<reloc>, HelpText<"Alias for --reloc">,
+  Group<grp_objdump>;
+
+def print_imm_hex : Flag<["--"], "print-imm-hex">,
+  HelpText<"Use hex format for immediate values">,
+  Group<grp_objdump>;
+
+def no_print_imm_hex : Flag<["--"], "no-print-imm-hex">,
+  HelpText<"Do not use hex format for immediate values (default)">,
+  Group<grp_objdump>;
+def : Flag<["--"], "print-imm-hex=false">, Alias<no_print_imm_hex>,
+  Group<grp_objdump>;
+
+def private_headers : Flag<["--"], "private-headers">,
+  HelpText<"Display format specific file headers">,
+  Group<grp_objdump>;
+def : Flag<["-"], "p">, Alias<private_headers>,
+  HelpText<"Alias for --private-headers">,
+  Group<grp_objdump>;
+
+def section_EQ : Joined<["--"], "section=">,
+  HelpText<"Operate on the specified sections only. "
+           "With --macho dump segment,section">,
+  Group<grp_objdump>;
+def : Separate<["--"], "section">, Alias<section_EQ>,
+  Group<grp_objdump>;
+def : JoinedOrSeparate<["-"], "j">, Alias<section_EQ>,
+  HelpText<"Alias for --section">,
+  Group<grp_objdump>;
+
+def section_headers : Flag<["--"], "section-headers">,
+  HelpText<"Display summaries of the headers for each section.">,
+  Group<grp_objdump>;
+def : Flag<["--"], "headers">, Alias<section_headers>,
+  HelpText<"Alias for --section-headers">,
+  Group<grp_objdump>;
+def : Flag<["-"], "h">, Alias<section_headers>,
+  HelpText<"Alias for --section-headers">,
+  Group<grp_objdump>;
+
+def show_lma : Flag<["--"], "show-lma">,
+  HelpText<"Display LMA column when dumping ELF section headers">,
+  Group<grp_objdump>;
+
+def source : Flag<["--"], "source">,
+  HelpText<"Display source inlined with disassembly. Implies disassemble object">,
+  Group<grp_objdump>;
+def : Flag<["-"], "S">, Alias<source>, HelpText<"Alias for --source">,
+  Group<grp_objdump>;
+
+def start_address_EQ : Joined<["--"], "start-address=">,
+  MetaVarName<"address">,
+  HelpText<"Disassemble beginning at address">,
+  Group<grp_objdump>;
+def stop_address_EQ : Joined<["--"], "stop-address=">,
+  MetaVarName<"address">,
+  HelpText<"Stop disassembly at address">,
+  Group<grp_objdump>;
+
+def syms : Flag<["--"], "syms">,
+  HelpText<"Display the symbol table">,
+  Group<grp_objdump>;
+def : Flag<["-"], "t">, Alias<syms>, HelpText<"Alias for --syms">,
+  Group<grp_objdump>;
+
+def symbolize_operands : Flag<["--"], "symbolize-operands">,
+  HelpText<"Symbolize instruction operands when disassembling">,
+  Group<grp_objdump>;
+
+def dynamic_syms : Flag<["--"], "dynamic-syms">,
+  HelpText<"Display the contents of the dynamic symbol table">,
+  Group<grp_objdump>;
+def : Flag<["-"], "T">, Alias<dynamic_syms>,
+  HelpText<"Alias for --dynamic-syms">,
+  Group<grp_objdump>;
+
+def triple_EQ : Joined<["--"], "triple=">,
+  HelpText<"Target triple to disassemble for, "
+            "see --version for available targets">,
+  Group<grp_objdump>;
+def : Separate<["--"], "triple">,
+  Alias<triple_EQ>,
+  Group<grp_objdump>;
+
+def unwind_info : Flag<["--"], "unwind-info">,
+  HelpText<"Display unwind information">,
+  Group<grp_objdump>;
+def : Flag<["-"], "u">, Alias<unwind_info>,
+  HelpText<"Alias for --unwind-info">,
+  Group<grp_objdump>;
+
+def wide : Flag<["--"], "wide">,
+  HelpText<"Ignored for compatibility with GNU objdump">,
+  Group<grp_objdump>;
+def : Flag<["-"], "w">, Alias<wide>,
+  Group<grp_objdump>;
+
+def prefix : Separate<["--"], "prefix">,
+  HelpText<"Add prefix to absolute paths">,
+  Group<grp_objdump>;
+
+def prefix_strip : Separate<["--"], "prefix-strip">,
+  HelpText<"Strip out initial directories from absolute "
+           "paths. No effect without --prefix">,
+  Group<grp_objdump>;
+
+def debug_vars_EQ : Joined<["--"], "debug-vars=">,
+  Values<"unicode,ascii">,
+  Group<grp_objdump>;
+def : Flag<["--"], "debug-vars">,
+  HelpText<"Print the locations (in registers or memory) of "
+           "source-level variables alongside disassembly">,
+  Alias<debug_vars_EQ>, AliasArgs<["unicode"]>,
+  Group<grp_objdump>;
+
+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<grp_objdump>;
+
+def x86_asm_syntax_att : Flag<["--"], "x86-asm-syntax=att">,
+  HelpText<"Emit AT&T-style disassembly">,
+  Group<grp_objdump>;
+
+def x86_asm_syntax_intel : Flag<["--"], "x86-asm-syntax=intel">,
+  HelpText<"Emit Intel-style disassembly">,
+  Group<grp_objdump>;
+
+
+
+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<grp_mach_o>;
+
+def exports_trie : Flag<["--"], "exports-trie">,
+  HelpText<"Display mach-o exported symbols">,
+  Group<grp_mach_o>;
+
+def rebase : Flag<["--"], "rebase">,
+  HelpText<"Display mach-o rebasing info">,
+  Group<grp_mach_o>;
+
+def bind : Flag<["--"], "bind">,
+  HelpText<"Display mach-o binding info">,
+  Group<grp_mach_o>;
+
+def lazy_bind : Flag<["--"], "lazy-bind">,
+  HelpText<"Display mach-o lazy binding info">,
+  Group<grp_mach_o>;
+
+def weak_bind : Flag<["--"], "weak-bind">,
+  HelpText<"Display mach-o weak binding info">,
+  Group<grp_mach_o>;
+
+def g : Flag<["-"], "g">,
+  HelpText<"Print line information from debug info if available">,
+  Group<grp_mach_o>;
+
+def dsym_EQ : Joined<["--"], "dsym=">,
+  HelpText<"Use .dSYM file for debug info">,
+  Group<grp_mach_o>;
+def : Separate<["--"], "dsym">,
+  Alias<dsym_EQ>,
+  Group<grp_mach_o>;
+
+def full_leading_addr : Flag<["--"], "full-leading-addr">,
+  HelpText<"Print full leading address">,
+  Group<grp_mach_o>;
+
+def no_leading_headers : Flag<["--"], "no-leading-headers">,
+  HelpText<"Print no leading headers">,
+  Group<grp_mach_o>;
+
+def universal_headers : Flag<["--"], "universal-headers">,
+  HelpText<"Print Mach-O universal headers (requires --macho)">,
+  Group<grp_mach_o>;
+
+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<grp_mach_o>;
+
+def indirect_symbols : Flag<["--"], "indirect-symbols">,
+  HelpText<"Print indirect symbol table for Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def data_in_code : Flag<["--"], "data-in-code">,
+  HelpText<"Print the data in code table for Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def function_starts : Flag<["--"], "function-starts">,
+  HelpText<"Print the function starts table for "
+           "Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def link_opt_hints : Flag<["--"], "link-opt-hints">,
+  HelpText<"Print the linker optimization hints for "
+           "Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def info_plist : Flag<["--"], "info-plist">,
+  HelpText<"Print the info plist section as strings for "
+           "Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def dylibs_used : Flag<["--"], "dylibs-used">,
+  HelpText<"Print the shared libraries used for linked "
+           "Mach-O files (requires --macho)">,
+  Group<grp_mach_o>;
+
+def dylib_id : Flag<["--"], "dylib-id">,
+  HelpText<"Print the shared library's id for the "
+           "dylib Mach-O file (requires --macho)">,
+  Group<grp_mach_o>;
+
+def non_verbose : Flag<["--"], "non-verbose">,
+  HelpText<"Print the info for Mach-O objects in non-verbose or "
+           "numeric form (requires --macho)">,
+  Group<grp_mach_o>;
+
+def objc_meta_data : Flag<["--"], "objc-meta-data">,
+  HelpText<"Print the Objective-C runtime meta data "
+           "for Mach-O files (requires --macho)">,
+  Group<grp_mach_o>;
+
+def dis_symname : Separate<["--"], "dis-symname">,
+  HelpText<"disassemble just this symbol's instructions (requires --macho)">,
+  Group<grp_mach_o>;
+
+def no_symbolic_operands : Flag<["--"], "no-symbolic-operands">,
+  HelpText<"do not symbolic operands when disassembling (requires --macho)">,
+  Group<grp_mach_o>;
+
+def arch_EQ : Joined<["--"], "arch=">,
+  HelpText<"architecture(s) from a Mach-O file to dump">,
+  Group<grp_mach_o>;
+def : Separate<["--"], "arch">,
+  Alias<arch_EQ>,
+  Group<grp_mach_o>;

diff  --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 13d60f721add..54b9471d1ba3 100644
--- 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] <input object files>").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<uint64_t> 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<bool>
-    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<std::string>
-    ArchName("arch-name",
-             cl::desc("Target arch to disassemble for, "
-                      "see --version for available targets"),
-             cl::cat(ObjdumpCat));
-
-cl::opt<bool>
-    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<bool> 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<bool> 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<bool> 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<bool> 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<std::string>
-    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<bool> 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<std::string>
-    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<DIDumpType> 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<bool> 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<bool>
-    FaultMapSection("fault-map-section",
-                    cl::desc("Display contents of faultmap section"),
-                    cl::cat(ObjdumpCat));
-
-static cl::opt<bool>
-    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<bool>
-    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<std::string> InputFilenames(cl::Positional,
-                                            cl::desc("<input object files>"),
-                                            cl::ZeroOrMore,
-                                            cl::cat(ObjdumpCat));
-
-static cl::opt<bool>
-    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<bool> 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<std::string> 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<std::string> 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<bool> objdump::NoShowRawInsn(
-    "no-show-raw-insn",
-    cl::desc(
-        "When disassembling instructions, do not print the instruction bytes."),
-    cl::cat(ObjdumpCat));
-
-cl::opt<bool> objdump::NoLeadingAddr("no-leading-addr",
-                                     cl::desc("Print no leading address"),
-                                     cl::cat(ObjdumpCat));
-
-static cl::opt<bool> RawClangAST(
-    "raw-clang-ast",
-    cl::desc("Dump the raw binary contents of the clang AST section"),
-    cl::cat(ObjdumpCat));
-
-cl::opt<bool>
-    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<bool>
-    objdump::PrintImmHex("print-imm-hex",
-                         cl::desc("Use hex format for immediate values"),
-                         cl::cat(ObjdumpCat));
-
-cl::opt<bool>
-    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<std::string>
-    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<bool> 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<bool>
-    ShowLMA("show-lma",
-            cl::desc("Display LMA column when dumping ELF section headers"),
-            cl::cat(ObjdumpCat));
-
-static cl::opt<bool> 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<uint64_t>
-    StartAddress("start-address", cl::desc("Disassemble beginning at address"),
-                 cl::value_desc("address"), cl::init(0), cl::cat(ObjdumpCat));
-static cl::opt<uint64_t> StopAddress("stop-address",
-                                     cl::desc("Stop disassembly at address"),
-                                     cl::value_desc("address"),
-                                     cl::init(UINT64_MAX), cl::cat(ObjdumpCat));
-
-cl::opt<bool> 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<bool> SymbolizeOperands(
-    "symbolize-operands",
-    cl::desc("Symbolize instruction operands when disassembling"),
-    cl::cat(ObjdumpCat));
-
-static cl::opt<bool> 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<std::string>
-    objdump::TripleName("triple",
-                        cl::desc("Target triple to disassemble for, see "
-                                 "--version for available targets"),
-                        cl::cat(ObjdumpCat));
-
-cl::opt<bool> 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<bool>
-    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<std::string> objdump::Prefix("prefix",
-                                     cl::desc("Add prefix to absolute paths"),
-                                     cl::cat(ObjdumpCat));
-
-cl::opt<uint32_t>
-    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<std::string> DisassembleSymbols;
+static bool DisassembleZeroes;
+static std::vector<std::string> DisassemblerOptions;
+DIDumpType objdump::DwarfDumpType;
+static bool DynamicRelocations;
+static bool FaultMapSection;
+static bool FileHeaders;
+bool objdump::SectionContents;
+static std::vector<std::string> InputFilenames;
+static bool PrintLines;
+static bool MachOOpt;
+std::string objdump::MCPU;
+std::vector<std::string> objdump::MAttrs;
+bool objdump::NoShowRawInsn;
+bool objdump::NoLeadingAddr;
+static bool RawClangAST;
+bool objdump::Relocations;
+bool objdump::PrintImmHex;
+bool objdump::PrivateHeaders;
+std::vector<std::string> 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<DebugVarsFormat> 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<int>
-    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 @@ static void checkForInvalidStartStopAddress(ObjectFile *Obj,
         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 @@ static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
     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 @@ static void dumpInput(StringRef file) {
     reportError(errorCodeToError(object_error::invalid_file_type), file);
 }
 
+template <typename T>
+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<std::string>
+commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
+  std::vector<std::string> Values;
+  for (StringRef Value : InputArgs.getAllArgValues(ID)) {
+    llvm::SmallVector<StringRef, 2> 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<DIDumpType>(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<DebugVarsFormat>(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<const char *> 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 @@ int main(int argc, char **argv) {
          FirstPrivateHeader || FunctionStarts || IndirectSymbols || InfoPlist ||
          LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
          UniversalHeaders || WeakBind || !FilterSections.empty()))) {
-    cl::PrintHelpMessage();
+    T.PrintObjdumpHelp(ToolName);
     return 2;
   }
 

diff  --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index 884702d11f85..601568d579be 100644
--- 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 @@ class RelocationRef;
 
 namespace objdump {
 
-extern cl::opt<bool> ArchiveHeaders;
-extern cl::opt<bool> Demangle;
-extern cl::opt<bool> Disassemble;
-extern cl::opt<bool> DisassembleAll;
-extern cl::opt<DIDumpType> DwarfDumpType;
-extern cl::list<std::string> FilterSections;
-extern cl::list<std::string> MAttrs;
-extern cl::opt<std::string> MCPU;
-extern cl::opt<bool> NoShowRawInsn;
-extern cl::opt<bool> NoLeadingAddr;
-extern cl::opt<std::string> Prefix;
-extern cl::opt<uint32_t> PrefixStrip;
-extern cl::opt<bool> PrintImmHex;
-extern cl::opt<bool> PrivateHeaders;
-extern cl::opt<bool> Relocations;
-extern cl::opt<bool> SectionHeaders;
-extern cl::opt<bool> SectionContents;
-extern cl::opt<bool> SymbolDescription;
-extern cl::opt<bool> SymbolTable;
-extern cl::opt<std::string> TripleName;
-extern cl::opt<bool> UnwindInfo;
+extern bool ArchiveHeaders;
+extern bool Demangle;
+extern bool Disassemble;
+extern bool DisassembleAll;
+extern DIDumpType DwarfDumpType;
+extern std::vector<std::string> FilterSections;
+extern std::vector<std::string> 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/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn
index c8ba176dd34f..bdf650b3a502 100644
--- 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 @@ group("symlinks") {
 
 executable("llvm-objdump") {
   deps = [
+    ":ObjdumpOpts",
     "//llvm/include/llvm/Config:config",
     "//llvm/lib/CodeGen",
     "//llvm/lib/DebugInfo/DWARF",
@@ -28,6 +35,7 @@ executable("llvm-objdump") {
     "//llvm/lib/MC",
     "//llvm/lib/MC/MCDisassembler",
     "//llvm/lib/Object",
+    "//llvm/lib/Option",
     "//llvm/lib/Support",
     "//llvm/lib/Target:AllTargetsDescs",
     "//llvm/lib/Target:AllTargetsDisassemblers",


        


More information about the llvm-commits mailing list