blob: 74eb475292d8114014d00869e1e9daeb86b3ecec [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_finish.h"
#include "src/developer/debug/zxdb/client/finish_thread_controller.h"
#include "src/developer/debug/zxdb/client/stack.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/output_buffer.h"
#include "src/developer/debug/zxdb/console/verbs.h"
namespace zxdb {
namespace {
const char kFinishShortHelp[] = "finish / fi: Finish execution of a stack frame.";
const char kFinishHelp[] =
R"(finish / fi
Alias: "fi"
Resume thread execution until the selected stack frame returns. This means
that the current function call will execute normally until it finished.
See also "until".
Examples
fi
finish
Exit the currently selected stack frame (see "frame").
pr 1 t 4 fi
process 1 thead 4 finish
Applies "finish" to process 1, thread 4.
f 2 fi
frame 2 finish
Exit frame 2, leaving program execution in what was frame 3. Try also
"frame 3 until" which will do the same thing when the function is not
recursive.
)";
Err RunVerbFinish(ConsoleContext* context, const Command& cmd) {
if (Err err = AssertStoppedThreadWithFrameCommand(context, cmd, "finish"); err.has_error())
return err;
Stack& stack = cmd.thread()->GetStack();
size_t frame_index;
if (auto found_frame_index = stack.IndexForFrame(cmd.frame()))
frame_index = *found_frame_index;
else
return Err("Internal error, frame not found in current thread.");
auto controller =
std::make_unique<FinishThreadController>(stack, frame_index, &ScheduleAsyncPrintReturnValue);
cmd.thread()->ContinueWith(std::move(controller), [](const Err& err) {
if (err.has_error())
Console::get()->Output(err);
});
return Err();
}
} // namespace
VerbRecord GetFinishVerbRecord() {
return VerbRecord(&RunVerbFinish, {"finish", "fi"}, kFinishShortHelp, kFinishHelp,
CommandGroup::kStep);
}
} // namespace zxdb