blob: c82d1f7c7232cc6f6a9ba137fea7d96faf9aae77 [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_PHYSICAL_FRAME_THREAD_CONTROLLER_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_FINISH_PHYSICAL_FRAME_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 Frame;
class Stack;
class UntilThreadController;
// Thread controller that runs a given physical stack frame to its completion. This can finish more
// than one frame at once, and there could be a combination of physical and inline frames being
// exited from as long as the bottom one being finished is a physical frame (it uses a breakpoint
// that requires knowing the return address which does not exist for inline frames).
//
// See FinishThreadController which uses this as a sub-controller to finish any frame.
class FinishPhysicalFrameThreadController : 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 at the given index must be a physical frame.
//
// 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 in the instruction the physical frame has completed.
FinishPhysicalFrameThreadController(Stack& stack, size_t frame_to_finish,
FunctionReturnCallback cb = FunctionReturnCallback());
~FinishPhysicalFrameThreadController() 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 Physical"; }
private:
// Called when both the frame fingerprint and the thread are known. Does final initialization.
void InitWithFingerprint(FrameFingerprint fingerprint);
// 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. During initialization or when stepping out of the earliest
// stack frame, this can be null.
std::unique_ptr<UntilThreadController> until_controller_;
LazySymbol function_being_finished_;
FunctionReturnCallback function_return_callback_; // Possibly null.
fxl::WeakPtrFactory<FinishPhysicalFrameThreadController> weak_factory_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_FINISH_PHYSICAL_FRAME_THREAD_CONTROLLER_H_