Beispiel #1
0
/* The string str is prepended with the GDB printout token and sent. Required
   in traditional implementations. */
void
putDebugString (const unsigned char *str, int length)
{
        remcomOutBuffer[0] = 'O';
        mem2hex(&remcomOutBuffer[1], (unsigned char *)str, length);
        putpacket(remcomOutBuffer);
}
Beispiel #2
0
void
prom_printf(char *fmt, ...)
{
	va_list args;
	char ch, *bptr;
	int i;

	va_start(args, fmt);

#ifdef CONFIG_KGDB
	ppbuf[0] = 'O';
	i = vsprintf(ppbuf + 1, fmt, args) + 1;
#else
	i = vsprintf(ppbuf, fmt, args);
#endif

	bptr = ppbuf;

#ifdef CONFIG_KGDB
	if (kgdb_initialized) {
		printk("kgdb_initialized = %d\n", kgdb_initialized);
		putpacket(bptr, 1);
	} else
#else
	while((ch = *(bptr++)) != 0) {
		if(ch == '\n')
			prom_putchar('\r');

		prom_putchar(ch);
	}
#endif
	va_end(args);
	return;
}
void gdb_stub_send_signal(int sigval)
{
	char *ptr;
	ptr = output_buffer;

	/*
	 * Send trap type (converted to signal)
	 */
	*ptr++ = 'S';
	*ptr++ = hexchars[sigval >> 4];
	*ptr++ = hexchars[sigval & 0xf];
	*ptr++ = 0;
	putpacket(output_buffer);	/* send it off... */
}
Beispiel #4
0
/* Output string in GDB O-packet format if GDB has connected. If nothing
   output, returns 0 (caller must then handle output). */
int
kgdb_output_string (const char* s, unsigned int count)
{
	char buffer[512];

	count = (count <= (sizeof(buffer) / 2 - 2))
		? count : (sizeof(buffer) / 2 - 2);

	buffer[0] = 'O';
	mem2hex ((char *)s, &buffer[1], count);
	putpacket((unsigned char *)&buffer);

	return 1;
}
Beispiel #5
0
/* See GDB's documentation: D.3 Stop Reply Packets
 * stop reason and r can be null. */
static void send_stop_reply(int signal, const char *stop_reason, const char *r) {
	char *ptr = remcomOutBuffer;
	*ptr++ = 'T';
	append_hex_char(ptr, signal);
	if (stop_reason) {
		strcpy(ptr, stop_reason);
		ptr += strlen(stop_reason);
		*ptr++ = ':';
		strcpy(ptr, r);
		ptr += strlen(ptr);
		*ptr++ = ';';
	}
	append_hex_char(ptr, 13);
	*ptr++ = ':';
	ptr = mem2hex(&arm.reg[13], ptr, sizeof(u32));
	*ptr++ = ';';
	append_hex_char(ptr, 15);
	*ptr++ = ':';
	ptr = mem2hex(&arm.reg[15], ptr, sizeof(u32));
	*ptr++ = ';';
	*ptr = 0;
	putpacket(remcomOutBuffer);
}
/*
 * This function does all command procesing for interfacing to gdb.
 */
void
handle_exception (int exceptionVector)
{
  int sigval;
  int addr, length, reg;
  char *ptr;
  int newPC;

  gdb_i386vector = exceptionVector;

  if (remote_debug)
    printf ("vector=%d, sr=0x%x, pc=0x%x\n",
	    exceptionVector,
	    registers[PS],
	    registers[PC]);

  /* Reply to host that an exception has occurred.  Always return the
     PC, SP, and FP, since gdb always wants them.  */
  ptr = remcomOutBuffer;
  *ptr++ = 'T';
  sigval = computeSignal (exceptionVector);
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval % 16];

  *ptr++ = hexchars[ESP];
  *ptr++ = ':';
  mem2hex ((char *) &registers[ESP], ptr, REGBYTES, 0);
  ptr += REGBYTES * 2;
  *ptr++ = ';';

  *ptr++ = hexchars[EBP];
  *ptr++ = ':';
  mem2hex ((char *) &registers[EBP], ptr, REGBYTES, 0);
  ptr += REGBYTES * 2;
  *ptr++ = ';';

  *ptr++ = hexchars[PC];
  *ptr++ = ':';
  mem2hex ((char *) &registers[PC], ptr, REGBYTES, 0);
  ptr += REGBYTES * 2;
  *ptr++ = ';';

  *ptr = '\0';

  putpacket (remcomOutBuffer);

  while (1 == 1)
    {
      error = 0;
      remcomOutBuffer[0] = 0;
      getpacket (remcomInBuffer);
      switch (remcomInBuffer[0])
	{
	case '?':
	  remcomOutBuffer[0] = 'S';
	  remcomOutBuffer[1] = hexchars[sigval >> 4];
	  remcomOutBuffer[2] = hexchars[sigval % 16];
	  remcomOutBuffer[3] = 0;
	  break;
	case 'd':
	  remote_debug = !(remote_debug);	/* toggle debug flag */
	  break;
	case 'g':		/* return the value of the CPU registers */
	  mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
	  break;
	case 'G':		/* set the value of the CPU registers - return OK */
	  hex2mem (&remcomInBuffer[1], (char *) registers, NUMREGBYTES, 0);
	  strcpy (remcomOutBuffer, "OK");
	  break;

	case 'P':		/* Set specific register */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &reg)
	      && *ptr++ == '=')
	    {
	      hex2mem (ptr, (char *) &registers[reg], REGBYTES, 0);
	      strcpy (remcomOutBuffer, "OK");
	    }
	  else
	    {
	      strcpy (remcomOutBuffer, "E01");
	      debug_error ("malformed register set command; %s",
			   remcomInBuffer);
	    }
	  break;

	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
	case 'm':
	  /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &addr))
	    if (*(ptr++) == ',')
	      if (hexToInt (&ptr, &length))
		{
		  ptr = 0;
		  mem_err = 0;
		  mem2hex ((char *) addr, remcomOutBuffer, length, 1);
		  if (mem_err)
		    {
		      strcpy (remcomOutBuffer, "E03");
		      debug_error ("memory fault", 0);
		    }
		}

	  if (ptr)
	    {
	      strcpy (remcomOutBuffer, "E01");
	      debug_error ("malformed read memory command: %s", remcomInBuffer);
	    }
	  break;

	  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
	case 'M':
	  /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &addr))
	    if (*(ptr++) == ',')
	      if (hexToInt (&ptr, &length))
		if (*(ptr++) == ':')
		  {
		    mem_err = 0;
		    hex2mem (ptr, (char *) addr, length, 1);

		    if (mem_err)
		      {
			strcpy (remcomOutBuffer, "E03");
			debug_error ("memory fault", 0);
		      }
		    else
		      {
			strcpy (remcomOutBuffer, "OK");
		      }

		    ptr = 0;
		  }
	  if (ptr)
	    {
	      strcpy (remcomOutBuffer, "E02");
	      debug_error ("malformed write memory command: %s", remcomInBuffer);
	    }
	  break;

	  /* cAA..AA    Continue at address AA..AA(optional) */
	  /* sAA..AA   Step one instruction from AA..AA(optional) */
	case 'c':
	case 's':
	  /* try to read optional parameter, pc unchanged if no parm */
	  ptr = &remcomInBuffer[1];
	  if (hexToInt (&ptr, &addr))
	    registers[PC] = addr;

	  newPC = registers[PC];

	  /* clear the trace bit */
	  registers[PS] &= 0xfffffeff;

	  /* set the trace bit if we're stepping */
	  if (remcomInBuffer[0] == 's')
	    registers[PS] |= 0x100;

	  _returnFromException ();	/* this is a jump */

	  break;

	  /* Detach.  */
	case 'D':
	  putpacket (remcomOutBuffer);
	  registers[PS] &= 0xfffffeff;
	  _returnFromException ();	/* this is a jump */

	  break;

	  /* kill the program */
	case 'k':		/* do nothing */
	  break;
	}			/* switch */

      /* reply to the request */
      putpacket (remcomOutBuffer);
    }
}
Beispiel #7
0
/**
 * Returns -1 if there is a socket error.
 */
