mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-12 13:13:43 +00:00
GDB Server: fix and cleanup
Move source files to Emu/GDB.cpp, GDB.h Remove "WITH_GDB" option, enable GDB Server by default. Change class name to gdb_thread. Alias for external access gdb_server. Change config option name to "GDB Server" Bind on 127.0.0.1 by default.
This commit is contained in:
parent
9d4de51cb6
commit
a29d4150df
@ -12,7 +12,6 @@ elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(WITH_GDB "WITH_GDB" OFF)
|
||||
option(USE_NATIVE_INSTRUCTIONS "USE_NATIVE_INSTRUCTIONS makes rpcs3 compile with -march=native, which is useful for local builds, but not good for packages." ON)
|
||||
option(WITH_LLVM "Enable usage of LLVM library" ON)
|
||||
option(BUILD_LLVM_SUBMODULE "Build LLVM from git submodule" ON)
|
||||
@ -28,10 +27,6 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/rpcs3/cmake_modules")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
if (WITH_GDB)
|
||||
add_definitions(-DWITH_GDB_DEBUGGER)
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "No build type selected, default to Release")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
|
@ -2,6 +2,7 @@
|
||||
IdManager.cpp
|
||||
System.cpp
|
||||
VFS.cpp
|
||||
GDB.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(rpcs3_emu
|
||||
@ -24,7 +25,6 @@ target_sources(rpcs3_emu PRIVATE
|
||||
../../Utilities/Config.cpp
|
||||
../../Utilities/dynamic_library.cpp
|
||||
../../Utilities/File.cpp
|
||||
../../Utilities/GDBDebugServer.cpp
|
||||
../../Utilities/JIT.cpp
|
||||
../../Utilities/Log.cpp
|
||||
../../Utilities/LUrlParser.cpp
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/vm_locking.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Utilities/GDBDebugServer.h"
|
||||
#include "Emu/GDB.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
|
||||
@ -194,12 +194,10 @@ cpu_thread::cpu_thread(u32 id)
|
||||
|
||||
bool cpu_thread::check_state() noexcept
|
||||
{
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
if (state & cpu_flag::dbg_pause)
|
||||
{
|
||||
fxm::get<GDBDebugServer>()->pause_from(this);
|
||||
g_fxo->get<gdb_server>()->pause_from(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool cpu_sleep_called = false;
|
||||
bool cpu_flag_memory = false;
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "SPURecompiler.h"
|
||||
#include "lv2/sys_sync.h"
|
||||
#include "lv2/sys_prx.h"
|
||||
#include "Utilities/GDBDebugServer.h"
|
||||
#include "Emu/GDB.h"
|
||||
|
||||
#ifdef LLVM_AVAILABLE
|
||||
#include "restore_new.h"
|
||||
@ -329,9 +329,9 @@ static bool ppu_break(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
// Pause and wait if necessary
|
||||
bool status = ppu.state.test_and_set(cpu_flag::dbg_pause);
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
fxm::get<GDBDebugServer>()->pause_from(&ppu);
|
||||
#endif
|
||||
|
||||
g_fxo->get<gdb_server>()->pause_from(&ppu);
|
||||
|
||||
if (!status && ppu.check_state())
|
||||
{
|
||||
return false;
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
|
||||
#include "GDBDebugServer.h"
|
||||
#include "Log.h"
|
||||
#include "GDB.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include <algorithm>
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/System.h"
|
||||
@ -12,8 +11,18 @@
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "fcntl.h"
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
extern void ppu_set_breakpoint(u32 addr);
|
||||
@ -21,31 +30,12 @@ extern void ppu_remove_breakpoint(u32 addr);
|
||||
|
||||
LOG_CHANNEL(gdbDebugServer);
|
||||
|
||||
int sock_init(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsa_data;
|
||||
return WSAStartup(MAKEWORD(1, 1), &wsa_data);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int sock_quit(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return WSACleanup();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
int closesocket(socket_t s) {
|
||||
int closesocket(int s)
|
||||
{
|
||||
return close(s);
|
||||
}
|
||||
const int SOCKET_ERROR = -1;
|
||||
const socket_t INVALID_SOCKET = -1;
|
||||
|
||||
#define sscanf_s sscanf
|
||||
#define HEX_U32 "x"
|
||||
#define HEX_U64 "lx"
|
||||
@ -54,7 +44,24 @@ const socket_t INVALID_SOCKET = -1;
|
||||
#define HEX_U64 "llx"
|
||||
#endif
|
||||
|
||||
bool check_errno_again() {
|
||||
struct gdb_cmd
|
||||
{
|
||||
std::string cmd;
|
||||
std::string data;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
class wrong_checksum_exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
wrong_checksum_exception(char const* const message)
|
||||
: runtime_error(message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
bool check_errno_again()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int err = GetLastError();
|
||||
return (err == WSAEWOULDBLOCK);
|
||||
@ -94,11 +101,12 @@ u64 hex_to_u64(std::string val) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void GDBDebugServer::start_server()
|
||||
void gdb_thread::start_server()
|
||||
{
|
||||
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (server_socket == INVALID_SOCKET) {
|
||||
if (server_socket == -1)
|
||||
{
|
||||
gdbDebugServer.error("Error creating server socket");
|
||||
return;
|
||||
}
|
||||
@ -116,33 +124,38 @@ void GDBDebugServer::start_server()
|
||||
|
||||
sockaddr_in server_saddr;
|
||||
server_saddr.sin_family = AF_INET;
|
||||
int port = g_cfg.misc.gdb_server_port;
|
||||
int port = 2345;
|
||||
server_saddr.sin_port = htons(port);
|
||||
server_saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
server_saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
err = bind(server_socket, (struct sockaddr *) &server_saddr, sizeof(server_saddr));
|
||||
if (err == SOCKET_ERROR) {
|
||||
if (err == -1)
|
||||
{
|
||||
gdbDebugServer.error("Error binding to port %d", port);
|
||||
return;
|
||||
}
|
||||
|
||||
err = listen(server_socket, 1);
|
||||
if (err == SOCKET_ERROR) {
|
||||
if (err == -1)
|
||||
{
|
||||
gdbDebugServer.error("Error listening on port %d", port);
|
||||
return;
|
||||
}
|
||||
|
||||
gdbDebugServer.success("GDB Debug Server listening on port %d", port);
|
||||
gdbDebugServer.notice("GDB Debug Server listening on port %d", port);
|
||||
}
|
||||
|
||||
int GDBDebugServer::read(void * buf, int cnt)
|
||||
int gdb_thread::read(void* buf, int cnt)
|
||||
{
|
||||
while (!stop) {
|
||||
while (!Emu.IsStopped())
|
||||
{
|
||||
int result = recv(client_socket, reinterpret_cast<char*>(buf), cnt, 0);
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
if (check_errno_again()) {
|
||||
thread_ctrl::wait_for(50);
|
||||
if (result == -1)
|
||||
{
|
||||
if (check_errno_again())
|
||||
{
|
||||
thread_ctrl::wait_for(5000);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -154,7 +167,7 @@ int GDBDebugServer::read(void * buf, int cnt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char GDBDebugServer::read_char()
|
||||
char gdb_thread::read_char()
|
||||
{
|
||||
char result;
|
||||
int cnt = read(&result, 1);
|
||||
@ -164,7 +177,7 @@ char GDBDebugServer::read_char()
|
||||
return result;
|
||||
}
|
||||
|
||||
u8 GDBDebugServer::read_hexbyte()
|
||||
u8 gdb_thread::read_hexbyte()
|
||||
{
|
||||
std::string s = "";
|
||||
s += read_char();
|
||||
@ -172,7 +185,7 @@ u8 GDBDebugServer::read_hexbyte()
|
||||
return hex_to_u8(s);
|
||||
}
|
||||
|
||||
void GDBDebugServer::try_read_cmd(gdb_cmd & out_cmd)
|
||||
void gdb_thread::try_read_cmd(gdb_cmd& out_cmd)
|
||||
{
|
||||
char c = read_char();
|
||||
//interrupt
|
||||
@ -228,32 +241,39 @@ void GDBDebugServer::try_read_cmd(gdb_cmd & out_cmd)
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBDebugServer::read_cmd(gdb_cmd & out_cmd)
|
||||
bool gdb_thread::read_cmd(gdb_cmd& out_cmd)
|
||||
{
|
||||
while (true) {
|
||||
try {
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
try_read_cmd(out_cmd);
|
||||
ack(true);
|
||||
return true;
|
||||
}
|
||||
catch (wrong_checksum_exception) {
|
||||
catch (const wrong_checksum_exception&)
|
||||
{
|
||||
ack(false);
|
||||
}
|
||||
catch (std::runtime_error e) {
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
gdbDebugServer.error(e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GDBDebugServer::send(const char * buf, int cnt)
|
||||
void gdb_thread::send(const char* buf, int cnt)
|
||||
{
|
||||
gdbDebugServer.trace("Sending %s (%d bytes)", buf, cnt);
|
||||
while (!stop) {
|
||||
while (!Emu.IsStopped())
|
||||
{
|
||||
int res = ::send(client_socket, buf, cnt, 0);
|
||||
if (res == SOCKET_ERROR) {
|
||||
if (check_errno_again()) {
|
||||
thread_ctrl::wait_for(50);
|
||||
if (res == -1)
|
||||
{
|
||||
if (check_errno_again())
|
||||
{
|
||||
thread_ctrl::wait_for(5000);
|
||||
continue;
|
||||
}
|
||||
gdbDebugServer.error("Failed sending %d bytes", cnt);
|
||||
@ -263,17 +283,17 @@ void GDBDebugServer::send(const char * buf, int cnt)
|
||||
}
|
||||
}
|
||||
|
||||
void GDBDebugServer::send_char(char c)
|
||||
void gdb_thread::send_char(char c)
|
||||
{
|
||||
send(&c, 1);
|
||||
}
|
||||
|
||||
void GDBDebugServer::ack(bool accepted)
|
||||
void gdb_thread::ack(bool accepted)
|
||||
{
|
||||
send_char(accepted ? '+' : '-');
|
||||
}
|
||||
|
||||
void GDBDebugServer::send_cmd(const std::string & cmd)
|
||||
void gdb_thread::send_cmd(const std::string& cmd)
|
||||
{
|
||||
u8 checksum = 0;
|
||||
std::string buf;
|
||||
@ -287,7 +307,7 @@ void GDBDebugServer::send_cmd(const std::string & cmd)
|
||||
send(buf.c_str(), static_cast<int>(buf.length()));
|
||||
}
|
||||
|
||||
bool GDBDebugServer::send_cmd_ack(const std::string & cmd)
|
||||
bool gdb_thread::send_cmd_ack(const std::string& cmd)
|
||||
{
|
||||
while (true) {
|
||||
send_cmd(cmd);
|
||||
@ -303,7 +323,7 @@ bool GDBDebugServer::send_cmd_ack(const std::string & cmd)
|
||||
}
|
||||
}
|
||||
|
||||
u8 GDBDebugServer::append_encoded_char(char c, std::string & str)
|
||||
u8 gdb_thread::append_encoded_char(char c, std::string& str)
|
||||
{
|
||||
u8 checksum = 0;
|
||||
if (UNLIKELY((c == '#') || (c == '$') || (c == '}'))) {
|
||||
@ -316,7 +336,7 @@ u8 GDBDebugServer::append_encoded_char(char c, std::string & str)
|
||||
return checksum;
|
||||
}
|
||||
|
||||
std::string GDBDebugServer::to_hexbyte(u8 i)
|
||||
std::string gdb_thread::to_hexbyte(u8 i)
|
||||
{
|
||||
std::string result = "00";
|
||||
u8 i1 = i & 0xF;
|
||||
@ -326,7 +346,7 @@ std::string GDBDebugServer::to_hexbyte(u8 i)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GDBDebugServer::select_thread(u64 id)
|
||||
bool gdb_thread::select_thread(u64 id)
|
||||
{
|
||||
//in case we have none at all
|
||||
selected_thread.reset();
|
||||
@ -342,7 +362,7 @@ bool GDBDebugServer::select_thread(u64 id)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string GDBDebugServer::get_reg(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
std::string gdb_thread::get_reg(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
{
|
||||
std::string result;
|
||||
//ids from gdb/features/rs6000/powerpc-64.c
|
||||
@ -373,7 +393,7 @@ std::string GDBDebugServer::get_reg(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBDebugServer::set_reg(std::shared_ptr<ppu_thread> thread, u32 rid, std::string value)
|
||||
bool gdb_thread::set_reg(std::shared_ptr<ppu_thread> thread, u32 rid, std::string value)
|
||||
{
|
||||
switch (rid) {
|
||||
case 64:
|
||||
@ -409,7 +429,7 @@ bool GDBDebugServer::set_reg(std::shared_ptr<ppu_thread> thread, u32 rid, std::s
|
||||
}
|
||||
}
|
||||
|
||||
u32 GDBDebugServer::get_reg_size(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
u32 gdb_thread::get_reg_size(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
{
|
||||
switch (rid) {
|
||||
case 66:
|
||||
@ -424,19 +444,23 @@ u32 GDBDebugServer::get_reg_size(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBDebugServer::send_reason()
|
||||
bool gdb_thread::send_reason()
|
||||
{
|
||||
return send_cmd_ack("S05");
|
||||
}
|
||||
|
||||
void GDBDebugServer::wait_with_interrupts() {
|
||||
void gdb_thread::wait_with_interrupts()
|
||||
{
|
||||
char c;
|
||||
while (!paused) {
|
||||
while (!paused)
|
||||
{
|
||||
int result = recv(client_socket, &c, 1, 0);
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
if (check_errno_again()) {
|
||||
thread_ctrl::wait_for(50);
|
||||
if (result == -1)
|
||||
{
|
||||
if (check_errno_again())
|
||||
{
|
||||
thread_ctrl::wait_for(5000);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -448,22 +472,22 @@ void GDBDebugServer::wait_with_interrupts() {
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_extended_mode(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_extended_mode(gdb_cmd& cmd)
|
||||
{
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_reason(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_reason(gdb_cmd& cmd)
|
||||
{
|
||||
return send_reason();
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_supported(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_supported(gdb_cmd& cmd)
|
||||
{
|
||||
return send_cmd_ack("PacketSize=1200");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_thread_info(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_thread_info(gdb_cmd& cmd)
|
||||
{
|
||||
std::string result = "";
|
||||
const auto on_select = [&](u32, cpu_thread& cpu)
|
||||
@ -483,12 +507,12 @@ bool GDBDebugServer::cmd_thread_info(gdb_cmd & cmd)
|
||||
return send_cmd_ack(result);;
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_current_thread(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_current_thread(gdb_cmd& cmd)
|
||||
{
|
||||
return send_cmd_ack(selected_thread.expired() ? "" : ("QC" + u64_to_padded_hex(selected_thread.lock()->id)));
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_read_register(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_read_register(gdb_cmd& cmd)
|
||||
{
|
||||
if (!select_thread(general_ops_thread_id)) {
|
||||
return send_cmd_ack("E02");
|
||||
@ -508,7 +532,7 @@ bool GDBDebugServer::cmd_read_register(gdb_cmd & cmd)
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_write_register(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_write_register(gdb_cmd& cmd)
|
||||
{
|
||||
if (!select_thread(general_ops_thread_id)) {
|
||||
return send_cmd_ack("E02");
|
||||
@ -533,7 +557,7 @@ bool GDBDebugServer::cmd_write_register(gdb_cmd & cmd)
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_read_memory(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_read_memory(gdb_cmd& cmd)
|
||||
{
|
||||
size_t s = cmd.data.find(',');
|
||||
u32 addr = hex_to_u32(cmd.data.substr(0, s));
|
||||
@ -555,7 +579,7 @@ bool GDBDebugServer::cmd_read_memory(gdb_cmd & cmd)
|
||||
return send_cmd_ack(result);
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_write_memory(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_write_memory(gdb_cmd& cmd)
|
||||
{
|
||||
size_t s = cmd.data.find(',');
|
||||
size_t s2 = cmd.data.find(':');
|
||||
@ -583,7 +607,7 @@ bool GDBDebugServer::cmd_write_memory(gdb_cmd & cmd)
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_read_all_registers(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_read_all_registers(gdb_cmd& cmd)
|
||||
{
|
||||
std::string result;
|
||||
select_thread(general_ops_thread_id);
|
||||
@ -602,7 +626,7 @@ bool GDBDebugServer::cmd_read_all_registers(gdb_cmd & cmd)
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_write_all_registers(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_write_all_registers(gdb_cmd& cmd)
|
||||
{
|
||||
select_thread(general_ops_thread_id);
|
||||
auto th = selected_thread.lock();
|
||||
@ -620,7 +644,7 @@ bool GDBDebugServer::cmd_write_all_registers(gdb_cmd & cmd)
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_set_thread_ops(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_set_thread_ops(gdb_cmd& cmd)
|
||||
{
|
||||
char type = cmd.data[0];
|
||||
std::string thread = cmd.data.substr(1);
|
||||
@ -637,24 +661,24 @@ bool GDBDebugServer::cmd_set_thread_ops(gdb_cmd & cmd)
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_attached_to_what(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_attached_to_what(gdb_cmd& cmd)
|
||||
{
|
||||
//creating processes from client is not available yet
|
||||
return send_cmd_ack("1");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_kill(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_kill(gdb_cmd& cmd)
|
||||
{
|
||||
Emu.Stop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_continue_support(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_continue_support(gdb_cmd& cmd)
|
||||
{
|
||||
return send_cmd_ack("vCont;c;s;C;S");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_vcont(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_vcont(gdb_cmd& cmd)
|
||||
{
|
||||
//todo: handle multiple actions and thread ids
|
||||
this->from_breakpoint = false;
|
||||
@ -690,7 +714,7 @@ bool GDBDebugServer::cmd_vcont(gdb_cmd & cmd)
|
||||
|
||||
static const u32 INVALID_PTR = 0xffffffff;
|
||||
|
||||
bool GDBDebugServer::cmd_set_breakpoint(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_set_breakpoint(gdb_cmd& cmd)
|
||||
{
|
||||
char type = cmd.data[0];
|
||||
//software breakpoint
|
||||
@ -712,7 +736,7 @@ bool GDBDebugServer::cmd_set_breakpoint(gdb_cmd & cmd)
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_remove_breakpoint(gdb_cmd & cmd)
|
||||
bool gdb_thread::cmd_remove_breakpoint(gdb_cmd& cmd)
|
||||
{
|
||||
char type = cmd.data[0];
|
||||
//software breakpoint
|
||||
@ -733,20 +757,46 @@ bool GDBDebugServer::cmd_remove_breakpoint(gdb_cmd & cmd)
|
||||
|
||||
#define PROCESS_CMD(cmds,handler) if (cmd.cmd == cmds) { if (!handler(cmd)) break; else continue; }
|
||||
|
||||
void GDBDebugServer::on_task()
|
||||
gdb_thread::gdb_thread() noexcept
|
||||
{
|
||||
sock_init();
|
||||
#ifdef _WIN32
|
||||
WSADATA wsa_data;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
gdb_thread::~gdb_thread()
|
||||
{
|
||||
if (server_socket != -1)
|
||||
{
|
||||
closesocket(server_socket);
|
||||
}
|
||||
|
||||
if (client_socket != -1)
|
||||
{
|
||||
closesocket(client_socket);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void gdb_thread::operator()()
|
||||
{
|
||||
start_server();
|
||||
|
||||
while (!stop) {
|
||||
while (!Emu.IsStopped())
|
||||
{
|
||||
sockaddr_in client;
|
||||
socklen_t client_len = sizeof(client);
|
||||
client_socket = accept(server_socket, (struct sockaddr *) &client, &client_len);
|
||||
|
||||
if (client_socket == INVALID_SOCKET) {
|
||||
if (check_errno_again()) {
|
||||
thread_ctrl::wait_for(50);
|
||||
if (client_socket == -1)
|
||||
{
|
||||
if (check_errno_again())
|
||||
{
|
||||
thread_ctrl::wait_for(5000);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -765,8 +815,10 @@ void GDBDebugServer::on_task()
|
||||
|
||||
gdb_cmd cmd;
|
||||
|
||||
while (!stop) {
|
||||
if (!read_cmd(cmd)) {
|
||||
while (!Emu.IsStopped())
|
||||
{
|
||||
if (!read_cmd(cmd))
|
||||
{
|
||||
break;
|
||||
}
|
||||
gdbDebugServer.trace("Command %s with data %s received", cmd.cmd.c_str(), cmd.data.c_str());
|
||||
@ -795,12 +847,14 @@ void GDBDebugServer::on_task()
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
if (client_socket) {
|
||||
if (client_socket != -1)
|
||||
{
|
||||
closesocket(client_socket);
|
||||
client_socket = 0;
|
||||
client_socket = -1;
|
||||
}
|
||||
|
||||
gdbDebugServer.error(e.what());
|
||||
}
|
||||
}
|
||||
@ -808,46 +862,20 @@ void GDBDebugServer::on_task()
|
||||
|
||||
#undef PROCESS_CMD
|
||||
|
||||
void GDBDebugServer::on_exit()
|
||||
void gdb_thread::pause_from(cpu_thread* t)
|
||||
{
|
||||
if (server_socket) {
|
||||
closesocket(server_socket);
|
||||
}
|
||||
if (client_socket) {
|
||||
closesocket(client_socket);
|
||||
}
|
||||
sock_quit();
|
||||
}
|
||||
|
||||
std::string GDBDebugServer::get_name() const
|
||||
{
|
||||
return "GDBDebugger";
|
||||
}
|
||||
|
||||
void GDBDebugServer::on_stop()
|
||||
{
|
||||
this->stop = true;
|
||||
//just in case we are waiting for breakpoint
|
||||
this->notify();
|
||||
old_thread::on_stop();
|
||||
}
|
||||
|
||||
void GDBDebugServer::pause_from(cpu_thread* t) {
|
||||
if (paused) {
|
||||
if (paused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
paused = true;
|
||||
pausedBy = t->id;
|
||||
notify();
|
||||
thread_ctrl::notify(*static_cast<gdb_server*>(this));
|
||||
}
|
||||
|
||||
u32 g_gdb_debugger_id = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
#undef sscanf_s
|
||||
#endif
|
||||
|
||||
#undef HEX_U32
|
||||
#undef HEX_U64
|
||||
|
||||
#endif
|
@ -1,49 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
#include "Utilities/Thread.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Thread.h"
|
||||
#include <Emu/IdManager.h>
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
struct gdb_cmd;
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
class cpu_thread;
|
||||
class ppu_thread;
|
||||
|
||||
#ifdef _WIN32
|
||||
using socket_t = SOCKET;
|
||||
#else
|
||||
using socket_t = int;
|
||||
#endif
|
||||
|
||||
typedef struct gdb_cmd {
|
||||
std::string cmd;
|
||||
std::string data;
|
||||
u8 checksum;
|
||||
} gdb_cmd;
|
||||
|
||||
class wrong_checksum_exception : public std::runtime_error {
|
||||
public:
|
||||
wrong_checksum_exception(char const* const message) : runtime_error(message) {}
|
||||
};
|
||||
|
||||
const u64 ALL_THREADS = 0xffffffffffffffff;
|
||||
const u64 ANY_THREAD = 0;
|
||||
|
||||
class GDBDebugServer
|
||||
class gdb_thread
|
||||
{
|
||||
socket_t server_socket;
|
||||
socket_t client_socket;
|
||||
static const u64 ALL_THREADS = 0xffffffffffffffff;
|
||||
static const u64 ANY_THREAD = 0;
|
||||
|
||||
int server_socket = -1;
|
||||
int client_socket = -1;
|
||||
std::weak_ptr<cpu_thread> selected_thread;
|
||||
u64 continue_ops_thread_id = ANY_THREAD;
|
||||
u64 general_ops_thread_id = ANY_THREAD;
|
||||
@ -71,10 +43,10 @@ class GDBDebugServer
|
||||
//acknowledge packet, either as accepted or declined
|
||||
void ack(bool accepted);
|
||||
//sends command body cmd to client
|
||||
void send_cmd(const std::string & cmd);
|
||||
void send_cmd(const std::string& cmd);
|
||||
//sends command to client until receives positive acknowledgement
|
||||
//returns false in case some error happened, and command wasn't sent
|
||||
bool send_cmd_ack(const std::string & cmd);
|
||||
bool send_cmd_ack(const std::string& cmd);
|
||||
//appends encoded char c to string str, and returns checksum. encoded byte can occupy 2 bytes
|
||||
static u8 append_encoded_char(char c, std::string& str);
|
||||
//convert u8 to 2 byte hexademical representation
|
||||
@ -114,14 +86,18 @@ class GDBDebugServer
|
||||
|
||||
public:
|
||||
bool from_breakpoint = true;
|
||||
bool stop = false;
|
||||
bool paused = false;
|
||||
u64 pausedBy;
|
||||
|
||||
gdb_thread() noexcept;
|
||||
~gdb_thread();
|
||||
gdb_thread(const gdb_thread&) = delete;
|
||||
gdb_thread& operator=(const gdb_thread&) = delete;
|
||||
|
||||
void operator()();
|
||||
void pause_from(cpu_thread* t);
|
||||
|
||||
static constexpr auto thread_name = "GDB Server"sv;
|
||||
};
|
||||
|
||||
extern u32 g_gdb_debugger_id;
|
||||
|
||||
#endif
|
||||
using gdb_server = named_thread<gdb_thread>;
|
@ -38,8 +38,6 @@
|
||||
#include <memory>
|
||||
#include <regex>
|
||||
|
||||
#include "Utilities/GDBDebugServer.h"
|
||||
|
||||
#include "Utilities/JIT.h"
|
||||
|
||||
#if defined(_WIN32) || defined(HAVE_VULKAN)
|
||||
@ -421,10 +419,6 @@ void Emulator::Init()
|
||||
make_path_verbose(fs::get_cache_dir() + "shaderlog/");
|
||||
make_path_verbose(fs::get_config_dir() + "captures/");
|
||||
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
LOG_SUCCESS(GENERAL, "GDB debug server will be started and listening on %d upon emulator boot", (int)g_cfg.misc.gdb_server_port);
|
||||
#endif
|
||||
|
||||
// Initialize patch engine
|
||||
g_fxo->init<patch_engine>()->append(fs::get_config_dir() + "/patch.yml");
|
||||
|
||||
@ -1661,11 +1655,6 @@ void Emulator::Run()
|
||||
|
||||
idm::select<named_thread<ppu_thread>>(on_select);
|
||||
idm::select<named_thread<spu_thread>>(on_select);
|
||||
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
// Initialize debug server at the end of emu run sequence
|
||||
fxm::make<GDBDebugServer>();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Emulator::Pause()
|
||||
|
@ -616,7 +616,7 @@ struct cfg_root : cfg::node
|
||||
cfg::_bool show_trophy_popups{ this, "Show trophy popups", true};
|
||||
cfg::_bool show_shader_compilation_hint{ this, "Show shader compilation hint", true };
|
||||
cfg::_bool use_native_interface{ this, "Use native user interface", true };
|
||||
cfg::_int<1, 65535> gdb_server_port{this, "Port", 2345};
|
||||
cfg::string gdb_server{this, "GDB Server", "127.0.0.1:2345"};
|
||||
|
||||
} misc{this};
|
||||
|
||||
|
@ -80,9 +80,6 @@
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\dynamic_library.cpp" />
|
||||
<ClCompile Include="..\Utilities\GDBDebugServer.cpp">
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\JIT.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@ -369,6 +366,7 @@
|
||||
<ClCompile Include="Emu\RSX\RSXThread.cpp" />
|
||||
<ClCompile Include="Emu\Memory\vm.cpp" />
|
||||
<ClCompile Include="Emu\System.cpp" />
|
||||
<ClCompile Include="Emu\GDB.cpp" />
|
||||
<ClCompile Include="Loader\ELF.cpp" />
|
||||
<ClCompile Include="Loader\PSF.cpp" />
|
||||
<ClCompile Include="Loader\PUP.cpp" />
|
||||
@ -397,7 +395,6 @@
|
||||
<ClInclude Include="..\Utilities\date_time.h" />
|
||||
<ClInclude Include="..\Utilities\dynamic_library.h" />
|
||||
<ClInclude Include="..\Utilities\event.h" />
|
||||
<ClInclude Include="..\Utilities\GDBDebugServer.h" />
|
||||
<ClInclude Include="..\Utilities\geometry.h" />
|
||||
<ClInclude Include="..\Utilities\GSL.h" />
|
||||
<ClInclude Include="..\Utilities\hash.h" />
|
||||
@ -618,6 +615,7 @@
|
||||
<ClInclude Include="Emu\RSX\rsx_methods.h" />
|
||||
<ClInclude Include="Emu\RSX\rsx_utils.h" />
|
||||
<ClInclude Include="Emu\System.h" />
|
||||
<ClInclude Include="Emu\GDB.h" />
|
||||
<ClInclude Include="Loader\ELF.h" />
|
||||
<ClInclude Include="Loader\PSF.h" />
|
||||
<ClInclude Include="Loader\PUP.h" />
|
||||
|
@ -728,8 +728,8 @@
|
||||
<ClCompile Include="Loader\TAR.cpp">
|
||||
<Filter>Loader</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\GDBDebugServer.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
<ClCompile Include="Emu\GDB.cpp">
|
||||
<Filter>Emu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\bin_patch.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
@ -1438,8 +1438,8 @@
|
||||
<ClInclude Include="Loader\TAR.h">
|
||||
<Filter>Loader</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\GDBDebugServer.h">
|
||||
<Filter>Utilities</Filter>
|
||||
<ClInclude Include="Emu\GDB.h">
|
||||
<Filter>Emu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\bin_patch.h">
|
||||
<Filter>Utilities</Filter>
|
||||
|
Loading…
x
Reference in New Issue
Block a user