blob: e702b12caee62397c47ccd6a4368b8bb78d8768d [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.
#pragma once
#include <optional>
#include <vector>
#include "garnet/bin/zxdb/client/frame_fingerprint.h"
#include "garnet/bin/zxdb/client/thread_controller.h"
#include "lib/fxl/memory/weak_ptr.h"
namespace zxdb {
class Frame;
class Stack;
class UntilThreadController;
// Thread controller that runs a given 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.
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.
FinishThreadController(Stack& stack, size_t frame_to_finish);
~FinishThreadController() override;
// ThreadController implementation.
void InitWithThread(Thread* thread,
std::function<void(const Err&)> cb) override;
ContinueOp GetContinueOp() override;
StopOp OnThreadStop(
debug_ipc::NotifyException::Type stop_type,
const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints) override;
const char* GetName() const override { return "Finish"; }
private:
// Called when both the frame fingerprint and the thread are known. Does
// final initialization.
void InitWithFingerprintAndThread();
// The from_frame_fingerprint_ will indicate the frame we're trying to
// finish. This being valid indicates that the stack has been fetched and
// the frame in question located (the operation may be async).
//
// This uses std::optional so the fingerprint can be tested to see if it's
// been set, even if the stack returns the null fingerprint (might happen
// for the bottom of the stack).
//
// The to_address_ will be the address we're returning to. This will be
// computed at the same time as from_frame_fingerprint_, but may be 0 if
// the user is trying to finish the oldest stack frame (there's no address
// to return to).
uint64_t to_address_ = 0;
std::optional<FrameFingerprint> from_frame_fingerprint_;
// The fingerprint can be computed asynchronously with initialization. This
// holds the InitWithThread callback for InitWithFingerprintAndThread().
std::function<void(const Err&)> init_callback_;
// 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_;
fxl::WeakPtrFactory<FinishThreadController> weak_factory_;
};
} // namespace zxdb