static int
processPacket_gdb( SOCKET_TYPE sock, const uint8_t *packet,
		   struct gdb_stub_state *stub) {
  //  uint8_t remcomOutBuffer[BUFMAX_GDB];
  struct debug_out_packet *out_packet = getOutPacket();
  uint8_t *out_ptr = out_packet->start_ptr;
  int send_reply = 1;
  uint32_t send_size = 0;

  DEBUG_LOG("Processing packet %c\n", packet[0]);
  gdbstub_mutex_lock();

  switch( packet[0]) {
  case 3:
    /* The break command */
    //stub->running_state = gdb_stub_state::STOPPED_GDB_STATE;
    //*ptr++ = 'S';
    //*ptr++ = hexchars[0x2 >> 4];
    //*ptr++ = hexchars[0x2 & 0xf];
    //*ptr++ = 0;
    send_reply = 0;
    break;

  case '?':
    send_size = make_stop_packet( out_ptr, stub->stop_type, stub->stop_address);
    /**ptr++ = 'S';
    *ptr++ = hexchars[stub->stop_reason >> 4];
    *ptr++ = hexchars[stub->stop_reason & 0xf];
    send_size = 3;*/
    break;

  case 'c':
  case 'k':
	stub->emu_stub_state = gdb_stub_state::RUNNING_EMU_GDB_STATE;
    stub->ctl_stub_state = gdb_stub_state::START_RUN_GDB_STATE;
    stub->main_stop_flag = 0;
    send_reply = 0;
    /* remove the cpu stall */
    stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
	NDS_debug_continue();
    break;

  case 's': {
    uint32_t instr_addr = stub->cpu_ctrl->read_reg( stub->cpu_ctrl->data, 15);
    /* Determine where the next instruction will take the CPU.
     * Execute the instruction using a copy of the CPU with a zero memory interface.
     */
    DEBUG_LOG( "Stepping instruction at %08x\n", instr_addr);

    /* install the post execution function */
    stub->step_instr_address = instr_addr;
    stub->cpu_ctrl->install_post_ex_fn( stub->cpu_ctrl->data,
                                        step_instruction_watch,
                                        stub);

    stub->emu_stub_state = gdb_stub_state::RUNNING_EMU_GDB_STATE;
    stub->ctl_stub_state = gdb_stub_state::START_RUN_GDB_STATE;
    stub->main_stop_flag = 0;
    send_reply = 0;

    /* remove the cpu stall */
    stub->cpu_ctrl->unstall( stub->cpu_ctrl->data);
	//NDS_debug_step();
	NDS_debug_continue();
    break;
  }

    /*
     * Register set
     */
  case 'P': {
    uint32_t reg;
    uint32_t value;
    const uint8_t *rx_ptr = &packet[1];

    DEBUG_LOG("Processing packet %s\n", packet);
    if ( hexToInt( &rx_ptr, &reg)) {
      if ( *rx_ptr++ == '=') {
        uint8_t tmp_mem[4];

        rx_ptr = hex2mem( rx_ptr, tmp_mem, 4);
        value = LITTLE_ENDIAN_TO_UINT32_T( tmp_mem);
        DEBUG_LOG("Setting reg %d to %08x\n", reg, value);
        if ( reg < 16)
          stub->cpu_ctrl->set_reg( stub->cpu_ctrl->data, reg, value);
        if ( reg == 25) {
          stub->cpu_ctrl->set_reg( stub->cpu_ctrl->data, 16, value);
        }

        strcpy( (char *)out_ptr, "OK");
        send_size = 2;
      }
    }
    break;
  }

  case 'm': {
    uint32_t addr = 0;
    uint32_t length = 0;
    int error01 = 1;
    const uint8_t *rx_ptr = &packet[1];

    if ( hexToInt( &rx_ptr, &addr)) {
      if ( *rx_ptr++ == ',') {
        if ( hexToInt( &rx_ptr, &length)) {
          //DEBUG_LOG("mem read from %08x (%d)\n", addr, length);
          if ( !mem2hex( stub->direct_memio, addr, out_ptr, length)) {
            strcpy ( (char *)out_ptr, "E03");
            send_size = 3;
          }
          else {
            send_size = length * 2;
          }
          error01 = 0;
        }
      }
    }
    if ( error01)
      strcpy( (char *)out_ptr,"E01");
    break;
  }

    /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
  case 'M': {
    /* Try to read '%x,%x:'.  */
    const uint8_t *rx_ptr = &packet[1];
    uint32_t addr = 0;
    uint32_t length = 0;
    int error01 = 1;
    DEBUG_LOG("Memory write %s\n", rx_ptr);
    if ( hexToInt(&rx_ptr, &addr)) {
      if ( *rx_ptr++ == ',') {
        if ( hexToInt(&rx_ptr, &length)) {
          if ( *rx_ptr++ == ':') {
            uint8_t write_byte;
            unsigned int i;
            DEBUG_LOG("Memory write of %d bytes to %08x\n",
                      length, addr);

            for ( i = 0; i < length; i++) {
              rx_ptr = hex2mem( rx_ptr, &write_byte, 1);

              stub->direct_memio->write8( stub->direct_memio->data,
                                         addr++, write_byte);
            }

            strcpy( (char *)out_ptr, "OK");
            error01 = 0;
          }
        }
        else {
          DEBUG_LOG("Failed to find length (addr %08x)\n", addr);
        }
      }
      else {
        DEBUG_LOG("expected ',' got '%c' (addr = %08x)\n", *rx_ptr, addr);
      }
    }
    else {
      DEBUG_LOG("Failed to find addr\n");
    }

    if ( error01) {
      strcpy( (char *)out_ptr, "E02");
    }
    break;
  }

  case 'Z':
  case 'z': {
    const uint8_t *rx_ptr = &packet[2];
    int remove_flag = 0;

    if ( packet[0] == 'z')
      remove_flag = 1;

    DEBUG_LOG( "%c%c packet %s (remove? %d)\n", packet[0], packet[1],
               rx_ptr, remove_flag);

    switch ( packet[1]) {

      /* all instruction breakpoints are treated the same */
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
      {
	uint32_t addr = 0;
	uint32_t length = 0;
	int error01 = 1;
        struct breakpoint_gdb **bpoint_list;

        switch ( packet[1]) {
        case '0':
        case '1':
          bpoint_list = &stub->instr_breakpoints;
          break;

        case '2':
          bpoint_list = &stub->write_breakpoints;
          break;

        case '3':
          bpoint_list = &stub->read_breakpoints;
          break;

        case '4':
          bpoint_list = &stub->access_breakpoints;
          break;
        }

        if ( *rx_ptr++ == ',') {
          DEBUG_LOG("%s\n", rx_ptr);

          if ( hexToInt( &rx_ptr, &addr)) {
            if ( *rx_ptr++ == ',') {
              DEBUG_LOG("addr %08x %s\n", addr, rx_ptr);

              if ( hexToInt( &rx_ptr, &length)) {
                if ( remove_flag) {
                  int removed = 0;
                  struct breakpoint_gdb *last_bpoint = NULL;
                  struct breakpoint_gdb *bpoint = *bpoint_list;

                  while ( bpoint != NULL && !removed) {
                    if ( bpoint->addr == addr) {
                      DEBUG_LOG("Breakpoint(%c) at %08x removed\n", packet[1], addr);
                      removed = 1;

                      if ( last_bpoint == NULL) {
                        *bpoint_list = bpoint->next;
                      }
                      else {
                        last_bpoint->next = bpoint->next;
                      }
                      bpoint->next = stub->free_breakpoints;
                      stub->free_breakpoints = bpoint;
                    }
                    last_bpoint = bpoint;
                    bpoint = bpoint->next;
                  }

                  strcpy( (char *)out_ptr, "OK");
                  send_size = 2;
                  error01 = 0;
                }
                else {
                  /* get a breakpoint descriptor from the free pool and add it to
                   * the current stub instruction breakpoint list */
                  struct breakpoint_gdb *bpoint = stub->free_breakpoints;

                  if ( bpoint != NULL) {
                    DEBUG_LOG( "Breakpoint(%c) added at %08x length %d\n",
                               packet[1],  addr, length);
                    stub->free_breakpoints = bpoint->next;

                    bpoint->addr = addr;
                    bpoint->size = length;

                    bpoint->next = *bpoint_list;
                    *bpoint_list = bpoint;

                    strcpy( (char *)out_ptr, "OK");
                    send_size = 2;
                    error01 = 0;
                  }
		}
	      }
	    }
	  }
	}

	if ( error01) {
	  strcpy( (char *)out_ptr, "E01");
	  send_size = 3;
	}
      }
      break;

    default:
      break;
    }
    break;
  }

    /*
     * Set the register values
     */
  case 'G':
    {
      int i;
      const uint8_t *rx_ptr = &packet[1];
      uint32_t reg_values[16];
      uint32_t cpsr;
      uint8_t tmp_mem[4];
      DEBUG_LOG("'G' command %s\n", rx_ptr);

      /* general purpose regs 0 to 15 */
      for ( i = 0; i < 16; i++) {
	rx_ptr = hex2mem( rx_ptr, tmp_mem, 4);

        reg_values[i] = LITTLE_ENDIAN_TO_UINT32_T( tmp_mem);
        DEBUG_LOG("Setting reg %d to %08x\n", i, reg_values[i]);
      }

      /* skip the floaing point registers and floating point status register */
      rx_ptr += 8 * (96 / 8 * 2);
      rx_ptr += 8;

      /* the CPSR register is last */
      rx_ptr = hex2mem( rx_ptr, tmp_mem, 4);
      cpsr = LITTLE_ENDIAN_TO_UINT32_T( tmp_mem);
      DEBUG_LOG("Setting cpsr to %08x\n", cpsr);

      strcpy( (char *)out_ptr, "OK");
      send_size = 2;
      break;
    }

  case 'g':		/* return the value of the CPU registers */
    {
      int i;
      int out_index = 0;
      uint32_t pc_value = stub->cpu_ctrl->read_reg( stub->cpu_ctrl->data, 15);
      uint32_t cpsr_value = stub->cpu_ctrl->read_reg( stub->cpu_ctrl->data, 16);

      DEBUG_LOG("'g' command PC = %08x\n", pc_value);

      /* general purpose regs 0 to 14 */
      for ( i = 0; i < 15; i++) {
        uint32_t reg = stub->cpu_ctrl->read_reg( stub->cpu_ctrl->data, i);
	out_ptr[out_index++] = hexchars[(reg >> 4) & 0xf];
	out_ptr[out_index++] = hexchars[(reg >> 0) & 0xf];
	out_ptr[out_index++] = hexchars[(reg >> 12) & 0xf];
	out_ptr[out_index++] = hexchars[(reg >> 8) & 0xf];
	out_ptr[out_index++] = hexchars[(reg >> 20) & 0xf];
	out_ptr[out_index++] = hexchars[(reg >> 16) & 0xf];
	out_ptr[out_index++] = hexchars[(reg >> 28) & 0xf];
	out_ptr[out_index++] = hexchars[(reg >> 24) & 0xf];
      }

      out_ptr[out_index++] = hexchars[(pc_value >> 4) & 0xf];
      out_ptr[out_index++] = hexchars[(pc_value >> 0) & 0xf];
      out_ptr[out_index++] = hexchars[(pc_value >> 12) & 0xf];
      out_ptr[out_index++] = hexchars[(pc_value >> 8) & 0xf];
      out_ptr[out_index++] = hexchars[(pc_value >> 20) & 0xf];
      out_ptr[out_index++] = hexchars[(pc_value >> 16) & 0xf];
      out_ptr[out_index++] = hexchars[(pc_value >> 28) & 0xf];
      out_ptr[out_index++] = hexchars[(pc_value >> 24) & 0xf];

      /* floating point registers (8 96bit) */
      for ( i = 0; i < 8; i++) {
	int j;
	for ( j = 0; j < (96/4); j++) {
	  out_ptr[out_index++] = '0';
	}
      }

      /* floating point status register? */
      for ( i = 0; i < 1; i++) {
	int j;
	for ( j = 0; j < 8; j++) {
	  out_ptr[out_index++] = '0';
	}
      }

      /* The CPSR */
      for ( i = 0; i < 1; i++) {
	out_ptr[out_index++] = hexchars[(cpsr_value >> 4) & 0xf];
	out_ptr[out_index++] = hexchars[(cpsr_value >> 0) & 0xf];
	out_ptr[out_index++] = hexchars[(cpsr_value >> 12) & 0xf];
	out_ptr[out_index++] = hexchars[(cpsr_value >> 8) & 0xf];
	out_ptr[out_index++] = hexchars[(cpsr_value >> 20) & 0xf];
	out_ptr[out_index++] = hexchars[(cpsr_value >> 16) & 0xf];
	out_ptr[out_index++] = hexchars[(cpsr_value >> 28) & 0xf];
	out_ptr[out_index++] = hexchars[(cpsr_value >> 24) & 0xf];
      }
      send_size = out_index;
    }
    break;
  }

  gdbstub_mutex_unlock();

  if ( send_reply) {
    return putpacket( sock, out_packet, send_size);
  }

  return 0;
}
Beispiel #8
0
static void
WINAPI listenerThread_gdb( void *data) {
  struct gdb_stub_state *state = (struct gdb_stub_state *)data;
  fd_set read_sock_set;
  fd_set main_set;
  int quit = 0;

  FD_ZERO( &main_set);

  FD_SET( state->listen_fd, &main_set);
  FD_SET( state->ctl_pipe[0], &main_set);

  while (!quit) {
    int sel_res;

    read_sock_set = main_set;

    //DEBUG_LOG("Waiting on sockets\n");

    sel_res = select( FD_SETSIZE, &read_sock_set, NULL, NULL, NULL);
    //DEBUG_LOG("sockets ready %d\n", sel_res);

    if ( sel_res > 0) {

      /* Is this a control message */
      if ( FD_ISSET( state->ctl_pipe[0], &read_sock_set)) {
	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

	switch ( ctl_command) {

	case CPU_STOPPED_STUB_MESSAGE:
	  if ( state->active &&
		  state->ctl_stub_state != gdb_stub_state::STOPPED_GDB_STATE) {
	    struct debug_out_packet *out_packet = getOutPacket();
	    uint8_t *ptr = out_packet->start_ptr;
            uint32_t send_size;

	    /* mark the stub as stopped and send the stop packet */
			state->ctl_stub_state = gdb_stub_state::STOPPED_GDB_STATE;
	    state->main_stop_flag = 1;

            send_size = make_stop_packet( ptr, state->stop_type, state->stop_address);

	    /*ptr[0] = 'S';
	    ptr[1] = hexchars[state->stop_reason >> 4];
	    ptr[2] = hexchars[state->stop_reason & 0xf];*/

	    putpacket( state->sock_fd, out_packet, send_size);
	    DEBUG_LOG( "\nBreak from Emulation\n");
	  }
	  else {
	    LOG_ERROR( "Asked to stop and already stopped\n");
	  }
	  break;

	default:
	  /* quit out */
	  quit = 1;
	  break;
	}
      }

      else {
        //struct armcpu_t *cpu = twin_states->cpus[i];
        SOCKET_TYPE arm_listener = state->listen_fd;

        /* check for a connection request */
        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

          //DEBUG_LOG("listener\n");

          /* accept the connection if we do not already have one */
          new_conn = accept( arm_listener, (struct sockaddr *)&gdb_addr,
                             &addr_size);

          if ( new_conn != -1) {
            int close_sock = 1;

            //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

              if ( set_res != 0) {
                LOG_ERROR( "Failed to set NODELAY socket option \"%s\"\n", strerror( errno));
              }

              FD_SET( new_conn, &main_set);
              state->sock_fd = new_conn;
            }

            if ( close_sock) {
              //DEBUG_LOG("closing new socket\n");
#ifdef WIN32
              closesocket( new_conn);
#else
              close( new_conn);
#endif
            }
	  }
        }

        /* handle the gdb connection */
        if ( state->sock_fd != -1 && state->active) {
          SOCKET_TYPE gdb_sock = state->sock_fd;
          if ( FD_ISSET( gdb_sock, &read_sock_set)) {
            enum read_res_gdb read_res = readPacket_gdb( gdb_sock, &state->rx_packet);

            //DEBUG_LOG("socket read %d\n", read_res);

            switch ( read_res) {
            case READ_NOT_FINISHED:
              /* do nothing here */
              break;

            case READ_SOCKET_ERROR:
              /* close the socket */
#ifdef WIN32
              closesocket( gdb_sock);
#else
              close( gdb_sock);
#endif
              state->sock_fd = -1;
              FD_CLR( gdb_sock, &main_set);
              break;

            case READ_BREAK: {
              /* break the running of the cpu */
				if ( state->ctl_stub_state != gdb_stub_state::STOPPED_GDB_STATE) {
                /* this will cause the emulation to break the execution */
                DEBUG_LOG( "Breaking execution\n");

                /* install the post execution function */
                state->cpu_ctrl->install_post_ex_fn( state->cpu_ctrl->data,
                                                     break_execution,
                                                     state);
              }
              break;
            }

            case READ_COMPLETE: {
              uint8_t reply;
              int write_res;
              int process_packet = 0;
              int close_socket = 0;
              struct packet_reader_gdb *packet = &state->rx_packet;

              if ( state->ctl_stub_state != gdb_stub_state::STOPPED_GDB_STATE) {
                /* not ready to process packet yet, send a bad reply */
                reply = '-';
              }
              else {
                /* send a reply based on the checksum and if okay process the packet */
                if ( packet->read_checksum == packet->checksum) {
                  reply = '+';
                  process_packet = 1;
                }
                else {
                  reply = '-';
                }
              }

              write_res = send( gdb_sock, (char*)&reply, 1, 0);
              
              if ( write_res != 1) {
                close_socket = 1;
              }
              else {
                if ( processPacket_gdb( gdb_sock, state->rx_packet.buffer,
                                        state) == -1) {
                  close_socket = 1;
                }
              }

              if ( close_socket) {
#ifdef WIN32
                closesocket( gdb_sock);
#else
                close( gdb_sock);
#endif
                state->sock_fd = -1;
                FD_CLR( gdb_sock, &main_set);
              }
              break;
            }
            }
	  }
	}
      }
    }
  }


  /* tidy up and leave */
  if ( state->sock_fd != -1) {
#ifdef WIN32
    closesocket( state->sock_fd);
#else
    close( state->sock_fd);
#endif
  }

  /* close the listenering sockets */
