📄 gdb.c
字号:
rc = GDB_ERROR_GENERAL;
break;
}
csum_rcv += char2hex( ch[i] );
}
}
if( verbose )
{
if( rc == GDB_BREAK )
{
printf( "(Break)" );
}
else
{
printf( "(From Host : %s#%c%c)", buf, ch[0], ch[1] );
}
}
if( (rc == GDB_OK) && checksum_on && (csum_rcv != csum_calc) )
rc = GDB_ERROR_CSUM;
return rc;
}
/************************************************************************
* determine_reply
************************************************************************/
static UINT32
determine_reply(
char *in_buf,
char *out_buf,
bool *ss )
{
char msg[80];
int i,t;
UINT32 count;
UINT64 val;
UINT8 data;
char ch;
UINT32 address, addr_kseg0;
char *ptr;
UINT32 reg, size;
bool binary = FALSE;
UINT32 rc;
/* Defaults */
*ss = FALSE;
/* Start sequence */
strcpy( out_buf, "$" );
out_buf+=1;
//printf3("cmd: \"%s\"\n",in_buf);
ch = *in_buf;
in_buf++;
//printf3("key = %c\n",ch);
switch( ch )
{
case '!' :
/*
* extended ops ! Use the extended remote protocol.
* Sticky -- only needs to be set once.
*/
extended = TRUE;
strcpy( out_buf, "OK" );
break;
case '?' :
/*
* last signal ? Reply the current reason for stopping.
* This is the same reply as is generated
* for step or cont : SAA where AA is the
* signal number.
*/
/* We always indicate TRAP */
strcpy( out_buf, "S05" );
break;
case 'G' :
/*
* write 32 bit regs GXX..XX Each byte of register data
* is described by two hex digits.
* reply OK for success
* ENN for an error
*/
rc = write_regs( in_buf, sizeof(UINT32) );
if( rc != GDB_OK )
return rc;
strcpy( out_buf, "OK" );
break;
case 'H' :
/*
* Set Thread (Hg | Hc) or "Write 64 bit regs" command.
*
* Set Thread request is ignored.
*
* Write 64 bit regs HXX..XX Each byte of register data
* is described by two hex digits.
* reply OK for success
* ENN for an error
*/
if( (*in_buf == 'g') || (*in_buf == 'c') )
{
/* Possibly "set thread" command */
if( strlen( in_buf ) <= 18 )
{
*out_buf = '\0';
break;
}
}
/* Write 64 bit regs command */
rc = write_regs( in_buf, sizeof(UINT64) );
if( rc != GDB_OK )
return rc;
strcpy( out_buf, "OK" );
break;
case 'g' :
/*
* read registers g[S] Registers of size S
* reply XX....X Each byte of register data
* is described by two hex digits.
* Registers are in the internal order
* for GDB, and the bytes in a register
* are in the same order the machine uses.
* or ENN for an error.
*/
if( *in_buf != '\0' )
{
size = gethex( in_buf, &ptr, &rc );
if( (rc != GDB_OK) || (*ptr != '\0') )
{
return GDB_ERROR_GENERAL;
}
if( (size != sizeof(UINT32)) &&
(size != sizeof(UINT64)) )
{
return GDB_ERROR_GENERAL;
}
}
else
size = sizeof(UINT32);
read_regs( out_buf, size );
break;
case 'r' :
/*
* Read single register (SDE extension) rNN[:S] Register NN
* of size S
*/
reg = gethex( in_buf, &ptr, &rc );
if( (rc != GDB_OK) || ( (*ptr != '\0') && (*ptr != ':') ) )
{
return GDB_ERROR_GENERAL;
}
else
{
if( *ptr == ':' )
{
ptr++;
size = gethex( ptr, &ptr, &rc );
if( (rc != GDB_OK) || (*ptr != '\0') )
{
return GDB_ERROR_GENERAL;
}
if( (size != sizeof(UINT32)) &&
(size != sizeof(UINT64)) )
{
return GDB_ERROR_GENERAL;
}
}
else
size = sizeof(UINT32);
}
setval( &out_buf, SYS_CPUREG(&context, reg), size );
*out_buf = '\0';
break;
case 'R' :
/*
* Command depends on whether we are running extended
* protocol (due to '!' command) or not.
*
* Normal : Identical to 'P', see below.
* Extended : Restart (reinitialise registers)
*/
if(extended && (*in_buf == '\0') )
{
init_data();
strcpy( out_buf, "OK" );
break;
}
/* Fallthrough !! */
case 'P' :
/*
* Write single register (SDE extension) PNN[:S]=XX Register NN
* of size S
*/
reg = gethex( in_buf, &ptr, &rc );
if( rc != GDB_OK )
return GDB_ERROR_GENERAL;
size = sizeof(UINT32); /* Default */
switch( *ptr )
{
case ':' :
ptr++;
size = gethex( ptr, &ptr, &rc );
if( (rc != GDB_OK) || (size != sizeof(UINT32)) || (*ptr != '=') )
{
return GDB_ERROR_GENERAL;
}
if( (size != sizeof(UINT32)) && (size != sizeof(UINT64)) )
{
return GDB_ERROR_GENERAL;
}
/* FALL THROUGH ! */
case '=' :
ptr++;
val = gethex( ptr, &ptr, &rc );
#ifdef EL
val = (val >> 24) & 0x000000ff // endian reversal
| (val >> 8) & 0x0000ff00
| (val << 8) & 0x00ff0000
| (val << 24) & 0xff000000;
#endif
if( (rc != GDB_OK) || (*ptr != '\0') )
{
return GDB_ERROR_GENERAL;
}
break;
default :
return GDB_ERROR_GENERAL;
}
//printf3(" register %d = %08x\n",reg,val);
SYS_CPUREG(&context, reg) = val;
strcpy( out_buf, "OK" );
break;
case 'm' :
/*
* read mem mAA..AA,LLLL AA..AA is address, LLLL is length.
* reply XX..XX XX..XX is mem contents
* Can be fewer bytes than requested
* if able to read only part of the data.
* or ENN NN is errno
*/
/**** Fall through !! ****/
case 'M' :
/*
* write mem MAA..AA,LLLL:XX..XX
* AA..AA is address,
* LLLL is number of bytes,
* XX..XX is data
* reply OK for success
* ENN for an error (this includes the case
* where only part of the data was
* written).
*/
/* Find the ',' */
ptr = strchr( in_buf, ',' );
if( ptr )
{
*ptr = '\0';
ptr++;
/* Get address */
address = gethex( in_buf, NULL, &rc );
if( rc != GDB_OK )
{
//printf3("bad address\n");
return GDB_ERROR_GENERAL;
}
/* Get count */
count = gethex( ptr, NULL, &rc );
if( rc != GDB_OK )
{
//printf3("bad count\n");
return GDB_ERROR_GENERAL;
}
}
if( !ptr )
{
//printf3("Missing comma\n");
return GDB_ERROR_GENERAL;
}
else
{
/* Validate range */
if( sys_validate_range( address,
count,
sizeof(UINT8),
FALSE ) != OK )
{
//printf3("invalid range: %08x:%08x\n",address,count);
return GDB_ERROR_ADDRESS;
}
if( ch == 'm' )
{
/* Read */
for( i=0; i<count; i++ )
{
setval( &out_buf, (UINT64)REG8(address), sizeof(UINT8) );
address++;
}
}
else
{
/* Write (M command) */
/* Find the ':' */
ptr = strchr( ptr, ':' );
if( !ptr )
{
//printf3("missing colon\n");
return GDB_ERROR_GENERAL;
}
else
ptr++;
//printf3(" write mem: %08x:%08x\n",address,count);
for( i=0; i<count; i++ )
{
rc = getval( &ptr, &val, sizeof(UINT8), FALSE );
if( rc != GDB_OK )
{
//printf3("bad value: %02x, rc = %d\n",val,rc);
return rc;
}
/* Convert to KSEG0 */
sys_kseg0( address, &addr_kseg0 );
//printf3(" Set Byte %08x = %02x\n",addr_kseg0,val);
REG8(addr_kseg0) = (UINT8)val;
/*
* Flush D-cache in order to store data in
* physical memory.
* Invalidate I-cache since new instructions may
* have been stored;
*/
sys_flush_cache_line( (void *)addr_kseg0 );
address++;
}
strcpy( out_buf, "OK" );
out_buf += 2;
}
*out_buf = '\0';
}
break;
case 'C' :
/*
* continue with Csig;AA..AA Continue with signal sig (hex signal
* signal number). If ;AA..AA is omitted,
* resume at same address.
*/
case 'S' :
/*
* step with Ssig;AA..AA Like 'C' but step not continue.
* signal
*/
/* skip sig; sequence */
ptr = strchr( in_buf, ';' );
if( ptr )
in_buf = ptr + 1;
/**** Fall through !! ****/
case 'c' :
/*
* continue cAA..AA AA..AA is address to resume
* If AA..AA is omitted,
* resume at same address.
*/
case 's' :
/*
* step sAA..AA AA..AA is address to resume
* If AA..AA is omitted,
* resume at same address.
*/
if( *in_buf != '\0' )
{
/* Get address */
address = gethex( in_buf, NULL, &rc );
if( rc != GDB_OK )
return GDB_ERROR_GENERAL;
else
{
/* Store address in epc */
context.cp0_epc = (INT64)((INT32)address);
/* Clear ERL and set EXL so that EPC will be used upon eret */
(UINT32)context.cp0_status &= ~C0_STATUS_ERL_BIT;
(UINT32)context.cp0_status |= C0_STATUS_EXL_BIT;
}
}
if( (ch == 's') || (ch =='S') )
{
if( !setup_single_step() )
return GDB_ERROR_ADDRESS;
*ss = TRUE;
}
return GDB_CONTINUE;
case 'D' :
/* detach D Reply OK. */
case 'k' :
/* kill request k */
strcpy( out_buf, "OK" ); /* Reply ignored by GBD for kill */
return GDB_KILL;
default : /* Other */
*out_buf = '\0';
break;
}
return GDB_OK;
}
/************************************************************************
* put_packet
************************************************************************/
static void
put_packet(
char *buf )
{
UINT8 csum = 0;
bool calc_csum = FALSE;
char ch[2];
char *s = buf;
while( *buf != '\0' )
{
PUTCHAR( GDB_PORT, *buf );
if( calc_csum )
csum += (UINT8)(*buf);
if( *buf == '$' )
calc_csum = TRUE;
buf++;
}
if( calc_csum )
{
ch[0] = hex2char( csum >> 4 );
ch[1] = hex2char( csum & 0xF );
PUTCHAR( GDB_PORT, '#' );
PUTCHAR( GDB_PORT, ch[0] );
PUTCHAR( GDB_PORT, ch[1] );
if( verbose )
{
printf( "(To Host : %s#%c%c)", s, ch[0], ch[1] );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -