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

📄 server-main.c

📁 在Linux下和multi-ice连接
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Main code for multi-ice server for GDB.   Copyright (C) 1999 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <getopt.h>#include <stdio.h>#include <signal.h>#include <string.h>#include <stdlib.h>#include "defs.h"#include "tm.h"#include "config.h"#include "server.h"#include "low.h"#include "remote-utils.h"/* * These variables are used to track command-line options. */int show_config_dialog = 0;int debug_on = 0;int show_help = 0;int show_version = 0;int rdi_logging = 0;/* * This is the sticky flag for using extended remote protocol. */int use_extended_ops = 1;/* * Keep track of the command line arguments here. */int exit_status = 0;int exit_now = 0;/* * This one is set by the Cntrl-C handler, and is used to * tell the server to close the connection to the remote * GDB. */int close_connection_now = 0;/* * Thread information.   */int selected_thread = 0;int current_thread = 0;int using_threads = 0;/* * This is the option descriptors, as used by getopt. * Remember, if you add an option, be sure to add a * help string to the help_strings array below as well. */struct option long_options[] ={  {"byte-sex", required_argument, 0, 'b'},  {"config-dialog", no_argument, &show_config_dialog, 1},  {"debug", no_argument, &debug_on, 1},  {"help", no_argument, &show_help, 1},  {"rdi-logging", no_argument, &rdi_logging, 1},  {"remote-port", required_argument, 0, 'r'},  {"stop-others", no_argument, &target_stop_others, 0},  {"target-driver", required_argument, 0, 'd'},  {"target-port", required_argument, 0, 't'},  {"version", no_argument, &show_version, 'v'}};/* * This is what is printed by print_help (and what you see if you * do --help.  Be sure to keep it in sync with the options. */char *help_strings[] ={  "  --byte-sex  {b,l}  - Specify the byte-sex of the target on restart.\n",  "  --config-dialog    - Post configuration dialog for Multi-ICE DLL.\n",  "  --debug            - Turn on debugging of remote protocol requests.\n",  "  --help             - Print out this help message.\n",  "  --rdi-logging      - Turn on RDI logging.\n",  "  --remote-port port - Specify the port to listen for remote connections.\n",  "  --stop-others      - Execution of target stops other modules.\n",  "  --target-driver driver - Specify which ICE driver to use.\n",  "  --target-port port - Specify the port to which the target is attached.\n",  "  --version          - Print version information and then exit.\n",  (char *) NULL};void exit_handler();int run_test(char *input_buffer);  /* ------------------------------------------------------------ *  main * * This is the main for the multi-ice variant of gdbserver.  It opens * a listening port, and a connection to the debug target, and then * waits for a connection on the listener.  When the connection is * made, it processes requests from the client till the connection is * closed, then goes back to listening. * ------------------------------------------------------------ */intmain (int argc, char *argv[]){#define INITIAL_LENGTH 2000    char initial_buf[INITIAL_LENGTH], *input_buffer = initial_buf;  int input_buffer_len = INITIAL_LENGTH, message_len;  char *remote_port = "2331", *target_port = NULL, *byte_sex = NULL;  char c;  /*   * First parse the command line options:   */  while (1)    {      int option_index;       c = getopt_long_only (argc, argv, "", long_options, &option_index);      if (c == EOF)	{	  break;	}      if (c == 0 && long_options[option_index].flag == 0)	  c = long_options[option_index].val;	switch (c)	  {	  case 0:	    break;	  case 'b':	    byte_sex = optarg;	    if ((*byte_sex != 'b') && (*byte_sex != 'l')		&& (*byte_sex != 'B') && (*byte_sex != 'L'))	      {		output_error ("Bad value for --byte-sex: \"%s\", ", byte_sex);		output_error ("should be \"b\" or \"l\"\n");		exit(1);	      }	    break;	  case 'r':	    remote_port = optarg;	    break;	  case 'd':	    target_driver_name = optarg;	    break;	  case 't':	    target_port = optarg;	    break;	  case 'v':            show_version = 1;	    break;  	  case '?':	    output ("Available options are:\n");	    print_help ();	    exit (1);	  }      }  if (show_version)    {      print_version(0);      exit (0);    }    print_version(1);    if (show_help)    {      print_help ();      exit (0);    }  /*   * Now do any platform specific initializations   */  platform_init();    /*   * First establish a connection to the target.   */    if (!low_open_target (target_port, byte_sex, show_config_dialog))    {      if (target_port == NULL)	output("Error opening target.\nExiting...\n");      else	output("Error opening target at %s\nExiting...\n", remote_port);            exit(1);    }  /*   * Now open the listening port.  Bag out if we can't open it.   */    if (!open_listener (remote_port))    {      output ("Error opening listener port %s\nExiting...\n", remote_port);      low_close_target ();      exit (1);    }  output ("GDB Server starting on port %s\n", remote_port);  signal (SIGINT, exit_handler);  signal (SIGTERM, exit_handler);  signal (SIGQUIT, exit_handler);    while (!exit_now)    {      if (wait_for_connection())	{            /*             * Reset environment             */            selected_thread = 0;            current_thread = 0;            using_threads = 0;#if 0            low_reset_thread_op();#endif            	  	  while (!exit_now && !close_connection_now)	    {	      if (!handle_system_events ())		{		  exit_now = 1;		  break;		}	      else if (close_connection_now)		{		  exit_now = 0;		  close_connection_now = 0;		  break;		}	      	      message_len = getpkt (input_buffer, &input_buffer_len);	      if (message_len >= 0)		{		  if (!dispatch (input_buffer, message_len))		    {		      /* Handle errors here */		    }		}	      else		{		  break;		}	    }	  /* If we got here, then the remote user died or detached,	   * so close the connection, and wait for another...	   */	  	  close_connection ();	  close_connection_now = 0;	}      else	{	  output_error ("Attempt to connect failed\n");	}    }  close_listener ();  low_close_target ();  output ("Exiting...\n");  return exit_status;}/* ------------------------------------------------------------ * update_current_thread * * This function tries to ensure that we know what the current thread * 'id' is.  This is important when performing thread-based queries * because the target can't reliably respond with register information * for the "current" thread (it's not available on the board). * ------------------------------------------------------------ */static voidupdate_current_thread(void){    char *result, *ptr;    int res;    if ((using_threads == 0) || (current_thread != 0)) return;        // Using thread operations    res = low_thread_op("qC#", &result);    if (res) {        current_thread = strtol(result+2, &ptr, 0x10);    } else {        output("Can't deduce current thread\n");    }}/* ------------------------------------------------------------ * dispatch * * This takes a message, decodes the protocol request, and dispatches * the message to the appropriate functions that in the target.  It also * handles whatever response the message requires before returning. * ------------------------------------------------------------ */intdispatch (char *input_buffer, int message_length){    char key;    char *res;    int signo, result;    enum bp_action_type bp_action = BREAKPOINT_SET;  if (debug_on)    {      output ("Recieved packet: %s\n", input_buffer);    }  key = input_buffer[0];    input_buffer++;        switch (key)      {      case 'H': /* Set thread */	return handle_thread (input_buffer, THREAD_SET);      case 'g': /* read registers */          update_current_thread();          if ((selected_thread == 0) ||               (current_thread == selected_thread)) {              return handle_read_registers(input_buffer);          } else {              result = low_thread_op(input_buffer-1, NULL);              if (result) return result;              return handle_read_registers (input_buffer);          }      case 'G': /* write registers */          if ((selected_thread == 0) ||               (current_thread == selected_thread)) {              return handle_write_registers (input_buffer);          } else {              result = low_thread_op(input_buffer-1, NULL);              if (result) return result;              return handle_write_registers (input_buffer);          }      case 'P': /* write a particular register */          if ((selected_thread == 0) ||               (current_thread == selected_thread)) {              return handle_write_a_register (input_buffer);          } else {              result = low_thread_op(input_buffer-1, NULL);              if (result) return result;              return handle_write_registers (input_buffer);          }      case 'm': /* read memory */	return handle_read_memory (input_buffer);      case 'M': /* write memory */	return handle_write_memory (input_buffer);      case 'X': /* write memory, binary data */	putpkt ("");	return 1;	/* For now, we don't support binary downloads... */	/* return handle_write_memory (input_buffer); */      case 'z': /* This is the breakpoint delete packet */	bp_action = BREAKPOINT_DELETE;      case 'Z': /* This is the breakpoint set packet */	key = input_buffer[0];	input_buffer++;	if (*input_buffer != ',')	  {	    output_error ("Malformed breakpoint set, no \",\".\n");	    putpkt ("ENN");	    return 0;	  }	input_buffer++;	switch (key)	  {	  case '0':	    /* JT's breakpoint patches don't explicitly request	       a HW breakpoint.  We will do our best on this side...	       putpkt ("ENN");	       output_error ("Can't do software breakpoints on this side.\n");	    */	  case '1':	    return handle_breakpoint (bp_action, input_buffer);	  case '2':	    return handle_watchpoint (bp_action, WATCHPOINT_WRITE,				      input_buffer);	  case '3':	    return handle_watchpoint (bp_action, WATCHPOINT_READ,				      input_buffer);	  case '4':	    return handle_watchpoint (bp_action, WATCHPOINT_ACCESS,				      input_buffer);	  default:	    output_error ("Bad \"Z\" packet index: %c.\n", key);	    putpkt ("ENN");	    return 0;	  }      case 'c': /* continue */	return handle_resume (input_buffer, RESUME_CONTINUE, 0);      case 'C': /* continue with signal */	input_buffer = remove_signal (input_buffer, &signo);	if (input_buffer == NULL)	  {	    return 0;	  }	return handle_resume (input_buffer, RESUME_CONTINUE, signo);      case 's': /* step */	return handle_resume (input_buffer, RESUME_STEP, 0);      case 'S': /* step with signal */	input_buffer = remove_signal (input_buffer, &signo);	return handle_resume (input_buffer, RESUME_STEP, signo);      case '?': /* query last signal */	return handle_last_signal (input_buffer);      case 'D': /* detach */	return handle_detach (input_buffer);      case 'T': /* query is thread alive */	return handle_thread (input_buffer, THREAD_ALIVE);      case 'R': /* restart the remote server */	return handle_restart (input_buffer);      case '!': /* use extended ops */	enable_extended_ops();	return 1;      case 'k': /* kill target */	return handle_kill_target (input_buffer);      case 'd': /* toggle debug */	return handle_toggle_debug (input_buffer);      case 'r': /* reset */	return handle_reset (input_buffer);      case 't': /* search memory */	return handle_search_memory (input_buffer);      case 'q': /* general query */	return handle_general_query (input_buffer);      case 'Q': /* general set */	return handle_general_set (input_buffer);      default:  /* Send a packet not recognized reply */	putpkt("");	return 1;      }}/* * print_help * * This prints out all the help strings. */voidprint_help(){    int i;    output ("Options:\n");    for (i = 0; help_strings[i] != NULL; i++)      {	output (help_strings[i]);      }}/* * print_version * * This prints out the program version and copyright/licensing information */voidprint_version(int banner_only){  /* From GNU coding standards, first line is meant to be easy for a     program to parse, and is just canonical program name and version     number, which starts after last space. */    output ("GNU Multi-ICE GDB server " VERSION "\n\n");    if (!banner_only)      output ("\Copyright 1999 Free Software Foundation, Inc.\n\This program is free software; you are welcome to change it and/or\n\redistribute it under the terms of the GNU General Public License.\n\This program is supported for customers of Cygnus Solutions.\n");}/* * handle_thread * * This handles all the thread queries using the H packed syntax. */inthandle_thread (char *input_buffer, enum thread_mode mode){  char key, *ptr;  long thread_id;  switch (mode)    {    case THREAD_SET:      key = input_buffer[0];      input_buffer++;            thread_id = strtol (input_buffer, &ptr, 0x10);  // Protocol uses hex values      if (ptr == input_buffer)	{	  putpkt ("ENN");	  output_error ("Got invalid thread id: %s\n", input_buffer);	  return 0;	}            switch (key)	{	case 'c':	  if (low_set_thread_for_resume (thread_id))	    {	      putpkt("OK");	      return 1;	    }	  else	    {	      putpkt("ENN");	      return 0;	    }	case 'g':          selected_thread = thread_id;          if (selected_thread) {              return low_set_thread_for_query (input_buffer-2);          } else {	      putpkt("OK");	      return 1;          }	default:	  putpkt("ENN");	}      break;    case THREAD_ALIVE:            thread_id = strtol (input_buffer, &ptr, 0x10);      if (ptr == input_buffer)	{	  putpkt ("ENN");	  output_error ("Got invalid thread id: %s\n", input_buffer);	  return 0;	}      if (thread_id) {          return low_is_thread_alive (input_buffer-1);      } else {	  putpkt("OK");      }      return 1;    default:      putpkt("");      return 1;    }    return 1;}/* * handle_read_registers * * This returns the entire register set in the form required by * the 'g' packet.  ** Only in non-thread mode */inthandle_read_registers (char *input_buffer){  char *buffer = alloca((REGISTER_BYTES * 2) + 1);  if (!low_update_registers ())    {        putpkt("ENN");        return 0;    }    convert_bytes_to_ascii (aregisters, buffer, REGISTER_BYTES, 0);  putpkt(buffer);  return 1;}

⌨️ 快捷键说明

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