#ifdef WIN32
  closesocket( state->listen_fd);
#else
  close( state->listen_fd);
#endif

  return;
}
Beispiel #9
0
/*
 * This function does all command procesing for interfacing to gdb.
 */
void
gdb_handle_exception (db_regs_t *raw_regs, int type, int code)
{
  int    sigval;
  long   addr, length;
  char * ptr;
  struct alpharegs {
    u_int64_t r[32];
    u_int64_t f[32];
    u_int64_t pc, vfp;
  };
  static struct alpharegs registers;
  int i;

  clear_single_step(raw_regs);

  bzero(&registers, sizeof registers);

  /*
   * Map trapframe to registers.
   * Ignore float regs for now.
   */
  for (i = 0; i < FRAME_SIZE; i++)
    if (tf2gdb[i] >= 0)
      registers.r[tf2gdb[i]] = raw_regs->tf_regs[i];
  registers.pc = raw_regs->tf_regs[FRAME_PC];

  /* reply to host that an exception has occurred */
  sigval = computeSignal (type, code);
  ptr = remcomOutBuffer;

  *ptr++ = 'T';
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval & 0xf];

  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.pc, ptr, 8);
  *ptr++ = ';';

  *ptr++ = hexchars[FP >> 4];
  *ptr++ = hexchars[FP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.r[FP], ptr, 8);
  *ptr++ = ';';

  *ptr++ = hexchars[SP >> 4];
  *ptr++ = hexchars[SP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.r[SP], ptr, 8);
  *ptr++ = ';';

  *ptr++ = 0;

  putpacket (remcomOutBuffer);

  while (1)
    {
      remcomOutBuffer[0] = 0;

      getpacket (remcomInBuffer);
      switch (remcomInBuffer[0]) 
	{
	case '?':
	  remcomOutBuffer[0] = 'S';
	  remcomOutBuffer[1] = hexchars[sigval >> 4];
	  remcomOutBuffer[2] = hexchars[sigval % 16];
	  remcomOutBuffer[3] = 0;
	  break;

	case 'D':		/* detach; say OK and turn off gdb */
	  putpacket(remcomOutBuffer);
	  boothowto &= ~RB_GDB;
	  return;

	case 'k':
	  prom_halt();
	  /*NOTREACHED*/
	  break;

	case 'g':		/* return the value of the CPU registers */
	  mem2hex ((vm_offset_t)&registers, remcomOutBuffer, NUMREGBYTES);
	  break;

	case 'G':		/* set the value of the CPU registers - return OK */
	  hex2mem (&remcomInBuffer[1], (vm_offset_t)&registers, NUMREGBYTES);
	  strcpy (remcomOutBuffer, "OK");
	  break;

	case 'P':		/* Set the value of one register */
	  {
	    long regno;

	    ptr = &remcomInBuffer[1];

	    if (hexToInt (&ptr, &regno)
		&& *ptr++ == '='
		&& regno < NUM_REGS)
	      {
		hex2mem (ptr, (vm_offset_t)&registers + regno * 8, 8);
		strcpy(remcomOutBuffer,"OK");
	      }
	    else
	      strcpy (remcomOutBuffer, "P01");
	    break;
	  }
	case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
	  /* Try to read %x,%x.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt (&ptr, &addr)
	      && *(ptr++) == ','
	      && hexToInt (&ptr, &length))
	    {
	      if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      break;
	    }
	  else
	    strcpy (remcomOutBuffer, "E01");
	  break;

	case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */

	  /* Try to read '%x,%x:'.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt(&ptr,&addr)
	      && *(ptr++) == ','
	      && hexToInt(&ptr, &length)
	      && *(ptr++) == ':')
	    {
	      if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      else
		strcpy (remcomOutBuffer, "OK");
	    }
	  else
	    strcpy (remcomOutBuffer, "E02");
	  break;

	  /* cAA..AA    Continue at address AA..AA(optional) */
	  /* sAA..AA   Step one instruction from AA..AA(optional) */
	case 'c' :
	case 's' :
	  /* try to read optional parameter, pc unchanged if no parm */

	  ptr = &remcomInBuffer[1];
	  if (hexToInt(&ptr,&addr))
	    registers.pc = addr;

	  /*
	   * Map gdb registers back to trapframe (ignoring fp regs).
	   */
	  for (i = 0; i < NUM_REGS; i++)
	    if (gdb2tf[i] >= 0)
	      raw_regs->tf_regs[gdb2tf[i]] = registers.r[i];
	  raw_regs->tf_regs[FRAME_PC] = registers.pc;

	  if (remcomInBuffer[0] == 's')
	    if (!set_single_step(raw_regs))
	      printf("Can't set single step breakpoint\n");

	  return;

	} /* switch */

      /* reply to the request */
      putpacket (remcomOutBuffer);
    }
}
Beispiel #10
0
/*
 * This function does all command processing for interfacing to gdb.
 */
static int
handle_exception (struct pt_regs *regs)
{
	int addr;
	int length;
	char *ptr;
	kgdb_data kd;
	int i;

	if (!initialized) {
		printf("kgdb: exception before kgdb is initialized! huh?\n");
		return (0);
	}

	/* probably should check which exception occured as well */
	if (longjmp_on_fault) {
		longjmp_on_fault = 0;
		kgdb_longjmp(error_jmp_buf, KGDBERR_MEMFAULT);
		panic("kgdb longjump failed!\n");
	}

	if (kgdb_active) {
		printf("kgdb: unexpected exception from within kgdb\n");
		return (0);
	}
	kgdb_active = 1;

	kgdb_interruptible(0);

	printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));

	if (kgdb_setjmp(error_jmp_buf) != 0)
		panic("kgdb: error or fault in entry init!\n");

	kgdb_enter(regs, &kd);

	if (first_entry) {
		/*
		 * the first time we enter kgdb, we save the processor
		 * state so that we can return to the monitor if the
		 * remote end quits gdb (or at least, tells us to quit
		 * with the 'k' packet)
		 */
		entry_regs = *regs;
		first_entry = 0;
	}

	ptr = remcomOutBuffer;

	*ptr++ = 'T';

	*ptr++ = hexchars[kd.sigval >> 4];
	*ptr++ = hexchars[kd.sigval & 0xf];

	for (i = 0; i < kd.nregs; i++) {
		kgdb_reg *rp = &kd.regs[i];

		*ptr++ = hexchars[rp->num >> 4];
		*ptr++ = hexchars[rp->num & 0xf];
		*ptr++ = ':';
		ptr = (char *)mem2hex((char *)&rp->val, ptr, 4);
		*ptr++ = ';';
	}

	*ptr = 0;

#ifdef KGDB_DEBUG
	if (kdebug)
		printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
#endif

	putpacket((unsigned char *)&remcomOutBuffer);

	while (1) {
		volatile int errnum;

		remcomOutBuffer[0] = 0;

		getpacket(remcomInBuffer);
		ptr = &remcomInBuffer[1];

#ifdef KGDB_DEBUG
		if (kdebug)
			printf("kgdb:  remcomInBuffer: %s\n", remcomInBuffer);
#endif

		errnum = kgdb_setjmp(error_jmp_buf);

		if (errnum == 0) switch (remcomInBuffer[0]) {

		case '?':               /* report most recent signal */
			remcomOutBuffer[0] = 'S';
			remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
			remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
			remcomOutBuffer[3] = 0;
			break;

#ifdef KGDB_DEBUG
		case 'd':
			/* toggle debug flag */
			kdebug ^= 1;
			break;
#endif

		case 'g':	/* return the value of the CPU registers. */
			length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
			mem2hex(remcomRegBuffer, remcomOutBuffer, length);
			break;

		case 'G':   /* set the value of the CPU registers */
			length = strlen(ptr);
			if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
			hex2mem(ptr, remcomRegBuffer, length/2);
			kgdb_putregs(regs, remcomRegBuffer, length/2);
			strcpy(remcomOutBuffer,"OK");
			break;

		case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
				/* Try to read %x,%x.  */

			if (hexToInt(&ptr, &addr)
			    && *ptr++ == ','
			    && hexToInt(&ptr, &length))	{
				mem2hex((char *)addr, remcomOutBuffer, length);
			} else {
				kgdb_error(KGDBERR_BADPARAMS);
			}
			break;

		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
			/* Try to read '%x,%x:'.  */

			if (hexToInt(&ptr, &addr)
			    && *ptr++ == ','
			    && hexToInt(&ptr, &length)
			    && *ptr++ == ':') {
				hex2mem(ptr, (char *)addr, length);
				strcpy(remcomOutBuffer, "OK");
			} else {
				kgdb_error(KGDBERR_BADPARAMS);
			}
			break;


		case 'k':    /* kill the program, actually return to monitor */
			kd.extype = KGDBEXIT_KILL;
			*regs = entry_regs;
			first_entry = 1;
			goto doexit;

		case 'C':    /* CSS  continue with signal SS */
			*ptr = '\0';	/* ignore the signal number for now */
			/* fall through */

		case 'c':    /* cAA..AA  Continue; address AA..AA optional */
			/* try to read optional parameter, pc unchanged if no parm */
			kd.extype = KGDBEXIT_CONTINUE;

			if (hexToInt(&ptr, &addr)) {
				kd.exaddr = addr;
				kd.extype |= KGDBEXIT_WITHADDR;
			}

			goto doexit;

		case 'S':    /* SSS  single step with signal SS */
			*ptr = '\0';	/* ignore the signal number for now */
			/* fall through */

		case 's':
			kd.extype = KGDBEXIT_SINGLE;

			if (hexToInt(&ptr, &addr)) {
				kd.exaddr = addr;
				kd.extype |= KGDBEXIT_WITHADDR;
			}

		doexit:
/* 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.
 */
			kgdb_flush_cache_all();
			kgdb_exit(regs, &kd);
			kgdb_active = 0;
			kgdb_interruptible(1);
			return (1);

		case 'r':		/* Reset (if user process..exit ???)*/
			panic("kgdb reset.");
			break;

		case 'P':    /* Pr=v  set reg r to value v (r and v are hex) */
			if (hexToInt(&ptr, &addr)
			    && *ptr++ == '='
			    && ((length = strlen(ptr)) & 1) == 0) {
				hex2mem(ptr, remcomRegBuffer, length/2);
				kgdb_putreg(regs, addr,
					remcomRegBuffer, length/2);
				strcpy(remcomOutBuffer,"OK");
			} else {
				kgdb_error(KGDBERR_BADPARAMS);
			}
			break;
		}			/* switch */

		if (errnum != 0)
			sprintf(remcomOutBuffer, "E%02d", errnum);

#ifdef KGDB_DEBUG
		if (kdebug)
			printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
#endif

		/* reply to the request */
		putpacket((unsigned char *)&remcomOutBuffer);

	} /* while(1) */
}
Beispiel #11
0
/*
 * This function does all command procesing for interfacing to gdb.
 */
