Skip to content

Commit

Permalink
[llvm-gsymutil] Switch to OptTable
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D148775
  • Loading branch information
abrachet committed Apr 26, 2023
1 parent 2384e84 commit a44fffb
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 107 deletions.
20 changes: 8 additions & 12 deletions llvm/test/tools/llvm-gsymutil/cmdline.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@ RUN: llvm-gsymutil --help 2>&1 | FileCheck --check-prefix=HELP %s
HELP: OVERVIEW: A tool for dumping, searching and creating GSYM files.
HELP: USAGE: llvm-gsymutil{{[^ ]*}} [options] <input GSYM files>
HELP: OPTIONS:
HELP: Conversion Options:
HELP: --arch=<arch>
HELP: --convert=<path>
HELP: --num-threads=<n>
HELP: --out-file=<path>
HELP: --address=<value>
HELP: --addresses-from-stdin
HELP: --arch=<value>
HELP: --convert=<value>
HELP: --help
HELP: --num-threads=<value>
HELP: --out-file=<value>
HELP: --quiet
HELP: --verbose
HELP: --verify
HELP: Generic Options:
HELP: --help
HELP: --version
HELP: Lookup Options:
HELP: --address=<addr>
HELP: --addresses-from-stdin
HELP: Options:
HELP: --verbose

RUN: llvm-gsymutil --version 2>&1 | FileCheck --check-prefix=VERSION %s
VERSION: {{ version }}
Expand Down
8 changes: 8 additions & 0 deletions llvm/tools/llvm-gsymutil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,18 @@ set(LLVM_LINK_COMPONENTS
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
)
37 changes: 37 additions & 0 deletions llvm/tools/llvm-gsymutil/Opts.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
include "llvm/Option/OptParser.td"

class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;

multiclass Eq<string name, string help> {
def NAME #_EQ : Joined<["--"], name #"=">, HelpText<help>;
def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
}

def help : FF<"help", "Display this help">;
def : F<"h", "Alias for --help">, Alias<help>;
def version : FF<"version", "Display the version">;
def : F<"v", "Alias for --version">, Alias<version>;
def verbose : FF<"verbose", "Enable verbose logging and encoding details">;
defm convert :
Eq<"convert",
"Convert the specified file to the GSYM format.\nSupported files include ELF and mach-o files that will have their debug info (DWARF) and symbol table converted">;
defm arch :
Eq<"arch",
"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">;
defm out_file :
Eq<"out-file",
"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">;
def : Separate<["-"], "o">, HelpText<"Alias for --out-file">, Alias<out_file_EQ>;
def verify : FF<"verify", "Verify the generated GSYM file against the information in the file that was converted">;
defm num_threads :
Eq<"num-threads",
"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">;
defm segment_size :
Eq<"segment-size",
"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">;
def quiet : FF<"quiet", "Do not output warnings about the debug information">;
defm address : Eq<"address", "Lookup an address in a GSYM file">;
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">;
225 changes: 130 additions & 95 deletions llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -52,85 +54,132 @@ using namespace object;
/// Command line options.
/// @{

namespace {
using namespace cl;

OptionCategory GeneralOptions("Options");
OptionCategory ConversionOptions("Conversion Options");
OptionCategory LookupOptions("Lookup Options");

static opt<bool> Help("h", desc("Alias for -help"), Hidden,
cat(GeneralOptions));

static opt<bool> Verbose("verbose",
desc("Enable verbose logging and encoding details."),
cat(GeneralOptions));

static list<std::string> InputFilenames(Positional, desc("<input GSYM files>"),
cat(GeneralOptions));

static opt<std::string>
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<std::string>
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<std::string>
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<bool> Verify("verify",
desc("Verify the generated GSYM file against the "
"information in the file that was converted."),
cat(ConversionOptions));

static opt<unsigned>
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<uint64_t>
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<bool>
Quiet("quiet", desc("Do not output warnings about the debug information"),
cat(ConversionOptions));

static list<uint64_t> LookupAddresses("address",
desc("Lookup an address in a GSYM file"),
cl::value_desc("addr"),
cat(LookupOptions));

static opt<bool> 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: <addr> <gsym-path>"),
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<llvm::StringLiteral> 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;
static std::vector<std::string> InputFilenames;
static std::string ConvertFilename;
static std::vector<std::string> ArchFilters;
static std::string OutputFilename;
static bool Verify;
static unsigned NumThreads;
static uint64_t SegmentSize;
static bool Quiet;
static std::vector<uint64_t> LookupAddresses;
static bool LookupAddressesFromStdin;

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] <input GSYM files>",
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);
}

/// @}
//===----------------------------------------------------------------------===//

Expand Down Expand Up @@ -443,29 +492,15 @@ static void doLookup(GsymReader &Gsym, uint64_t Addr, raw_ostream &OS) {
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);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.

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();

Expand Down
9 changes: 9 additions & 0 deletions llvm/utils/gn/secondary/llvm/tools/llvm-gsymutil/BUILD.gn
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
14 changes: 14 additions & 0 deletions utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3449,6 +3449,18 @@ cc_binary(
],
)

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([
Expand All @@ -3462,8 +3474,10 @@ cc_binary(
":DebugInfo",
":DebugInfoDWARF",
":DebugInfoGSYM",
":GSYMUtilOptionsTableGen",
":MC",
":Object",
":Option",
":Support",
":Target",
":TargetParser",
Expand Down

0 comments on commit a44fffb

Please sign in to comment.