⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server-main.c

📁 在Linux下和multi-ice连接
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * handle_write_registers * * This stores away all the registers...  In the grand tradition of * gdb, we don't actually write down to the board till we restart. */inthandle_write_registers (char *input_buffer){  char *buffer = alloca(REGISTER_BYTES);    if (!low_update_registers ())    {      putpkt ("ENN");      return 0;    }    convert_ascii_to_bytes (input_buffer, buffer, REGISTER_BYTES, 0);  memcpy (&aregisters, (char *) buffer, REGISTER_BYTES);  registers_are_dirty = 1;  low_write_registers ();  return 1;}/* * handle_write_a_register * * This writes a single register into the register array.  The register * is not actually written down to the board at this point. */inthandle_write_a_register (char *input_buffer){  char *val_ptr;  int regno;  if (!low_update_registers ())    {      putpkt ("ENN");      return 0;    }  val_ptr = (char *) strchr (input_buffer, '=');  if (val_ptr == NULL)    {      if (debug_on)	{	  output_error ("Malformed P request - no \"=\": %s\n", input_buffer);	}      putpkt ("ENN");      return 0;    }  *val_ptr = '\0';  sscanf (input_buffer, "%x", &regno);  /* FIXME - Check that regno is a valid register */    val_ptr++;  if (strlen (val_ptr) != (REGISTER_RAW_SIZE (regno) * 2))    {      output_error ("Malformed register value for register %d ", regno);      output_error ("- wrong size: %s\n", val_ptr);      return 0;    }  convert_ascii_to_bytes (val_ptr, &aregisters[REGISTER_BYTE (regno)],			  REGISTER_RAW_SIZE (regno), 0);  registers_are_dirty = 1;  /* For now, I am always flushing the changes so I can test the     code.  Remove this from the production version. */    low_write_registers();    putpkt("OK");  return 1;}inthandle_read_memory (char *input_buffer){  unsigned int len, nbytes, nchars;  char static_buf[1024];  char *buffer = static_buf;  CORE_ADDR start_addr;  int result;  decode_m_packet (input_buffer, &start_addr, &nbytes);    if (debug_on)    {      output ("Reading %d bytes starting at 0x%x\n", nbytes, start_addr);    }  nchars = 2 * nbytes + 1;  if (nchars > 1024)    {      buffer = (char *) malloc (nchars);    }    len = low_read_memory (buffer, start_addr, nbytes);  if (len > 0)    {      result = 1;    }  else    {      /* HACK ALERT:  When  gdb first tries to connect, to the	 target, the fp often points into never-never land.  If tries	 to decode the prolog, and than ends up getting it to read	 invalid memory, and the whole thing chokes.  To keep this	 from happening, I will return as many zeros as requested... */            memset (buffer, '0', nchars);      output_error ("Failed to read memory at address 0x%x\n", start_addr);      result = 0;    }  putpkt (buffer);    if (buffer != static_buf)    {      free (buffer);    }    return result;}inthandle_write_memory (char *input_buffer){  unsigned int len, nbytes;  char data[1024]; /* FIXME -static buffer used! */  CORE_ADDR start_addr;  decode_M_packet (input_buffer, data, &start_addr, &nbytes);    if (debug_on)    {      output ("Writing %d bytes starting at 0x%x\n", nbytes, start_addr);    }    len = low_write_memory (data, start_addr, nbytes);  if (len == nbytes)    {      putpkt ("OK");      return 1;    }  else    {      putpkt ("ENN");      return 0;    }}/* * remove_signal * * This strips the signal part off the C & S packets, and returns * the value in SIGNO.  It returns a pointer to the first character in * input_buffer after the ';', or NULL for error. */char *remove_signal (char *input_buffer, int *signo){  char *p;    p = (char *) strchr (input_buffer, ';');  /* If there is no ";", then the whole thing is the signal... */  if (p == NULL)    {      sscanf (input_buffer, "%x", signo);      p = input_buffer + strlen(input_buffer);    }  else    {      *p = '\0';      sscanf (input_buffer, "%x", signo);            p = input_buffer++;    }  return p;}/* * handle_resume * * This resumes the target.  RESUME_MODE is one of RESUME_STEP or * RESUME_CONTINUE.  The input buffer can be blank, or can optionally contain * the line at which to resume execution.  SIGNO is the signal with which * to resume.  It is ignored. */inthandle_resume (char *input_buffer, enum resume_mode mode, int signo){  int stop_signal;  char return_pkt[128];  char PC_reg[16], SP_reg[16];  /* Forget about 'selected' thread */  selected_thread = 0;  current_thread = 0;    /*   * See if there is an address to resume at, if not default   * to the current PC.   */  if (*input_buffer != '\0')    {      convert_ascii_to_bytes (input_buffer,			      &aregisters[REGISTER_BYTE (PC_REGNUM)],			      REGISTER_RAW_SIZE (PC_REGNUM), 0);    }  if (debug_on && (mode == RESUME_CONTINUE))    {      output ("Executing...\n");    }  enable_async_io();  stop_signal = low_resume (mode, signo);  disable_async_io();  if (debug_on && (mode == RESUME_CONTINUE))    {      output ("Stopped...\n");    }    /* We have run, so the registers are no longer up-to-date */  registers_up_to_date = 0;  registers_are_dirty = 0;  /* Now write the return signal. */  sprintf (return_pkt, "S%02x", stop_signal);  update_current_thread();  if (current_thread != 0) {      /* Return thread-based result, registers are up-to-date */      convert_bytes_to_ascii(&aregisters[REGISTER_BYTE (PC_REGNUM)],                             PC_reg,                             REGISTER_RAW_SIZE (PC_REGNUM), 0);      convert_bytes_to_ascii(&aregisters[REGISTER_BYTE (SP_REGNUM)],                             SP_reg,                             REGISTER_RAW_SIZE (SP_REGNUM), 0);      sprintf (return_pkt, "T%02xthread:%08x;%02x:%s;%02x:%s;",                stop_signal, current_thread, PC_REGNUM, PC_reg, SP_REGNUM, SP_reg);  } else {      /* Now write the return signal. */      sprintf (return_pkt, "S%02x", stop_signal);  }    putpkt (return_pkt);    return 1;}/* * handle_last_signal * * Actually, this returns the last reason for stopping. */inthandle_last_signal (char *input_buffer){  enum target_signal signal;  char buffer[8];    signal = low_query_last_signal ();  sprintf (buffer, "S%02x", signal);  putpkt (buffer);  return 1;}/* * handle_detach * * This detaches from the remote connection, and the we wait for * another connection. */inthandle_detach (char *input_buffer){  close_connection_now = 1;  putpkt ("OK");  return 1;}/* * handle_restart * * I am hijacking this to mean kill the server.  Not great, but it * is better than kill or detach. */inthandle_restart (char *input_buffer){  close_connection_now = 1;  exit_now = 1;  return 1;}/* * handle_toggle_debug * * This toggles the internal debugging flag. */inthandle_toggle_debug (char *input_buffer){  if (debug_on)    debug_on = 0;  else    debug_on = 1;    return 1;}inthandle_reset (char *input_buffer){  return 1;}/* * handle_kill_target * * This actually just disconnects.  Since gdb issues 'k' when it exits * it would be very inconvenient if this were to kill the target. */inthandle_kill_target (char *input_buffer){  close_connection_now = 1;  return 1;}/* * handle_search_memory * * Currently a no-op */inthandle_search_memory (char *input_buffer){  return 1;}/* * handle_general_query * * This handles the 'q' packets.  Right now it does qOffset, and the * thread query (though this returns nothing useful since you can't * query threads through the RDI. */inthandle_general_query (char *input_buffer){  char key;  long thread_id;  char *result, *ptr;  int res;    /* I couldn't find a general enumeration of the     general query messages...  So these are all I could find. */    key = input_buffer[0];  switch (key)    {    case 'C': /* This is the Current thread request */      res = low_thread_op(input_buffer-1, &result);      if (res) {          // Look at result to decode answer          if (strncmp(result, "QC", 2) == 0) {              using_threads = 1;              current_thread = strtol (result+2, &ptr, 0x10);  // Protocol uses hex values          } else {              current_thread = 0;  // Unknown          }          putpkt(result);      } else {          putpkt("");      }      return res;    case 'O': /* The offsets query */      {	char buffer[256];	CORE_ADDR text, data, bss;		if (low_get_offsets (&text, &data, &bss))	  {	    sprintf (buffer, "Text=%x;Data=%x;Bss=%x", text, data, bss);	    putpkt (buffer);	    return 1;	  }	else	  {	    putpkt ("");	    return 0;	  }      }    case 'L': /* Get thread list */    case 'P': /* This is the thread info request */      res = low_thread_op(input_buffer-1, NULL);      if (!res) putpkt("");      return res;    case 'E': /* This is for private use, to do tests... */      return run_test(++input_buffer);    default:      putpkt ("");      return 1;    }  return 1;}/* * handle_general_set * * This would handle the catchall set commands.  For now we do nothing. * Set thread is about the only one I currently know what to do anything * about, and that doesn't work for RDI1.50, so there... */inthandle_general_set (char *input_buffer){  return 1;}/* * handle_breakpoint * * This handles setting and deleting breakpoints.  ACTION is one of * BREAKPOINT_SET of BREAKPOINT_DELETE.  The rest of INPUT_BUFFER * contains the address. */inthandle_breakpoint (enum bp_action_type action, char *input_buffer){  char ch;  char *p;  CORE_ADDR bp_addr;  int result;  int size = 0;  if ((p = (char *) strchr(input_buffer, ',')) != NULL)    {      *p = '\0';      p++;      sscanf (p, "%d", &size);    }  bp_addr = 0;  while ((ch = *(input_buffer++)) != '\0')    {      bp_addr = bp_addr << 4;      bp_addr |= fromhex (ch) & 0x0f;    }  switch (action)    {    case BREAKPOINT_SET:      if (debug_on)	{	  output ("Setting breakpoint at %x of length %d\n", bp_addr, size);	}      result = low_set_breakpoint (bp_addr, size);      break;    case BREAKPOINT_DELETE:      if (debug_on)	{	  output ("Removing breakpoint at %x of length %d\n", bp_addr, size);	}      result = low_delete_breakpoint (bp_addr, size);      break;    }  if (result)    {      putpkt ("OK");    }  else    {      putpkt ("ENN");    }    return result;}/* * handle_watchpoint * * This would handle watchpoint requests.  These are not yet wired into * the target vector, however, so I don't think that gdb can send them... */int handle_watchpoint (enum bp_action_type action,		       enum watch_type type,		       char *input_buffer){  char ch;  char *p;  CORE_ADDR watch_addr;  int result;  int size = 0;  if ((p = (char *) strchr(input_buffer, ',')) != NULL)    {      *p = '\0';      p++;      sscanf (p, "%d", &size);    }  watch_addr = 0;  while ((ch = *(input_buffer++)) != '\0')    {      watch_addr = watch_addr << 4;      watch_addr |= fromhex (ch) & 0x0f;    }  switch (action)    {    case BREAKPOINT_SET:      if (debug_on)	{	  output ("Setting watchpoint at %x of length %d\n", watch_addr, size);	}      result = low_set_watchpoint (watch_addr, size, type);      break;    case BREAKPOINT_DELETE:      if (debug_on)	{	  output ("Removing watchpoint at %x of length %d\n", watch_addr, size);	}      result = low_delete_watchpoint (watch_addr, size, type);      break;    }  if (result)    {      putpkt ("OK");    }  else    {      putpkt ("ENN");    }    return result;}/* * enable_extended_ops * * Store away the fact that we are using the extended remote protocol. */void enable_extended_ops (){  use_extended_ops = 1;}/* * exit_handler * * Flag the main loop to exit. */voidexit_handler(){  exit_now = 1;  close_connection_now = 1;}#define ARMword unsigned intextern void record_register (int regno, ARMword val);extern ARMword restore_register (int regno);/* run_test * * This does nothing now, but you can shove in anything here, and * sending an 'qE' packet will activate it.  Just for testing. */intrun_test (char *input_buffer){  return low_test (input_buffer);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -