Index: llvm/test/tools/llvm-gsymutil/cmdline.test
===================================================================
--- llvm/test/tools/llvm-gsymutil/cmdline.test
+++ llvm/test/tools/llvm-gsymutil/cmdline.test
@@ -3,21 +3,17 @@
HELP: OVERVIEW: A tool for dumping, searching and creating GSYM files.
HELP: USAGE: llvm-gsymutil{{[^ ]*}} [options]
HELP: OPTIONS:
-HELP: Conversion Options:
-HELP: --arch=
-HELP: --convert=
-HELP: --num-threads=
-HELP: --out-file=
+HELP: --address=
+HELP: --addresses-from-stdin
+HELP: --arch=
+HELP: --convert=
+HELP: --help
+HELP: --num-threads=
+HELP: --out-file=
HELP: --quiet
+HELP: --verbose
HELP: --verify
-HELP: Generic Options:
-HELP: --help
HELP: --version
-HELP: Lookup Options:
-HELP: --address=
-HELP: --addresses-from-stdin
-HELP: Options:
-HELP: --verbose
RUN: llvm-gsymutil --version 2>&1 | FileCheck --check-prefix=VERSION %s
VERSION: {{ version }}
Index: llvm/tools/llvm-gsymutil/CMakeLists.txt
===================================================================
--- llvm/tools/llvm-gsymutil/CMakeLists.txt
+++ llvm/tools/llvm-gsymutil/CMakeLists.txt
@@ -4,10 +4,18 @@
DebugInfoGSYM
MC
Object
+ Option
Support
TargetParser
)
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(GSYMUtilOptsTableGen)
+
add_llvm_tool(llvm-gsymutil
llvm-gsymutil.cpp
+
+ DEPENDS
+ GSYMUtilOptsTableGen
)
Index: llvm/tools/llvm-gsymutil/Opts.td
===================================================================
--- /dev/null
+++ llvm/tools/llvm-gsymutil/Opts.td
@@ -0,0 +1,27 @@
+include "llvm/Option/OptParser.td"
+
+class F : Flag<["-"], letter>, HelpText;
+class FF : Flag<["--"], name>, HelpText;
+
+multiclass Eq {
+ def NAME #_EQ : Joined<["--"], name #"=">, HelpText;
+ def : Separate<["--"], name>, Alias(NAME #_EQ)>;
+}
+
+def help : FF<"help", "Display this help">;
+def : F<"h", "Alias for --help">, Alias;
+def version : FF<"version", "Display the version">;
+def : F<"v", "Alias for --version">, Alias;
+def verbose : FF<"verbose", "Enable verbose logging and encoding details.">;
+defm convert : Eq<"convert", "path">;
+defm arch : Eq<"arch", "arch">;
+defm out_file : Eq<"out-file", "path">;
+def : Separate<["-"], "o">, HelpText<"Alias for --out-file.">, Alias;
+def verify : FF<"verify", "Verify the generated GSYM file against the information in the file that was converted.">;
+defm num_threads : Eq<"num-threads", "n">;
+defm segment_size : Eq<"segment-size", "s">;
+def quiet : FF<"quiet", "Do not output warnings about the debug information">;
+defm address : Eq<"address", "addr">;
+def addresses_from_stdin :
+ FF<"addresses-from-stdin",
+ "Emit a section containing remark diagnostics metadata. By default, this is enabled for the following formats: yaml-strtab, bitstream.">;
Index: llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
===================================================================
--- llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
+++ llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
@@ -14,6 +14,8 @@
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
@@ -52,85 +54,132 @@
/// Command line options.
/// @{
-namespace {
-using namespace cl;
-
-OptionCategory GeneralOptions("Options");
-OptionCategory ConversionOptions("Conversion Options");
-OptionCategory LookupOptions("Lookup Options");
-
-static opt Help("h", desc("Alias for -help"), Hidden,
- cat(GeneralOptions));
-
-static opt Verbose("verbose",
- desc("Enable verbose logging and encoding details."),
- cat(GeneralOptions));
-
-static list InputFilenames(Positional, desc(""),
- cat(GeneralOptions));
-
-static opt
- ConvertFilename("convert", cl::init(""),
- cl::desc("Convert the specified file to the GSYM format.\n"
- "Supported files include ELF and mach-o files "
- "that will have their debug info (DWARF) and "
- "symbol table converted."),
- cl::value_desc("path"), cat(ConversionOptions));
-
-static list
- ArchFilters("arch",
- desc("Process debug information for the specified CPU "
- "architecture only.\nArchitectures may be specified by "
- "name or by number.\nThis option can be specified "
- "multiple times, once for each desired architecture."),
- cl::value_desc("arch"), cat(ConversionOptions));
-
-static opt
- OutputFilename("out-file", cl::init(""),
- cl::desc("Specify the path where the converted GSYM file "
- "will be saved.\nWhen not specified, a '.gsym' "
- "extension will be appended to the file name "
- "specified in the --convert option."),
- cl::value_desc("path"), cat(ConversionOptions));
-static alias OutputFilenameAlias("o", desc("Alias for -out-file."),
- aliasopt(OutputFilename),
- cat(ConversionOptions));
-
-static opt Verify("verify",
- desc("Verify the generated GSYM file against the "
- "information in the file that was converted."),
- cat(ConversionOptions));
-
-static opt
- NumThreads("num-threads",
- desc("Specify the maximum number (n) of simultaneous threads "
- "to use when converting files to GSYM.\nDefaults to the "
- "number of cores on the current machine."),
- cl::value_desc("n"), cat(ConversionOptions));
-
-static opt
- SegmentSize("segment-size",
- desc("Specify the size in bytes of the size the final GSYM file "
- "should be segmented into. This allows GSYM files to be "
- "split across multiple files."),
- cl::value_desc("s"), cat(ConversionOptions));
-
-static opt
- Quiet("quiet", desc("Do not output warnings about the debug information"),
- cat(ConversionOptions));
-
-static list LookupAddresses("address",
- desc("Lookup an address in a GSYM file"),
- cl::value_desc("addr"),
- cat(LookupOptions));
-
-static opt LookupAddressesFromStdin(
- "addresses-from-stdin",
- desc("Lookup addresses in a GSYM file that are read from stdin\nEach input "
- "line is expected to be of the following format: "),
- cat(LookupOptions));
-
-} // namespace
+using namespace llvm::opt;
+enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ OPT_##ID,
+#include "Opts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) \
+ constexpr llvm::StringLiteral NAME##_init[] = VALUE; \
+ constexpr llvm::ArrayRef NAME( \
+ NAME##_init, std::size(NAME##_init) - 1);
+#include "Opts.inc"
+#undef PREFIX
+
+const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ { \
+ PREFIX, NAME, HELPTEXT, \
+ METAVAR, OPT_##ID, opt::Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, \
+ OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Opts.inc"
+#undef OPTION
+};
+
+class GSYMUtilOptTable : public llvm::opt::GenericOptTable {
+public:
+ GSYMUtilOptTable() : GenericOptTable(InfoTable) {
+ setGroupedShortOptions(true);
+ }
+};
+
+static bool Verbose = false;
+static std::vector InputFilenames;
+static std::string ConvertFilename;
+static std::vector ArchFilters;
+static std::string OutputFilename;
+static bool Verify = false;
+static unsigned NumThreads = 0;
+static uint64_t SegmentSize = 0;
+static bool Quiet = false;
+static std::vector LookupAddresses;
+static bool LookupAddressesFromStdin = false;
+
+static void parseArgs(int argc, char **argv) {
+ GSYMUtilOptTable Tbl;
+ llvm::StringRef ToolName = argv[0];
+ llvm::BumpPtrAllocator A;
+ llvm::StringSaver Saver{A};
+ llvm::opt::InputArgList Args =
+ Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+ llvm::errs() << Msg << '\n';
+ std::exit(1);
+ });
+ if (Args.hasArg(OPT_help)) {
+ const char *Overview =
+ "A tool for dumping, searching and creating GSYM files.\n\n"
+ "Specify one or more GSYM paths as arguments to dump all of the "
+ "information in each GSYM file.\n"
+ "Specify a single GSYM file along with one or more --lookup options to "
+ "lookup addresses within that GSYM file.\n"
+ "Use the --convert option to specify a file with option --out-file "
+ "option to convert to GSYM format.\n";
+
+ Tbl.printHelp(llvm::outs(), "llvm-gsymutil [options] ",
+ Overview);
+ std::exit(0);
+ }
+ if (Args.hasArg(OPT_version)) {
+ llvm::outs() << ToolName << '\n';
+ cl::PrintVersionMessage();
+ std::exit(0);
+ }
+
+ Verbose = Args.hasArg(OPT_verbose);
+
+ for (const llvm::opt::Arg *A : Args.filtered(OPT_INPUT))
+ InputFilenames.emplace_back(A->getValue());
+
+ if (const llvm::opt::Arg *A = Args.getLastArg(OPT_convert_EQ))
+ ConvertFilename = A->getValue();
+
+ for (const llvm::opt::Arg *A : Args.filtered(OPT_arch_EQ))
+ ArchFilters.emplace_back(A->getValue());
+
+ if (const llvm::opt::Arg *A = Args.getLastArg(OPT_out_file_EQ))
+ OutputFilename = A->getValue();
+
+ Verify = Args.hasArg(OPT_verify);
+
+ if (const llvm::opt::Arg *A = Args.getLastArg(OPT_num_threads_EQ)) {
+ StringRef S{A->getValue()};
+ if (!llvm::to_integer(S, NumThreads, 0)) {
+ llvm::errs() << ToolName << ": for the --num-threads option: '" << S
+ << "' value invalid for uint argument!\n";
+ std::exit(1);
+ }
+ }
+
+ if (const llvm::opt::Arg *A = Args.getLastArg(OPT_segment_size_EQ)) {
+ StringRef S{A->getValue()};
+ if (!llvm::to_integer(S, SegmentSize, 0)) {
+ llvm::errs() << ToolName << ": for the --segment-size option: '" << S
+ << "' value invalid for uint argument!\n";
+ std::exit(1);
+ }
+ }
+
+ Quiet = Args.hasArg(OPT_quiet);
+
+ for (const llvm::opt::Arg *A : Args.filtered(OPT_address_EQ)) {
+ StringRef S{A->getValue()};
+ if (!llvm::to_integer(S, LookupAddresses.emplace_back(), 0)) {
+ llvm::errs() << ToolName << ": for the --segment-size option: '" << S
+ << "' value invalid for uint argument!\n";
+ std::exit(1);
+ }
+ }
+
+ LookupAddressesFromStdin = Args.hasArg(OPT_addresses_from_stdin);
+}
+
/// @}
//===----------------------------------------------------------------------===//
@@ -443,7 +492,7 @@
OS << "\n";
}
-int main(int argc, char const *argv[]) {
+int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
@@ -451,21 +500,7 @@
llvm::InitializeAllTargets();
- const char *Overview =
- "A tool for dumping, searching and creating GSYM files.\n\n"
- "Specify one or more GSYM paths as arguments to dump all of the "
- "information in each GSYM file.\n"
- "Specify a single GSYM file along with one or more --lookup options to "
- "lookup addresses within that GSYM file.\n"
- "Use the --convert option to specify a file with option --out-file "
- "option to convert to GSYM format.\n";
- HideUnrelatedOptions({&GeneralOptions, &ConversionOptions, &LookupOptions});
- cl::ParseCommandLineOptions(argc, argv, Overview);
-
- if (Help) {
- PrintHelpMessage(/*Hidden =*/false, /*Categorized =*/true);
- return 0;
- }
+ parseArgs(argc, argv);
raw_ostream &OS = outs();
Index: llvm/utils/gn/secondary/llvm/tools/llvm-gsymutil/BUILD.gn
===================================================================
--- llvm/utils/gn/secondary/llvm/tools/llvm-gsymutil/BUILD.gn
+++ llvm/utils/gn/secondary/llvm/tools/llvm-gsymutil/BUILD.gn
@@ -1,8 +1,17 @@
+import("//llvm/utils/TableGen/tablegen.gni")
+
+tablegen("Opts") {
+ visibility = [ ":llvm-gsymutil" ]
+ args = [ "-gen-opt-parser-defs" ]
+}
+
executable("llvm-gsymutil") {
deps = [
+ ":Opts",
"//llvm/lib/DebugInfo/DWARF",
"//llvm/lib/DebugInfo/GSYM",
"//llvm/lib/Object",
+ "//llvm/lib/Option",
"//llvm/lib/Support",
"//llvm/lib/Target",
"//llvm/lib/Target:TargetsToBuild",
Index: utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
===================================================================
--- utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -3449,6 +3449,18 @@
],
)
+gentbl(
+ name = "GSYMUtilOptionsTableGen",
+ strip_include_prefix = "tools/llvm-gsymutil",
+ tbl_outs = [(
+ "-gen-opt-parser-defs",
+ "tools/llvm-gsymutil/Opts.inc",
+ )],
+ tblgen = ":llvm-tblgen",
+ td_file = "tools/llvm-gsymutil/Opts.td",
+ td_srcs = ["include/llvm/Option/OptParser.td"],
+)
+
cc_binary(
name = "llvm-gsymutil",
srcs = glob([
@@ -3462,8 +3474,10 @@
":DebugInfo",
":DebugInfoDWARF",
":DebugInfoGSYM",
+ ":GSYMUtilOptionsTableGen",
":MC",
":Object",
+ ":Option",
":Support",
":Target",
":TargetParser",