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

📄 mi-main.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* MI Command Set.   Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation,   Inc.   Contributed by Cygnus Solutions (a Red Hat company).   This file is part of GDB.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the 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 of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.  *//* Work in progress */#include "defs.h"#include "target.h"#include "inferior.h"#include "gdb_string.h"#include "top.h"#include "gdbthread.h"#include "mi-cmds.h"#include "mi-parse.h"#include "mi-getopt.h"#include "mi-console.h"#include "ui-out.h"#include "mi-out.h"#include "interps.h"#include "event-loop.h"#include "event-top.h"#include "gdbcore.h"		/* for write_memory() */#include "value.h"		/* for deprecated_write_register_bytes() */#include "regcache.h"#include "gdb.h"#include "frame.h"#include "mi-main.h"#include <ctype.h>#include <sys/time.h>enum  {    FROM_TTY = 0  };/* Enumerations of the actions that may result from calling   captured_mi_execute_command */enum captured_mi_execute_command_actions  {    EXECUTE_COMMAND_DISPLAY_PROMPT,    EXECUTE_COMMAND_SUPRESS_PROMPT,    EXECUTE_COMMAND_DISPLAY_ERROR  };/* This structure is used to pass information from captured_mi_execute_command   to mi_execute_command. */struct captured_mi_execute_command_args{  /* This return result of the MI command (output) */  enum mi_cmd_result rc;  /* What action to perform when the call is finished (output) */  enum captured_mi_execute_command_actions action;  /* The command context to be executed (input) */  struct mi_parse *command;};int mi_debug_p;struct ui_file *raw_stdout;/* The token of the last asynchronous command */static char *last_async_command;static char *previous_async_command;char *mi_error_message;static char *old_regs;extern void _initialize_mi_main (void);static enum mi_cmd_result mi_cmd_execute (struct mi_parse *parse);static void mi_execute_cli_command (const char *cmd, int args_p,				    const char *args);static enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, int from_tty);static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg);static int register_changed_p (int regnum);static int get_register (int regnum, int format);/* Command implementations. FIXME: Is this libgdb? No.  This is the MI   layer that calls libgdb.  Any operation used in the below should be   formalized. */enum mi_cmd_resultmi_cmd_gdb_exit (char *command, char **argv, int argc){  /* We have to print everything right here because we never return */  if (last_async_command)    fputs_unfiltered (last_async_command, raw_stdout);  fputs_unfiltered ("^exit\n", raw_stdout);  mi_out_put (uiout, raw_stdout);  /* FIXME: The function called is not yet a formal libgdb function */  quit_force (NULL, FROM_TTY);  return MI_CMD_DONE;}enum mi_cmd_resultmi_cmd_exec_run (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("run", args, from_tty);}enum mi_cmd_resultmi_cmd_exec_next (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("next", args, from_tty);}enum mi_cmd_resultmi_cmd_exec_next_instruction (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("nexti", args, from_tty);}enum mi_cmd_resultmi_cmd_exec_step (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("step", args, from_tty);}enum mi_cmd_resultmi_cmd_exec_step_instruction (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("stepi", args, from_tty);}enum mi_cmd_resultmi_cmd_exec_finish (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("finish", args, from_tty);}enum mi_cmd_resultmi_cmd_exec_until (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("until", args, from_tty);}enum mi_cmd_resultmi_cmd_exec_return (char *args, int from_tty){  /* This command doesn't really execute the target, it just pops the     specified number of frames. */  if (*args)    /* Call return_command with from_tty argument equal to 0 so as to       avoid being queried. */    return_command (args, 0);  else    /* Call return_command with from_tty argument equal to 0 so as to       avoid being queried. */    return_command (NULL, 0);  /* Because we have called return_command with from_tty = 0, we need     to print the frame here. */  print_stack_frame (get_selected_frame (), 1, LOC_AND_ADDRESS);  return MI_CMD_DONE;}enum mi_cmd_resultmi_cmd_exec_continue (char *args, int from_tty){  /* FIXME: Should call a libgdb function, not a cli wrapper */  return mi_execute_async_cli_command ("continue", args, from_tty);}/* Interrupt the execution of the target. Note how we must play around   with the token varialbes, in order to display the current token in   the result of the interrupt command, and the previous execution   token when the target finally stops. See comments in   mi_cmd_execute. */enum mi_cmd_resultmi_cmd_exec_interrupt (char *args, int from_tty){  if (!target_executing)    {      mi_error_message = xstrprintf ("mi_cmd_exec_interrupt: Inferior not executing.");      return MI_CMD_ERROR;    }  interrupt_target_command (args, from_tty);  if (last_async_command)    fputs_unfiltered (last_async_command, raw_stdout);  fputs_unfiltered ("^done", raw_stdout);  xfree (last_async_command);  if (previous_async_command)    last_async_command = xstrdup (previous_async_command);  xfree (previous_async_command);  previous_async_command = NULL;  mi_out_put (uiout, raw_stdout);  mi_out_rewind (uiout);  fputs_unfiltered ("\n", raw_stdout);  return MI_CMD_QUIET;}enum mi_cmd_resultmi_cmd_thread_select (char *command, char **argv, int argc){  enum gdb_rc rc;  if (argc != 1)    {      mi_error_message = xstrprintf ("mi_cmd_thread_select: USAGE: threadnum.");      return MI_CMD_ERROR;    }  else    rc = gdb_thread_select (uiout, argv[0]);  /* RC is enum gdb_rc if it is successful (>=0)     enum return_reason if not (<0). */  if ((int) rc < 0 && (enum return_reason) rc == RETURN_ERROR)    return MI_CMD_CAUGHT_ERROR;  else if ((int) rc >= 0 && rc == GDB_RC_FAIL)    return MI_CMD_ERROR;  else    return MI_CMD_DONE;}enum mi_cmd_resultmi_cmd_thread_list_ids (char *command, char **argv, int argc){  enum gdb_rc rc = MI_CMD_DONE;  if (argc != 0)    {      mi_error_message = xstrprintf ("mi_cmd_thread_list_ids: No arguments required.");      return MI_CMD_ERROR;    }  else    rc = gdb_list_thread_ids (uiout);  if (rc == GDB_RC_FAIL)    return MI_CMD_CAUGHT_ERROR;  else    return MI_CMD_DONE;}enum mi_cmd_resultmi_cmd_data_list_register_names (char *command, char **argv, int argc){  int regnum, numregs;  int i;  struct cleanup *cleanup;  /* Note that the test for a valid register must include checking the     REGISTER_NAME because NUM_REGS may be allocated for the union of     the register sets within a family of related processors.  In this     case, some entries of REGISTER_NAME will change depending upon     the particular processor being debugged.  */  numregs = NUM_REGS + NUM_PSEUDO_REGS;  cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names");  if (argc == 0)		/* No args, just do all the regs */    {      for (regnum = 0;	   regnum < numregs;	   regnum++)	{	  if (REGISTER_NAME (regnum) == NULL	      || *(REGISTER_NAME (regnum)) == '\0')	    ui_out_field_string (uiout, NULL, "");	  else	    ui_out_field_string (uiout, NULL, REGISTER_NAME (regnum));	}    }  /* Else, list of register #s, just do listed regs */  for (i = 0; i < argc; i++)    {      regnum = atoi (argv[i]);      if (regnum < 0 || regnum >= numregs)	{	  do_cleanups (cleanup);	  mi_error_message = xstrprintf ("bad register number");	  return MI_CMD_ERROR;	}      if (REGISTER_NAME (regnum) == NULL	  || *(REGISTER_NAME (regnum)) == '\0')	ui_out_field_string (uiout, NULL, "");      else	ui_out_field_string (uiout, NULL, REGISTER_NAME (regnum));    }  do_cleanups (cleanup);  return MI_CMD_DONE;}enum mi_cmd_resultmi_cmd_data_list_changed_registers (char *command, char **argv, int argc){  int regnum, numregs, changed;  int i;  struct cleanup *cleanup;  /* Note that the test for a valid register must include checking the     REGISTER_NAME because NUM_REGS may be allocated for the union of     the register sets within a family of related processors.  In this     case, some entries of REGISTER_NAME will change depending upon     the particular processor being debugged.  */  numregs = NUM_REGS + NUM_PSEUDO_REGS;  cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");  if (argc == 0)		/* No args, just do all the regs */    {      for (regnum = 0;	   regnum < numregs;	   regnum++)	{	  if (REGISTER_NAME (regnum) == NULL	      || *(REGISTER_NAME (regnum)) == '\0')	    continue;	  changed = register_changed_p (regnum);	  if (changed < 0)	    {	      do_cleanups (cleanup);	      mi_error_message = xstrprintf ("mi_cmd_data_list_changed_registers: Unable to read register contents.");	      return MI_CMD_ERROR;	    }	  else if (changed)	    ui_out_field_int (uiout, NULL, regnum);	}    }  /* Else, list of register #s, just do listed regs */  for (i = 0; i < argc; i++)    {      regnum = atoi (argv[i]);      if (regnum >= 0	  && regnum < numregs	  && REGISTER_NAME (regnum) != NULL	  && *REGISTER_NAME (regnum) != '\000')	{	  changed = register_changed_p (regnum);	  if (changed < 0)	    {	      do_cleanups (cleanup);	      mi_error_message = xstrprintf ("mi_cmd_data_list_register_change: Unable to read register contents.");	      return MI_CMD_ERROR;	    }	  else if (changed)	    ui_out_field_int (uiout, NULL, regnum);	}      else	{	  do_cleanups (cleanup);	  mi_error_message = xstrprintf ("bad register number");	  return MI_CMD_ERROR;	}    }  do_cleanups (cleanup);  return MI_CMD_DONE;}static intregister_changed_p (int regnum){  char raw_buffer[MAX_REGISTER_SIZE];  if (! frame_register_read (deprecated_selected_frame, regnum, raw_buffer))    return -1;  if (memcmp (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,	      register_size (current_gdbarch, regnum)) == 0)    return 0;  /* Found a changed register. Return 1. */  memcpy (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,	  register_size (current_gdbarch, regnum));  return 1;}/* Return a list of register number and value pairs. The valid   arguments expected are: a letter indicating the format in which to   display the registers contents. This can be one of: x (hexadecimal), d   (decimal), N (natural), t (binary), o (octal), r (raw).  After the   format argumetn there can be a sequence of numbers, indicating which   registers to fetch the content of. If the format is the only argument,   a list of all the registers with their values is returned. */enum mi_cmd_resultmi_cmd_data_list_register_values (char *command, char **argv, int argc){  int regnum, numregs, format, result;  int i;  struct cleanup *list_cleanup, *tuple_cleanup;  /* Note that the test for a valid register must include checking the     REGISTER_NAME because NUM_REGS may be allocated for the union of     the register sets within a family of related processors.  In this     case, some entries of REGISTER_NAME will change depending upon     the particular processor being debugged.  */  numregs = NUM_REGS + NUM_PSEUDO_REGS;  if (argc == 0)    {      mi_error_message = xstrprintf ("mi_cmd_data_list_register_values: Usage: -data-list-register-values <format> [<regnum1>...<regnumN>]");      return MI_CMD_ERROR;    }  format = (int) argv[0][0];  if (!target_has_registers)    {      mi_error_message = xstrprintf ("mi_cmd_data_list_register_values: No registers.");      return MI_CMD_ERROR;    }  list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values");  if (argc == 1)		/* No args, beside the format: do all the regs */    {      for (regnum = 0;	   regnum < numregs;	   regnum++)	{	  if (REGISTER_NAME (regnum) == NULL	      || *(REGISTER_NAME (regnum)) == '\0')	    continue;	  tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);	  ui_out_field_int (uiout, "number", regnum);	  result = get_register (regnum, format);	  if (result == -1)	    {	      do_cleanups (list_cleanup);	      return MI_CMD_ERROR;	    }	  do_cleanups (tuple_cleanup);	}    }  /* Else, list of register #s, just do listed regs */  for (i = 1; i < argc; i++)    {      regnum = atoi (argv[i]);      if (regnum >= 0	  && regnum < numregs	  && REGISTER_NAME (regnum) != NULL	  && *REGISTER_NAME (regnum) != '\000')	{	  tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);	  ui_out_field_int (uiout, "number", regnum);	  result = get_register (regnum, format);	  if (result == -1)	    {	      do_cleanups (list_cleanup);	      return MI_CMD_ERROR;	    }	  do_cleanups (tuple_cleanup);

⌨️ 快捷键说明

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