blob: 0c4f4fd671529383afc6236d4cb575e1f4e694ed [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_BREAKPOINT_IMPL_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_BREAKPOINT_IMPL_H_
#include <map>
#include "src/developer/debug/zxdb/client/breakpoint.h"
#include "src/developer/debug/zxdb/client/breakpoint_action.h"
#include "src/developer/debug/zxdb/client/process_observer.h"
#include "src/developer/debug/zxdb/client/system_observer.h"
#include "src/developer/debug/zxdb/client/target_observer.h"
#include "src/developer/debug/zxdb/client/thread_observer.h"
#include "src/developer/debug/zxdb/symbols/resolve_options.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace debug_ipc {
struct BreakpointStats;
}
namespace zxdb {
class BreakpointLocationImpl;
class BreakpointImpl : public Breakpoint,
public TargetObserver,
public ProcessObserver,
public ThreadObserver {
public:
// The controller can be null in which case it will perform the default behavior. The controller
// must outlive the breakpoint.
BreakpointImpl(Session* session, bool is_internal);
~BreakpointImpl() override;
// This flag doesn't control anything in the breakpoint but is stored here for the use of external
// consumers. Internal breakpoints are set by the debugger internally as part of implementing
// other features such as stepping. They should not be shown to the user.
bool is_internal() const { return is_internal_; }
// Identifies this breakpoint to the backend in IPC messages. This will not change.
uint32_t backend_id() const { return backend_id_; }
// Breakpoint implementation:
BreakpointSettings GetSettings() const override;
using Breakpoint::SetSettings; // Pull in one-arg helper.
void SetSettings(const BreakpointSettings& settings, SetCallback cb) override;
bool IsInternal() const override;
std::vector<const BreakpointLocation*> GetLocations() const override;
std::vector<BreakpointLocation*> GetLocations() override;
debug_ipc::BreakpointStats GetStats() override;
// Called whenever new stats are available from the debug agent.
void UpdateStats(const debug_ipc::BreakpointStats& stats);
// Called when the backend reports that the breakpoint has been automatically
// removed.
void BackendBreakpointRemoved();
private:
friend BreakpointLocationImpl;
struct ProcessRecord;
// TargetObserver.
void WillDestroyTarget(Target* target) override;
// ProcessObserver.
void DidCreateProcess(Process* process, bool autoattached, uint64_t timestamp) override;
void WillDestroyProcess(Process* process, ProcessObserver::DestroyReason reason, int exit_code,
uint64_t timestamp) override;
void DidLoadModuleSymbols(Process* process, LoadedModuleSymbols* module) override;
void WillUnloadModuleSymbols(Process* process, LoadedModuleSymbols* module) override;
// ThreadObserver.
void WillDestroyThread(Thread* thread) override;
// These functions update the debug_agent. The optional callback will be issued on confirmed
// success or failure.
void SyncBackend(SetCallback cb = SetCallback());
void SendBackendAddOrChange(SetCallback cb = SetCallback());
void SendBackendRemove(SetCallback cb = SetCallback());
void OnAddOrChangeComplete(const Err& err, debug_ipc::AddOrChangeBreakpointReply reply,
SetCallback cb);
void OnRemoveComplete(const Err& err, debug_ipc::RemoveBreakpointReply reply, SetCallback cb);
// Notification from BreakpointLocationImpl that the enabled state has changed and the breakpoint
// state needs to be synced.
void DidChangeLocation();
// Returns true if the breakpoint could possibly apply to the given process (if things like
// symbols aren't found, it still may not necessarily apply).
bool CouldApplyToProcess(Process* process) const;
// Returns true if there are any enabled breakpoint locations that the backend needs to know
// about.
bool HasEnabledLocation() const;
// Given a process which is new or might apply to us for the first time, Returns true if any
// addresses were resolved.
bool RegisterProcess(Process* process);
// Returns the options for converting this breakpoint's input location to addresses,
ResolveOptions GetResolveOptions() const;
// Returns true if all input locations for this breakpoint are addesses.
bool AllLocationsAddresses() const;
bool is_internal_;
// ID used to refer to this in the backend.
const uint32_t backend_id_;
BreakpointSettings settings_;
debug_ipc::BreakpointStats stats_;
// Indicates if the backend knows about this breakpoint.
bool backend_installed_ = false;
// Every process which this breakpoint can apply to is in this map, even if there are no addresses
// associated with it.
std::map<Process*, ProcessRecord> procs_;
fxl::WeakPtrFactory<BreakpointImpl> impl_weak_factory_;
// Set when we're a thread-scoped breakpoint and so are registered as a thread observer. There
// are potentially a lot of threads and breakpoints, and thread-scoped breakpoints are rare, so
// we don't regiter for these unless necessary.
bool registered_as_thread_observer_ = false;
FXL_DISALLOW_COPY_AND_ASSIGN(BreakpointImpl);
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_BREAKPOINT_IMPL_H_