void handle_exception (int exceptionVector)
{
    int sigval, stepping;
    int addr, length;
    char *ptr;
    int newPC;
    Frame *frame;

    if (remote_debug)
        printf ("vector=%d, sr=0x%x, pc=0x%x\n",
                exceptionVector, registers[PS], registers[PC]);

    /* reply to host that an exception has occurred */
    sigval = computeSignal (exceptionVector);
    remcomOutBuffer[0] = 'S';
    remcomOutBuffer[1] = hexchars[sigval >> 4];
    remcomOutBuffer[2] = hexchars[sigval % 16];
    remcomOutBuffer[3] = 0;

    putpacket (remcomOutBuffer);

    stepping = 0;

    while (1 == 1)
    {
        remcomOutBuffer[0] = 0;
        ptr = getpacket ();
        switch (*ptr++)
        {
        case '?':
            remcomOutBuffer[0] = 'S';
            remcomOutBuffer[1] = hexchars[sigval >> 4];
            remcomOutBuffer[2] = hexchars[sigval % 16];
            remcomOutBuffer[3] = 0;
            break;
        case 'd':
            remote_debug = !(remote_debug);	/* toggle debug flag */
            break;
        case 'g':		/* return the value of the CPU registers */
            mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES);
            break;
        case 'G':		/* set the value of the CPU registers - return OK */
            hex2mem (ptr, (char *) registers, NUMREGBYTES);
            strcpy (remcomOutBuffer, "OK");
            break;

        /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
        case 'm':
            if (setjmp (remcomEnv) == 0)
            {
                exceptionHandler (2, handle_buserror);

                /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
                if (hexToInt (&ptr, &addr))
                    if (*(ptr++) == ',')
                        if (hexToInt (&ptr, &length))
                        {
                            ptr = 0;
                            mem2hex ((char *) addr, remcomOutBuffer, length);
                        }

                if (ptr)
                {
                    strcpy (remcomOutBuffer, "E01");
                }
            }
            else
            {
                exceptionHandler (2, _catchException);
                strcpy (remcomOutBuffer, "E03");
                debug_error ("%s","bus error");
            }

            /* restore handler for bus error */
            exceptionHandler (2, _catchException);
            break;

        /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
        case 'M':
            if (setjmp (remcomEnv) == 0)
            {
                exceptionHandler (2, handle_buserror);

                /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
                if (hexToInt (&ptr, &addr))
                    if (*(ptr++) == ',')
                        if (hexToInt (&ptr, &length))
                            if (*(ptr++) == ':')
                            {
                                hex2mem (ptr, (char *) addr, length);
                                ptr = 0;
                                strcpy (remcomOutBuffer, "OK");
                            }
                if (ptr)
                {
                    strcpy (remcomOutBuffer, "E02");
                }
            }
            else
            {
                exceptionHandler (2, _catchException);
                strcpy (remcomOutBuffer, "E03");
                debug_error ("%s","bus error");
            }

            /* restore handler for bus error */
            exceptionHandler (2, _catchException);
            break;

        /* cAA..AA    Continue at address AA..AA(optional) */
        /* sAA..AA   Step one instruction from AA..AA(optional) */
        case 's':
            stepping = 1;
        case 'c':
            /* try to read optional parameter, pc unchanged if no parm */
            if (hexToInt (&ptr, &addr))
                registers[PC] = addr;

            newPC = registers[PC];

            /* clear the trace bit */
            registers[PS] &= 0x7fff;

            /* set the trace bit if we're stepping */
            if (stepping)
                registers[PS] |= 0x8000;

            /*
             * look for newPC in the linked list of exception frames.
             * if it is found, use the old frame it.  otherwise,
             * fake up a dummy frame in returnFromException().
             */
            if (remote_debug)
                printf ("new pc = 0x%x\n", newPC);
            frame = lastFrame;
            while (frame)
            {
                if (remote_debug)
                    printf ("frame at 0x%x has pc=0x%x, except#=%d\n",
                            frame, frame->exceptionPC, frame->exceptionVector);
                if (frame->exceptionPC == newPC)
                    break;		/* bingo! a match */
                /*
                 * for a breakpoint instruction, the saved pc may
                 * be off by two due to re-executing the instruction
                 * replaced by the trap instruction.  Check for this.
                 */
                if ((frame->exceptionVector == 33) &&
                        (frame->exceptionPC == (newPC + 2)))
                    break;
                if (frame == frame->previous)
                {
                    frame = 0;	/* no match found */
                    break;
                }
                frame = frame->previous;
            }

            /*
             * If we found a match for the PC AND we are not returning
             * as a result of a breakpoint (33),
             * trace exception (9), nmi (31), jmp to
             * the old exception handler as if this code never ran.
             */
            if (frame)
            {
                if ((frame->exceptionVector != 9) &&
                        (frame->exceptionVector != 31) &&
                        (frame->exceptionVector != 33))
                {
                    /*
                     * invoke the previous handler.
                     */
                    if (oldExceptionHook)
                        (*oldExceptionHook) (frame->exceptionVector);
                    newPC = registers[PC];	/* pc may have changed  */
                    if (newPC != frame->exceptionPC)
                    {
                        if (remote_debug)
                            printf ("frame at 0x%x has pc=0x%x, except#=%d\n",
                                    frame, frame->exceptionPC,
                                    frame->exceptionVector);
                        /* re-use the last frame, we're skipping it (longjump?) */
                        frame = (Frame *) 0;
                        _returnFromException (frame);	/* this is a jump */
                    }
                }
            }

            /* if we couldn't find a frame, create one */
            if (frame == 0)
            {
                frame = lastFrame - 1;

                /* by using a bunch of print commands with breakpoints,
                   it's possible for the frame stack to creep down.  If it creeps
                   too far, give up and reset it to the top.  Normal use should
                   not see this happen.
                 */
                if ((unsigned int) (frame - 2) < (unsigned int) &gdbFrameStack)
                {
                    initializeRemcomErrorFrame ();
                    frame = lastFrame;
                }
                frame->previous = lastFrame;
                lastFrame = frame;
                frame = 0;	/* null so _return... will properly initialize it */
            }

            _returnFromException (frame);	/* this is a jump */

            break;

        /* kill the program */
        case 'k':		/* do nothing */
            break;
        }			/* switch */

        /* reply to the request */
        putpacket (remcomOutBuffer);
    }
}
Beispiel #12
0
/* Build and send a response packet in order to inform the host the
   stub is stopped. TAAn...:r...;n...:r...;n...:r...;
                    AA = signal number
                    n... = register number (hex)
                    r... = register contents
                    n... = `thread'
                    r... = thread process ID.  This is a hex integer.
                    n... = other string not starting with valid hex digit.
                    gdb should ignore this n,r pair and go on to the next.
                    This way we can extend the protocol. */
