Update some Android dependencies and fix build by making boost-process optional (#120)

Based on #119

Co-authored-by: Ramiro <ramiro.depaoli@gmail.com>
Co-authored-by: spectranator <spectranator@y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion>
Reviewed-on: http://vub63vv26q6v27xzv2dtcd25xumubshogm67yrpaz2rculqxs7jlfqad.onion/torzu-emu/torzu/pulls/120
This commit is contained in:
spectranator
2025-04-16 19:47:40 +00:00
parent 8561b75518
commit 634acab40b
20 changed files with 203 additions and 100 deletions

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/debugger/debugger.h"
#include <algorithm>
#include <mutex>
#include <thread>
@@ -9,33 +11,34 @@
#include <boost/process/v1/async_pipe.hpp>
#include "common/logging/log.h"
#include "common/polyfill_thread.h"
#include "common/thread.h"
#include "core/core.h"
#include "core/debugger/debugger.h"
#include "core/debugger/debugger_interface.h"
#include "core/debugger/gdbstub.h"
#include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scheduler.h"
template <typename Readable, typename Buffer, typename Callback>
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) {
template<typename Readable, typename Buffer, typename Callback>
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c)
{
static_assert(std::is_trivial_v<Buffer>);
auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))};
r.async_read_some(
boost_buffer, [&, c](const boost::system::error_code& error, size_t bytes_read) {
if (!error.failed()) {
const u8* buffer_start = reinterpret_cast<const u8*>(&buffer);
std::span<const u8> received_data{buffer_start, buffer_start + bytes_read};
c(received_data);
AsyncReceiveInto(r, buffer, c);
}
});
r.async_read_some(boost_buffer,
[&, c](const boost::system::error_code& error, size_t bytes_read) {
if (!error.failed()) {
const u8* buffer_start = reinterpret_cast<const u8*>(&buffer);
std::span<const u8> received_data{buffer_start,
buffer_start + bytes_read};
c(received_data);
AsyncReceiveInto(r, buffer, c);
}
});
}
template <typename Callback>
static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c) {
template<typename Callback>
static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c)
{
acceptor.async_accept([&, c](const boost::system::error_code& error, auto&& peer_socket) {
if (!error.failed()) {
c(peer_socket);
@@ -44,8 +47,9 @@ static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c)
});
}
template <typename Readable, typename Buffer>
static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer) {
template<typename Readable, typename Buffer>
static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer)
{
static_assert(std::is_trivial_v<Buffer>);
auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))};
size_t bytes_read = r.read_some(boost_buffer);
@@ -60,7 +64,8 @@ enum class SignalType {
ShuttingDown,
};
struct SignalInfo {
struct SignalInfo
{
SignalType type;
Kernel::KThread* thread;
const Kernel::DebugWatchpoint* watchpoint;
@@ -68,17 +73,19 @@ struct SignalInfo {
namespace Core {
class DebuggerImpl : public DebuggerBackend {
class DebuggerImpl : public DebuggerBackend
{
public:
explicit DebuggerImpl(Core::System& system_, u16 port) : system{system_} {
explicit DebuggerImpl(Core::System& system_, u16 port)
: system{system_}
{
InitializeServer(port);
}
~DebuggerImpl() override {
ShutdownServer();
}
~DebuggerImpl() override { ShutdownServer(); }
bool SignalDebugger(SignalInfo signal_info) {
bool SignalDebugger(SignalInfo signal_info)
{
std::scoped_lock lk{connection_lock};
if (stopped || !state) {
@@ -100,25 +107,24 @@ public:
// These functions are callbacks from the frontend, and the lock will be held.
// There is no need to relock it.
std::span<const u8> ReadFromClient() override {
std::span<const u8> ReadFromClient() override
{
return ReceiveInto(state->client_socket, state->client_data);
}
void WriteToClient(std::span<const u8> data) override {
void WriteToClient(std::span<const u8> data) override
{
boost::asio::write(state->client_socket,
boost::asio::buffer(data.data(), data.size_bytes()));
}
void SetActiveThread(Kernel::KThread* thread) override {
state->active_thread = thread;
}
void SetActiveThread(Kernel::KThread* thread) override { state->active_thread = thread; }
Kernel::KThread* GetActiveThread() override {
return state->active_thread.GetPointerUnsafe();
}
Kernel::KThread* GetActiveThread() override { return state->active_thread.GetPointerUnsafe(); }
private:
void InitializeServer(u16 port) {
void InitializeServer(u16 port)
{
using boost::asio::ip::tcp;
LOG_INFO(Debug_GDBStub, "Starting server on port {}...", port);
@@ -142,7 +148,8 @@ private:
});
}
void AcceptConnection(boost::asio::ip::tcp::socket&& peer) {
void AcceptConnection(boost::asio::ip::tcp::socket&& peer)
{
LOG_INFO(Debug_GDBStub, "Accepting new peer connection");
std::scoped_lock lk{connection_lock};
@@ -177,13 +184,15 @@ private:
frontend->Connected();
}
void ShutdownServer() {
void ShutdownServer()
{
connection_thread.request_stop();
io_context.stop();
connection_thread.join();
}
void PipeData(std::span<const u8> data) {
void PipeData(std::span<const u8> data)
{
std::scoped_lock lk{connection_lock};
switch (state->info.type) {
@@ -197,8 +206,7 @@ private:
UpdateActiveThread();
if (state->info.type == SignalType::Watchpoint) {
frontend->Watchpoint(std::addressof(*state->active_thread),
*state->info.watchpoint);
frontend->Watchpoint(std::addressof(*state->active_thread), *state->info.watchpoint);
} else {
frontend->Stopped(std::addressof(*state->active_thread));
}
@@ -220,7 +228,8 @@ private:
}
}
void ClientData(std::span<const u8> data) {
void ClientData(std::span<const u8> data)
{
std::scoped_lock lk{connection_lock};
const auto actions{frontend->ClientData(data)};
@@ -262,7 +271,8 @@ private:
}
}
void PauseEmulation() {
void PauseEmulation()
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()};
@@ -272,7 +282,8 @@ private:
}
}
void ResumeEmulation(Kernel::KThread* except = nullptr) {
void ResumeEmulation(Kernel::KThread* except = nullptr)
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()};
@@ -287,13 +298,15 @@ private:
}
}
template <typename Callback>
void MarkResumed(Callback&& cb) {
template<typename Callback>
void MarkResumed(Callback&& cb)
{
stopped = false;
cb();
}
void UpdateActiveThread() {
void UpdateActiveThread()
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
auto& threads{ThreadList()};
@@ -307,13 +320,9 @@ private:
}
private:
void SetDebugProcess() {
debug_process = std::move(system.Kernel().GetProcessList().back());
}
void SetDebugProcess() { debug_process = std::move(system.Kernel().GetProcessList().back()); }
Kernel::KProcess::ThreadList& ThreadList() {
return debug_process->GetThreadList();
}
Kernel::KProcess::ThreadList& ThreadList() { return debug_process->GetThreadList(); }
private:
System& system;
@@ -324,7 +333,8 @@ private:
std::jthread connection_thread;
std::mutex connection_lock;
struct ConnectionState {
struct ConnectionState
{
boost::asio::ip::tcp::socket client_socket;
boost::process::v1::async_pipe signal_pipe;
@@ -338,7 +348,8 @@ private:
bool stopped{};
};
Debugger::Debugger(Core::System& system, u16 port) {
Debugger::Debugger(Core::System& system, u16 port)
{
try {
impl = std::make_unique<DebuggerImpl>(system, port);
} catch (const std::exception& ex) {
@@ -348,16 +359,18 @@ Debugger::Debugger(Core::System& system, u16 port) {
Debugger::~Debugger() = default;
bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) {
bool Debugger::NotifyThreadStopped(Kernel::KThread* thread)
{
return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread, nullptr});
}
bool Debugger::NotifyThreadWatchpoint(Kernel::KThread* thread,
const Kernel::DebugWatchpoint& watch) {
bool Debugger::NotifyThreadWatchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint& watch)
{
return impl && impl->SignalDebugger(SignalInfo{SignalType::Watchpoint, thread, &watch});
}
void Debugger::NotifyShutdown() {
void Debugger::NotifyShutdown()
{
if (impl) {
impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr, nullptr});
}