Mercurial > ecos
diff packages/hal/common/current/src/generic-stub.c @ 0:3111d98ba7b3 ecos-v1_1-release
Initial commit of eCos version 1.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 11:16:07 +0000 |
| parents | |
| children | 443894e2e912 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/hal/common/current/src/generic-stub.c @@ -0,0 +1,1075 @@ +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for SPARC by Stu Grossman, Cygnus Support. + * Modified for generic CygMON stub support by Bob Manson, Cygnus Solutions. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * bBB..BB Set baud rate to BB..BB OK or BNN, then sets + * baud rate + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include <pkgconf/hal.h> + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include <cyg/hal/hal_stub.h> + +#define SIGHUP 1 /* hangup */ +#define SIGINT 2 /* interrupt */ +#define SIGQUIT 3 /* quit */ +#define SIGILL 4 /* illegal instruction (not reset when caught) */ +#define SIGTRAP 5 /* trace trap (not reset when caught) */ +#define SIGIOT 6 /* IOT instruction */ +#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */ +#define SIGEMT 7 /* EMT instruction */ +#define SIGFPE 8 /* floating point exception */ +#define SIGKILL 9 /* kill (cannot be caught or ignored) */ +#define SIGBUS 10 /* bus error */ +#define SIGSEGV 11 /* segmentation violation */ +#define SIGSYS 12 /* bad argument to system call */ +#define SIGPIPE 13 /* write on a pipe with no one to read it */ +#define SIGALRM 14 /* alarm clock */ +#define SIGTERM 15 /* software termination signal from kill */ + +#include <cyg/hal/hal_arch.h> // HAL header + +#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT +#define DEBUG_THREADS 1 // FIXME: put in header file? +#else +#define DEBUG_THREADS 0 // FIXME: put in header file? +#endif + +#define uint32 cyg_uint32 +#include "thread-pkts.h" + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 2048 + +static int process_exception (int sigval); +static void do_nothing (void); /* and do it gracefully */ +static int syscall_do_nothing (int); +static void kill_program (int sigval); +static void process_query (char *pkt); +static void process_set (char *pkt); + +volatile __PFI __process_exception_vec = process_exception; +volatile __PFV __process_exit_vec = do_nothing; +volatile __PFI __process_syscall_vec = syscall_do_nothing; +volatile __PFI __process_signal_vec = NULL; +volatile __PFI __interruptible_control = NULL; + +static const char hexchars[] = "0123456789abcdef"; + +extern target_register_t registers[]; /* The current saved registers */ +extern target_register_t * _registers ; +extern HAL_SavedRegisters *_hal_registers; + +int __process_target_query(char * pkt, char * out, int maxOut) +{ return 0 ; } +int __process_target_set(char * pkt, char * out, int maxout) +{ return 0 ; } +int __process_target_packet(char * pkt, char * out, int maxout) +{ return 0 ; } + + +/* Return the value corresponding to register REG of the active thread. */ +static target_register_t thread_get_register (regnames_t reg) +{ + return _registers[reg]; +} + + +/* Store VALUE in the register corresponding to WHICH of the active thread. */ +static void thread_put_register (regnames_t which, target_register_t value) +{ + _registers[which] = value; +} + + +char +__tohex (int c) +{ + return hexchars [c & 15]; +} + +target_register_t *__our_registers; + +#ifndef NUMREGS_GDB +#define NUMREGS_GDB NUMREGS +#endif + +static char *strcpy( char *s, const char *t) +{ + char *r = s; + + while( *t ) *s++ = *t++; + + return r; +} + +static int strlen( const char *s ) +{ + int r = 0; + while( *s++ ) r++; + return r; +} + +// Use this function to disable serial interrupts whenever reply +// characters are expected from GDB. The reason we want to control +// whether the target can be interrupted or not is simply that GDB on +// the host will be sending acknowledge characters/commands while the +// stub is running - if serial interrupts were still active, the +// characters would never reach the (polling) getDebugChar. +static void +interruptible (int state) +{ + static int current_state = 0; + + if (__interruptible_control) { + if (state) { + current_state--; + if (0 >= current_state) { + current_state = 0; + __interruptible_control (1); + } + } else { + current_state++; + if (1 == current_state) + __interruptible_control (0); + } + } +} + + +/* One pushback character. */ +int ungot_char = -1; + +static int +readDebugChar (void) +{ + if (ungot_char > 0) + { + int result = ungot_char; + ungot_char = -1; + return result; + } + else + return getDebugChar (); +} + +struct gdb_packet +{ + /* The checksum calculated so far. */ + int checksum; + /* The checksum we've received from the remote side. */ + int xmitcsum; + /* Contents of the accumulated packet. */ + char *contents; + /* Number of characters received. */ + int length; + /* + * state is the current state: + * 0 = looking for start of packet + * 1 = got start of packet, looking for # terminator + * 2 = looking for first byte of checksum + * 3 = looking for second byte of checksum (indicating end of packet) + */ + char state; +}; + +/* Convert ch from a hex digit to an int. */ + +int +stubhex(unsigned char ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +static void +getpacket(char *buffer) +{ + struct gdb_packet packet; + + packet.state = 0; + packet.contents = buffer; + while (__add_char_to_packet (readDebugChar () & 0x7f, &packet) != 1) + { + /* Empty */ + } +} + +int +__add_char_to_packet (int ch, struct gdb_packet *packet) +{ + if (packet->state == 0) + { + if (ch == '$') + { + packet->state = 1; + packet->length = 0; + packet->checksum = 0; + packet->xmitcsum = -1; + } + return 0; + } + + if (packet->state == 1) + { + if (ch == '#') + { + packet->contents[packet->length] = 0; + packet->state = 2; + } + else + { + if (packet->length == BUFMAX) { + packet->state = 0; + return -1; + } + packet->checksum += ch; + packet->contents[packet->length++] = ch; + } + return 0; + } + + if (packet->state == 2) + { + packet->xmitcsum = stubhex (ch) << 4; + packet->state = 3; + return 0; + } + + if (packet->state == 3) + { + packet->xmitcsum |= stubhex(ch); + if ((packet->checksum & 255) != packet->xmitcsum) + { + putDebugChar ('-'); /* failed checksum */ + packet->state = 0; + return -1; + } + else + { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (packet->contents[2] == ':') + { + int count = packet->length; + int i; + putDebugChar (packet->contents[0]); + putDebugChar (packet->contents[1]); + /* remove sequence chars from buffer */ + for (i=3; i <= count; i++) + packet->contents[i-3] = packet->contents[i]; + } + return 1; + } + } + /* We should never get here. */ + packet->state = 0; + return -1; +} + +/* send the packet in buffer. */ + +static void +putpacket(unsigned char *buffer) +{ + unsigned char checksum; + int count; + unsigned char ch; + + interruptible (0); + + /* $<packet info>#<checksum>. */ + do + { + putDebugChar ('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count])) + { + putDebugChar (ch); + checksum += ch; + count += 1; + } + + putDebugChar ('#'); + putDebugChar (hexchars[(checksum >> 4) & 0xf]); + putDebugChar (hexchars[checksum & 0xf]); + + } + while ((readDebugChar () & 0x7f) != '+'); + + interruptible (1); +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; + +/* Indicate to caller of mem2hex or hex2mem that there has been an + error. */ +volatile int __mem_fault = 0; + +static int +__copy_mem_safe (unsigned char *dst, unsigned char *src, int count) +{ + int res; + + __set_mem_fault_trap (1); + while (count--) + *(dst++) = *(src++); + res = __mem_fault; + __set_mem_fault_trap (0); + return res ? 1 : 0; +} + +int +__read_mem_safe (unsigned char *dst, target_register_t src, int count) +{ + return __copy_mem_safe (dst, (unsigned char*) src, count); +} + +int +__write_mem_safe (unsigned char *src, target_register_t dst, int count) +{ + return __copy_mem_safe ((unsigned char*) dst, src, count); +} + +/* Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null), in case of mem fault, + * return 0. + * If MAY_FAULT is non-zero, then we will handle memory faults by returning + * a 0, else treat a fault like any other fault in the stub. + */ + +unsigned char * +__mem2hex(mem, buf, count, may_fault) + unsigned char *mem; + unsigned char *buf; + int count; + int may_fault; +{ + unsigned char ch; + + __set_mem_fault_trap(may_fault); + + while (count-- > 0) + { + ch = *mem++; + if (__mem_fault) + return 0; + *buf++ = hexchars[(ch >> 4) & 0xf]; + *buf++ = hexchars[ch & 0xf]; + } + + *buf = 0; + + __set_mem_fault_trap(0); + + return buf; +} + +/* convert the hex array pointed to by buf into binary to be placed in mem + * return a pointer to the character AFTER the last byte written */ + +static char * +hex2mem(unsigned char *buf, unsigned char *mem, int count, int may_fault) +{ + int i; + unsigned char ch; + + __set_mem_fault_trap (may_fault); + + for (i=0; i<count; i++) + { + ch = stubhex(*buf++) << 4; + ch |= stubhex(*buf++); + *mem++ = ch; + if (__mem_fault) + return 0; + } + + __set_mem_fault_trap(0); + + return mem; +} + +/* + * While we find nice hex chars, build an int. + * Return number of chars processed. + */ + +static unsigned int +__hexToInt(char **ptr, target_register_t *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = stubhex(**ptr); + if (hexValue < 0) + break; + + *intValue = (*intValue << 4) | hexValue; + numChars ++; + + (*ptr)++; + } + + return (numChars); +} + +/* + * Complement of __hexToInt: take an int of size "numBits", + * convert it to a hex string. Return length of (unterminated) output. + */ + +unsigned int +__intToHex (char *ptr, target_register_t intValue, int numBits) +{ + int numChars = 0; + + if (intValue == 0) + { + *(ptr++) = '0'; + *(ptr++) = '0'; + return 2; + } + + numBits = (numBits + 7) / 8; + while (numBits) + { + int v = (intValue >> ((numBits - 1) * 8)); + if (v || (numBits == 1)) + { + v = v & 255; + *(ptr++) = __tohex ((v / 16) & 15); + *(ptr++) = __tohex (v & 15); + numChars += 2; + } + numBits--; + } + + return (numChars); +} + +void +__handle_exception (void) +{ + void breakinst(void); + int sigval; + + interruptible (0); + + // Expand the HAL_SavedRegisters structure into the GDB register + // array format. + HAL_GET_GDB_REGISTERS (®isters[0], _hal_registers); + _registers = ®isters[0]; + + /* reply to host that an exception has occurred */ + sigval = __computeSignal (__get_trap_number ()); + + if (__is_breakpoint_function ()) + __skipinst (); + +#if 0 //def SIGSYSCALL + if(sigval == SIGSYSCALL) + { + int val; + /* Do the skipinst FIRST. */ + __skipinst (); + val = __process_syscall_vec (__get_syscall_num ()); + if (val == 0) + return; + else if (val < 0) + sigval = -val; + } + +#endif + + while (__process_exception_vec (sigval)); + + + // Compact register array again. + HAL_SET_GDB_REGISTERS (_hal_registers, ®isters[0]); + + interruptible (1); +} + +static int +process_packet (char *packet) +{ +//diag_printf("pkt %s\n",packet); + 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; + } + + case 'd': + /* toggle debug flag */ + break; + + case 'q': + /* general query packet */ + process_query (&packet[1]); + break; + + case 'Q': + /* general set packet */ + process_set (&packet[1]); + break; + + case 'g': /* return the value of the CPU registers */ + { + char *ptr = remcomOutBuffer; + int x; + + for (x = 0; x < NUMREGS_GDB; x++) + { + /* We need to compensate for the value offset within the + register. */ + target_register_t addr = thread_get_register (x); + char *vptr = ((char *)&addr) + sizeof(addr) - REGSIZE(x); + + ptr = __mem2hex(vptr, ptr, REGSIZE(x), 0); + } + break; + } + + case 'P': + case 'G': /* set the value of the CPU registers - return OK */ + { + int x; + int sr = 0, er = NUMREGS_GDB; + char *ptr = &packet[1]; + + if (packet[0] == 'P') + { + target_register_t regno; + + if (__hexToInt (&ptr, ®no) + && (*ptr++ == '=')) + { + sr = regno; + er = regno + 1; + } + else + { + strcpy (remcomOutBuffer, "P01"); + break; + } + } + + for (x = sr; x < er; x++) + { + target_register_t value = 0; + + char *vptr = ((char *)&value) + sizeof(value) - REGSIZE(x); + hex2mem(ptr, vptr, REGSIZE (x), 0); + thread_put_register (x, value); + ptr += REGSIZE(x) * 2; + } + + strcpy (remcomOutBuffer, "OK"); + break; + } + + case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + /* Try to read %x,%x. */ + { + target_register_t addr, length; + char *ptr = &packet[1]; + + if (__hexToInt(&ptr, &addr) + && *ptr++ == ',' + && __hexToInt(&ptr, &length)) + { + if (__mem2hex ((char *)addr, remcomOutBuffer, length, 1)) + break; + + strcpy (remcomOutBuffer, "E03"); + } + else + strcpy(remcomOutBuffer,"E01"); + break; + } + + case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + /* Try to read '%x,%x:'. */ + { + target_register_t addr, length; + char *ptr = &packet[1]; + + if (__hexToInt(&ptr, &addr) + && *ptr++ == ',' + && __hexToInt(&ptr, &length) + && *ptr++ == ':') + { + if (hex2mem(ptr, (char *)addr, length, 1)) + 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_register_t addr; + target_register_t foo = 99999; + target_register_t sigval; + +//diag_printf("stepping\n"); + sigval = foo; + if (packet[0] == 'C' || packet[0] == 'S') + { + __hexToInt (&ptr, &sigval); + if (*ptr == ';') + ptr++; + } + + if (__hexToInt(&ptr, &addr)) + set_pc (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. + */ + + flush_i_cache (); + + if (sigval != foo) + { + if (__process_signal_vec != NULL) + { + if (! __process_signal_vec (sigval)) + return -1; + } + sigval = SIGKILL; /* Always nuke the program */ + kill_program (sigval); + return 0; + } + + /* Set machine state to force a single step. */ + if (packet[0] == 's' || packet[0] == 'S') + single_step (); + + return -1; + } + + /* kill the program */ + case 'k' : + __process_exit_vec (); + return 1; +#if 0 + case 't': /* Test feature */ + __asm__ (" std %f30,[%sp]"); + break; +#endif + case 'r': /* Reset */ + __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': /* 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; + } + } + + /* reply to the request */ + putpacket (remcomOutBuffer); + return 0; +} + +static void +send_t_packet (int sigval) +{ + __build_t_packet (sigval, remcomOutBuffer); + putpacket(remcomOutBuffer); +} + +/* + * This function does all command procesing for interfacing to gdb. + */ + +static int +process_exception (int sigval) +{ + int status; + + /* Nasty. */ + if (ungot_char < 0) + send_t_packet (sigval); + + /* Undo effect of previous single step. */ + clear_single_step (); + + do { + getpacket (remcomInBuffer); + status = process_packet (remcomInBuffer); + } while (status == 0); + + + /* Install breakpoints that may have been set to perform single stepping. */ + install_breakpoints (); + + if (status < 0) + return 0; + else + return 1; +} + +void +__send_exit_status (int status) +{ + remcomOutBuffer[0] = 'W'; + remcomOutBuffer[1] = hexchars[(status >> 4) & 0xf]; + remcomOutBuffer[2] = hexchars[status & 0xf]; + remcomOutBuffer[3] = 0; + putpacket (remcomOutBuffer); +} + +int +__get_gdb_input (char *dest, int maxlen, int block) +{ + char buf[4]; + int len, i; + + buf[0] = 'I'; + buf[1] = '0'; + buf[2] = block ? '0' : '1'; + buf[3] = 0; + putpacket (buf); + getpacket (remcomInBuffer); + if (remcomInBuffer[0] != 'I') + return -1; + len = stubhex (remcomInBuffer[1]) * 16 + stubhex (remcomInBuffer[2]); + for (i = 0; i < len; i++) + { + dest[i] = stubhex (remcomInBuffer[3 + i * 2]) * 16; + dest[i] |= stubhex (remcomInBuffer[3 + i * 2 + 1]); + } + dest[i] = '\0'; + return len; +} + +void +__output_hex_value (target_register_t i) +{ + char buf[32], *ptr=buf+31; + unsigned int x; + + *ptr = 0; + for (x = 0; x < (sizeof(i) * 2); x++) + { + *(--ptr) = hexchars[i & 15]; + i = i >> 4; + } + while (*ptr) + { + putDebugChar (*(ptr++)); + } +} + +int +__output_gdb_string(const char *str, int string_len) +{ + static char buf[1024]; + int x; + int len; + + if (string_len == 0) + string_len = strlen (str); + + len = string_len * 2 + 1; + + buf[0] = 'O'; + for (x = 0; x < string_len; x++) + { + char c = str[x]; + buf[x*2+1] = hexchars[(c >> 4) & 0xf]; + buf[x*2+2] = hexchars[c % 16]; + } + buf[x*2+1] = 0; + putpacket (buf); + return string_len; +} + +static void +do_nothing (void) +{ + /* mmmm */ +} + +static int +syscall_do_nothing (int junk) +{ + return 0; +} + +/* Start the stub running. */ +void +__switch_to_stub () +{ + __process_exception_vec = process_exception; +} + +void +ungetDebugChar (int c) +{ + ungot_char = c; +} + +static void +kill_program (int sigval) +{ + remcomOutBuffer[0] = 'X'; + remcomOutBuffer[1] = hexchars[(sigval >> 4) & 15]; + remcomOutBuffer[2] = hexchars[sigval & 15]; + remcomOutBuffer[3] = 0; + putpacket (remcomOutBuffer); +} + +/* Table used by the crc32 function to calcuate the checksum. */ +static uint32 crc32_table[256]; +static int tableInit = 0; + +/* + Calculate a CRC-32 using LEN bytes of PTR. CRC is the initial CRC + value. + PTR is assumed to be a pointer in the user program. */ + +static uint32 +crc32 (unsigned char *ptr, int len, uint32 crc) +{ + if (! tableInit) + { + /* Initialize the CRC table and the decoding table. */ + uint32 i, j; + uint32 c; + + tableInit = 1; + for (i = 0; i < 256; i++) + { + for (c = i << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1); + crc32_table[i] = c; + } + } + + __mem_fault = 0; + while (len--) + { + unsigned char ch; + + __read_mem_safe (&ch, (target_register_t) ptr, 1); + if (__mem_fault) + { + break; + } + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ ch) & 255]; + ptr++; + } + return crc; +} + +/* Handle the 'q' request */ + +static void +process_query (char *pkt) +{ + remcomOutBuffer[0] = '\0'; + if ('C' == pkt[0] && + 'R' == pkt[1] && + 'C' == pkt[2] && + ':' == pkt[3]) + { + target_register_t startmem; + target_register_t length; + uint32 our_crc; + + pkt += 4; + if (__hexToInt (&pkt, &startmem) + && *(pkt++) == ',' + && __hexToInt (&pkt, &length)) + { + our_crc = crc32 ((unsigned char *) startmem, length, 0xffffffff); + if (__mem_fault) + { + strcpy (remcomOutBuffer, "E01"); + } + else + { + int numb = __intToHex (remcomOutBuffer + 1, our_crc, 32); + remcomOutBuffer[0] = 'C'; + remcomOutBuffer[numb + 1] = 0; + } + } + return; + } + else + { + char ch ; + char * subpkt ; + ch = *pkt ; + subpkt = pkt + 1 ; + switch (ch) + { + case 'L' : /* threadlistquery */ + STUB_PKT_GETTHREADLIST (subpkt, remcomOutBuffer, 300); + break ; + case 'P' : /* Thread or process information request */ + STUB_PKT_GETTHREADINFO (subpkt, remcomOutBuffer, 300); + break ; + default: + __process_target_query (pkt, remcomOutBuffer, 300); + break ; + } + } +} + +/* Handle the 'Q' request */ + +static void +process_set (char *pkt) +{ + char ch ; + ch = *pkt ; + + switch (ch) + { + case 'p' : /* Set current process or thread */ + /* reserve the packet id even if support is not present */ + /* Dont strip the 'p' off the header, there are several variations of + this packet */ + STUB_PKT_CHANGETHREAD (pkt, remcomOutBuffer, 300) ; + break ; + default: + __process_target_set (pkt, remcomOutBuffer, 300); + break ; + } +} + +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