static void
stub_is_stopped(int sigval)
{
	char *ptr = remcomOutBuffer;
	int regno;

	unsigned int reg_cont;
	int status;
        
	/* Send trap type (converted to signal) */

	*ptr++ = 'T';
	ptr = hex_byte_pack(ptr, sigval);

	/* Send register contents. We probably only need to send the
	 * PC, frame pointer and stack pointer here. Other registers will be
	 * explicitly asked for. But for now, send all.
	 */
	
	for (regno = R0; regno <= USP; regno++) {
		/* Store n...:r...; for the registers in the buffer. */

                status = read_register (regno, &reg_cont);
                
		if (status == SUCCESS) {
			ptr = hex_byte_pack(ptr, regno);
                        *ptr++ = ':';

                        ptr = mem2hex(ptr, (unsigned char *)&reg_cont,
                                      register_size[regno]);
                        *ptr++ = ';';
                }
                
	}

#ifdef PROCESS_SUPPORT
	/* Store the registers of the executing thread. Assume that both step,
	   continue, and register content requests are with respect to this
	   thread. The executing task is from the operating system scheduler. */

	current_thread_c = executing_task;
	current_thread_g = executing_task;

	/* A struct assignment translates into a libc memcpy call. Avoid
	   all libc functions in order to prevent recursive break points. */
	copy_registers (&reg_g, &reg, sizeof(registers));

	/* Store thread:r...; with the executing task TID. */
	gdb_cris_strcpy (&remcomOutBuffer[pos], "thread:");
	pos += gdb_cris_strlen ("thread:");
	remcomOutBuffer[pos++] = hex_asc_hi(executing_task);
	remcomOutBuffer[pos++] = hex_asc_lo(executing_task);
	gdb_cris_strcpy (&remcomOutBuffer[pos], ";");
#endif

	/* null-terminate and send it off */

	*ptr = 0;

	putpacket (remcomOutBuffer);
}
int handle_exception(arch & archi, int sigval)
{
	char *ptr;
	int addr, length;
	static int ThreadInfoFirst=0;

	ptr = remcomOutBuffer;

	writeTPacket(remcomOutBuffer, archi, sigval);

	if(putpacket(remcomOutBuffer))
		return 2;

	while(1)
	{
		remcomOutBuffer[0] = 0;

		if(!(ptr = getpacket()))
			return 2;
		switch (*ptr++)
		{
			case '?':
				remcomOutBuffer[0] = 'S';
				sprintf(&(remcomOutBuffer[1]), "%02X", sigval);
				break;

			case 'd':	/* toggle debug flag */
				break;

			case 'g':	/* return the value of the CPU registers */
				ptr = remcomOutBuffer;
				writegRepPacket(&ptr, archi);
				break;

			case 'G':	/* set the value of the CPU registers - return OK */
				writeGPacketToReg(ptr, archi);

				strcpy(remcomOutBuffer, "OK");
				break;

			case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
				/* Try to read %x,%x.  */
				if(hexToInt(&ptr, &addr) && *ptr++ == ','
				  && hexToInt(&ptr, &length))
				{
					mem2hex(addr, remcomOutBuffer, length, archi);
					break;
				}
				else
					strcpy(remcomOutBuffer, "E01");	/* Pas réussi à lire la trame */
				break;

			case 'M':	/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
				if(hexToInt(&ptr, &addr) && *ptr++ == ','
				  && hexToInt(&ptr, &length) && *ptr++ == ':')
				{
					if(hex2mem(ptr, addr, length, archi))
						strcpy(remcomOutBuffer, "OK");
					else
						strcpy(remcomOutBuffer, "E03");	/* écriture fail */
				}
				else
					strcpy(remcomOutBuffer, "E02");	/*Pas capable de décoder */
				break;

			case 'c':	/* cAA..AA    Continue at address AA..AA(optional) */
				if(hexToInt(&ptr, &addr))
				{
					archi.setProgramCounter(addr);
				}
				return 0;

			case 'C':	/* cAA..AA    Continue at address AA..AA(optional) */
				return 0;

			case 's':	/*sAA..AA Execute one instruction from AA..AA (optional) */
				if(hexToInt(&ptr, &addr))
				{
					archi.setProgramCounter(addr);
					printf("{step from addr %d}", addr);
				}

#ifdef DEBUG
				printf("%s", (archi.disassemble(archi.programCounter(), 2)).c_str());	/* print instruction to execute */
#endif
				printf("{%d}", archi.execInst(1));
				writeTPacket(remcomOutBuffer, archi, 5);

				break;
			case 'Z':
				switch (*ptr++)
				{
					case '0':
					case '1':
						if(*ptr++ == ',' && hexToInt(&ptr, &addr)
						  && *ptr++ == ',' && hexToInt(&ptr, &length))
						{
							archi.addBreakpoint(addr);
							strcpy(remcomOutBuffer, "OK");
						}
						else
							strcpy(remcomOutBuffer, "E01");	/* Pas réussi à lire la trame */
						break;

					case '2':	/* Read breakpoint */
					case '3':	/* Write breakpoint */
					case '4':	/* Acces breakpoint */
						remcomOutBuffer[0] = '\0';	/* Not suported */
						break;
				}
				break;

			case 'z':
				switch (*ptr++)
				{
					case '0':
					case '1':
						if(*ptr++ == ',' && hexToInt(&ptr, &addr)
						  && *ptr++ == ',' && hexToInt(&ptr, &length))
						{
							archi.removeBreakpoint(addr);
							strcpy(remcomOutBuffer, "OK");
						}
						else
							strcpy(remcomOutBuffer, "E01");	/* Pas réussi à lire la trame */
						break;

					case '2':	/* Read  breakpoint */
					case '3':	/* Write breakpoint */
					case '4':	/* Acces breakpoint */
						remcomOutBuffer[0] = '\0';	/* Not suported */
						break;
				}
				break;

				/* kill the program */
			case 'k':

#ifdef DEBUG
				printf("{[Stub] KILL!}");
#endif
				return -1;

			case 'r':	/* Reset */
#ifdef DEBUG
				printf("{[Stub] Reset!}");
#endif
				archi.reset();
				break;
			case 'D':
#ifdef DEBUG
				printf("{[Stub] Detach}");
#endif
				return 1;
			case 'q':	/*General query packet */
				switch (*ptr++)
				{
					case 'f':
						if(strcmp(ptr, "ThreadInfo") == 0)
						{
							ThreadInfoFirst = 1;
							strcpy(remcomOutBuffer, "m0");
						}
						break;

					case 's':
						if(strcmp(ptr, "ThreadInfo") == 0)
						{
							if(ThreadInfoFirst)
							{
								ThreadInfoFirst = 0;
								strcpy(remcomOutBuffer, "l");
							}
							else
							{
								ThreadInfoFirst = 1;
								strcpy(remcomOutBuffer, "m0");
							}
						}
						break;

					case 'C':
						strcpy(remcomOutBuffer, "QC0");
						break;
				}

		}	/* switch */

		/* reply to the request */
		if(putpacket(remcomOutBuffer))
			return 2;
	}
}
Beispiel #14
0
/*
 * This function does all command procesing for interfacing to gdb.
 */
