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
|
||||
#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
|
||||
|
||||
//int xxctr=0;
|
||||
|
@ -2056,9 +2061,7 @@ void NDS_debug_step()
|
|||
template<bool FORCE>
|
||||
void NDS_exec(s32 nb)
|
||||
{
|
||||
#ifdef GDB_STUB
|
||||
gdbstub_mutex_lock();
|
||||
#endif
|
||||
GDBSTUB_MUTEX_LOCK();
|
||||
|
||||
LagFrameFlag=1;
|
||||
|
||||
|
@ -2092,13 +2095,9 @@ void NDS_exec(s32 nb)
|
|||
|
||||
while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute)
|
||||
{
|
||||
#ifdef GDB_STUB
|
||||
gdbstub_mutex_unlock();
|
||||
#endif
|
||||
GDBSTUB_MUTEX_UNLOCK();
|
||||
driver->EMU_DebugIdleUpdate();
|
||||
#ifdef GDB_STUB
|
||||
gdbstub_mutex_lock();
|
||||
#endif
|
||||
GDBSTUB_MUTEX_LOCK();
|
||||
nds_debug_continuing[0] = nds_debug_continuing[1] = true;
|
||||
}
|
||||
|
||||
|
@ -2199,9 +2198,7 @@ void NDS_exec(s32 nb)
|
|||
DEBUG_Notify.NextFrame();
|
||||
if(cheats) cheats->process(CHEAT_TYPE_INTERNAL);
|
||||
|
||||
#ifdef GDB_STUB
|
||||
gdbstub_mutex_unlock();
|
||||
#endif
|
||||
GDBSTUB_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
template<int PROCNUM> static void execHardware_interrupts_core()
|
||||
|
|
|
@ -63,6 +63,21 @@
|
|||
#ifdef GDB_STUB
|
||||
#include "../armcpu.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
|
||||
|
||||
volatile bool execute = false;
|
||||
|
@ -478,6 +493,19 @@ static void desmume_cycle(struct ctrls_event_config * cfg)
|
|||
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) {
|
||||
class configured_features my_config;
|
||||
struct ctrls_event_config ctrls_cfg;
|
||||
|
@ -568,7 +596,7 @@ int main(int argc, char ** argv) {
|
|||
slot2_Init();
|
||||
slot2_Change((NDS_SLOT2_TYPE)slot2_device_type);
|
||||
|
||||
driver = new BaseDriver();
|
||||
driver = new CliDriver();
|
||||
|
||||
#ifdef GDB_STUB
|
||||
gdbstub_mutex_init();
|
||||
|
@ -577,37 +605,22 @@ int main(int argc, char ** argv) {
|
|||
* Activate the GDB stubs
|
||||
* This has to come after NDS_Init() where the CPUs are set up.
|
||||
*/
|
||||
gdbstub_handle_t arm9_gdb_stub = NULL;
|
||||
gdbstub_handle_t arm7_gdb_stub = NULL;
|
||||
|
||||
gdbstub_handle_t stubs[2] = {};
|
||||
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,
|
||||
&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) {
|
||||
arm7_gdb_stub = createStub_gdb( my_config.arm7_gdb_port,
|
||||
stubs[1] = setup_gdb_stub(my_config.arm7_gdb_port,
|
||||
&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
|
||||
|
||||
if ( !my_config.disable_sound) {
|
||||
|
@ -795,11 +808,8 @@ int main(int argc, char ** argv) {
|
|||
uninit_joy();
|
||||
|
||||
#ifdef GDB_STUB
|
||||
destroyStub_gdb( arm9_gdb_stub);
|
||||
arm9_gdb_stub = NULL;
|
||||
|
||||
destroyStub_gdb( arm7_gdb_stub);
|
||||
arm7_gdb_stub = NULL;
|
||||
destroyStub_gdb( stubs[0]);
|
||||
destroyStub_gdb( stubs[1]);
|
||||
|
||||
gdbstub_mutex_destroy();
|
||||
#endif
|
||||
|
|
|
@ -45,6 +45,22 @@ destroyStub_gdb( gdbstub_handle_t stub);
|
|||
void
|
||||
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
|
||||
* for the GDB stub to function.
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#endif
|
||||
#endif // HOST_WINDOWS
|
||||
|
||||
|
||||
slock *cpu_mutex = NULL;
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -68,6 +69,113 @@ slock *cpu_mutex = NULL;
|
|||
#define LOG_ERROR( fmt, ...)
|
||||
#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) (\
|
||||
((v)[3] << 24) | \
|
||||
((v)[2] << 16) | \
|
||||
|
@ -187,28 +295,50 @@ void gdbstub_mutex_unlock()
|
|||
static void
|
||||
causeQuit_gdb( struct gdb_stub_state *stub) {
|
||||
uint8_t command = QUIT_STUB_MESSAGE;
|
||||
|
||||
#ifdef WIN32
|
||||
send( stub->ctl_pipe[1], (char*)&command, 1, 0);
|
||||
#else
|
||||
write( stub->ctl_pipe[1], &command, 1);
|
||||
#endif
|
||||
SEND( stub->ctl_pipe[1], &command, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
indicateCPUStop_gdb( struct gdb_stub_state *stub) {
|
||||
uint8_t command = CPU_STOPPED_STUB_MESSAGE;
|
||||
|
||||
#ifdef WIN32
|
||||
send( stub->ctl_pipe[1], (char*)&command, 1, 0);
|
||||
#else
|
||||
write( stub->ctl_pipe[1], &command, 1);
|
||||
#endif
|
||||
SEND( stub->ctl_pipe[1], &command, 1);
|
||||
}
|
||||
|
||||
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:
|
||||
if ( cur_byte == '#') {
|
||||
//DEBUG_LOG( "\nAbout to get checksum\n");
|
||||
packet->buffer[packet->pos_index] = '\0';
|
||||
DEBUG_LOG( "\nAbout to get checksum for %s\n", packet->buffer);
|
||||
packet->state = FIRST_CHECKSUM_READ_STATE;
|
||||
}
|
||||
else if ( packet->pos_index >= BUFMAX - 1) {
|
||||
|
@ -603,6 +733,7 @@ processPacket_gdb( SOCKET_TYPE sock, const uint8_t *packet,
|
|||
/* remove the cpu stall */
|
||||
stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
|
||||
NDS_debug_continue();
|
||||
infopipe_send(stub, 1);
|
||||
break;
|
||||
|
||||
case 's': {
|
||||
|
@ -627,6 +758,7 @@ processPacket_gdb( SOCKET_TYPE sock, const uint8_t *packet,
|
|||
stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
|
||||
//NDS_debug_step();
|
||||
NDS_debug_continue();
|
||||
infopipe_send(stub, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -974,29 +1106,17 @@ createSocket ( int port) {
|
|||
|
||||
sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
#ifdef WIN32
|
||||
if ( sock != INVALID_SOCKET)
|
||||
#else
|
||||
if (sock != -1)
|
||||
#endif
|
||||
{
|
||||
if (bind (sock, (struct sockaddr *) &bind_addr,
|
||||
sizeof (bind_addr)) == -1) {
|
||||
LOG_ERROR("Bind failed \"%s\" port %d\n", strerror( errno), port);
|
||||
#ifdef WIN32
|
||||
closesocket( sock);
|
||||
#else
|
||||
close (sock);
|
||||
#endif
|
||||
CLOSESOCKET( sock);
|
||||
sock = -1;
|
||||
}
|
||||
else if (listen (sock, 5) == -1) {
|
||||
LOG_ERROR("Listen failed \"%s\"\n", strerror( errno));
|
||||
#ifdef WIN32
|
||||
closesocket( sock);
|
||||
#else
|
||||
close (sock);
|
||||
#endif
|
||||
CLOSESOCKET( sock);
|
||||
sock = -1;
|
||||
}
|
||||
}
|
||||
|
@ -1083,11 +1203,7 @@ WINAPI listenerThread_gdb( void *data) {
|
|||
uint8_t ctl_command;
|
||||
|
||||
//DEBUG_LOG("Control message\n");
|
||||
#ifdef WIN32
|
||||
recv( state->ctl_pipe[0], (char*)&ctl_command, 1, 0);
|
||||
#else
|
||||
read( state->ctl_pipe[0], (char*)&ctl_command, 1);
|
||||
#endif
|
||||
RECV( state->ctl_pipe[0], &ctl_command, 1);
|
||||
|
||||
switch ( ctl_command) {
|
||||
|
||||
|
@ -1131,11 +1247,7 @@ WINAPI listenerThread_gdb( void *data) {
|
|||
if ( FD_ISSET( arm_listener, &read_sock_set)) {
|
||||
SOCKET_TYPE new_conn;
|
||||
struct sockaddr_in gdb_addr;
|
||||
#ifdef WIN32
|
||||
int addr_size = sizeof( gdb_addr);
|
||||
#else
|
||||
socklen_t addr_size = sizeof( gdb_addr);
|
||||
#endif
|
||||
SOCKLEN_T addr_size = sizeof( gdb_addr);
|
||||
|
||||
//DEBUG_LOG("listener\n");
|
||||
|
||||
|
@ -1148,24 +1260,14 @@ WINAPI listenerThread_gdb( void *data) {
|
|||
|
||||
//DEBUG_LOG("got new socket\n");
|
||||
if ( state->sock_fd == -1 && state->active) {
|
||||
#ifdef WIN32
|
||||
BOOL nodelay_opt = 1;
|
||||
#else
|
||||
int nodelay_opt = 1;
|
||||
#endif
|
||||
|
||||
int set_res;
|
||||
|
||||
//DEBUG_LOG("new connection\n");
|
||||
|
||||
close_sock = 0;
|
||||
/* make the socket NODELAY */
|
||||
#ifdef WIN32
|
||||
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
|
||||
set_res = set_socket_nodelay( new_conn);
|
||||
|
||||
if ( set_res != 0) {
|
||||
LOG_ERROR( "Failed to set NODELAY socket option \"%s\"\n", strerror( errno));
|
||||
|
@ -1177,11 +1279,7 @@ WINAPI listenerThread_gdb( void *data) {
|
|||
|
||||
if ( close_sock) {
|
||||
//DEBUG_LOG("closing new socket\n");
|
||||
#ifdef WIN32
|
||||
closesocket( new_conn);
|
||||
#else
|
||||
close( new_conn);
|
||||
#endif
|
||||
CLOSESOCKET( new_conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1201,11 +1299,7 @@ WINAPI listenerThread_gdb( void *data) {
|
|||
|
||||
case READ_SOCKET_ERROR:
|
||||
/* close the socket */
|
||||
#ifdef WIN32
|
||||
closesocket( gdb_sock);
|
||||
#else
|
||||
close( gdb_sock);
|
||||
#endif
|
||||
CLOSESOCKET( gdb_sock);
|
||||
state->sock_fd = -1;
|
||||
FD_CLR( gdb_sock, &main_set);
|
||||
break;
|
||||
|
@ -1259,11 +1353,7 @@ WINAPI listenerThread_gdb( void *data) {
|
|||
}
|
||||
|
||||
if ( close_socket) {
|
||||
#ifdef WIN32
|
||||
closesocket( gdb_sock);
|
||||
#else
|
||||
close( gdb_sock);
|
||||
#endif
|
||||
CLOSESOCKET( gdb_sock);
|
||||
state->sock_fd = -1;
|
||||
FD_CLR( gdb_sock, &main_set);
|
||||
}
|
||||
|
@ -1279,19 +1369,11 @@ WINAPI listenerThread_gdb( void *data) {
|
|||
|
||||
/* tidy up and leave */
|
||||
if ( state->sock_fd != -1) {
|
||||
#ifdef WIN32
|
||||
closesocket( state->sock_fd);
|
||||
#else
|
||||
close( state->sock_fd);
|
||||
#endif
|
||||
CLOSESOCKET( state->sock_fd);
|
||||
}
|
||||
|
||||
/* close the listenering sockets */
|
||||
#ifdef WIN32
|
||||
closesocket( state->listen_fd);
|
||||
#else
|
||||
close( state->listen_fd);
|
||||
#endif
|
||||
CLOSESOCKET( state->listen_fd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1446,46 +1528,6 @@ static const armcpu_memory_iface gdb_memory_iface = {
|
|||
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
|
||||
|
@ -1528,69 +1570,8 @@ createStub_gdb( uint16_t port,
|
|||
stub->write_breakpoints = NULL;
|
||||
stub->access_breakpoints = NULL;
|
||||
|
||||
#ifdef WIN32
|
||||
/* initialise the winsock library */
|
||||
{
|
||||
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 {
|
||||
if ( INIT_SOCKETS() != 0) return NULL;
|
||||
if ( (res = INIT_PIPE(stub->ctl_pipe)) == 0 && INIT_PIPE(stub->info_pipe) == 0) {
|
||||
stub->active = 1;
|
||||
stub->emu_stub_state = gdb_stub_state::RUNNING_EMU_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 */
|
||||
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];
|
||||
|
||||
/** 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