mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-31 03:45:38 +00:00
Qt: Run GDB server on emulation thread
This commit is contained in:
parent
4494a2c73c
commit
7810e68a58
|
@ -7,28 +7,31 @@
|
|||
#include "qthost.h"
|
||||
Log_SetChannel(GDBConnection);
|
||||
|
||||
GDBConnection::GDBConnection(QObject* parent, int descriptor) : QThread(parent), m_descriptor(descriptor)
|
||||
GDBConnection::GDBConnection(GDBServer* parent, intptr_t descriptor) : QTcpSocket(parent), m_descriptor(descriptor)
|
||||
{
|
||||
Log_InfoPrintf("(%u) Accepted new connection on GDB server", m_descriptor);
|
||||
|
||||
connect(&m_socket, &QTcpSocket::readyRead, this, &GDBConnection::receivedData);
|
||||
connect(&m_socket, &QTcpSocket::disconnected, this, &GDBConnection::gotDisconnected);
|
||||
|
||||
if (m_socket.setSocketDescriptor(m_descriptor))
|
||||
if (!setSocketDescriptor(descriptor))
|
||||
{
|
||||
g_emu_thread->setSystemPaused(true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_ErrorPrintf("(%u) Failed to set socket descriptor: %s", m_descriptor,
|
||||
m_socket.errorString().toUtf8().constData());
|
||||
Log_ErrorPrintf("(%" PRIdPTR ") Failed to set socket descriptor: %s", descriptor,
|
||||
errorString().toUtf8().constData());
|
||||
deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(g_emu_thread, &EmuThread::systemPaused, this, &GDBConnection::onEmulationPaused);
|
||||
connect(g_emu_thread, &EmuThread::systemResumed, this, &GDBConnection::onEmulationResumed);
|
||||
connect(this, &QTcpSocket::readyRead, this, &GDBConnection::receivedData);
|
||||
connect(this, &QTcpSocket::disconnected, this, &GDBConnection::gotDisconnected);
|
||||
|
||||
Log_InfoPrintf("(%" PRIdPTR ") Client connected", m_descriptor);
|
||||
|
||||
m_seen_resume = System::IsPaused();
|
||||
g_emu_thread->setSystemPaused(true);
|
||||
}
|
||||
|
||||
void GDBConnection::gotDisconnected()
|
||||
{
|
||||
Log_InfoPrintf("(%u) Client disconnected", m_descriptor);
|
||||
this->exit(0);
|
||||
Log_InfoPrintf("(%" PRIdPTR ") Client disconnected", m_descriptor);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void GDBConnection::receivedData()
|
||||
|
@ -36,7 +39,7 @@ void GDBConnection::receivedData()
|
|||
qint64 bytesRead;
|
||||
char buffer[256];
|
||||
|
||||
while ((bytesRead = m_socket.read(buffer, sizeof(buffer))) > 0)
|
||||
while ((bytesRead = read(buffer, sizeof(buffer))) > 0)
|
||||
{
|
||||
for (char c : std::string_view(buffer, bytesRead))
|
||||
{
|
||||
|
@ -44,19 +47,19 @@ void GDBConnection::receivedData()
|
|||
|
||||
if (GDBProtocol::IsPacketInterrupt(m_readBuffer))
|
||||
{
|
||||
Log_DebugPrintf("(%u) > Interrupt request", m_descriptor);
|
||||
g_emu_thread->setSystemPaused(true, true);
|
||||
Log_DebugPrintf("(%" PRIdPTR ") > Interrupt request", m_descriptor);
|
||||
g_emu_thread->setSystemPaused(true);
|
||||
m_readBuffer.erase();
|
||||
}
|
||||
else if (GDBProtocol::IsPacketContinue(m_readBuffer))
|
||||
{
|
||||
Log_DebugPrintf("(%u) > Continue request", m_descriptor);
|
||||
g_emu_thread->setSystemPaused(false, false);
|
||||
Log_DebugPrintf("(%" PRIdPTR ") > Continue request", m_descriptor);
|
||||
g_emu_thread->setSystemPaused(false);
|
||||
m_readBuffer.erase();
|
||||
}
|
||||
else if (GDBProtocol::IsPacketComplete(m_readBuffer))
|
||||
{
|
||||
Log_DebugPrintf("(%u) > %s", m_descriptor, m_readBuffer.c_str());
|
||||
Log_DebugPrintf("(%" PRIdPTR ") > %s", m_descriptor, m_readBuffer.c_str());
|
||||
writePacket(GDBProtocol::ProcessPacket(m_readBuffer));
|
||||
m_readBuffer.erase();
|
||||
}
|
||||
|
@ -64,7 +67,8 @@ void GDBConnection::receivedData()
|
|||
}
|
||||
if (bytesRead == -1)
|
||||
{
|
||||
Log_ErrorPrintf("(%u) Failed to read from socket: %s", m_descriptor, m_socket.errorString().toUtf8().constData());
|
||||
Log_ErrorPrintf("(%" PRIdPTR ") Failed to read from socket: %s", m_descriptor,
|
||||
errorString().toUtf8().constData());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,9 +91,10 @@ void GDBConnection::onEmulationResumed()
|
|||
|
||||
void GDBConnection::writePacket(std::string_view packet)
|
||||
{
|
||||
Log_DebugPrintf("(%u) < %*s", m_descriptor, packet.length(), packet.data());
|
||||
if (m_socket.write(packet.data(), packet.length()) == -1)
|
||||
Log_DebugPrintf("(%" PRIdPTR ") < %*s", m_descriptor, packet.length(), packet.data());
|
||||
if (write(packet.data(), packet.length()) == -1)
|
||||
{
|
||||
Log_ErrorPrintf("(%u) Failed to write to socket: %s", m_descriptor, m_socket.errorString().toUtf8().constData());
|
||||
Log_ErrorPrintf("(%" PRIdPTR ") Failed to write to socket: %s", m_descriptor,
|
||||
errorString().toUtf8().constData());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
#include <QtCore/QThread>
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
|
||||
class GDBConnection : public QThread
|
||||
class GDBServer;
|
||||
|
||||
class GDBConnection : public QTcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GDBConnection(QObject *parent, int descriptor);
|
||||
GDBConnection(GDBServer *parent, intptr_t descriptor);
|
||||
|
||||
public Q_SLOTS:
|
||||
void gotDisconnected();
|
||||
|
@ -21,8 +23,7 @@ public Q_SLOTS:
|
|||
private:
|
||||
void writePacket(std::string_view data);
|
||||
|
||||
int m_descriptor;
|
||||
QTcpSocket m_socket;
|
||||
intptr_t m_descriptor;
|
||||
std::string m_readBuffer;
|
||||
bool m_seen_resume;
|
||||
};
|
||||
|
|
|
@ -7,33 +7,46 @@
|
|||
#include "qthost.h"
|
||||
Log_SetChannel(GDBServer);
|
||||
|
||||
GDBServer::GDBServer(QObject *parent, u16 port)
|
||||
GDBServer::GDBServer(QObject *parent)
|
||||
: QTcpServer(parent)
|
||||
{
|
||||
if (listen(QHostAddress::LocalHost, port)) {
|
||||
Log_InfoPrintf("GDB server listening on TCP port %u", port);
|
||||
}
|
||||
else {
|
||||
Log_InfoPrintf("Failed to listen on TCP port %u for GDB server: %s", port, errorString().toUtf8().constData());
|
||||
}
|
||||
}
|
||||
|
||||
GDBServer::~GDBServer()
|
||||
{
|
||||
Log_InfoPrint("GDB server stopped");
|
||||
for (auto* thread : m_connections) {
|
||||
thread->quit();
|
||||
thread->wait();
|
||||
delete thread;
|
||||
stop();
|
||||
}
|
||||
|
||||
void GDBServer::start(quint16 port) {
|
||||
if (isListening())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!listen(QHostAddress::LocalHost, port))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to listen on TCP port %u for GDB server: %s", port,
|
||||
errorString().toUtf8().constData());
|
||||
return;
|
||||
}
|
||||
|
||||
Log_InfoPrintf("GDB server listening on TCP port %u", port);
|
||||
}
|
||||
|
||||
void GDBServer::stop()
|
||||
{
|
||||
if (isListening())
|
||||
{
|
||||
close();
|
||||
Log_InfoPrint("GDB server stopped");
|
||||
}
|
||||
|
||||
for (QObject* connection : children()) {
|
||||
connection->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void GDBServer::incomingConnection(qintptr descriptor)
|
||||
{
|
||||
Log_InfoPrint("Accepted connection on GDB server");
|
||||
GDBConnection *thread = new GDBConnection(this, descriptor);
|
||||
connect(g_emu_thread, &EmuThread::systemPaused, thread, &GDBConnection::onEmulationPaused);
|
||||
connect(g_emu_thread, &EmuThread::systemResumed, thread, &GDBConnection::onEmulationResumed);
|
||||
thread->start();
|
||||
m_connections.push_back(thread);
|
||||
new GDBConnection(this, descriptor);
|
||||
}
|
||||
|
|
|
@ -11,12 +11,13 @@ class GDBServer : public QTcpServer
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GDBServer(QObject* parent, u16 port);
|
||||
GDBServer(QObject* parent = nullptr);
|
||||
~GDBServer();
|
||||
|
||||
public Q_SLOTS:
|
||||
void start(quint16 port);
|
||||
void stop();
|
||||
|
||||
protected:
|
||||
void incomingConnection(qintptr socketDescriptor) override;
|
||||
|
||||
private:
|
||||
std::list<GDBConnection*> m_connections;
|
||||
};
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "frontend-common/platform_misc.h"
|
||||
#include "gamelistsettingswidget.h"
|
||||
#include "gamelistwidget.h"
|
||||
#include "gdbserver.h"
|
||||
#include "memorycardeditordialog.h"
|
||||
#include "qthost.h"
|
||||
#include "qtutils.h"
|
||||
|
@ -1723,17 +1722,13 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool cheevo
|
|||
if ((!starting && !running) || running)
|
||||
m_open_debugger_on_start = false;
|
||||
|
||||
if (g_settings.debugging.enable_gdb_server)
|
||||
if (!g_gdb_server->isListening() && g_settings.debugging.enable_gdb_server && starting)
|
||||
{
|
||||
if (starting && !m_gdb_server)
|
||||
{
|
||||
m_gdb_server = new GDBServer(this, g_settings.debugging.gdb_server_port);
|
||||
}
|
||||
else if (!running && m_gdb_server)
|
||||
{
|
||||
delete m_gdb_server;
|
||||
m_gdb_server = nullptr;
|
||||
}
|
||||
QMetaObject::invokeMethod(g_gdb_server, "start", Qt::QueuedConnection, Q_ARG(quint16, g_settings.debugging.gdb_server_port));
|
||||
}
|
||||
else if (g_gdb_server->isListening() && !running)
|
||||
{
|
||||
QMetaObject::invokeMethod(g_gdb_server, "stop", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
m_ui.statusBar->clearMessage();
|
||||
|
|
|
@ -33,8 +33,6 @@ namespace GameList {
|
|||
struct Entry;
|
||||
}
|
||||
|
||||
class GDBServer;
|
||||
|
||||
class MainWindow final : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -286,8 +284,6 @@ private:
|
|||
bool m_was_disc_change_request = false;
|
||||
bool m_is_closing = false;
|
||||
|
||||
GDBServer* m_gdb_server = nullptr;
|
||||
|
||||
#ifdef _WIN32
|
||||
void* m_device_notification_handle = nullptr;
|
||||
#endif
|
||||
|
|
|
@ -98,6 +98,7 @@ static bool s_start_fullscreen_ui = false;
|
|||
static bool s_start_fullscreen_ui_fullscreen = false;
|
||||
|
||||
EmuThread* g_emu_thread;
|
||||
GDBServer* g_gdb_server;
|
||||
|
||||
EmuThread::EmuThread(QThread* ui_thread) : QThread(), m_ui_thread(ui_thread) {}
|
||||
|
||||
|
@ -1373,6 +1374,8 @@ void EmuThread::start()
|
|||
AssertMsg(!g_emu_thread, "Emu thread does not exist");
|
||||
|
||||
g_emu_thread = new EmuThread(QThread::currentThread());
|
||||
g_gdb_server = new GDBServer();
|
||||
g_gdb_server->moveToThread(g_emu_thread);
|
||||
g_emu_thread->QThread::start();
|
||||
g_emu_thread->m_started_semaphore.acquire();
|
||||
g_emu_thread->moveToThread(g_emu_thread);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "frontend-common/common_host.h"
|
||||
#include "frontend-common/game_list.h"
|
||||
#include "frontend-common/input_manager.h"
|
||||
#include "gdbserver.h"
|
||||
#include "qtutils.h"
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QMetaType>
|
||||
|
@ -235,6 +236,7 @@ private:
|
|||
};
|
||||
|
||||
extern EmuThread* g_emu_thread;
|
||||
extern GDBServer* g_gdb_server;
|
||||
|
||||
namespace QtHost {
|
||||
/// Sets batch mode (exit after game shutdown).
|
||||
|
|
Loading…
Reference in a new issue