static boolean
do_gdb_interface(struct kdebug_entry *entry, CPU_REGISTERS *ctx, ulong_t signal) {
    int    length;

struct kdebug_info		*kinfo;
const struct kdebug_private	*kprivate;
THREAD *thread;

    /* 
     * Indicate that we've gone back to debug mode
     */
    for (length = 0; length < 4; length++) dbg_putc('|');
	if(protocol == 0) {
		// generic GDB 4.16 wants the response to the continue/step
		// command sent before it transmits anything else.
		ksprintf(outbuf,"S%02xk", (unsigned)signal);
		putpacket();
	}

	while(getpacket()) {
		connected = TRUE;

		outbuf[0] = 0;

#ifdef DEBUG_GDB
kprintf("Processing packet '%s'\n", inbuf);		
#endif
        switch(inbuf[0]) {

		/* Tell the gdb client our signal number */
		case '?' :
			if(gdb_test_reloc_sem()) {
				paddr_t					base;
				char					*str = SYSPAGE_ENTRY(strings)->data;
				struct asinfo_entry		*as = SYSPAGE_ENTRY(asinfo);
		
				while(strcmp(&str[as->name], "imagefs") != 0) {
					++as;
				}
				base = gdb_image_base(as->start);
				gdb_clear_reloc_sem();
				ksprintf(outbuf,"N%02x%P;%P;%P",
					(unsigned)signal, base, base, (paddr_t)(base + as->end - as->start + 1));
			} else {
				ksprintf(outbuf,"S%02xk", (unsigned)signal);
			}
	
			for(length=1;outbuf[length];length++) {
				if((outbuf[length] >= 'A') && 
					(outbuf[length] <='Z'))
					outbuf[length]=outbuf[length]+('a'-'A');
			}
			if(gdb_debug) gdb_printf("%s", outbuf);
	
			break;
	
		/* toggle debug flag */
		case 'd' :
			gdb_debug = !(gdb_debug);
			break; 
		
		/* return the value of the CPU registers */
		case 'g' :
/* temp solution, need to add an offset item in kdebug_private for fpu data	*/
			if((kinfo = private->kdebug_info)== NULL || (kprivate = kinfo->kdbg_private) == NULL ||
				(thread = ((void **)kprivate->actives)[0]) == NULL) {
				gdb_get_cpuregs(ctx,NULL);
			} else {
				gdb_get_cpuregs(ctx,thread->fpudata);
			}
			break;
	
		/* set the value of the CPU registers - return OK */
		case 'G' : 
/* temp solution, need to add an offset item in kdebug_private for fpu data	*/
			if((kinfo = private->kdebug_info)== NULL || (kprivate = kinfo->kdbg_private) == NULL ||
				(thread = ((void **)kprivate->actives)[0]) == NULL) {
				gdb_set_cpuregs(ctx,NULL);
			} else {
				gdb_set_cpuregs(ctx,thread->fpudata);
			}
			strcpy(outbuf,"OK");
			break;

		/* get target information */
		case 'i':
			gdb_get_info();
			break;
		  
		/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
		case 'm' : 
			gdb_read_membytes(ctx);
			break;
		  
		/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
		case 'M' : 
			gdb_write_membytes(ctx);
			break;
		 
		/* cAA..AA    Continue at address AA..AA(optional) */
		case 'c' : 
			gdb_proc_continue(ctx, 0);	/* continue the process */
			return(TRUE);
	
		/* sAA..AA   Step one instruction from AA..AA(optional) */
		case 's' : 
			gdb_proc_continue(ctx, 1);	/* step one instruction */
			return(TRUE);

		/* q???? Generic query */	

		case 'q': 
			if(memcmp(&inbuf[1], "Rcmd,", 5) == 0) {
				// remote command
				char	*p;

				p = &inbuf[6];
				hex2mem(p, scratch, strlen(p));
				#define MEM_CMD	"mem "
				if(memcmp(scratch, MEM_CMD, sizeof(MEM_CMD)-1) == 0) {
					monitor_mem(&scratch[sizeof(MEM_CMD)-1]);
				}
			}
			break;

		/* k		Kill program */
		case 'k' :
			putpacket(); /*ACK the packet early (since we're going bye-bye) */
			gdb_prep_reboot();
			SYSPAGE_ENTRY(callout)->reboot(_syspage_ptr, 0);
			break;

		/* D		Detach from host */
		case 'D' :
			connected = FALSE;
			return(FALSE);
			  
		} /* switch */ 
/*
 * This function does all command processing for interfacing to gdb.  It
 * returns 1 if you should skip the instruction at the trap address, 0
 * otherwise.
 */
void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval)
{
	int trap;			/* Trap type */
	int addr;
	int length;
	char *ptr;
	unsigned long *stack;

	
	/*
	 * reply to host that an exception has occurred
	 */
	send_signal(sigval);

	/*
	 * Wait for input from remote GDB
	 */
	while (1) {
		output_buffer[0] = 0;
		getpacket(input_buffer);

		switch (input_buffer[0])
		{
		case '?':
			send_signal(sigval);
			continue;

		case 'd':
			/* toggle debug flag */
			break;

		/*
		 * Return the value of the CPU registers
		 */
		case 'g':
			gdb_stub_get_non_pt_regs(regs);
			ptr = output_buffer;
			ptr=  mem2hex((char *)regs,ptr,sizeof(s390_regs_common),FALSE);
			ptr=  mem2hex((char *)&regs->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
			ptr = mem2hex((char *)&regs->fp_regs, ptr,sizeof(s390_fp_regs));
			break;
	  
		/*
		 * set the value of the CPU registers - return OK
		 * FIXME: Needs to be written
		 */
		case 'G':
			ptr=input_buffer;
			hex2mem (ptr, (char *)regs,sizeof(s390_regs_common), FALSE);
			ptr+=sizeof(s390_regs_common)*2;
			hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
			ptr+=NUM_CRS*CR_SIZE*2;
			hex2mem (ptr, (char *)regs->fp_regs,sizeof(s390_fp_regs), FALSE);
			gdb_stub_set_non_pt_regs(regs);
			strcpy(output_buffer,"OK");
		break;

		/*
		 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
		 */
		case 'm':
			ptr = &input_buffer[1];

			if (hexToInt(&ptr, &addr)
				&& *ptr++ == ','
				&& hexToInt(&ptr, &length)) {
				if (mem2hex((char *)addr, output_buffer, length, 1))
					break;
				strcpy (output_buffer, "E03");
			} else
				strcpy(output_buffer,"E01");
			break;

		/*
		 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
		 */
		case 'M': 
			ptr = &input_buffer[1];

			if (hexToInt(&ptr, &addr)
				&& *ptr++ == ','
				&& hexToInt(&ptr, &length)
				&& *ptr++ == ':') {
				if (hex2mem(ptr, (char *)addr, length, 1))
					strcpy(output_buffer, "OK");
				else
					strcpy(output_buffer, "E03");
			}
			else
				strcpy(output_buffer, "E02");
			break;

		/*
		 * cAA..AA    Continue at address AA..AA(optional)
		 */
		case 'c':    
			/* try to read optional parameter, pc unchanged if no parm */

			ptr = &input_buffer[1];
			if (hexToInt(&ptr, &addr))
				regs->cp0_epc = 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.
			 * NB: We flush both caches, just to be sure...
			 */

			flush_cache_all();
			return;
			/* NOTREACHED */
			break;


		/*
		 * kill the program
		 */
		case 'k' :
			break;		/* do nothing */


		/*
		 * Reset the whole machine (FIXME: system dependent)
		 */
		case 'r':
			break;


		/*
		 * Step to next instruction
		 */
		case 's':
			/*
			 * There is no single step insn in the MIPS ISA, so we
			 * use breakpoints and continue, instead.
			 */
			single_step(regs);
			flush_cache_all();
			return;
			/* NOTREACHED */

		}
		break;

		}			/* switch */

		/*
		 * reply to the request
		 */

		putpacket(output_buffer);

	} /* while */
Beispiel #16
0
void gdbstub_loop(void) {
	int addr;
	int length;
	char *ptr, *ptr1;
	void *ramaddr;
	unsigned long regbuf[NUMREGS];
	bool reply, set;
	
	while (1)	{
		remcomOutBuffer[0] = 0;

		ptr = getpacket();
		if (!ptr) {
			gdbstub_disconnect();
			return;
		}
		reply = true;
		switch (*ptr++) 	{
			case '?':
				send_stop_reply(SIGNAL_TRAP, NULL, 0);
				reply = false; // already done
				break;

			case 'g':  /* return the value of the CPU registers */
				get_registers(regbuf);
				ptr = remcomOutBuffer;
				ptr = mem2hex(regbuf, ptr, NUMREGS * sizeof(unsigned long)); 
				break;
		
			case 'G':  /* set the value of the CPU registers - return OK */
				hex2mem(ptr, regbuf, NUMREGS * sizeof(unsigned long));
				set_registers(regbuf);
				strcpy(remcomOutBuffer,"OK");
				break;
				
			case 'p': /* pn Read the value of register n */
				if (hexToInt(&ptr, &addr) && (size_t)addr < sizeof(regbuf)) {
					mem2hex(get_registers(regbuf) + addr, remcomOutBuffer, sizeof(unsigned long));
				} else {
					strcpy(remcomOutBuffer,"E01");
				}
				break;
				
			case 'P': /* Pn=r Write register n with value r */
				ptr = strtok(ptr, "=");
				if (hexToInt(&ptr, &addr)
					  && (ptr=strtok(NULL, ""))
					  && (size_t)addr < sizeof(regbuf)
					  // TODO hex2mem doesn't check the format
					  && hex2mem((char*)ptr, &get_registers(regbuf)[addr], sizeof(u32))
					  ) {
					set_registers(regbuf);
					strcpy(remcomOutBuffer, "OK");
				} else {
					strcpy(remcomOutBuffer,"E01");
				}
				break;
		
			case 'm':  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
				/* Try to read %x,%x */
				if (hexToInt(&ptr, &addr)
				    && *ptr++ == ','
				    && hexToInt(&ptr, &length)) {
					ramaddr = virt_mem_ptr(addr, length);
					if (!ramaddr || mem2hex(ramaddr, remcomOutBuffer, length))
						break;
					strcpy(remcomOutBuffer, "E03");
				}	else
					strcpy(remcomOutBuffer,"E01");
				break;
		
			case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA  */
				/* Try to read '%x,%x:' */
				if (hexToInt(&ptr, &addr)
				    && *ptr++ == ','
				    && hexToInt(&ptr, &length)
				    && *ptr++ == ':')	{
				  ramaddr = virt_mem_ptr(addr, length);
				  if (!ramaddr) {
				  	strcpy(remcomOutBuffer, "E03");
				  	break;
				  }
				  if (range_translated((u32)ramaddr, (u32)((char *)ramaddr + length)))
				  	flush_translations();
					if (hex2mem(ptr, ramaddr, length))
						strcpy(remcomOutBuffer, "OK");
					else
						strcpy(remcomOutBuffer, "E03");
				}	else
					strcpy(remcomOutBuffer, "E02");
				break;
		
			case 'S': /* Ssig[;AA..AA] Step with signal at address AA..AA(optional). Same as 's' for us. */
				ptr = strchr(ptr, ';'); /* skip the signal */
				if (ptr)
					ptr++;
			case 's': /* s[AA..AA]  Step at address AA..AA(optional) */
				cpu_events |= EVENT_DEBUG_STEP;
				goto parse_new_pc;
			case 'C': /* Csig[;AA..AA] Continue with signal at address AA..AA(optional). Same as 'c' for us. */
				ptr = strchr(ptr, ';'); /* skip the signal */
				if (ptr)
					ptr++;
			case 'c':    /* c[AA..AA]    Continue at address AA..AA(optional) */
parse_new_pc:
				if (ptr && hexToInt(&ptr, &addr)) {
					arm.reg[15] = addr;
				}
				return;
			case 'q':
				if (!strcmp("Offsets", ptr)) {
					sprintf(remcomOutBuffer, "Text=%x;Data=%x;Bss=%x",
						ndls_debug_alloc_block, ndls_debug_alloc_block,	ndls_debug_alloc_block);
				}
				break;
			case 'Z': /* 0|1|2|3|4,addr,kind  */
				set = true;
				goto z;
			case 'z': /* 0|1|2|3|4,addr,kind  */
				set = false;
			// kinds other than 4 aren't supported
z:
				ptr1 = ptr++;
				ptr = strtok(ptr, ","); 
				if (ptr && hexToInt(&ptr, &addr) && (ramaddr = virt_mem_ptr(addr & ~3, 4))) {
					u32 *flags = &RAM_FLAGS(ramaddr);
					switch (*ptr1) {
						case '0': // mem breakpoint
						case '1': // hw breakpoint
							if (set) {
								if (*flags & RF_CODE_TRANSLATED) flush_translations();
								*flags |= RF_EXEC_BREAKPOINT;
							} else
								*flags &= ~RF_EXEC_BREAKPOINT;
							break;
						case '2': // write watchpoint
						case '4': // access watchpoint
							if (set) *flags |= RF_WRITE_BREAKPOINT;
							else *flags &= ~RF_WRITE_BREAKPOINT;
							if (*ptr1 != 4)
								break;
						case '3': // read watchpoint, access watchpoint
							if (set) *flags |= RF_READ_BREAKPOINT;
							else *flags &= ~RF_READ_BREAKPOINT;
							break;
						default:
							goto reply;
					}
					strcpy(remcomOutBuffer, "OK");
				} else
					strcpy(remcomOutBuffer, "E01");
				break;
		}			/* switch */

reply:
		/* reply to the request */
		if (reply)
			putpacket(remcomOutBuffer);
	}
}
Beispiel #17
0
/* All expected commands are sent from remote.c. Send a response according
   to the description in remote.c. */
static void
handle_exception (int sigval)
{
	/* Avoid warning of not used. */

	USEDFUN(handle_exception);
	USEDVAR(internal_stack[0]);

	/* Send response. */

	stub_is_stopped (sigval);

	for (;;) {
		remcomOutBuffer[0] = '\0';
		getpacket (remcomInBuffer);
		switch (remcomInBuffer[0]) {
			case 'g':
				/* Read registers: g
				   Success: 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.
				   Failure: void. */
				
				{
#ifdef PROCESS_SUPPORT
					/* Use the special register content in the executing thread. */
					copy_registers (&reg_g, &reg, sizeof(registers));
					/* Replace the content available on the stack. */
					if (current_thread_g != executing_task) {
						copy_registers_from_stack (current_thread_g, &reg_g);
					}
					mem2hex ((unsigned char *)remcomOutBuffer, (unsigned char *)&reg_g, sizeof(registers));
#else
					mem2hex(remcomOutBuffer, (char *)&reg, sizeof(registers));
#endif
				}
				break;
				
			case 'G':
				/* Write registers. GXX..XX
				   Each byte of register data  is described by two hex digits.
				   Success: OK
				   Failure: void. */
#ifdef PROCESS_SUPPORT
				hex2mem ((unsigned char *)&reg_g, &remcomInBuffer[1], sizeof(registers));
				if (current_thread_g == executing_task) {
					copy_registers (&reg, &reg_g, sizeof(registers));
				}
				else {
					copy_registers_to_stack(current_thread_g, &reg_g);
				}
#else
				hex2mem((char *)&reg, &remcomInBuffer[1], sizeof(registers));
#endif
				gdb_cris_strcpy (remcomOutBuffer, "OK");
				break;
				
			case 'P':
				/* Write register. Pn...=r...
				   Write register n..., hex value without 0x, with value r...,
				   which contains a hex value without 0x and two hex digits
				   for each byte in the register (target byte order). P1f=11223344 means
				   set register 31 to 44332211.
				   Success: OK
				   Failure: E02, E05 */
				{
					char *suffix;
					int regno = gdb_cris_strtol (&remcomInBuffer[1], &suffix, 16);
					int status;
#ifdef PROCESS_SUPPORT
					if (current_thread_g != executing_task)
						status = write_stack_register (current_thread_g, regno, suffix+1);
					else
#endif
						status = write_register (regno, suffix+1);

					switch (status) {
						case E02:
							/* Do not support read-only registers. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E02]);
							break;
						case E05:
							/* Do not support non-existing registers. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E05]);
							break;
						case E07:
							/* Do not support non-existing registers on the stack. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E07]);
							break;
						default:
							/* Valid register number. */
							gdb_cris_strcpy (remcomOutBuffer, "OK");
							break;
					}
				}
				break;
				
			case 'm':
				/* Read from memory. mAA..AA,LLLL
				   AA..AA is the address and LLLL is the length.
				   Success: XX..XX is the memory content.  Can be fewer bytes than
				   requested if only part of the data may be read. m6000120a,6c means
				   retrieve 108 byte from base address 6000120a.
				   Failure: void. */
				{
                                        char *suffix;
					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1],
                                                                                               &suffix, 16);                                        int length = gdb_cris_strtol(suffix+1, 0, 16);
                                        
                                        mem2hex(remcomOutBuffer, addr, length);
                                }
				break;
				
			case 'X':
				/* Write to memory. XAA..AA,LLLL:XX..XX
				   AA..AA is the start address,  LLLL is the number of bytes, and
				   XX..XX is the binary data.
				   Success: OK
				   Failure: void. */
			case 'M':
				/* Write to memory. MAA..AA,LLLL:XX..XX
				   AA..AA is the start address,  LLLL is the number of bytes, and
				   XX..XX is the hexadecimal data.
				   Success: OK
				   Failure: void. */
				{
					char *lenptr;
					char *dataptr;
					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1],
										      &lenptr, 16);
					int length = gdb_cris_strtol(lenptr+1, &dataptr, 16);
					if (*lenptr == ',' && *dataptr == ':') {
						if (remcomInBuffer[0] == 'M') {
							hex2mem(addr, dataptr + 1, length);
						}
						else /* X */ {
							bin2mem(addr, dataptr + 1, length);
						}
						gdb_cris_strcpy (remcomOutBuffer, "OK");
					}
					else {
						gdb_cris_strcpy (remcomOutBuffer, error_message[E06]);
					}
				}
				break;
				
			case 'c':
				/* Continue execution. cAA..AA
				   AA..AA is the address where execution is resumed. If AA..AA is
				   omitted, resume at the present address.
				   Success: return to the executing thread.
				   Failure: will never know. */
				if (remcomInBuffer[1] != '\0') {
					reg.pc = gdb_cris_strtol (&remcomInBuffer[1], 0, 16);
				}
				enableDebugIRQ();
				return;
				
			case 's':
				/* Step. sAA..AA
				   AA..AA is the address where execution is resumed. If AA..AA is
				   omitted, resume at the present address. Success: return to the
				   executing thread. Failure: will never know.
				   
				   Should never be invoked. The single-step is implemented on
				   the host side. If ever invoked, it is an internal error E04. */
				gdb_cris_strcpy (remcomOutBuffer, error_message[E04]);
				putpacket (remcomOutBuffer);
				return;
				
			case '?':
				/* The last signal which caused a stop. ?
				   Success: SAA, where AA is the signal number.
				   Failure: void. */
				remcomOutBuffer[0] = 'S';
				remcomOutBuffer[1] = hex_asc_hi(sigval);
				remcomOutBuffer[2] = hex_asc_lo(sigval);
				remcomOutBuffer[3] = 0;
				break;
				
			case 'D':
				/* Detach from host. D
				   Success: OK, and return to the executing thread.
				   Failure: will never know */
				putpacket ("OK");
				return;
				
			case 'k':
			case 'r':
				/* kill request or reset request.
				   Success: restart of target.
				   Failure: will never know. */
				kill_restart ();
				break;
				
			case 'C':
			case 'S':
			case '!':
			case 'R':
			case 'd':
				/* Continue with signal sig. Csig;AA..AA
				   Step with signal sig. Ssig;AA..AA
				   Use the extended remote protocol. !
				   Restart the target system. R0
				   Toggle debug flag. d
				   Search backwards. tAA:PP,MM
				   Not supported: E04 */
				gdb_cris_strcpy (remcomOutBuffer, error_message[E04]);
				break;
#ifdef PROCESS_SUPPORT

			case 'T':
				/* Thread alive. TXX
				   Is thread XX alive?
				   Success: OK, thread XX is alive.
				   Failure: E03, thread XX is dead. */
				{
					int thread_id = (int)gdb_cris_strtol (&remcomInBuffer[1], 0, 16);
					/* Cannot tell whether it is alive or not. */
					if (thread_id >= 0 && thread_id < number_of_tasks)
						gdb_cris_strcpy (remcomOutBuffer, "OK");
				}
				break;
								
			case 'H':
				/* Set thread for subsequent operations: Hct
				   c = 'c' for thread used in step and continue;
				   t can be -1 for all threads.
				   c = 'g' for thread used in other  operations.
				   t = 0 means pick any thread.
				   Success: OK
				   Failure: E01 */
				{
					int thread_id = gdb_cris_strtol (&remcomInBuffer[2], 0, 16);
					if (remcomInBuffer[1] == 'c') {
						/* c = 'c' for thread used in step and continue */
						/* Do not change current_thread_c here. It would create a mess in
						   the scheduler. */
						gdb_cris_strcpy (remcomOutBuffer, "OK");
					}
					else if (remcomInBuffer[1] == 'g') {
						/* c = 'g' for thread used in other  operations.
						   t = 0 means pick any thread. Impossible since the scheduler does
						   not allow that. */
						if (thread_id >= 0 && thread_id < number_of_tasks) {
							current_thread_g = thread_id;
							gdb_cris_strcpy (remcomOutBuffer, "OK");
						}
						else {
							/* Not expected - send an error message. */
							gdb_cris_strcpy (remcomOutBuffer, error_message[E01]);
						}
					}
					else {
						/* Not expected - send an error message. */
						gdb_cris_strcpy (remcomOutBuffer, error_message[E01]);
					}
				}
				break;
				
			case 'q':
			case 'Q':
				/* Query of general interest. qXXXX
				   Set general value XXXX. QXXXX=yyyy */
				{
					int pos;
					int nextpos;
					int thread_id;
					
					switch (remcomInBuffer[1]) {
						case 'C':
							/* Identify the remote current thread. */
							gdb_cris_strcpy (&remcomOutBuffer[0], "QC");
							remcomOutBuffer[2] = hex_asc_hi(current_thread_c);
							remcomOutBuffer[3] = hex_asc_lo(current_thread_c);
							remcomOutBuffer[4] = '\0';
							break;
						case 'L':
							gdb_cris_strcpy (&remcomOutBuffer[0], "QM");
							/* Reply with number of threads. */
							if (os_is_started()) {
								remcomOutBuffer[2] = hex_asc_hi(number_of_tasks);
								remcomOutBuffer[3] = hex_asc_lo(number_of_tasks);
							}
							else {
								remcomOutBuffer[2] = hex_asc_hi(0);
								remcomOutBuffer[3] = hex_asc_lo(1);
							}
							/* Done with the reply. */
							remcomOutBuffer[4] = hex_asc_lo(1);
							pos = 5;
							/* Expects the argument thread id. */
							for (; pos < (5 + HEXCHARS_IN_THREAD_ID); pos++)
								remcomOutBuffer[pos] = remcomInBuffer[pos];
							/* Reply with the thread identifiers. */
							if (os_is_started()) {
								/* Store the thread identifiers of all tasks. */
								for (thread_id = 0; thread_id < number_of_tasks; thread_id++) {
									nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
									for (; pos < nextpos; pos ++)
										remcomOutBuffer[pos] = hex_asc_lo(0);
									remcomOutBuffer[pos++] = hex_asc_lo(thread_id);
								}
							}
							else {
								/* Store the thread identifier of the boot task. */
								nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
								for (; pos < nextpos; pos ++)
									remcomOutBuffer[pos] = hex_asc_lo(0);
								remcomOutBuffer[pos++] = hex_asc_lo(current_thread_c);
							}
							remcomOutBuffer[pos] = '\0';
							break;
						default:
							/* Not supported: "" */
							/* Request information about section offsets: qOffsets. */
							remcomOutBuffer[0] = 0;
							break;
					}
				}
				break;
#endif /* PROCESS_SUPPORT */
				
			default:
				/* The stub should ignore other request and send an empty
				   response ($#<checksum>). This way we can extend the protocol and GDB
				   can tell whether the stub it is talking to uses the old or the new. */
				remcomOutBuffer[0] = 0;
				break;
		}
		putpacket(remcomOutBuffer);
	}
}
Beispiel #18
0
/*
 * This function does all command procesing for interfacing to gdb.
 */
