| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/developer/debug/zxdb/console/commands/verb_backtrace.h" |
| |
| #include "src/developer/debug/zxdb/console/command.h" |
| #include "src/developer/debug/zxdb/console/console.h" |
| #include "src/developer/debug/zxdb/console/format_frame.h" |
| #include "src/developer/debug/zxdb/console/format_location.h" |
| #include "src/developer/debug/zxdb/console/format_node_console.h" |
| #include "src/developer/debug/zxdb/console/output_buffer.h" |
| #include "src/developer/debug/zxdb/console/verbs.h" |
| |
| namespace zxdb { |
| |
| namespace { |
| |
| constexpr int kForceAllTypes = 1; |
| constexpr int kRawOutput = 2; |
| constexpr int kVerboseBacktrace = 3; |
| |
| const char kBacktraceShortHelp[] = "backtrace / bt: Print a backtrace."; |
| const char kBacktraceHelp[] = |
| R"(backtrace / bt |
| |
| Prints a backtrace of the thread, including function parameters. |
| |
| To see just function names and line numbers, use "frame" or just "f". |
| |
| Arguments |
| |
| -r |
| --raw |
| Expands frames that were collapsed by the "pretty" stack formatter. |
| |
| -t |
| --types |
| Include all type information for function parameters. |
| |
| -v |
| --verbose |
| Include extra stack frame information: |
| • Full template lists and function parameter types. |
| • Instruction pointer. |
| • Stack pointer. |
| • Stack frame base pointer. |
| |
| Examples |
| |
| t 2 bt |
| thread 2 backtrace |
| )"; |
| |
| Err RunVerbBacktrace(ConsoleContext* context, const Command& cmd) { |
| if (Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread}); err.has_error()) |
| return err; |
| |
| if (!cmd.thread()) |
| return Err("There is no thread to have frames."); |
| |
| FormatStackOptions opts; |
| |
| if (!cmd.HasSwitch(kRawOutput)) |
| opts.pretty_stack = context->pretty_stack_manager(); |
| |
| opts.frame.loc = FormatLocationOptions(cmd.target()); |
| opts.frame.loc.show_params = cmd.HasSwitch(kForceAllTypes); |
| opts.frame.loc.func.name.elide_templates = true; |
| opts.frame.loc.func.name.bold_last = true; |
| opts.frame.loc.func.params = FormatFunctionNameOptions::kElideParams; |
| |
| opts.frame.detail = FormatFrameOptions::kParameters; |
| if (cmd.HasSwitch(kVerboseBacktrace)) { |
| opts.frame.detail = FormatFrameOptions::kVerbose; |
| opts.frame.loc.func.name.elide_templates = false; |
| opts.frame.loc.func.params = FormatFunctionNameOptions::kParamTypes; |
| } |
| |
| // These are minimal since there is often a lot of data. |
| opts.frame.variable.verbosity = ConsoleFormatOptions::Verbosity::kMinimal; |
| opts.frame.variable.verbosity = cmd.HasSwitch(kForceAllTypes) |
| ? ConsoleFormatOptions::Verbosity::kAllTypes |
| : ConsoleFormatOptions::Verbosity::kMinimal; |
| opts.frame.variable.pointer_expand_depth = 1; |
| opts.frame.variable.max_depth = 3; |
| |
| // Always force update the stack. Various things can have changed and when the user requests |
| // a stack we want to be sure things are correct. |
| Console::get()->Output(FormatStack(cmd.thread(), true, opts)); |
| return Err(); |
| } |
| |
| } // namespace |
| |
| VerbRecord GetBacktraceVerbRecord() { |
| VerbRecord backtrace(&RunVerbBacktrace, {"backtrace", "bt"}, kBacktraceShortHelp, kBacktraceHelp, |
| CommandGroup::kQuery); |
| SwitchRecord force_types(kForceAllTypes, false, "types", 't'); |
| SwitchRecord raw(kRawOutput, false, "raw", 'r'); |
| SwitchRecord verbose(kVerboseBacktrace, false, "verbose", 'v'); |
| backtrace.switches = {force_types, raw, verbose}; |
| |
| return backtrace; |
| } |
| |
| } // namespace zxdb |