blob: 4a1ebd3e76f83ef165b23391500e507c1db46556 [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_UNTIL_THREAD_CONTROLLER_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_UNTIL_THREAD_CONTROLLER_H_
#include <stdint.h>
#include <vector>
#include "lib/fit/function.h"
#include "src/developer/debug/zxdb/client/frame_fingerprint.h"
#include "src/developer/debug/zxdb/client/thread_controller.h"
#include "src/developer/debug/zxdb/symbols/input_location.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace zxdb {
class Breakpoint;
class BreakpointLocation;
class Err;
class System;
class Target;
// The "until" thread controller continues until a given instruction is reached. It sets a
// breakpoint at the desired location(s) and continues execution.
//
// Setting the breakpoint may fail in several different ways. In the simplest case the location
// to run to isn't found (symbol resolution failure). The breakpoint could also fail to be set.
// In addition to weird errors and race conditions that could cause the breakpoint set to fail, this
// can happen if the breakpoint location is in unwritable memory, like the vDSO (this can happen
// during certain stepping operations involving syscalls).
//
// These errors are indicated by the callback given to InitWithThread() which can be issued
// asynchronously. Callers should be sure to handle these errors as otherwise program execution will
// continue and the user's stepping location can be lost!
class UntilThreadController : public ThreadController {
public:
enum FrameComparison {
// The program will run until the current frame is older than the given one. In this case if the
// frame fingerprints compare equal, the program will continue to run. Anything older will stop.
kRunUntilOlderFrame,
// Stops when the current frame is the same as or older than the given one.
kRunUntilEqualOrOlderFrame
};
// Runs a thread until the given location. The location will only be matched if the stack base
// pointer position of the location is greater than end_sp this means that the stack has grown up
// to a higher frame. When end_bp is 0, every stack pointer will be larger and it will always
// trigger. Supporting the stack pointer allows this class to be used for stack-aware options (as
// a subset of "finish" for example).
explicit UntilThreadController(std::vector<InputLocation> locations);
// Runs to the given location until the current frame compares to the given frame according to the
// given comparator. This allows stepping backward in the call stack.
UntilThreadController(std::vector<InputLocation> locations, FrameFingerprint newest_frame,
FrameComparison cmp);
~UntilThreadController() 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 "Until"; }
// Returns the resolved locations where this thread controller is running to. When active, this
// will always contain at least one element (InitWithThread() will report error if there are no
// addresses resolved).
std::vector<const BreakpointLocation*> GetLocations() const;
private:
System* GetSystem();
Target* GetTarget();
void OnBreakpointSetComplete(const Err& err, fit::callback<void(const Err&)> cb);
std::vector<InputLocation> locations_;
// Indicates the frame. This frame is compared to the current one according to the comparison_
// function.
//
// When no frame checking is needed, the threshold frame will be !is_valid().
FrameFingerprint threshold_frame_;
FrameComparison comparison_ = kRunUntilOlderFrame;
fxl::WeakPtr<Breakpoint> breakpoint_;
fxl::WeakPtrFactory<UntilThreadController> weak_factory_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_UNTIL_THREAD_CONTROLLER_H_