void
gdb_handle_exception (db_regs_t *raw_regs, int type, int code)
{
  int    sigval;
  int    addr, length;
  char * ptr;
  struct i386regs {
    unsigned int eax;
    unsigned int ecx;
    unsigned int edx;
    unsigned int ebx;
    unsigned int esp;
    unsigned int ebp;
    unsigned int esi;
    unsigned int edi;
    unsigned int eip;
    unsigned int eflags;
    unsigned int cs;
    unsigned int ss;
    unsigned int ds;
    unsigned int es;
  };
  struct i386regs registers;

  registers.eax = raw_regs->tf_eax;
  registers.ebx = raw_regs->tf_ebx;
  registers.ecx = raw_regs->tf_ecx;
  registers.edx = raw_regs->tf_edx;

  registers.esp = raw_regs->tf_esp;
  registers.ebp = raw_regs->tf_ebp;
  registers.esi = raw_regs->tf_esi;
  registers.edi = raw_regs->tf_edi;

  registers.eip = raw_regs->tf_eip;
  registers.eflags = raw_regs->tf_eflags;

  registers.cs = raw_regs->tf_cs;
  registers.ss = raw_regs->tf_ss;
  registers.ds = raw_regs->tf_ds;
  registers.es = raw_regs->tf_es;

  /* reply to host that an exception has occurred */
  sigval = computeSignal (type);
  ptr = remcomOutBuffer;

  *ptr++ = 'T';
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval & 0xf];

  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.eip, ptr, 4);
  *ptr++ = ';';

  *ptr++ = hexchars[FP >> 4];
  *ptr++ = hexchars[FP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.ebp, ptr, 4);
  *ptr++ = ';';

  *ptr++ = hexchars[SP >> 4];
  *ptr++ = hexchars[SP & 0xf];
  *ptr++ = ':';
  ptr = mem2hex ((vm_offset_t)&registers.esp, ptr, 4);
  *ptr++ = ';';

  *ptr++ = 0;

  putpacket (remcomOutBuffer);

  while (1)
    {
      remcomOutBuffer[0] = 0;

      getpacket (remcomInBuffer);
      switch (remcomInBuffer[0]) 
	{
	case '?':
	  remcomOutBuffer[0] = 'S';
	  remcomOutBuffer[1] = hexchars[sigval >> 4];
	  remcomOutBuffer[2] = hexchars[sigval % 16];
	  remcomOutBuffer[3] = 0;
	  break;

	case 'D':		/* detach; say OK and turn off gdb */
	  putpacket(remcomOutBuffer);
	  boothowto &= ~RB_GDB;
	  return;

	case 'g':		/* return the value of the CPU registers */
	  mem2hex ((vm_offset_t)&registers, remcomOutBuffer, NUMREGBYTES);
	  break;

	case 'G':		/* set the value of the CPU registers - return OK */
	  hex2mem (&remcomInBuffer[1], (vm_offset_t)&registers, NUMREGBYTES);
	  strcpy (remcomOutBuffer, "OK");
	  break;

	case 'P':		/* Set the value of one register */
	  {
	    int regno;

	    ptr = &remcomInBuffer[1];

	    if (hexToInt (&ptr, &regno)
		&& *ptr++ == '='
		&& regno < NUM_REGS)
	      {
		hex2mem (ptr, (vm_offset_t)&registers + regno * 4, 4);
		strcpy(remcomOutBuffer,"OK");
	      }
	    else
	      strcpy (remcomOutBuffer, "P01");
	    break;
	  }
	case 'm':	/* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
	  /* Try to read %x,%x.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt (&ptr, &addr)
	      && *(ptr++) == ','
	      && hexToInt (&ptr, &length))
	    {
	      if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      break;
	    }
	  else
	    strcpy (remcomOutBuffer, "E01");
	  break;

	case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */

	  /* Try to read '%x,%x:'.  */

	  ptr = &remcomInBuffer[1];

	  if (hexToInt(&ptr,&addr)
	      && *(ptr++) == ','
	      && hexToInt(&ptr, &length)
	      && *(ptr++) == ':')
	    {
	      if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL)
		strcpy (remcomOutBuffer, "E03");
	      else
		strcpy (remcomOutBuffer, "OK");
	    }
	  else
	    strcpy (remcomOutBuffer, "E02");
	  break;

	  /* cAA..AA    Continue at address AA..AA(optional) */
	  /* sAA..AA   Step one instruction from AA..AA(optional) */
	case 'c' :
	case 's' :
	  /* try to read optional parameter, pc unchanged if no parm */

	  ptr = &remcomInBuffer[1];
	  if (hexToInt(&ptr,&addr))
	    registers.eip = addr;


	  /* set the trace bit if we're stepping */
	  if (remcomInBuffer[0] == 's')
	    registers.eflags |= PSL_T;
	  else
	    registers.eflags &= ~PSL_T;

	  raw_regs->tf_eax = registers.eax;
	  raw_regs->tf_ebx = registers.ebx;
	  raw_regs->tf_ecx = registers.ecx;
	  raw_regs->tf_edx = registers.edx;

	  raw_regs->tf_esp = registers.esp;
	  raw_regs->tf_ebp = registers.ebp;
	  raw_regs->tf_esi = registers.esi;
	  raw_regs->tf_edi = registers.edi;

	  raw_regs->tf_eip = registers.eip;
	  raw_regs->tf_eflags = registers.eflags;

	  raw_regs->tf_cs = registers.cs;
	  raw_regs->tf_ss = registers.ss;
	  raw_regs->tf_ds = registers.ds;
	  raw_regs->tf_es = registers.es;
	  return;

	} /* switch */

      /* reply to the request */
      putpacket (remcomOutBuffer);
    }
}
Beispiel #19
0
void
gdb_event_loop(int sigval, unsigned long *registers)
{
  int addr;
  int length;
  unsigned char *ptr;
  ptr = packet_out_buf;

  DEBUG (1, "In gdb_event_loop");

  while (1) {
    packet_out_buf[0] = 0;
    
    getpacket(packet_in_buf);      
    ptr = &packet_in_buf[1];

    switch (packet_in_buf[0]) {
    case '?':		/* get the last known signal */
      gdb_last_signal(sigval);
      break;
      
    case 'd':		/* toggle debug messages from the stub */
      gdb_toggle();
      break;
      
    case 'g':		/* return the value of the CPU registers */
      target_read_registers(registers);
      break;
      
    case 'G':	   /* set the value of the CPU registers - return OK */
      target_write_registers(registers);
      break;
      
    case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
      /* Try to read %x,%x.  */
      if (hex2int((char **)&ptr, &addr)
	  && *ptr++ == ','
	  && hex2int((char **)&ptr, &length)) {
	gdb_read_memory(addr, length);
      } else {
	make_return_packet(1);
      }
      break;
      
    case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
      /* Try to read '%x,%x:'.  */
      if (hex2int((char **)&ptr, &addr)
	  && *ptr++ == ','
	  && hex2int((char **)&ptr, &length)
	  && *ptr++ == ':') {
	gdb_write_memory (addr, length, ptr);
      } else {
	make_return_packet(2);
      }
      break;
      
    case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
      /* try to read optional parameter, pc unchanged if no parm */
      if (hex2int((char **)&ptr, &addr)) {
	write_pc(registers, addr);
      }
      
      /*
       * we 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();
      /* by returning, we pick up execution where we left off */
      return;

      /* kill the program */
    case 'k' :
      gdb_kill();
      break;
    case 'r':		/* Reset */
      target_reset();
      break;
    }			/* switch */
    
    /* reply to the request */
    putpacket(packet_out_buf);
  }
  DEBUG (1, "Leaving handle_exception()");
}
Beispiel #20
0
/* return value: 0 if the simulator is to be killed,
 *               1 if the simulator is to be continued.
 */
