blob: f7bc402807d7d2f4713d87c72f6a6777e79b5153 [file] [log] [blame]
// Copyright 2025 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_exception_info.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/command_utils.h"
#include "src/developer/debug/zxdb/console/console.h"
#include "src/developer/debug/zxdb/console/format_exception.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/verbs.h"
namespace zxdb {
namespace {
const char kExceptionInfoShortHelp[] =
"exception-info/ excp: Display info about the current exception if any.";
const char kExceptionInfoUsage[] = "exception-info / excp";
const char kExceptionInfoHelp[] = R"(
Prints information about exceptions. Exceptions are only available when the
given thread is stopped in the "Exception" state. Threads that are not
currently in this state will report "No exception".
With no additional context, this command will attempt to print information
about an exception on the currently selected thread of the active process (see
`process` and `thread`).
Supply additional context to select different processes and/or threads.
Examples
excp
exception-info
Print exception information for the currently selected thread.
t 2 excp
thread 2 exception-info
Print exception information for thread 2 in the active process.
pr 3 t 5 exception-info
process 3 thread 5 exception-info
Print exception information for thread 5 in process 3.
t * excp
thread * exception-info
Print exception information for all threads in the active process.
pr 2 t * excp
process 2 thread * exception-info
Print exception information for all threads in process 2.
)";
void RunVerbExceptionInfo(const Command& cmd, fxl::RefPtr<CommandContext> cmd_context) {
if (Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread}, true); err.has_error())
return cmd_context->ReportError(err);
// Should always be present because we were called synchronously.
ConsoleContext* console_context = cmd_context->GetConsoleContext();
std::vector<Thread*> threads;
if (cmd.HasNoun(Noun::kThread)) {
if (cmd.GetNounIndex(Noun::kThread) == Command::kWildcard) {
auto active_process = console_context->GetActiveTarget()->GetProcess();
threads = active_process->GetThreads();
} else {
threads.push_back(cmd.thread());
}
} else if (cmd.HasNoun(Noun::kProcess) &&
cmd.GetNounIndex(Noun::kProcess) == Command::kWildcard) {
// All threads for process.
return cmd_context->ReportError(Err("process * exception-info is not supported."));
} else if (auto active_thread = console_context->GetActiveThreadForTarget(cmd.target())) {
threads.push_back(active_thread);
} else {
return cmd_context->ReportError(Err("What thread?"));
}
for (const auto& thread : threads) {
if (auto stop_info = thread->CurrentStopInfo()) {
auto buf = FormatException(console_context, thread, stop_info->exception_record);
buf.Append("\n");
cmd_context->Output(buf);
} else {
OutputBuffer buf;
buf.Append("Thread ");
buf.Append(std::to_string(thread->GetKoid()));
buf.Append(" has no exception.");
cmd_context->Output(buf);
}
}
}
} // namespace
VerbRecord GetExceptionInfoVerbRecord() {
VerbRecord record{&RunVerbExceptionInfo, {"exception-info", "excp"}, kExceptionInfoShortHelp,
kExceptionInfoUsage, kExceptionInfoHelp, CommandGroup::kQuery,
SourceAffinity::kSource};
return record;
}
} // namespace zxdb