diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/tools/llvm-symbolizer | |
parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
download | src-344a3780b2e33f6ca763666c380202b18aab72a3.tar.gz src-344a3780b2e33f6ca763666c380202b18aab72a3.zip |
Vendor import of llvm-project main 88e66fa60ae5, the last commit beforevendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
the upstream release/13.x branch was created.
Diffstat (limited to 'llvm/tools/llvm-symbolizer')
-rw-r--r-- | llvm/tools/llvm-symbolizer/Opts.td | 27 | ||||
-rw-r--r-- | llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp | 134 |
2 files changed, 93 insertions, 68 deletions
diff --git a/llvm/tools/llvm-symbolizer/Opts.td b/llvm/tools/llvm-symbolizer/Opts.td index ac23639f130e..6026e24d6ffa 100644 --- a/llvm/tools/llvm-symbolizer/Opts.td +++ b/llvm/tools/llvm-symbolizer/Opts.td @@ -1,17 +1,20 @@ include "llvm/Option/OptParser.td" multiclass B<string name, string help1, string help2> { - def NAME: Flag<["--", "-"], name>, HelpText<help1>; - def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText<help2>; + def NAME: Flag<["--"], name>, HelpText<help1>; + def no_ # NAME: Flag<["--"], "no-" # name>, HelpText<help2>; } multiclass Eq<string name, string help> { - def NAME #_EQ : Joined<["--", "-"], name #"=">, + def NAME #_EQ : Joined<["--"], name #"=">, HelpText<help>; - def : Separate<["--", "-"], name>, Alias<!cast<Joined>(NAME #_EQ)>; + def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>; } -class F<string name, string help>: Flag<["--", "-"], name>, HelpText<help>; +class F<string name, string help>: Flag<["--"], name>, HelpText<help>; + +def grp_mach_o : OptionGroup<"kind">, + HelpText<"llvm-symbolizer Mach-O Specific Options">; def addresses : F<"addresses", "Show address before line information">; defm adjust_vma @@ -19,13 +22,19 @@ defm adjust_vma MetaVarName<"<offset>">; def basenames : Flag<["--"], "basenames">, HelpText<"Strip directory names from paths">; defm debug_file_directory : Eq<"debug-file-directory", "Path to directory where to look for debug files">, MetaVarName<"<dir>">; -defm default_arch : Eq<"default-arch", "Default architecture (for multi-arch objects)">; +defm default_arch + : Eq<"default-arch", "Default architecture (for multi-arch objects)">, + Group<grp_mach_o>; defm demangle : B<"demangle", "Demangle function names", "Don't demangle function names">; def functions : F<"functions", "Print function name for a given address">; def functions_EQ : Joined<["--"], "functions=">, HelpText<"Print function name for a given address">, Values<"none,short,linkage">; def help : F<"help", "Display this help">; defm dwp : Eq<"dwp", "Path to DWP file to be use for any split CUs">, MetaVarName<"<file>">; -defm dsym_hint : Eq<"dsym-hint", "Path to .dSYM bundles to search for debug info for the object files">, MetaVarName<"<dir>">; +defm dsym_hint + : Eq<"dsym-hint", + "Path to .dSYM bundles to search for debug info for the object files">, + MetaVarName<"<dir>">, + Group<grp_mach_o>; defm fallback_debug_path : Eq<"fallback-debug-path", "Fallback path for debug binaries">, MetaVarName<"<dir>">; defm inlines : B<"inlines", "Print all inlined frames for a given address", "Do not print inlined frames">; @@ -33,9 +42,9 @@ defm obj : Eq<"obj", "Path to object file to be symbolized (if not provided, " "object file should be specified for each input line)">, MetaVarName<"<file>">; defm output_style - : Eq<"output-style", "Specify print style. Supported styles: LLVM, GNU">, + : Eq<"output-style", "Specify print style. Supported styles: LLVM, GNU, JSON">, MetaVarName<"style">, - Values<"LLVM,GNU">; + Values<"LLVM,GNU,JSON">; def pretty_print : F<"pretty-print", "Make the output more human friendly">; defm print_source_context_lines : Eq<"print-source-context-lines", "Print N lines of source file context">; def relative_address : F<"relative-address", "Interpret addresses as addresses relative to the image base">; diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp index 9c68acee0ae2..227ce12a6d9a 100644 --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -66,23 +66,35 @@ static const opt::OptTable::Info InfoTable[] = { class SymbolizerOptTable : public opt::OptTable { public: - SymbolizerOptTable() : OptTable(InfoTable, true) {} + SymbolizerOptTable() : OptTable(InfoTable) { + setGroupedShortOptions(true); + } }; } // namespace -static cl::list<std::string> ClInputAddresses(cl::Positional, - cl::desc("<input addresses>..."), - cl::ZeroOrMore); +template <typename T> +static void print(const Request &Request, Expected<T> &ResOrErr, + DIPrinter &Printer) { + if (ResOrErr) { + // No error, print the result. + Printer.print(Request, *ResOrErr); + return; + } + + // Handle the error. + bool PrintEmpty = true; + handleAllErrors(std::move(ResOrErr.takeError()), + [&](const ErrorInfoBase &EI) { + PrintEmpty = Printer.printError( + Request, EI, "LLVMSymbolizer: error reading file: "); + }); -template<typename T> -static bool error(Expected<T> &ResOrErr) { - if (ResOrErr) - return false; - logAllUnhandledErrors(ResOrErr.takeError(), errs(), - "LLVMSymbolizer: error reading file: "); - return true; + if (PrintEmpty) + Printer.print(Request, T()); } +enum class OutputStyle { LLVM, GNU, JSON }; + enum class Command { Code, Data, @@ -136,7 +148,7 @@ static bool parseCommand(StringRef BinaryName, bool IsAddr2Line, } static void symbolizeInput(const opt::InputArgList &Args, uint64_t AdjustVMA, - bool IsAddr2Line, DIPrinter::OutputStyle OutputStyle, + bool IsAddr2Line, OutputStyle Style, StringRef InputString, LLVMSymbolizer &Symbolizer, DIPrinter &Printer) { Command Cmd; @@ -144,57 +156,49 @@ static void symbolizeInput(const opt::InputArgList &Args, uint64_t AdjustVMA, uint64_t Offset = 0; if (!parseCommand(Args.getLastArgValue(OPT_obj_EQ), IsAddr2Line, StringRef(InputString), Cmd, ModuleName, Offset)) { - outs() << InputString << "\n"; + Printer.printInvalidCommand({ModuleName, None}, InputString); return; } - if (Args.hasArg(OPT_addresses)) { - outs() << "0x"; - outs().write_hex(Offset); - StringRef Delimiter = Args.hasArg(OPT_pretty_print) ? ": " : "\n"; - outs() << Delimiter; - } - Offset -= AdjustVMA; + uint64_t AdjustedOffset = Offset - AdjustVMA; if (Cmd == Command::Data) { - auto ResOrErr = Symbolizer.symbolizeData( - ModuleName, {Offset, object::SectionedAddress::UndefSection}); - Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get()); + Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData( + ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection}); + print({ModuleName, Offset}, ResOrErr, Printer); } else if (Cmd == Command::Frame) { - auto ResOrErr = Symbolizer.symbolizeFrame( - ModuleName, {Offset, object::SectionedAddress::UndefSection}); - if (!error(ResOrErr)) { - for (DILocal Local : *ResOrErr) - Printer << Local; - if (ResOrErr->empty()) - outs() << "??\n"; - } + Expected<std::vector<DILocal>> ResOrErr = Symbolizer.symbolizeFrame( + ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection}); + print({ModuleName, Offset}, ResOrErr, Printer); } else if (Args.hasFlag(OPT_inlines, OPT_no_inlines, !IsAddr2Line)) { - auto ResOrErr = Symbolizer.symbolizeInlinedCode( - ModuleName, {Offset, object::SectionedAddress::UndefSection}); - Printer << (error(ResOrErr) ? DIInliningInfo() : ResOrErr.get()); - } else if (OutputStyle == DIPrinter::OutputStyle::GNU) { + Expected<DIInliningInfo> ResOrErr = Symbolizer.symbolizeInlinedCode( + ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection}); + print({ModuleName, Offset}, ResOrErr, Printer); + } else if (Style == OutputStyle::GNU) { // With PrintFunctions == FunctionNameKind::LinkageName (default) // and UseSymbolTable == true (also default), Symbolizer.symbolizeCode() // may override the name of an inlined function with the name of the topmost // caller function in the inlining chain. This contradicts the existing // behavior of addr2line. Symbolizer.symbolizeInlinedCode() overrides only // the topmost function, which suits our needs better. - auto ResOrErr = Symbolizer.symbolizeInlinedCode( - ModuleName, {Offset, object::SectionedAddress::UndefSection}); - Printer << (error(ResOrErr) ? DILineInfo() : ResOrErr.get().getFrame(0)); + Expected<DIInliningInfo> ResOrErr = Symbolizer.symbolizeInlinedCode( + ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection}); + Expected<DILineInfo> Res0OrErr = + !ResOrErr + ? Expected<DILineInfo>(ResOrErr.takeError()) + : ((ResOrErr->getNumberOfFrames() == 0) ? DILineInfo() + : ResOrErr->getFrame(0)); + print({ModuleName, Offset}, Res0OrErr, Printer); } else { - auto ResOrErr = Symbolizer.symbolizeCode( - ModuleName, {Offset, object::SectionedAddress::UndefSection}); - Printer << (error(ResOrErr) ? DILineInfo() : ResOrErr.get()); + Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode( + ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection}); + print({ModuleName, Offset}, ResOrErr, Printer); } - if (OutputStyle == DIPrinter::OutputStyle::LLVM) - outs() << "\n"; } static void printHelp(StringRef ToolName, const SymbolizerOptTable &Tbl, raw_ostream &OS) { const char HelpText[] = " [options] addresses..."; - Tbl.PrintHelp(OS, (ToolName + HelpText).str().c_str(), + Tbl.printHelp(OS, (ToolName + HelpText).str().c_str(), ToolName.str().c_str()); // TODO Replace this with OptTable API once it adds extrahelp support. OS << "\nPass @FILE as argument to read options from FILE.\n"; @@ -204,7 +208,6 @@ static opt::InputArgList parseOptions(int Argc, char *Argv[], bool IsAddr2Line, StringSaver &Saver, SymbolizerOptTable &Tbl) { StringRef ToolName = IsAddr2Line ? "llvm-addr2line" : "llvm-symbolizer"; - Tbl.setGroupedShortOptions(true); // The environment variable specifies initial options which can be overridden // by commnad line options. Tbl.setInitialOptionsFromEnvironment(IsAddr2Line ? "LLVM_ADDR2LINE_OPTS" @@ -268,7 +271,7 @@ int main(int argc, char **argv) { LLVMSymbolizer::Options Opts; uint64_t AdjustVMA; - unsigned SourceContextLines; + PrinterConfig Config; parseIntArg(Args, OPT_adjust_vma_EQ, AdjustVMA); if (const opt::Arg *A = Args.getLastArg(OPT_basenames, OPT_relativenames)) { Opts.PathStyle = @@ -285,7 +288,8 @@ int main(int argc, char **argv) { Opts.FallbackDebugPath = Args.getLastArgValue(OPT_fallback_debug_path_EQ).str(); Opts.PrintFunctions = decideHowToPrintFunctions(Args, IsAddr2Line); - parseIntArg(Args, OPT_print_source_context_lines_EQ, SourceContextLines); + parseIntArg(Args, OPT_print_source_context_lines_EQ, + Config.SourceContextLines); Opts.RelativeAddresses = Args.hasArg(OPT_relative_address); Opts.UntagAddresses = Args.hasFlag(OPT_untag_addresses, OPT_no_untag_addresses, !IsAddr2Line); @@ -297,6 +301,10 @@ int main(int argc, char **argv) { } #endif Opts.UseSymbolTable = true; + Config.PrintAddress = Args.hasArg(OPT_addresses); + Config.PrintFunctions = Opts.PrintFunctions != FunctionNameKind::None; + Config.Pretty = Args.hasArg(OPT_pretty_print); + Config.Verbose = Args.hasArg(OPT_verbose); for (const opt::Arg *A : Args.filtered(OPT_dsym_hint_EQ)) { StringRef Hint(A->getValue()); @@ -308,18 +316,24 @@ int main(int argc, char **argv) { } } - auto OutputStyle = - IsAddr2Line ? DIPrinter::OutputStyle::GNU : DIPrinter::OutputStyle::LLVM; + auto Style = IsAddr2Line ? OutputStyle::GNU : OutputStyle::LLVM; if (const opt::Arg *A = Args.getLastArg(OPT_output_style_EQ)) { - OutputStyle = strcmp(A->getValue(), "GNU") == 0 - ? DIPrinter::OutputStyle::GNU - : DIPrinter::OutputStyle::LLVM; + if (strcmp(A->getValue(), "GNU") == 0) + Style = OutputStyle::GNU; + else if (strcmp(A->getValue(), "JSON") == 0) + Style = OutputStyle::JSON; + else + Style = OutputStyle::LLVM; } LLVMSymbolizer Symbolizer(Opts); - DIPrinter Printer(outs(), Opts.PrintFunctions != FunctionNameKind::None, - Args.hasArg(OPT_pretty_print), SourceContextLines, - Args.hasArg(OPT_verbose), OutputStyle); + std::unique_ptr<DIPrinter> Printer; + if (Style == OutputStyle::GNU) + Printer = std::make_unique<GNUPrinter>(outs(), errs(), Config); + else if (Style == OutputStyle::JSON) + Printer = std::make_unique<JSONPrinter>(outs(), Config); + else + Printer = std::make_unique<LLVMPrinter>(outs(), errs(), Config); std::vector<std::string> InputAddresses = Args.getAllArgValues(OPT_INPUT); if (InputAddresses.empty()) { @@ -331,14 +345,16 @@ int main(int argc, char **argv) { std::string StrippedInputString(InputString); llvm::erase_if(StrippedInputString, [](char c) { return c == '\r' || c == '\n'; }); - symbolizeInput(Args, AdjustVMA, IsAddr2Line, OutputStyle, - StrippedInputString, Symbolizer, Printer); + symbolizeInput(Args, AdjustVMA, IsAddr2Line, Style, StrippedInputString, + Symbolizer, *Printer); outs().flush(); } } else { + Printer->listBegin(); for (StringRef Address : InputAddresses) - symbolizeInput(Args, AdjustVMA, IsAddr2Line, OutputStyle, Address, - Symbolizer, Printer); + symbolizeInput(Args, AdjustVMA, IsAddr2Line, Style, Address, Symbolizer, + *Printer); + Printer->listEnd(); } return 0; |