blob: 96e415db32e3985fa2a447919203a8cb2fbd7a03 [file] [log] [blame]
// 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.func.name.elide_templates = true;
opts.frame.loc.func.name.bold_last = true;
opts.frame.loc.func.params = cmd.HasSwitch(kForceAllTypes)
? FormatFunctionNameOptions::kParamTypes
: 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