blob: 81842675b3525ddb70e5d06df050c8d4d6e68074 [file] [log] [blame]
// Copyright 2020 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_DEBUG_ADAPTER_CONTEXT_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_DEBUG_ADAPTER_CONTEXT_H_
#include <dap/protocol.h>
#include <dap/session.h>
#include "src/developer/debug/shared/stream_buffer.h"
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/process_observer.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/thread_observer.h"
#include "src/developer/debug/zxdb/common/err.h"
namespace zxdb {
class Session;
class DebugAdapterServer;
class DebugAdapterReader;
class DebugAdapterWriter;
// Handles processing requests from debug adapter client with help from zxdb client session and dap
// library.
// Note: All methods in this class need to be executed on main thread to avoid concurrency bugs.
class DebugAdapterContext : public ThreadObserver, ProcessObserver {
public:
explicit DebugAdapterContext(Session* session, debug_ipc::StreamBuffer* stream);
virtual ~DebugAdapterContext();
Session* session() { return session_; }
dap::Session& dap() { return *dap_; }
bool supports_run_in_terminal() { return supports_run_in_terminal_; };
// Notification about the stream.
void OnStreamReadable();
// ThreadObserver implementation:
void DidCreateThread(Thread* thread) override;
void WillDestroyThread(Thread* thread) override;
void OnThreadStopped(Thread* thread, const StopInfo& info) override;
void OnThreadFramesInvalidated(Thread* thread) override;
// ProcessObserver implementation:
void DidCreateProcess(Process* process, bool autoattached_to_new_process,
uint64_t timestamp) override;
Target* GetCurrentTarget();
Process* GetCurrentProcess();
Thread* GetThread(uint64_t koid);
// Checks if thread is in stopped state; returns error if not stopped.
// `thread` can be nullptr, in which case an error is returned.
Err CheckStoppedThread(Thread* thread);
// Helper methods to get/set frame to ID mapping
int IdForFrame(Frame* frame, int stack_index);
Frame* FrameforId(int id);
void DeleteFrameIdsForThread(Thread* thread);
private:
Session* const session_;
const std::unique_ptr<dap::Session> dap_;
std::shared_ptr<DebugAdapterReader> reader_;
std::shared_ptr<DebugAdapterWriter> writer_;
bool supports_run_in_terminal_ = false;
bool supports_invalidate_event_ = false;
bool init_done_ = false;
struct FrameRecord {
uint64_t thread_koid = 0;
int stack_index = 0;
};
std::map<int, FrameRecord> id_to_frame_;
int next_frame_id_ = 1;
void Init();
};
class DebugAdapterReader : public dap::Reader {
public:
explicit DebugAdapterReader(debug_ipc::StreamBuffer* stream) : stream_(stream) {}
size_t read(void* buffer, size_t n) override {
if (!stream_) {
return 0;
}
auto ret = stream_->Read(static_cast<char*>(buffer), n);
return ret;
}
bool isOpen() override { return !!stream_; }
void close() override { stream_ = nullptr; }
private:
debug_ipc::StreamBuffer* stream_ = nullptr;
};
class DebugAdapterWriter : public dap::Writer {
public:
explicit DebugAdapterWriter(debug_ipc::StreamBuffer* stream) : stream_(stream) {}
bool write(const void* buffer, size_t n) override {
if (!stream_) {
return false;
}
stream_->Write(
std::vector<char>(static_cast<const char*>(buffer), static_cast<const char*>(buffer) + n));
return true;
}
bool isOpen() override { return !!stream_; }
void close() override { stream_ = nullptr; }
private:
debug_ipc::StreamBuffer* stream_ = nullptr;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_DEBUG_ADAPTER_CONTEXT_H_