blob: 32424c06b6d48e8f5357f71d2e26e02e09957fd2 [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 <map>
#include "garnet/bin/zxdb/client/breakpoint.h"
#include "garnet/bin/zxdb/client/breakpoint_action.h"
#include "garnet/bin/zxdb/client/process_observer.h"
#include "garnet/bin/zxdb/client/system_observer.h"
#include "garnet/bin/zxdb/client/target_observer.h"
#include "garnet/public/lib/fxl/memory/weak_ptr.h"
namespace debug_ipc {
struct BreakpointStats;
}
namespace zxdb {
class BreakpointLocationImpl;
class BreakpointImpl : public Breakpoint,
public ProcessObserver,
public SystemObserver {
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;
void SetSettings(const BreakpointSettings& settings,
std::function<void(const Err&)> callback) override;
bool IsInternal() const override;
std::vector<BreakpointLocation*> GetLocations() 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;
// ProcessObserver.
void WillDestroyThread(Process* process, Thread* thread) override;
void DidLoadModuleSymbols(Process* process,
LoadedModuleSymbols* module) override;
void WillUnloadModuleSymbols(Process* process,
LoadedModuleSymbols* module) override;
// SystemObserver.
void WillDestroyTarget(Target* target) override;
void GlobalDidCreateProcess(Process* process) override;
void GlobalWillDestroyProcess(Process* process) override;
void SyncBackend(std::function<void(const Err&)> callback =
std::function<void(const Err&)>());
void SendBackendAddOrChange(std::function<void(const Err&)> callback);
void SendBackendRemove(std::function<void(const Err&)> callback);
// 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);
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_;
FXL_DISALLOW_COPY_AND_ASSIGN(BreakpointImpl);
};
} // namespace zxdb