blob: e0726cbedf98f5dd64053db70e34937c7aeaeefd [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_up.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/commands/verb_down.h"
#include "src/developer/debug/zxdb/console/console.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/verbs.h"
namespace zxdb {
namespace {
const char kUpShortHelp[] = "up: Move up the stack";
const char kUpHelp[] =
R"(up
Switch the active frame to the one above (backward in time from) the current.
Examples
up
Move one frame up the stack
t 1 up
Move up the stack on thread 1
)";
Err RunVerbUp(ConsoleContext* context, const Command& cmd) {
if (Err err = AssertStoppedThreadWithFrameCommand(context, cmd, "up"); err.has_error())
return err;
// This computes the frame index from the callback in case the user does "up" faster than an
// async stack request can complete. Doing the new index computation from the callback ensures
// that all commands are executed.
auto on_has_frames = [weak_thread = cmd.thread()->GetWeakPtr()](const Err& err) {
if (!weak_thread) {
Console::get()->Output(Err("Thread destroyed."));
return;
}
const Thread* thread = weak_thread.get();
ConsoleContext* context = &Console::get()->context();
auto id = context->GetActiveFrameIdForThread(thread);
if (id < 0 || thread->GetStack().size() == 0) {
Console::get()->Output(Err("No current frame."));
return;
}
id += 1;
if (static_cast<size_t>(id) >= thread->GetStack().size()) {
Console::get()->Output(Err("At top of stack."));
return;
}
context->SetActiveFrameIdForThread(thread, id);
OutputFrameInfoForChange(thread->GetStack()[id], id);
};
if (cmd.thread()->GetStack().has_all_frames()) {
on_has_frames(Err());
} else {
cmd.thread()->GetStack().SyncFrames(std::move(on_has_frames));
}
return Err();
}
} // namespace
VerbRecord GetUpVerbRecord() {
return VerbRecord(&RunVerbUp, {"up"}, kUpShortHelp, kUpHelp, CommandGroup::kGeneral);
}
} // namespace zxdb