Skip to content
Snippets Groups Projects
Commit 59f7ab7c authored by cnlohr's avatar cnlohr
Browse files

Getting started on GDB server.

parent fe2c56a3
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,8 @@ all : $(TOOLS)
CFLAGS:=-O0 -g3 -Wall
C_S:=minichlink.c pgm-wch-linke.c pgm-esp32s2-ch32xx.c nhc-link042.c minichgdb.c
ifeq ($(OS),Windows_NT)
LDFLAGS:=-lpthread -lusb-1.0 -lsetupapi
else
......@@ -20,13 +22,14 @@ else
endif
endif
# will need mingw-w64-x86-64-dev gcc-mingw-w64-x86-64
minichlink.exe : $(C_S)
x86_64-w64-mingw32-gcc -o $@ $^ -Os -s -lsetupapi ./libusb-1.0.dll
minichlink : minichlink.c pgm-wch-linke.c pgm-esp32s2-ch32xx.c nhc-link042.c
minichlink : $(C_S)
gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) $(INCS)
minichlink.so : minichlink.c pgm-wch-linke.c pgm-esp32s2-ch32xx.c nhc-link042.c
minichlink.so : $(C_S)
gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) $(INCS) -shared -fPIC
install_udev_rules :
......
#include "minichlink.h"
#ifdef WIN32
#include <winsock2.h>
#define socklen_t uint32_t
#define SHUT_RDWR SD_BOTH
#define MSG_NOSIGNAL 0
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <poll.h>
uint16_t htons(uint16_t hostshort);
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
int listenMode; // 0 for uninit. 1 for server, 2 for client.
int serverSocket;
char gdbbuffer[65536];
uint8_t gdbchecksum = 0;
int gdbbufferplace = 0;
int gdbbufferstate = 0;
void HandleClientData( const uint8_t * rxdata, int len )
{
int pl = 0;
do
{
int c = rxdata[pl];
if( c == '$' )
{
gdbbufferplace = 0;
gdbbufferstate = 1;
}
switch( gdbbufferstate )
{
default:
break;
case 1:
if( gdbbufferplace < 65535 )
{
gdbbuffer[gdbbufferplace++] = c;
}
if( c == '#' ) gdbbufferstate = 2;
case 2:
case 3:
if( c >= '0' && c <= '9' ) c = c - '0';
else if( c >= 'A' && c <= 'F' ) c = c - 'A' + 10;
else if( c >= 'a' && c <= 'f' ) c = c - 'a' + 10;
if( gdbbufferstate == 2 ) gdbchecksum = c << 4;
else if( gdbbufferstate == 3 ) gdbchecksum = c << 4;
gdbbufferstate++;
break;
case 4:
// Got a packet?
{
int i;
for( i = 0; i < gdbbufferplace; i++ )
{
}
}
}
if( gdbbufferstate == 0 )
printf( "rececived: %d\n", rx );
int i;
for( i = 0; i < rx;i ++ )
{
printf( "%02x (%c) ", buffer[i], buffer[i] );
}
printf( "\n" );
}
#define GDBSERVER_PORT 2345
static int GDBListen()
{
struct sockaddr_in sin;
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
//Make sure the socket worked.
if( serverSocket == -1 )
{
fprintf( stderr, "Error: Cannot create socket.\n" );
return -1;
}
//Disable SO_LINGER (Well, enable it but turn it way down)
#ifdef WIN32
struct linger lx;
lx.l_onoff = 1;
lx.l_linger = 0;
setsockopt( serverSocket, SOL_SOCKET, SO_LINGER, (const char *)&lx, sizeof( lx ) );
//Enable SO_REUSEADDR
int reusevar = 1;
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reusevar, sizeof(reusevar));
#else
struct linger lx;
lx.l_onoff = 1;
lx.l_linger = 0;
setsockopt( serverSocket, SOL_SOCKET, SO_LINGER, &lx, sizeof( lx ) );
//Enable SO_REUSEADDR
int reusevar = 1;
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &reusevar, sizeof(reusevar));
#endif
//Setup socket for listening address.
memset( &sin, 0, sizeof( sin ) );
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons( GDBSERVER_PORT );
//Actually bind to the socket
if( bind( serverSocket, (struct sockaddr *) &sin, sizeof( sin ) ) == -1 )
{
fprintf( stderr, "Could not bind to socket: %d\n", GDBSERVER_PORT );
closesocket( serverSocket );
serverSocket = 0;
return -1;
}
//Finally listen.
if( listen( serverSocket, 5 ) == -1 )
{
fprintf(stderr, "Could not lieten to socket.");
closesocket( serverSocket );
serverSocket = 0;
return -1;
}
return 0;
}
int PollGDBServer()
{
if( !serverSocket ) return -4;
struct pollfd allpolls[2];
int pollct = 1;
allpolls[0].fd = serverSocket;
allpolls[0].events = POLLIN;
//Do something to watch all currently-waiting sockets.
poll( allpolls, pollct, 0 );
//If there's faults, bail.
if( allpolls[0].revents & (POLLERR|POLLHUP) )
{
closesocket( serverSocket );
if( listenMode == 1 )
{
// Some sort of weird fatal close? Is this even possible?
fprintf( stderr, "Error: serverSocke was forcibly closed\n" );
exit( -4 );
}
else if( listenMode == 2 )
{
serverSocket = 0;
listenMode = 1;
GDBListen();
}
}
if( allpolls[0].revents & POLLIN )
{
if( listenMode == 1 )
{
struct sockaddr_in tin;
socklen_t addrlen = sizeof(tin);
memset( &tin, 0, addrlen );
int tsocket = accept( serverSocket, (struct sockaddr *)&tin, &addrlen );
closesocket( serverSocket );
serverSocket = tsocket;
listenMode = 2;
gdbbufferstate = 0;
// Established.
}
else if( listenMode == 2 )
{
// Got data from a peer.
uint8_t buffer[16384];
ssize_t rx = recv( serverSocket, buffer, sizeof( buffer ), MSG_NOSIGNAL );
HandleClientData( buffer, (int)rx );
}
}
if( listenMode == 2 )
{
// Otherwise, is anything else interesting going on?
}
return 0;
}
void ExitGDBServer()
{
shutdown( serverSocket, SHUT_RDWR );
}
int SetupGDBServer()
{
#ifdef WIN32
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
fprintf( stderr, "WSAStartup failed with error: %d\n", err);
return 1;
}
}
#endif
listenMode = 1;
return GDBListen();
}
......@@ -162,8 +162,12 @@ keep_going:
break;
case 'T':
{
if( !MCF.PollTerminal )
goto unimplemented;
SetupGDBServer();
do
{
uint8_t buffer[256];
......@@ -177,6 +181,7 @@ keep_going:
{
fwrite( buffer, r, 1, stdout );
}
PollGDBServer();
} while( 1 );
}
case 's':
......@@ -201,7 +206,7 @@ keep_going:
goto unimplemented;
break;
}
case 'g':
case 'm':
{
iarg+=1;
if( iarg >= argc )
......@@ -474,14 +479,14 @@ help:
fprintf( stderr, " -D Configure NRST as GPIO\n" );
fprintf( stderr, " -d Configure NRST as NRST\n" );
fprintf( stderr, " -s [debug register] [value]\n" );
fprintf( stderr, " -g [debug register]\n" );
fprintf( stderr, " -m [debug register]\n" );
// fprintf( stderr, " -P Enable Read Protection (UNTESTED)\n" );
// fprintf( stderr, " -p Disable Read Protection (UNTESTED)\n" );
fprintf( stderr, " -w [binary image to write] [address, decimal or 0x, try0x08000000]\n" );
fprintf( stderr, " -r [output binary image] [memory address, decimal or 0x, try 0x08000000] [size, decimal or 0x, try 16384]\n" );
fprintf( stderr, " Note: for memory addresses, you can use 'flash' 'launcher' 'bootloader' 'option' 'ram' and say \"ram+0x10\" for instance\n" );
fprintf( stderr, " For filename, you can use - for raw or + for hex.\n" );
fprintf( stderr, " -T is a terminal. This MUST be the last argument. You MUST have resumed or \n" );
fprintf( stderr, " -T is a terminal. This MUST be the last argument. Also, will start a gdbserver.\n" );
return -1;
......
......@@ -123,5 +123,10 @@ int SetupAutomaticHighLevelFunctions( void * dev );
// Useful for converting numbers like 0x, etc.
int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber );
int SetupGDBServer();
int PollGDBServer();
void ExitGDBServer();
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment