blob: 7f1f34ae1bf213ca29003fda6b414ab2a145e7ce [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 <stdint.h>
#include <map>
#include <memory>
#include "src/developer/debug/zxdb/client/client_object.h"
#include "src/developer/debug/zxdb/client/process_observer.h"
#include "src/lib/containers/cpp/circular_deque.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/lib/fxl/observer_list.h"
namespace debug_ipc {
struct MemoryBlock;
struct Module;
struct ThreadRecord;
struct AddressRegion;
} // namespace debug_ipc
namespace zxdb {
class Err;
struct InputLocation;
class BacktraceCache;
class MemoryDump;
class ProcessSymbols;
class SymbolDataProvider;
class Target;
class Thread;
class Process : public ClientObject {
public:
// Documents how this process was started.
// This is useful for user feedback.
enum class StartType {
kAttach,
kComponent,
kLaunch,
};
const char* StartTypeToString(StartType);
Process(Session* session, StartType);
~Process() override;
void AddObserver(ProcessObserver* observer);
void RemoveObserver(ProcessObserver* observer);
fxl::WeakPtr<Process> GetWeakPtr();
// Returns the target associated with this process. Guaranteed non-null.
virtual Target* GetTarget() const = 0;
// The Process koid is guaranteed non-null.
virtual uint64_t GetKoid() const = 0;
// Returns the "name" of the process. This is the process object name which
// is normally based on the file name, but isn't the same as the file name.
virtual const std::string& GetName() const = 0;
// Returns the interface for querying symbols for this process.
virtual ProcessSymbols* GetSymbols() = 0;
// Queries the process for the currently-loaded modules (this always
// recomputes the list).
virtual void GetModules(
std::function<void(const Err&, std::vector<debug_ipc::Module>)>) = 0;
// Queries the process for its address map if |address| is zero the entire
// map is requested. If |address| is non-zero only the containing region
// if exists will be retrieved.
virtual void GetAspace(
uint64_t address,
std::function<void(const Err&, std::vector<debug_ipc::AddressRegion>)>)
const = 0;
// Returns all threads in the process. This is as of the last update from
// the system. If the program is currently running, the actual threads may be
// different since it can be asynchronously creating and destroying them.
//
// Some programs also change thread names dynamically, so the names may be
// stale. Call SyncThreads() to update the thread list with the debuggee.
//
// The pointers will only be valid until you return to the message loop.
virtual std::vector<Thread*> GetThreads() const = 0;
// Returns the thread in this process associated with the given koid.
virtual Thread* GetThreadFromKoid(uint64_t koid) = 0;
// Returns a pointer to the backtrace cache associated with this koid.
// Returns null if there is no cache present (mostly in tests).
virtual BacktraceCache* GetBacktraceCacheFromKoid(uint64_t koid);
// Asynchronously refreshes the thread list from the debugged process. This
// will ensure the thread names are up-to-date, and is also used after
// attaching when there are no thread notifications for existing threads.
//
// If the Process is destroyed before the call completes, the callback will
// not be issued. If this poses a problem in the future, we can add an
// error code to the callback, but will need to be careful to make clear the
// Process object is not valid at that point (callers may want to use it to
// format error messages).
//
// To get the computed threads, call GetThreads() once the callback runs.
virtual void SyncThreads(std::function<void()> callback) = 0;
// Pauses (suspends in Zircon terms) all threads in the process, it does not
// affect other 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.
virtual void Pause(std::function<void()> on_paused) = 0;
// Applies to all threads in the process.
virtual void Continue() = 0;
// The callback does NOT mean the step has completed, but rather the setup
// for the function was successful. Symbols and breakpoint setup can cause
// asynchronous failures.
virtual void ContinueUntil(const InputLocation& location,
std::function<void(const Err&)> cb) = 0;
// Returns the SymbolDataProvider that can be used to evaluate symbols
// in the context of this process. This will not have any frame information
// so the available operations will be limited.
//
// If the caller has a Frame, prefer Frame::GetSymbolDataProvider() which
// does have access to registers and other frame data.
virtual fxl::RefPtr<SymbolDataProvider> GetSymbolDataProvider() const = 0;
// Reads memory from the debugged process.
virtual void ReadMemory(
uint64_t address, uint32_t size,
std::function<void(const Err&, MemoryDump)> callback) = 0;
// Write memory to the debugged process.
virtual void WriteMemory(uint64_t address, std::vector<uint8_t> data,
std::function<void(const Err&)> callback) = 0;
StartType start_type() const { return start_type_; }
static constexpr size_t kMaxIOBufferSize = 1 * 1024 * 1024; // In bytes.
const containers::circular_deque<uint8_t>& get_stdout() const {
return stdout_;
}
const containers::circular_deque<uint8_t>& get_stderr() const {
return stderr_;
}
protected:
fxl::ObserverList<ProcessObserver>& observers() { return observers_; }
containers::circular_deque<uint8_t> stdout_;
containers::circular_deque<uint8_t> stderr_;
private:
StartType start_type_;
fxl::ObserverList<ProcessObserver> observers_;
fxl::WeakPtrFactory<Process> weak_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(Process);
};
} // namespace zxdb