Merge pull request #477 from rofl0r/gdbstub_block
Gdbstub improvement, fix 100% cpu use in cli frontend
This commit is contained in:
commit
b8bed7082b
|
@ -67,6 +67,11 @@ extern HWND DisViewWnd[2];
|
||||||
|
|
||||||
#ifdef GDB_STUB
|
#ifdef GDB_STUB
|
||||||
#include "gdbstub.h"
|
#include "gdbstub.h"
|
||||||
|
#define GDBSTUB_MUTEX_LOCK() gdbstub_mutex_lock()
|
||||||
|
#define GDBSTUB_MUTEX_UNLOCK() gdbstub_mutex_unlock()
|
||||||
|
#else
|
||||||
|
#define GDBSTUB_MUTEX_LOCK() do {} while(0)
|
||||||
|
#define GDBSTUB_MUTEX_UNLOCK() do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//int xxctr=0;
|
//int xxctr=0;
|
||||||
|
@ -2056,9 +2061,7 @@ void NDS_debug_step()
|
||||||
template<bool FORCE>
|
template<bool FORCE>
|
||||||
void NDS_exec(s32 nb)
|
void NDS_exec(s32 nb)
|
||||||
{
|
{
|
||||||
#ifdef GDB_STUB
|
GDBSTUB_MUTEX_LOCK();
|
||||||
gdbstub_mutex_lock();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LagFrameFlag=1;
|
LagFrameFlag=1;
|
||||||
|
|
||||||
|
@ -2092,13 +2095,9 @@ void NDS_exec(s32 nb)
|
||||||
|
|
||||||
while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute)
|
while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute)
|
||||||
{
|
{
|
||||||
#ifdef GDB_STUB
|
GDBSTUB_MUTEX_UNLOCK();
|
||||||
gdbstub_mutex_unlock();
|
|
||||||
#endif
|
|
||||||
driver->EMU_DebugIdleUpdate();
|
driver->EMU_DebugIdleUpdate();
|
||||||
#ifdef GDB_STUB
|
GDBSTUB_MUTEX_LOCK();
|
||||||
gdbstub_mutex_lock();
|
|
||||||
#endif
|
|
||||||
nds_debug_continuing[0] = nds_debug_continuing[1] = true;
|
nds_debug_continuing[0] = nds_debug_continuing[1] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2199,9 +2198,7 @@ void NDS_exec(s32 nb)
|
||||||
DEBUG_Notify.NextFrame();
|
DEBUG_Notify.NextFrame();
|
||||||
if(cheats) cheats->process(CHEAT_TYPE_INTERNAL);
|
if(cheats) cheats->process(CHEAT_TYPE_INTERNAL);
|
||||||
|
|
||||||
#ifdef GDB_STUB
|
GDBSTUB_MUTEX_UNLOCK();
|
||||||
gdbstub_mutex_unlock();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int PROCNUM> static void execHardware_interrupts_core()
|
template<int PROCNUM> static void execHardware_interrupts_core()
|
||||||
|
|
|
@ -63,6 +63,21 @@
|
||||||
#ifdef GDB_STUB
|
#ifdef GDB_STUB
|
||||||
#include "../armcpu.h"
|
#include "../armcpu.h"
|
||||||
#include "../gdbstub.h"
|
#include "../gdbstub.h"
|
||||||
|
class CliDriver : public BaseDriver
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
gdbstub_handle_t __stubs[2];
|
||||||
|
public:
|
||||||
|
virtual void EMU_DebugIdleUpdate() {
|
||||||
|
gdbstub_wait(__stubs, -1L);
|
||||||
|
}
|
||||||
|
virtual void setStubs(gdbstub_handle_t stubs[2]) {
|
||||||
|
this->__stubs[0] = stubs[0];
|
||||||
|
this->__stubs[1] = stubs[1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class CliDriver : public BaseDriver {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
volatile bool execute = false;
|
volatile bool execute = false;
|
||||||
|
@ -478,6 +493,19 @@ static void desmume_cycle(struct ctrls_event_config * cfg)
|
||||||
SPU_Emulate_user();
|
SPU_Emulate_user();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
static gdbstub_handle_t setup_gdb_stub(u16 port, armcpu_t *cpu, const armcpu_memory_iface *memio, const char* desc) {
|
||||||
|
gdbstub_handle_t stub = createStub_gdb(port, cpu, memio);
|
||||||
|
if ( stub == NULL) {
|
||||||
|
fprintf( stderr, "Failed to create %s gdbstub on port %d\n", desc, port);
|
||||||
|
exit( 1);
|
||||||
|
} else {
|
||||||
|
activateStub_gdb(stub);
|
||||||
|
}
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
class configured_features my_config;
|
class configured_features my_config;
|
||||||
struct ctrls_event_config ctrls_cfg;
|
struct ctrls_event_config ctrls_cfg;
|
||||||
|
@ -568,7 +596,7 @@ int main(int argc, char ** argv) {
|
||||||
slot2_Init();
|
slot2_Init();
|
||||||
slot2_Change((NDS_SLOT2_TYPE)slot2_device_type);
|
slot2_Change((NDS_SLOT2_TYPE)slot2_device_type);
|
||||||
|
|
||||||
driver = new BaseDriver();
|
driver = new CliDriver();
|
||||||
|
|
||||||
#ifdef GDB_STUB
|
#ifdef GDB_STUB
|
||||||
gdbstub_mutex_init();
|
gdbstub_mutex_init();
|
||||||
|
@ -577,37 +605,22 @@ int main(int argc, char ** argv) {
|
||||||
* Activate the GDB stubs
|
* Activate the GDB stubs
|
||||||
* This has to come after NDS_Init() where the CPUs are set up.
|
* This has to come after NDS_Init() where the CPUs are set up.
|
||||||
*/
|
*/
|
||||||
gdbstub_handle_t arm9_gdb_stub = NULL;
|
gdbstub_handle_t stubs[2] = {};
|
||||||
gdbstub_handle_t arm7_gdb_stub = NULL;
|
|
||||||
|
|
||||||
if ( my_config.arm9_gdb_port > 0) {
|
if ( my_config.arm9_gdb_port > 0) {
|
||||||
arm9_gdb_stub = createStub_gdb( my_config.arm9_gdb_port,
|
stubs[0] = setup_gdb_stub(my_config.arm9_gdb_port,
|
||||||
&NDS_ARM9,
|
&NDS_ARM9,
|
||||||
&arm9_direct_memory_iface);
|
&arm9_direct_memory_iface, "ARM9");
|
||||||
|
|
||||||
if ( arm9_gdb_stub == NULL) {
|
|
||||||
fprintf( stderr, "Failed to create ARM9 gdbstub on port %d\n",
|
|
||||||
my_config.arm9_gdb_port);
|
|
||||||
exit( 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
activateStub_gdb( arm9_gdb_stub);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ( my_config.arm7_gdb_port > 0) {
|
if ( my_config.arm7_gdb_port > 0) {
|
||||||
arm7_gdb_stub = createStub_gdb( my_config.arm7_gdb_port,
|
stubs[1] = setup_gdb_stub(my_config.arm7_gdb_port,
|
||||||
&NDS_ARM7,
|
&NDS_ARM7,
|
||||||
&arm7_base_memory_iface);
|
&arm7_base_memory_iface, "ARM7");
|
||||||
|
|
||||||
if ( arm7_gdb_stub == NULL) {
|
|
||||||
fprintf( stderr, "Failed to create ARM7 gdbstub on port %d\n",
|
|
||||||
my_config.arm7_gdb_port);
|
|
||||||
exit( 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
activateStub_gdb( arm7_gdb_stub);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
((CliDriver*)driver)->setStubs(stubs);
|
||||||
|
gdbstub_wait_set_enabled(stubs[0], 1);
|
||||||
|
gdbstub_wait_set_enabled(stubs[1], 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( !my_config.disable_sound) {
|
if ( !my_config.disable_sound) {
|
||||||
|
@ -795,11 +808,8 @@ int main(int argc, char ** argv) {
|
||||||
uninit_joy();
|
uninit_joy();
|
||||||
|
|
||||||
#ifdef GDB_STUB
|
#ifdef GDB_STUB
|
||||||
destroyStub_gdb( arm9_gdb_stub);
|
destroyStub_gdb( stubs[0]);
|
||||||
arm9_gdb_stub = NULL;
|
destroyStub_gdb( stubs[1]);
|
||||||
|
|
||||||
destroyStub_gdb( arm7_gdb_stub);
|
|
||||||
arm7_gdb_stub = NULL;
|
|
||||||
|
|
||||||
gdbstub_mutex_destroy();
|
gdbstub_mutex_destroy();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,6 +45,22 @@ destroyStub_gdb( gdbstub_handle_t stub);
|
||||||
void
|
void
|
||||||
activateStub_gdb( gdbstub_handle_t stub);
|
activateStub_gdb( gdbstub_handle_t stub);
|
||||||
|
|
||||||
|
/* wait until either of 2 gdb stubs gives control back to the emulator.
|
||||||
|
pass a stubs[2], one of them may be NULL.
|
||||||
|
the primary usecase for this is to do a blocking wait until the stub returns
|
||||||
|
control to the emulator, in order to not waste cpu cycles.
|
||||||
|
the timeout parameter specifies the maximum time in milliseconds to wait.
|
||||||
|
if timeout == -1L, block indefinitely, if timeout == 0 return immediately,
|
||||||
|
effecting a poll.
|
||||||
|
return value: response from stub | (stub number<<31),
|
||||||
|
i.e. if stub 1 responded, the high bit is set (and so the result negative).
|
||||||
|
returns 0 on failure or if no response was available. */
|
||||||
|
int gdbstub_wait( gdbstub_handle_t *stubs, long timeout);
|
||||||
|
|
||||||
|
/* enable or disable use of the pipe for gdbstub_wait() */
|
||||||
|
void gdbstub_wait_set_enabled(gdbstub_handle_t stub, int on);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An implementation of the following functions is required
|
* An implementation of the following functions is required
|
||||||
* for the GDB stub to function.
|
* for the GDB stub to function.
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif // HOST_WINDOWS
|
#endif // HOST_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
slock *cpu_mutex = NULL;
|
slock *cpu_mutex = NULL;
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -68,6 +69,113 @@ slock *cpu_mutex = NULL;
|
||||||
#define LOG_ERROR( fmt, ...)
|
#define LOG_ERROR( fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define RECV(A,B,C) recv(A, B, C, 0)
|
||||||
|
#define SEND(A,B,C) send(A, (char*)B, C, 0)
|
||||||
|
#define CLOSESOCKET(A) closesocket(A)
|
||||||
|
#define SOCKLEN_T int
|
||||||
|
static int set_socket_nodelay(int socket) {
|
||||||
|
BOOL nodelay_opt = 1;
|
||||||
|
return setsockopt( socket, IPPROTO_TCP, TCP_NODELAY,
|
||||||
|
(char*)&nodelay_opt, sizeof( nodelay_opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int INIT_SOCKETS(void) {
|
||||||
|
/* initialise the winsock library */
|
||||||
|
WORD wVersionRequested;
|
||||||
|
WSADATA wsaData;
|
||||||
|
wVersionRequested = MAKEWORD( 2, 2 );
|
||||||
|
return WSAStartup( wVersionRequested, &wsaData );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct socket_creator_data {
|
||||||
|
SOCKET_TYPE *sock;
|
||||||
|
int port_num;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
static DWORD WINAPI
|
||||||
|
control_creator( LPVOID lpParameter)
|
||||||
|
{
|
||||||
|
struct socket_creator_data *my_data = (struct socket_creator_data *)lpParameter;
|
||||||
|
|
||||||
|
*my_data->sock = socket( PF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if ( *my_data->sock != INVALID_SOCKET) {
|
||||||
|
int connect_res;
|
||||||
|
struct sockaddr_in clientService;
|
||||||
|
|
||||||
|
clientService.sin_family = AF_INET;
|
||||||
|
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
|
||||||
|
clientService.sin_port = htons( my_data->port_num);
|
||||||
|
|
||||||
|
connect_res = connect( *my_data->sock, (SOCKADDR*) &clientService, sizeof(clientService));
|
||||||
|
|
||||||
|
if ( connect_res == SOCKET_ERROR) {
|
||||||
|
LOG_ERROR( "Failed to connect to socket\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int INIT_PIPE(SOCKET_TYPE *pipefds) {
|
||||||
|
struct socket_creator_data temp_data = {
|
||||||
|
pipefds,
|
||||||
|
24689
|
||||||
|
};
|
||||||
|
SOCKET_TYPE temp_sock = createSocket ( temp_data.port_num);
|
||||||
|
HANDLE temp_thread = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD temp_threadID;
|
||||||
|
|
||||||
|
res = -1;
|
||||||
|
|
||||||
|
if ( temp_sock != -1) {
|
||||||
|
/* create a thread to connect to this socket */
|
||||||
|
temp_thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)control_creator, &temp_data, 0, &temp_threadID);
|
||||||
|
if ( temp_thread != INVALID_HANDLE_VALUE) {
|
||||||
|
struct sockaddr_in ignore_addr;
|
||||||
|
int addr_size = sizeof( ignore_addr);
|
||||||
|
|
||||||
|
pipefds[1] = accept( temp_sock, (struct sockaddr *)&ignore_addr, &addr_size);
|
||||||
|
|
||||||
|
if ( pipefds[1] != INVALID_SOCKET) {
|
||||||
|
if (set_socket_nodelay( pipefds+1) == 0) {
|
||||||
|
closesocket( temp_sock);
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( res != 0) {
|
||||||
|
LOG_ERROR( "Failed to create pipe\n");
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define INVALID_SOCKET -1
|
||||||
|
#define RECV(A,B,C) read(A, (char*)B, C)
|
||||||
|
#define SEND(A,B,C) write(A, B, C)
|
||||||
|
#define CLOSESOCKET(A) close(A)
|
||||||
|
#define SOCKLEN_T socklen_t
|
||||||
|
static int set_socket_nodelay(int socket) {
|
||||||
|
int nodelay_opt = 1;
|
||||||
|
return setsockopt( socket, IPPROTO_TCP, TCP_NODELAY,
|
||||||
|
&nodelay_opt, sizeof( nodelay_opt));
|
||||||
|
}
|
||||||
|
#define INIT_SOCKETS() 0
|
||||||
|
static int INIT_PIPE(SOCKET_TYPE *pipefds) {
|
||||||
|
int res;
|
||||||
|
res = pipe( pipefds);
|
||||||
|
if ( res != 0) {
|
||||||
|
LOG_ERROR( "Failed to create pipe \"%s\"\n", strerror( errno));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define LITTLE_ENDIAN_TO_UINT32_T( v) (\
|
#define LITTLE_ENDIAN_TO_UINT32_T( v) (\
|
||||||
((v)[3] << 24) | \
|
((v)[3] << 24) | \
|
||||||
((v)[2] << 16) | \
|
((v)[2] << 16) | \
|
||||||
|
@ -187,28 +295,50 @@ void gdbstub_mutex_unlock()
|
||||||
static void
|
static void
|
||||||
causeQuit_gdb( struct gdb_stub_state *stub) {
|
causeQuit_gdb( struct gdb_stub_state *stub) {
|
||||||
uint8_t command = QUIT_STUB_MESSAGE;
|
uint8_t command = QUIT_STUB_MESSAGE;
|
||||||
|
SEND( stub->ctl_pipe[1], &command, 1);
|
||||||
#ifdef WIN32
|
|
||||||
send( stub->ctl_pipe[1], (char*)&command, 1, 0);
|
|
||||||
#else
|
|
||||||
write( stub->ctl_pipe[1], &command, 1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
indicateCPUStop_gdb( struct gdb_stub_state *stub) {
|
indicateCPUStop_gdb( struct gdb_stub_state *stub) {
|
||||||
uint8_t command = CPU_STOPPED_STUB_MESSAGE;
|
uint8_t command = CPU_STOPPED_STUB_MESSAGE;
|
||||||
|
SEND( stub->ctl_pipe[1], &command, 1);
|
||||||
#ifdef WIN32
|
|
||||||
send( stub->ctl_pipe[1], (char*)&command, 1, 0);
|
|
||||||
#else
|
|
||||||
write( stub->ctl_pipe[1], &command, 1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gdbstub_wait(gdbstub_handle_t *stubs, long timeout) {
|
||||||
|
struct gdb_stub_state* g[2];
|
||||||
|
g[0] = (struct gdb_stub_state *) stubs[0];
|
||||||
|
g[1] = (struct gdb_stub_state *) stubs[1];
|
||||||
|
fd_set set;
|
||||||
|
unsigned i;
|
||||||
|
struct timeval tv = {}, *tvp = &tv;
|
||||||
|
FD_ZERO(&set);
|
||||||
|
for (i = 0; i < 2; ++i)
|
||||||
|
if(g[i]) FD_SET( g[i]->info_pipe[0], &set);
|
||||||
|
if (timeout == -1L) tvp = NULL;
|
||||||
|
else {
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
}
|
||||||
|
int res = select( FD_SETSIZE, &set, NULL, NULL, tvp);
|
||||||
|
if (res <= 0) return 0;
|
||||||
|
for (i = 0; i < 2; ++i)
|
||||||
|
if ( g[i] && FD_ISSET( g[i]->info_pipe[0], &set)) {
|
||||||
|
RECV( g[i]->info_pipe[0], &res, 4);
|
||||||
|
return res | (i << 31);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdbstub_wait_set_enabled(gdbstub_handle_t stub, int on) {
|
||||||
|
struct gdb_stub_state* g = (struct gdb_stub_state *) stub;
|
||||||
|
if(g) g->info_pipe_enabled = on;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void infopipe_send(struct gdb_stub_state* g, int status) {
|
||||||
|
int resp = status;
|
||||||
|
if (g->info_pipe_enabled)
|
||||||
|
SEND(g->info_pipe[1], &resp, 4);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -383,8 +513,8 @@ readPacket_gdb( SOCKET_TYPE sock, struct packet_reader_gdb *packet) {
|
||||||
|
|
||||||
case MID_PACKET_READ_STATE:
|
case MID_PACKET_READ_STATE:
|
||||||
if ( cur_byte == '#') {
|
if ( cur_byte == '#') {
|
||||||
//DEBUG_LOG( "\nAbout to get checksum\n");
|
|
||||||
packet->buffer[packet->pos_index] = '\0';
|
packet->buffer[packet->pos_index] = '\0';
|
||||||
|
DEBUG_LOG( "\nAbout to get checksum for %s\n", packet->buffer);
|
||||||
packet->state = FIRST_CHECKSUM_READ_STATE;
|
packet->state = FIRST_CHECKSUM_READ_STATE;
|
||||||
}
|
}
|
||||||
else if ( packet->pos_index >= BUFMAX - 1) {
|
else if ( packet->pos_index >= BUFMAX - 1) {
|
||||||
|
@ -603,6 +733,7 @@ processPacket_gdb( SOCKET_TYPE sock, const uint8_t *packet,
|
||||||
/* remove the cpu stall */
|
/* remove the cpu stall */
|
||||||
stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
|
stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
|
||||||
NDS_debug_continue();
|
NDS_debug_continue();
|
||||||
|
infopipe_send(stub, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's': {
|
case 's': {
|
||||||
|
@ -627,6 +758,7 @@ processPacket_gdb( SOCKET_TYPE sock, const uint8_t *packet,
|
||||||
stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
|
stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
|
||||||
//NDS_debug_step();
|
//NDS_debug_step();
|
||||||
NDS_debug_continue();
|
NDS_debug_continue();
|
||||||
|
infopipe_send(stub, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,29 +1106,17 @@ createSocket ( int port) {
|
||||||
|
|
||||||
sock = socket (PF_INET, SOCK_STREAM, 0);
|
sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
if ( sock != INVALID_SOCKET)
|
if ( sock != INVALID_SOCKET)
|
||||||
#else
|
|
||||||
if (sock != -1)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (bind (sock, (struct sockaddr *) &bind_addr,
|
if (bind (sock, (struct sockaddr *) &bind_addr,
|
||||||
sizeof (bind_addr)) == -1) {
|
sizeof (bind_addr)) == -1) {
|
||||||
LOG_ERROR("Bind failed \"%s\" port %d\n", strerror( errno), port);
|
LOG_ERROR("Bind failed \"%s\" port %d\n", strerror( errno), port);
|
||||||
#ifdef WIN32
|
CLOSESOCKET( sock);
|
||||||
closesocket( sock);
|
|
||||||
#else
|
|
||||||
close (sock);
|
|
||||||
#endif
|
|
||||||
sock = -1;
|
sock = -1;
|
||||||
}
|
}
|
||||||
else if (listen (sock, 5) == -1) {
|
else if (listen (sock, 5) == -1) {
|
||||||
LOG_ERROR("Listen failed \"%s\"\n", strerror( errno));
|
LOG_ERROR("Listen failed \"%s\"\n", strerror( errno));
|
||||||
#ifdef WIN32
|
CLOSESOCKET( sock);
|
||||||
closesocket( sock);
|
|
||||||
#else
|
|
||||||
close (sock);
|
|
||||||
#endif
|
|
||||||
sock = -1;
|
sock = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1083,11 +1203,7 @@ WINAPI listenerThread_gdb( void *data) {
|
||||||
uint8_t ctl_command;
|
uint8_t ctl_command;
|
||||||
|
|
||||||
//DEBUG_LOG("Control message\n");
|
//DEBUG_LOG("Control message\n");
|
||||||
#ifdef WIN32
|
RECV( state->ctl_pipe[0], &ctl_command, 1);
|
||||||
recv( state->ctl_pipe[0], (char*)&ctl_command, 1, 0);
|
|
||||||
#else
|
|
||||||
read( state->ctl_pipe[0], (char*)&ctl_command, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch ( ctl_command) {
|
switch ( ctl_command) {
|
||||||
|
|
||||||
|
@ -1131,11 +1247,7 @@ WINAPI listenerThread_gdb( void *data) {
|
||||||
if ( FD_ISSET( arm_listener, &read_sock_set)) {
|
if ( FD_ISSET( arm_listener, &read_sock_set)) {
|
||||||
SOCKET_TYPE new_conn;
|
SOCKET_TYPE new_conn;
|
||||||
struct sockaddr_in gdb_addr;
|
struct sockaddr_in gdb_addr;
|
||||||
#ifdef WIN32
|
SOCKLEN_T addr_size = sizeof( gdb_addr);
|
||||||
int addr_size = sizeof( gdb_addr);
|
|
||||||
#else
|
|
||||||
socklen_t addr_size = sizeof( gdb_addr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//DEBUG_LOG("listener\n");
|
//DEBUG_LOG("listener\n");
|
||||||
|
|
||||||
|
@ -1148,24 +1260,14 @@ WINAPI listenerThread_gdb( void *data) {
|
||||||
|
|
||||||
//DEBUG_LOG("got new socket\n");
|
//DEBUG_LOG("got new socket\n");
|
||||||
if ( state->sock_fd == -1 && state->active) {
|
if ( state->sock_fd == -1 && state->active) {
|
||||||
#ifdef WIN32
|
|
||||||
BOOL nodelay_opt = 1;
|
|
||||||
#else
|
|
||||||
int nodelay_opt = 1;
|
|
||||||
#endif
|
|
||||||
int set_res;
|
int set_res;
|
||||||
|
|
||||||
//DEBUG_LOG("new connection\n");
|
//DEBUG_LOG("new connection\n");
|
||||||
|
|
||||||
close_sock = 0;
|
close_sock = 0;
|
||||||
/* make the socket NODELAY */
|
/* make the socket NODELAY */
|
||||||
#ifdef WIN32
|
set_res = set_socket_nodelay( new_conn);
|
||||||
set_res = setsockopt( new_conn, IPPROTO_TCP, TCP_NODELAY,
|
|
||||||
(char*)&nodelay_opt, sizeof( nodelay_opt));
|
|
||||||
#else
|
|
||||||
set_res = setsockopt( new_conn, IPPROTO_TCP, TCP_NODELAY,
|
|
||||||
&nodelay_opt, sizeof( nodelay_opt));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( set_res != 0) {
|
if ( set_res != 0) {
|
||||||
LOG_ERROR( "Failed to set NODELAY socket option \"%s\"\n", strerror( errno));
|
LOG_ERROR( "Failed to set NODELAY socket option \"%s\"\n", strerror( errno));
|
||||||
|
@ -1177,11 +1279,7 @@ WINAPI listenerThread_gdb( void *data) {
|
||||||
|
|
||||||
if ( close_sock) {
|
if ( close_sock) {
|
||||||
//DEBUG_LOG("closing new socket\n");
|
//DEBUG_LOG("closing new socket\n");
|
||||||
#ifdef WIN32
|
CLOSESOCKET( new_conn);
|
||||||
closesocket( new_conn);
|
|
||||||
#else
|
|
||||||
close( new_conn);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1201,11 +1299,7 @@ WINAPI listenerThread_gdb( void *data) {
|
||||||
|
|
||||||
case READ_SOCKET_ERROR:
|
case READ_SOCKET_ERROR:
|
||||||
/* close the socket */
|
/* close the socket */
|
||||||
#ifdef WIN32
|
CLOSESOCKET( gdb_sock);
|
||||||
closesocket( gdb_sock);
|
|
||||||
#else
|
|
||||||
close( gdb_sock);
|
|
||||||
#endif
|
|
||||||
state->sock_fd = -1;
|
state->sock_fd = -1;
|
||||||
FD_CLR( gdb_sock, &main_set);
|
FD_CLR( gdb_sock, &main_set);
|
||||||
break;
|
break;
|
||||||
|
@ -1259,11 +1353,7 @@ WINAPI listenerThread_gdb( void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( close_socket) {
|
if ( close_socket) {
|
||||||
#ifdef WIN32
|
CLOSESOCKET( gdb_sock);
|
||||||
closesocket( gdb_sock);
|
|
||||||
#else
|
|
||||||
close( gdb_sock);
|
|
||||||
#endif
|
|
||||||
state->sock_fd = -1;
|
state->sock_fd = -1;
|
||||||
FD_CLR( gdb_sock, &main_set);
|
FD_CLR( gdb_sock, &main_set);
|
||||||
}
|
}
|
||||||
|
@ -1279,19 +1369,11 @@ WINAPI listenerThread_gdb( void *data) {
|
||||||
|
|
||||||
/* tidy up and leave */
|
/* tidy up and leave */
|
||||||
if ( state->sock_fd != -1) {
|
if ( state->sock_fd != -1) {
|
||||||
#ifdef WIN32
|
CLOSESOCKET( state->sock_fd);
|
||||||
closesocket( state->sock_fd);
|
|
||||||
#else
|
|
||||||
close( state->sock_fd);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close the listenering sockets */
|
/* close the listenering sockets */
|
||||||
#ifdef WIN32
|
CLOSESOCKET( state->listen_fd);
|
||||||
closesocket( state->listen_fd);
|
|
||||||
#else
|
|
||||||
close( state->listen_fd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1446,46 +1528,6 @@ static const armcpu_memory_iface gdb_memory_iface = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
struct socket_creator_data {
|
|
||||||
SOCKET_TYPE *sock;
|
|
||||||
int port_num;
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
static DWORD WINAPI
|
|
||||||
control_creator( LPVOID lpParameter)
|
|
||||||
{
|
|
||||||
struct socket_creator_data *my_data = (struct socket_creator_data *)lpParameter;
|
|
||||||
|
|
||||||
*my_data->sock = socket( PF_INET, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
if ( *my_data->sock != INVALID_SOCKET) {
|
|
||||||
int connect_res;
|
|
||||||
struct sockaddr_in clientService;
|
|
||||||
|
|
||||||
clientService.sin_family = AF_INET;
|
|
||||||
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
|
|
||||||
clientService.sin_port = htons( my_data->port_num);
|
|
||||||
|
|
||||||
connect_res = connect( *my_data->sock, (SOCKADDR*) &clientService, sizeof(clientService));
|
|
||||||
|
|
||||||
if ( connect_res == SOCKET_ERROR) {
|
|
||||||
LOG_ERROR( "Failed to connect to socket\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
gdbstub_handle_t
|
gdbstub_handle_t
|
||||||
|
@ -1528,69 +1570,8 @@ createStub_gdb( uint16_t port,
|
||||||
stub->write_breakpoints = NULL;
|
stub->write_breakpoints = NULL;
|
||||||
stub->access_breakpoints = NULL;
|
stub->access_breakpoints = NULL;
|
||||||
|
|
||||||
#ifdef WIN32
|
if ( INIT_SOCKETS() != 0) return NULL;
|
||||||
/* initialise the winsock library */
|
if ( (res = INIT_PIPE(stub->ctl_pipe)) == 0 && INIT_PIPE(stub->info_pipe) == 0) {
|
||||||
{
|
|
||||||
WORD wVersionRequested;
|
|
||||||
WSADATA wsaData;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
wVersionRequested = MAKEWORD( 2, 2 );
|
|
||||||
|
|
||||||
err = WSAStartup( wVersionRequested, &wsaData );
|
|
||||||
if ( err != 0 ) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
struct socket_creator_data temp_data = {
|
|
||||||
&stub->ctl_pipe[0],
|
|
||||||
24689
|
|
||||||
};
|
|
||||||
SOCKET_TYPE temp_sock = createSocket ( temp_data.port_num);
|
|
||||||
HANDLE temp_thread = INVALID_HANDLE_VALUE;
|
|
||||||
DWORD temp_threadID;
|
|
||||||
|
|
||||||
res = -1;
|
|
||||||
|
|
||||||
if ( temp_sock != -1) {
|
|
||||||
/* create a thread to connect to this socket */
|
|
||||||
temp_thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)control_creator, &temp_data, 0, &temp_threadID);
|
|
||||||
if ( temp_thread != INVALID_HANDLE_VALUE) {
|
|
||||||
struct sockaddr_in ignore_addr;
|
|
||||||
int addr_size = sizeof( ignore_addr);
|
|
||||||
|
|
||||||
stub->ctl_pipe[1] = accept( temp_sock, (struct sockaddr *)&ignore_addr, &addr_size);
|
|
||||||
|
|
||||||
if ( stub->ctl_pipe[1] != INVALID_SOCKET) {
|
|
||||||
BOOL nodelay_opt = 1;
|
|
||||||
int set_res;
|
|
||||||
|
|
||||||
/* make the socket NODELAY */
|
|
||||||
set_res = setsockopt( stub->ctl_pipe[1], IPPROTO_TCP, TCP_NODELAY,
|
|
||||||
(char*)&nodelay_opt, sizeof( nodelay_opt));
|
|
||||||
if ( set_res == 0) {
|
|
||||||
closesocket( temp_sock);
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( res != 0) {
|
|
||||||
LOG_ERROR( "Failed to create control socket\n");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* create the control pipe */
|
|
||||||
res = pipe( stub->ctl_pipe);
|
|
||||||
|
|
||||||
if ( res != 0) {
|
|
||||||
LOG_ERROR( "Failed to create control pipe \"%s\"\n", strerror( errno));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else {
|
|
||||||
stub->active = 1;
|
stub->active = 1;
|
||||||
stub->emu_stub_state = gdb_stub_state::RUNNING_EMU_GDB_STATE;
|
stub->emu_stub_state = gdb_stub_state::RUNNING_EMU_GDB_STATE;
|
||||||
stub->ctl_stub_state = gdb_stub_state::STOPPED_GDB_STATE;
|
stub->ctl_stub_state = gdb_stub_state::STOPPED_GDB_STATE;
|
||||||
|
|
|
@ -171,8 +171,14 @@ struct gdb_stub_state {
|
||||||
/** the free breakpoint descriptor list */
|
/** the free breakpoint descriptor list */
|
||||||
struct breakpoint_gdb *free_breakpoints;
|
struct breakpoint_gdb *free_breakpoints;
|
||||||
|
|
||||||
/** the control pipe (or socket) to the gdb stub */
|
/** the control pipe (or socket) to the gdb stub. this allows to send commands to the stub. */
|
||||||
SOCKET_TYPE ctl_pipe[2];
|
SOCKET_TYPE ctl_pipe[2];
|
||||||
|
|
||||||
|
/** this pipe allows the stub to communicate to the controlling program. */
|
||||||
|
SOCKET_TYPE info_pipe[2];
|
||||||
|
|
||||||
|
/** whether above pipe is enabled */
|
||||||
|
int info_pipe_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue