📄 generic-stub.c
字号:
strcpy (ptr, "INVALID");
return;
}
}
for (regnum = sr; regnum < er; regnum++)
{
/* We need to compensate for the value offset within the
register. */
char dummyDat[32];
target_register_t addr;
char *vptr;
int reg_valid = 1;
#ifdef TARGET_HAS_LARGE_REGISTERS
if (sizeof (target_register_t) < REGSIZE (regnum)) {
get_register_as_bytes (regnum, dummyDat);
vptr = dummyDat;
} else
#endif
{
if (_get_trace_register_hook)
reg_valid = _get_trace_register_hook (regnum, &addr);
else
{
addr = get_register (regnum);
#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
reg_valid = get_register_valid (regnum);
#endif
}
vptr = ((char *) &addr);
if (sizeof (addr) > REGSIZE(regnum)) {
/* May need to cope with endian-ness */
#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN)
vptr += sizeof (addr) - REGSIZE (regnum);
#endif
} else if (sizeof (addr) < REGSIZE (regnum)) {
int off = REGSIZE (regnum) - sizeof (addr);
int x;
char extend_val = 0;
#ifdef CYGARC_SIGN_EXTEND_REGISTERS
{
unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8
target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
if ((addr & sign_bit_mask) == sign_bit_mask)
extend_val = ~0;
}
#endif
#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN)
for (x = 0; x < off; x++)
dummyDat[x + sizeof(addr)] = extend_val;
_memcpy (dummyDat, &addr, sizeof (addr));
#else
for (x = 0; x < off; x++)
dummyDat[x] = extend_val;
_memcpy (dummyDat + off, &addr, sizeof (addr));
#endif
vptr = dummyDat;
}
}
if (reg_valid) { /* we have a valid reg value */
ptr = __mem2hex (vptr, ptr, REGSIZE (regnum), 0);
} else {
/* Trace component returned a failure code.
This means that the register value is not available.
We'll fill it with 'x's, and GDB will understand. */
_memset (ptr, 'x', 2 * REGSIZE (regnum));
ptr += 2 * REGSIZE (regnum);
}
}
}
void
stub_update_registers(char *in_ptr, char *out_ptr)
{
char *ptr = &in_ptr[1];
int x;
int sr = 0, er = NUMREGS_GDB;
if (*in_ptr == 'P') {
target_register_t regno;
if (__hexToInt (&ptr, ®no) && (*ptr++ == '=')) {
sr = regno;
er = regno + 1;
} else {
strcpy (out_ptr, "P01");
return;
}
}
for (x = sr; x < er; x++) {
target_register_t value = 0;
char *vptr;
#ifdef TARGET_HAS_LARGE_REGISTERS
if (sizeof (target_register_t) < REGSIZE (x)) {
char dummyDat [32];
__hex2mem (ptr, dummyDat, REGSIZE (x), 0);
put_register_as_bytes (x, dummyDat);
} else
#endif
{
vptr = ((char *) &value);
#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN)
vptr += sizeof (value) - REGSIZE (x);
#endif
__hex2mem (ptr, vptr, REGSIZE (x), 0);
put_register (x, value);
}
ptr += REGSIZE (x) * 2;
}
strcpy (out_ptr, "OK");
}
int
__process_packet (char *packet)
{
int is_binary = 0;
#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE)
int is_Z = 0;
#endif
__remcomOutBuffer[0] = 0;
switch (packet[0])
{
case '?':
{
int sigval = __computeSignal (__get_trap_number ());
__remcomOutBuffer[0] = 'S';
__remcomOutBuffer[1] = hexchars[(sigval >> 4) & 0xf];
__remcomOutBuffer[2] = hexchars[sigval & 0xf];
__remcomOutBuffer[3] = 0;
break;
}
#ifdef __ECOS__
#if !defined(CYG_HAL_STARTUP_RAM) // Only for ROM based stubs
#if 0 // Disable to avoid conflict with stub-breakpoint z/Z-packets
case 'z':
/* report IO buffer sizes so download can achieve optimal
download speed */
{
int i;
i = __intToHex (__remcomOutBuffer, BUFMAX, 32);
__remcomOutBuffer[i] = 0;
break;
}
#endif
case 'd':
/* toggle debug flag */
strcpy(__remcomOutBuffer, GDB_stubs_version);
break;
#endif
#endif // __ECOS__
case 'q':
/* general query packet */
process_query (&packet[1]);
break;
case 'Q':
/* general set packet */
process_set (&packet[1]);
break;
case 'p': /* return the value of a single CPU register */
case 'g': /* return the value of the CPU registers */
{
stub_format_registers(&packet[0], __remcomOutBuffer);
break;
}
case 'A': /* set program arguments */
{
#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS
if (packet[1] == '\0')
{
__free_program_args ();
strcpy (__remcomOutBuffer, "OK");
}
else
{
target_register_t arglen, argnum;
char *ptr = &packet[1];
while (1)
{
if (__hexToInt (&ptr, &arglen)
&& (*ptr++ == ',')
&& __hexToInt (&ptr, &argnum)
&& (*ptr++ == ','))
{
if (arglen > 0)
{
char *s = __add_program_arg (argnum, arglen);
if (s != NULL)
{
__hex2mem (ptr, s, arglen, 0);
}
ptr += arglen * 2;
}
if (*ptr == ',')
ptr++;
else
break;
}
else
break;
}
if (*ptr == '\0')
strcpy (__remcomOutBuffer, "OK");
else
strcpy (__remcomOutBuffer, "E01");
}
#else
strcpy (__remcomOutBuffer, "E01");
#endif
}
break;
case 'P':
case 'G': /* set the value of the CPU registers - return OK */
{
char *in_ptr = &packet[0];
char *out_ptr = __remcomOutBuffer;
stub_update_registers(in_ptr, out_ptr);
break;
}
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
/* Try to read %x,%x. */
{
target_register_t length;
char *ptr = &packet[1];
target_addr_t addr;
if (__hexToAddr (&ptr, &addr)
&& *ptr++ == ','
&& __hexToInt (&ptr, &length))
{
if (__mem2hex_safe (addr, __remcomOutBuffer, length))
break;
strcpy (__remcomOutBuffer, "E03");
}
else
strcpy (__remcomOutBuffer, "E01");
break;
}
case 'X':
/* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA */
is_binary = 1;
/* fall through */
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
/* Try to read '%x,%x:'. */
{
target_register_t length;
char *ptr = &packet[1], buf[128];
int i;
target_addr_t addr;
if (__hexToAddr (&ptr, &addr)
&& *ptr++ == ','
&& __hexToInt (&ptr, &length)
&& *ptr++ == ':')
{
/* GDB sometimes sends an impossible length */
if (length < 0 || length >= BUFMAX)
strcpy (__remcomOutBuffer, "E01");
else if (is_binary)
{
while (length > 0)
{
for (i = 0; i < sizeof(buf) && i < length; i++)
if ((buf[i] = *ptr++) == 0x7d)
buf[i] = 0x20 | (*ptr++ & 0xff);
#ifdef TARGET_HAS_HARVARD_MEMORY
if (TARGET_ADDR_IS_PROGMEM(addr)) {
if (__write_progmem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i)
break;
} else
#endif
if (__write_mem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i)
break;
length -= i;
addr += i;
}
if (length <= 0)
strcpy (__remcomOutBuffer, "OK");
else
strcpy (__remcomOutBuffer, "E03");
}
else
{
if (__hex2mem_safe (ptr, addr, length) != NULL)
strcpy (__remcomOutBuffer, "OK");
else
strcpy (__remcomOutBuffer, "E03");
}
}
else
strcpy (__remcomOutBuffer, "E02");
break;
}
case 'S':
case 's': /* sAA..AA Step from address AA..AA (optional) */
case 'C':
case 'c': /* cAA..AA Continue at address AA..AA (optional) */
/* try to read optional parameter, pc unchanged if no parm */
{
char *ptr = &packet[1];
target_addr_t addr;
target_register_t sigval = 0;
if (packet[0] == 'C' || packet[0] == 'S')
{
__hexToInt (&ptr, &sigval);
if (*ptr == ';')
ptr++;
}
if (__hexToAddr (&ptr, &addr))
set_pc ((target_register_t)TARGET_ADDR_TO_PTR(addr));
/* Need to flush the instruction cache here, as we may have
deposited a breakpoint, and the icache probably has no way of
knowing that a data ref to some location may have changed
something that is in the instruction cache. */
#ifdef __ECOS__
__data_cache (CACHE_FLUSH) ;
#endif
__instruction_cache (CACHE_FLUSH) ;
/* If we have a function to handle signals, call it. */
if (sigval != 0 && __process_signal_vec != NULL)
{
/* If 0 is returned, we either ignored the signal or invoked a user
handler. Otherwise, the user program should die. */
if (! __process_signal_vec (sigval))
sigval = 0;
}
if (sigval != 0)
{
sigval = SIGKILL; /* Always nuke the program */
__kill_program (sigval);
return 0;
}
#ifdef __ECOS__
// CASE 102327 - watchpoints fight with output, so do not step
// through $O packet output routines.
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
if ( cyg_hal_gdb_break_is_set() ) {
packet[0] = 'c'; // Force it to be a "continue" instead of step.
cyg_hal_gdb_running_step = 1; // And tell the hal_stub...
}
#endif
#endif
/* Set machine state to force a single step. */
if (packet[0] == 's' || packet[0] == 'S')
{
lock_thread_scheduler (0); /* 0 == single-step */
#ifdef __ECOS__
// PR 19845 workaround:
// Make sure the single-step magic affects the correct registers.
_registers = ®isters[0];
#endif
__single_step ();
}
else
{
lock_thread_scheduler (1); /* 1 == continue */
}
#ifdef __ECOS__
/* Need to flush the data and instruction cache here, as we may have
deposited a breakpoint in __single_step. */
__data_cache (CACHE_FLUSH) ;
__instruction_cache (CACHE_FLUSH) ;
hal_flush_output();
#endif
return -1;
}
case 'D' : /* detach */
__putpacket (__remcomOutBuffer);
/* fall through */
case 'k' : /* kill the program */
#ifdef __ECOS__
hal_flush_output();
#endif
__process_exit_vec ();
return -1;
case 'r': /* Reset */
/* With the next 'k' packet, reset the board */
__process_exit_vec = &__reset;
break;
case 'H':
STUB_PKT_CHANGETHREAD (packet+1, __remcomOutBuffer, 300) ;
break ;
case 'T' :
STUB_PKT_THREAD_ALIVE (packet+1, __remcomOutBuffer, 300) ;
break ;
case 'B':
/* breakpoint */
{
target_register_t addr;
char mode;
char *ptr = &packet[1];
if (__hexToInt (&ptr, &addr) && *(ptr++) == ',')
{
mode = *(ptr++);
if (mode == 'C')
__remove_breakpoint (addr,0);
else
__set_breakpoint (addr,0);
strcpy (__remcomOutBuffer, "OK");
}
else
{
strcpy (__remcomOutBuffer, "E01");
}
break;
}
case 'b': /* bBB... Set baud rate to BB... */
{
target_register_t baudrate;
char *ptr = &packet[1];
if (!__hexToInt (&ptr, &baudrate))
{
strcpy (__remcomOutBuffer, "B01");
break;
}
__putpacket ("OK"); /* Ack before changing speed */
__set_baud_rate (baudrate);
break;
}
#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) && (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0)
case 'Z':
is_Z = 1;
case 'z':
{
char *ptr = &packet[1];
target_register_t ztype, addr, length;
int err;
target_addr_t taddr;
if (__hexToInt (&ptr, &ztype) && *(ptr++) == ',')
{
if (__hexToAddr (&ptr, &taddr))
{
if (*(ptr++) == ',')
{
/* When there is a comma, there must be a length */
if (!__hexToInt (&ptr, &length))
{
strcpy (__remcomOutBuffer, "E02");
break;
}
}
else
length = 0;
addr = (target_register_t)TARGET_ADDR_TO_PTR(taddr);
switch (ztype)
{
case ZTYPE_SW_BREAKPOINT:
/* sw breakpoint */
if (is_Z)
err = __set_breakpoint(addr,length);
else
err = __remove_breakpoint(addr,length);
if (!err)
strcpy (__remcomOutBuffer, "OK");
else
strcpy (__remcomOutBuffer, "E02");
break;
case ZTYPE_HW_BREAKPOINT:
#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0)
if (is_Z)
err = __set_hw_breakpoint(addr, length);
else
err = __remove_hw_breakpoint(addr, length);
if (!err)
strcpy (__remcomOutBuffer, "OK");
else
#endif
strcpy (__remcomOutBuffer, "E02");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -