blob: 5ae353d3cd2def737f16fa7a3d6279e6312d7f68 [file]
// 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_handle.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/target.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_handle.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/verbs.h"
namespace zxdb {
namespace {
constexpr int kHexSwitch = 1;
const char kHandleShortHelp[] = "handle[s]: Print handle list or details.";
const char kHandleHelp[] =
R"(handle[s] [ <handle-expression> ]
With no arguments, prints all handles for the process.
If an expression is given, the information corresponding to the resulting
handle value will be printed.
👉 See "help expressions" for how to write expressions.
Options
-x
Print numbers as hexadecimal. Defaults to decimal.
Examples
handle
process 1 handles
Print all handles for the current/given process.
handle -x h
handle -x some_object->handle
Prints the information for the given handle.
)";
void OnEvalComplete(fxl::RefPtr<EvalContext> eval_context, fxl::WeakPtr<Process> weak_process,
ErrOrValue value, bool hex) {
Console* console = Console::get();
if (!weak_process)
return console->Output(Err("Process exited while requesting handles."));
if (value.has_error())
return console->Output(value.err());
uint64_t handle_value = 0;
if (Err err = value.value().PromoteTo64(&handle_value); err.has_error())
return console->Output(err);
weak_process->LoadInfoHandleTable([handle_value, hex](
ErrOr<std::vector<debug_ipc::InfoHandleExtended>> handles) {
Console* console = Console::get();
if (handles.has_error())
return console->Output(handles.err());
// Find the handle in the table.
for (const auto& handle : handles.value()) {
if (handle.handle_value == handle_value)
return console->Output(FormatHandle(handle, hex));
}
console->Output("No handle with value " + std::to_string(handle_value) + " in the process.");
});
}
Err RunVerbHandle(ConsoleContext* context, const Command& cmd) {
if (Err err = AssertRunningTarget(context, "handle", cmd.target()); err.has_error())
return err;
bool hex = cmd.HasSwitch(kHexSwitch);
if (cmd.args().empty()) {
cmd.target()->GetProcess()->LoadInfoHandleTable(
[hex](ErrOr<std::vector<debug_ipc::InfoHandleExtended>> handles) {
Console* console = Console::get();
if (handles.has_error())
return console->Output(handles.err());
auto handles_sorted = handles.take_value();
std::sort(
handles_sorted.begin(), handles_sorted.end(),
[](const debug_ipc::InfoHandleExtended& a, const debug_ipc::InfoHandleExtended& b) {
return a.handle_value < b.handle_value;
});
console->Output(FormatHandles(handles_sorted, hex));
});
} else {
// Evaluate the expression, then print just that handle.
fxl::RefPtr<EvalContext> eval_context = GetEvalContextForCommand(cmd);
return EvalCommandExpression(
cmd, "handle", eval_context, false, false,
[eval_context, weak_process = cmd.target()->GetProcess()->GetWeakPtr(),
hex](ErrOrValue value) {
OnEvalComplete(eval_context, weak_process, std::move(value), hex);
});
}
return Err();
}
} // namespace
VerbRecord GetHandleVerbRecord() {
VerbRecord handle(&RunVerbHandle, {"handle", "handles"}, kHandleShortHelp, kHandleHelp,
CommandGroup::kQuery);
handle.param_type = VerbRecord::kOneParam;
handle.switches.emplace_back(kHexSwitch, false, "", 'x');
return handle;
}
} // namespace zxdb