blob: 8aaf9a3ff7b1416e09a2d0ebb2905965adfa682a [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_SYSTEM_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_SYSTEM_H_
#include <memory>
#include <vector>
#include "lib/fit/function.h"
#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/zxdb/client/client_object.h"
#include "src/developer/debug/zxdb/client/filter_observer.h"
#include "src/developer/debug/zxdb/client/map_setting_store.h"
#include "src/developer/debug/zxdb/client/setting_store_observer.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/symbols/system_symbols.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/lib/fxl/observer_list.h"
namespace zxdb {
class Breakpoint;
class BreakpointImpl;
class Download;
class Err;
class Filter;
class Job;
class ProcessImpl;
class SymbolServer;
class SystemObserver;
class TargetImpl;
// Represents the client's view of the system-wide state on the debugged
// computer.
class System : public ClientObject,
public FilterObserver,
public SettingStoreObserver,
public SystemSymbols::DownloadHandler {
public:
// Callback for requesting the process tree.
using ProcessTreeCallback = fit::callback<void(const Err&, debug_ipc::ProcessTreeReply)>;
explicit System(Session* session);
~System() override;
fxl::WeakPtr<System> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
void AddObserver(SystemObserver* observer) { observers_.AddObserver(observer); }
void RemoveObserver(SystemObserver* observer) { observers_.RemoveObserver(observer); }
MapSettingStore& settings() { return settings_; }
// Provides the setting schema for this object.
static fxl::RefPtr<SettingSchema> GetSchema();
ProcessImpl* ProcessImplFromKoid(uint64_t koid) const;
std::vector<TargetImpl*> GetTargetImpls() const;
// Like CreateNewTarget but returns the implementation.
TargetImpl* CreateNewTargetImpl(TargetImpl* clone);
SystemSymbols* GetSymbols();
// Returns all targets currently in this System instance. The returned pointers are managed by the
// System object and should not be cached once you return to the message loop. There is a single
// default Target, which is not initially attached to anything.
std::vector<Target*> GetTargets() const;
// Returns all jobs currently in this System instance. The returned pointers are managed
// by the System object and should not be cached once you return to the message loop.
std::vector<Job*> GetJobs() const;
// Returns all non-internal breakpoints currently in this System instance. The returned pointers
// are managed by the System object and should not be cached once you return to the message loop.
std::vector<Breakpoint*> GetBreakpoints() const;
// Returns all filters currently in this System instance. The returned pointers are managed by the
// System object and should not be cached once you return to the message loop.
std::vector<Filter*> GetFilters() const;
// Returns all symbol servers registered with this symbol instance. The returned pointers are
// managed by the System object and should not be cached once you return to the message loop.
std::vector<SymbolServer*> GetSymbolServers() const;
// Returns the process (and hence Target) associated with the given live koid. Returns 0 if not
// found.
Process* ProcessFromKoid(uint64_t koid) const;
// Schedules a request for the system process tree.
void GetProcessTree(ProcessTreeCallback callback);
// Creates/Deletes a target in this System instance. If "clone" is given, the settings from that
// target will be cloned into the new one. If clone is null, an empty Target will be allocated.
//
// Targets can't be deleted if they're running, and there must always be at least one target
// in the system. Delete will fail otherwise.
Target* CreateNewTarget(Target* clone);
Err DeleteTarget(Target* t);
// New jobs will have no attached job.
Job* CreateNewJob();
void DeleteJob(Job* job);
// Creates a new breakpoint. It will have no associated process or location and will be disabled.
Breakpoint* CreateNewBreakpoint();
// Creates an internal breakpoint. Internal breakpoints are not reported by GetBreakpoints() and
// are used to implement internal stepping functions.
Breakpoint* CreateNewInternalBreakpoint();
// Deletes the given breakpoint. The passed-in pointer will be invalid after this call. Used for
// both internal and external breakpoints.
void DeleteBreakpoint(Breakpoint* breakpoint);
// Creates a new filter. It will have no associated pattern.
Filter* CreateNewFilter();
// Delete a filter. The passed-in pointer will be invalid after this call.
void DeleteFilter(Filter* filter);
// Pauses (suspends in Zircon terms) all threads of all attached processes.
//
// The backend will try to ensure the threads are actually paused before issuing the on_paused
// callback. But this is best effort and not guaranteed: both because there's a timeout for the
// synchronous suspending and because a different continue message could race with the reply.
void Pause(fit::callback<void()> on_paused);
// Applies to all threads of all debugged processes.
void Continue(bool forward);
// Stops all thread controllers which may be doing automatic stepping for all threads in all
// processes. See Thread::CancelAllThreadControllers() for more.
void CancelAllThreadControllers();
// Whether there's a download pending for the given build ID.
bool HasDownload(const std::string& build_id);
// Get a test download object.
std::shared_ptr<Download> InjectDownloadForTesting(const std::string& build_id);
// DownloadHandler implementation:
void RequestDownload(const std::string& build_id, DebugSymbolFileType file_type,
bool quiet) override;
// Notification that a connection has been made/terminated to a target system.
//
// The is_local flag will be set when the connection is just a loopback to the local computer.
void DidConnect(bool is_local);
void DidDisconnect();
// Returns the breakpoint implementation for the given ID, or null if the ID was not found in the
// map. This will include both internal and regular breakpoints (it is used for notification
// dispatch).
BreakpointImpl* BreakpointImplForId(uint32_t id);
// SettingStoreObserver implementation.
void OnSettingChanged(const SettingStore&, const std::string& setting_name) override;
// Add a symbol server for testing purposes.
void InjectSymbolServerForTesting(std::unique_ptr<SymbolServer> server);
// Will attach to any process we are not already attached to.
void OnFilterMatches(Job* job, const std::vector<uint64_t>& matched_pids) override;
// Searches through for an open slot (Target without an attached process) or creates another one
// if none is found. Calls attach on that target, passing |callback| into it.
void AttachToProcess(uint64_t pid, Target::CallbackWithTimestamp callback);
private:
void AddNewTarget(std::unique_ptr<TargetImpl> target);
void AddNewJob(std::unique_ptr<Job> job);
void AddSymbolServer(std::unique_ptr<SymbolServer> server);
// Called when we have attempted to download debug symbols and failed. If err is set then
// something went wrong during the attempt, otherwise the symbols simply weren't available from
// any of the servers.
void NotifyFailedToFindDebugSymbols(const Err& err, const std::string& build_id,
DebugSymbolFileType file_type);
// Called when a symbol server under our control enters the Ready state.
void OnSymbolServerBecomesReady(SymbolServer* server);
// Called every time a new download starts.
void DownloadStarted();
// Called every time a download ends.
void DownloadFinished();
// Create a new download obect for downloading a given build ID. If quiet is set, don't report the
// status of this download.
//
// If multiple callers request a download of the same build ID, this will return the same object
// to each. The first caller's preference is taken for the quiet parameter.
std::shared_ptr<Download> GetDownload(std::string build_id, DebugSymbolFileType file_type,
bool quiet);
// Number of symbol servers currently initializing.
size_t servers_initializing_ = 0;
// The number of downloads currently active.
size_t download_count_ = 0;
// The number of downloads that have succeeded. Every time download_count_ reaches 0, this number
// is reported via an event, and then cleared to zero.
size_t download_success_count_ = 0;
// The number of downloads that have failed. Semantics are the same as download_success_count_
size_t download_fail_count_ = 0;
// We hold pointers to downloads while we have servers initializing so that those servers have
// time to join the download.
std::vector<std::shared_ptr<Download>> suspended_downloads_;
std::vector<std::unique_ptr<SymbolServer>> symbol_servers_;
std::vector<std::unique_ptr<TargetImpl>> targets_;
std::vector<std::unique_ptr<Job>> jobs_;
// Downloads currently in progress.
std::map<std::pair<std::string, DebugSymbolFileType>, std::weak_ptr<Download>> downloads_;
// The breakpoints are indexed by their unique backend ID. This is separate from the index
// generated by the console frontend to describe the breakpoint noun.
std::map<uint32_t, std::unique_ptr<BreakpointImpl>> breakpoints_;
std::vector<std::unique_ptr<Filter>> filters_;
SystemSymbols symbols_;
MapSettingStore settings_;
fxl::ObserverList<SystemObserver> observers_;
fxl::WeakPtrFactory<System> weak_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(System);
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_SYSTEM_H_