blob: e0256bf2e86e114a7a4a350183b35db405d32126 [file] [log] [blame]
// Copyright 2018 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.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_FINISH_THREAD_CONTROLLER_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_FINISH_THREAD_CONTROLLER_H_
#include <optional>
#include <vector>
#include "src/developer/debug/zxdb/client/frame_fingerprint.h"
#include "src/developer/debug/zxdb/client/function_return_info.h"
#include "src/developer/debug/zxdb/client/thread_controller.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace zxdb {
class FinishPhysicalFrameThreadController;
class Stack;
class StepOverThreadController;
class StepThreadController;
// Thread controller that runs a given stack frame to its completion. This can finish more than one
// frame at once, and there could be any combination of physical and inline frames being exited
// from.
//
// This works by first finishing to the nearest physical frame using the
// FinishPhysicalFrameThreadController (if there is no physical frame above the one being finished,
// this will be a no-op). Then any inline frames will be iteratively finished using the
// StepOverThreadController to step over the inline code ranges until the desired frame is reached.
class FinishThreadController : public ThreadController {
public:
// Finishes the given frame of the stack, leaving control at frame |frame_to_finish + 1] when the
// controller is complete.
//
// The frame_to_finish must have its fingerprint computable. This means that either you're
// finishing frame 0, or have synced all frames.
//
// The optional callback will be issued when a physical frame is stepped out of. It will be on
// the instruction immediately following the return. This controller might be used to step out
// of inline frames or a physical frame followed by some inline frames. This will be issued on the
// outermost physical frame, and never on any inline frames. So it might not get called at all,
// and the call might not be the outermost function call from the user's perspective.
FinishThreadController(Stack& stack, size_t frame_to_finish,
FunctionReturnCallback cb = FunctionReturnCallback());
~FinishThreadController() override;
// ThreadController implementation.
void InitWithThread(Thread* thread, fit::callback<void(const Err&)> cb) override;
ContinueOp GetContinueOp() override;
StopOp OnThreadStop(debug_ipc::ExceptionType stop_type,
const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints) override;
const char* GetName() const override { return "Finish"; }
private:
// Handles stepping out of the frames. Having this separate allows the "frame 0" handling at the
// end to be pulled out in one place.
StopOp OnThreadStopFrameStepping(debug_ipc::ExceptionType stop_type,
const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints);
// Creates the controller for stepping out of the inline function at the top of the stack. Issues
// the callback in all cases. Returns false on failure.
bool CreateInlineStepOverController(fit::callback<void(const Err&)> cb);
// Index of the frame to finish. Invalid after the thread is resumed.
size_t frame_to_finish_;
#ifndef NDEBUG
// IP of the frame to step out of. This is a sanity check to make sure the stack didn't change
// between construction and InitWithThread.
uint64_t frame_ip_;
#endif
// Will be non-null when stepping out of the nearest physical frame. When doing the subsequent
// inline step this will be null.
std::unique_ptr<FinishPhysicalFrameThreadController> finish_physical_controller_;
// The frame being stepped out of. This will be set when the frame being stepped out of is an
// inline frame. Otherwise, only the physical frame stepper is required.
FrameFingerprint from_inline_frame_fingerprint_;
// Will be non-null when stepping out of inline frames. When doing the initial step out of a
// physical frame, this will be null.
std::unique_ptr<StepOverThreadController> step_over_inline_controller_;
// This controller manages the skipping of "line 0" after the finish operations.
std::unique_ptr<StepThreadController> step_over_line_0_controller_;
FunctionReturnCallback function_return_callback_; // Possibly null.
fxl::WeakPtrFactory<FinishThreadController> weak_factory_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_FINISH_THREAD_CONTROLLER_H_