static int process_gdb_loop(void)
{
  int addr;
  int length;
  int cpu_id;
  int step_cpu, other_cpu = 0;
  char *ptr;
  char type;
  int regnum;
  uint32_t val;

  regnum = regnum;
  step_cpu = other_cpu = 0;

  /* if the hardware is running, we dropped here because the user has
   * hit break in gdb, so we send a signal to GDB indicating that */
  if (hardware->running == 1) {
      remcomOutBuffer[0] = 'S';
      remcomOutBuffer[1] = '0';
      remcomOutBuffer[2] = '5';
      remcomOutBuffer[3] = 0;
      putpacket((unsigned char *)remcomOutBuffer);
  }

  while (1)
    {
      remcomOutBuffer[0] = 0;

      ptr = (char*)getpacket();
      if (ptr == NULL) {
          /* we didn't receive a valid packet, assume that
             the connection has been terminated */
          gdb_interface_close();

          return 1;
      }

      if (debug_packets) printf("from gdb:%s\n", ptr);
      switch (*ptr++) {
      case '?': /* `?' -- last signal */
          remcomOutBuffer[0] = 'S';
          remcomOutBuffer[1] = '0';
          remcomOutBuffer[2] = '1';
          remcomOutBuffer[3] = 0;
          break;
      case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
          if (hexToInt(&ptr, &addr))
              set_pc(step_cpu, addr);
          hardware->running = 1;
          return 1;
          break;
      case 'd': /* `d' -- toggle debug *(deprecated)* */
          debug_packets = (debug_packets + 1) % 2;
          break;
      case 'g':		/* return the value of the CPU registers */
          read_registers(other_cpu, remcomOutBuffer);
          break;
      case 'G':	   /* set the value of the CPU registers - return OK */
          write_registers(other_cpu, ptr);
          strcpy(remcomOutBuffer,"OK");
	  break;
      case 'H': /* `H'CT... -- set thread */
          type = *ptr++;
          if (hexToInt(&ptr, &cpu_id)) {
              if (cpu_id == -1 || cpu_id == 0) /* XXX all threads */
                  cpu_id = 1;
              if (type == 'c') {
                  step_cpu = cpu_id - 1; /* minus one because
                                            gdb threats start from 1
                                            and yams cpu's from 0. */
                  strcpy(remcomOutBuffer, "OK");
              } else if (type == 'g') {
                  other_cpu = cpu_id - 1; /* same here */
                  strcpy(remcomOutBuffer, "OK");
              } else
                  strcpy(remcomOutBuffer, "E01");
          } else
              strcpy(remcomOutBuffer, "E01");
          break;
      case 'k' : 	  /* kill the program */
          return 0;
          break;
      case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
          if (hexToInt(&ptr,&addr) &&*ptr++==','&& hexToInt(&ptr,&length)) {
              if (read_mem(addr, length, remcomOutBuffer))
                  strcpy(remcomOutBuffer, "E03");
          } else
              strcpy(remcomOutBuffer, "E01");
          break;
      case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA */
          if (hexToInt(&ptr, &addr) && *ptr++ == ','
              && hexToInt(&ptr, &length) && *ptr++ == ':') {
              if (!write_mem(addr, length, ptr))
                  strcpy(remcomOutBuffer, "OK");
              else
                  strcpy(remcomOutBuffer, "E03");
          }
          else
              strcpy(remcomOutBuffer, "E02");
          break;
      case 'p': /* `p'HEX NUMBER OF REGISTER -- read register packet */
          if (hexToInt(&ptr, &regnum) && regnum <= 73)
              sprintf(remcomOutBuffer, "%08x",
                      read_register(other_cpu, regnum));
          else
              sprintf(remcomOutBuffer, "E01");
          break;
      case 'P': /* `P'N...`='R... -- write register */
          if (hexToInt(&ptr, (int*)&regnum) && *ptr++=='=' && hexToInt(&ptr, (int*)&val)) {
              write_register(other_cpu, regnum, val);
              sprintf(remcomOutBuffer, "OK");
          } else
              sprintf(remcomOutBuffer, "E01");
      case 'q': /* `q'QUERY -- general query */
          if (!strcmp(ptr, "fThreadInfo")) {
              int i;
              char *ptr = remcomOutBuffer;
              ptr += sprintf(ptr, "m01");
              if (hardware->num_cpus > 1)
                  for (i = 1; i < hardware->num_cpus; i++)
                      ptr += sprintf(ptr, ",%02x", i + 1);
              sprintf(ptr, "l");
          }
          break;
      case 's': /* `s'ADDR -- step */
          command_step(1);
          sprintf(remcomOutBuffer, "S01");
          break;
      case 'T': /* `T'XX -- thread alive */
          if (hexToInt(&ptr, &cpu_id) && --cpu_id < hardware->num_cpus)
              strcpy(remcomOutBuffer, "OK");
          else
              strcpy(remcomOutBuffer, "E01");
          break;
      case 'z':   /* remove breakpoint: `Z'TYPE`,'ADDR`,'LENGTH */
          type = *ptr++;
          if (*ptr++== ',' && hexToInt(&ptr, &addr)
              && *ptr++ == ',' && hexToInt(&ptr, &length)) {
              if (type == '1') { /* hardware breakpoint */
                  command_breakpoint(0xFFFFFFFF);
                  strcpy(remcomOutBuffer, "OK");
              } else /* all others are unsupported */
                  strcpy(remcomOutBuffer, "E01");
          } else
              strcpy(remcomOutBuffer, "E02");
          break;
      case 'Z':  /* insert breakpoint: `Z'TYPE`,'ADDR`,'LENGTH */
          type = *ptr++;
          if (*ptr++== ',' && hexToInt(&ptr, &addr)
              && *ptr++ == ',' && hexToInt(&ptr, &length)) {
              if (type == '1') { /* hardware breakpoint */
                  command_breakpoint(addr);
                  strcpy(remcomOutBuffer, "OK");
              } else /* all others are unsupported */
                  strcpy(remcomOutBuffer, "E01");

          } else
              strcpy(remcomOutBuffer, "E02");
          break;
      default:
          break;
      }			/* switch */

      /* reply to the request */
      putpacket((unsigned char *)remcomOutBuffer);
      if (debug_packets) printf("to gdb: %s\n", remcomOutBuffer);
    }

}
Beispiel #21
0
void c_debug_handler(frame_context *frame)
{
    char *ptr;
    s32 addr,len;
    s32 thread,current_thread;
    s32 host_has_detached;
    frame_context *regptr;

    thread = gdbstub_getcurrentthread();
    current_thread = thread;

    if(current_device->open(current_device)<0) return;

    if(dbg_active) {
        gdbstub_report_exception(frame,thread);
        putpacket(remcomOutBuffer);
    }

    if(frame->SRR0==(u32)__breakinst) frame->SRR0 += 4;

    host_has_detached = 0;
    while(!host_has_detached) {
        remcomOutBuffer[0]= 0;
        getpacket(remcomInBuffer);
        switch(remcomInBuffer[0]) {
        case '?':
            gdbstub_report_exception(frame,thread);
            break;
        case 'D':
            dbg_instep = 0;
            dbg_active = 0;
            frame->SRR1 &= ~MSR_SE;
            strcpy(remcomOutBuffer,"OK");
            host_has_detached = 1;
            break;
        case 'k':
            dbg_instep = 0;
            dbg_active = 0;
            frame->SRR1 &= ~MSR_SE;
            frame->SRR0 = 0x80001800;
            host_has_detached = 1;
            goto exit;
        case 'g':
            regptr = frame;
            ptr = remcomOutBuffer;
            if(current_thread!=thread) regptr = &current_thread_registers;

            ptr = mem2hstr(ptr,(char*)regptr->GPR,32*4);
            ptr = mem2hstr(ptr,(char*)regptr->FPR,32*8);
            ptr = mem2hstr(ptr,(char*)&regptr->SRR0,4);
            ptr = mem2hstr(ptr,(char*)&regptr->SRR1,4);
            ptr = mem2hstr(ptr,(char*)&regptr->CR,4);
            ptr = mem2hstr(ptr,(char*)&regptr->LR,4);
            ptr = mem2hstr(ptr,(char*)&regptr->CTR,4);
            ptr = mem2hstr(ptr,(char*)&regptr->XER,4);
            ptr = mem2hstr(ptr,(char*)&regptr->FPSCR,4);
            break;
        case 'm':
            ptr = &remcomInBuffer[1];
            if(hexToInt(&ptr,&addr) && ((addr&0xC0000000)==0xC0000000 || (addr&0xC0000000)==0x80000000)
                    && *ptr++==','
                    && hexToInt(&ptr,&len) && len<=((BUFMAX - 4)/2))
                mem2hstr(remcomOutBuffer,(void*)addr,len);
            else
                strcpy(remcomOutBuffer,"E00");
            break;
        case 'q':
            process_query(remcomInBuffer,remcomOutBuffer,thread);
            break;
        case 'c':
            dbg_instep = 0;
            dbg_active = 1;
            frame->SRR1 &= ~MSR_SE;
            current_device->wait(current_device);
            goto exit;
        case 's':
            dbg_instep = 1;
            dbg_active = 1;
            frame->SRR1 |= MSR_SE;
            current_device->wait(current_device);
            goto exit;
        case 'z':
        {
            s32 ret,type,len;
            char *addr;

            ret = parsezbreak(remcomInBuffer,&type,&addr,&len);
            if(!ret) {
                strcpy(remcomOutBuffer,"E01");
                break;
            }
            if(type!=0) break;

            if(len<4) {
                strcpy(remcomOutBuffer,"E02");
                break;
            }

            ret = remove_bp(addr);
            if(!ret) {
                strcpy(remcomOutBuffer,"E03");
                break;
            }
            strcpy(remcomOutBuffer,"OK");
        }
        break;
        case 'H':
            if(remcomInBuffer[1]=='g')
            {
                s32 tmp,ret;

                if(vhstr2thread(&remcomInBuffer[2],&tmp)==NULL) {
                    strcpy(remcomOutBuffer,"E01");
                    break;
                }
                if(!tmp) tmp = thread;
                if(tmp==current_thread) {
                    strcpy(remcomOutBuffer,"OK");
                    break;
                }

                if(current_thread!=thread) ret = gdbstub_setthreadregs(current_thread,&current_thread_registers);
                if(tmp!=thread) {
                    ret = gdbstub_getthreadregs(tmp,&current_thread_registers);
                    if(!ret) {
                        strcpy(remcomOutBuffer,"E02");
                        break;
                    }
                }
                current_thread= tmp;
            }
            strcpy(remcomOutBuffer,"OK");
            break;
        case 'T':
        {
            s32 tmp;

            if(vhstr2thread(&remcomInBuffer[1],&tmp)==NULL) {
                strcpy(remcomOutBuffer,"E01");
                break;
            }
            if(gdbstub_indextoid(tmp)==NULL) strcpy(remcomOutBuffer,"E02");
            else strcpy(remcomOutBuffer,"OK");
        }
        break;
        case 'Z':
        {
            s32 ret,type,len;
            char *addr;

            ret = parsezbreak(remcomInBuffer,&type,&addr,&len);
            if(!ret) {
                strcpy(remcomOutBuffer,"E01");
                break;
            }
            if(type!=0) {
                strcpy(remcomOutBuffer,"E02");
                break;
            }
            if(len<4) {
                strcpy(remcomOutBuffer,"E03");
                break;
            }

            ret = insert_bp(addr);
            if(!ret) {
                strcpy(remcomOutBuffer,"E04");
                break;
            }
            strcpy(remcomOutBuffer,"OK");
        }
        break;
        }
        putpacket(remcomOutBuffer);
    }
    current_device->close(current_device);
exit:
    return;
}