OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [reverse.c] - Diff between revs 834 and 842

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 834 Rev 842
/* Reverse execution and reverse debugging.
/* Reverse execution and reverse debugging.
 
 
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include "defs.h"
#include "defs.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "target.h"
#include "target.h"
#include "top.h"
#include "top.h"
#include "cli/cli-cmds.h"
#include "cli/cli-cmds.h"
#include "cli/cli-decode.h"
#include "cli/cli-decode.h"
#include "inferior.h"
#include "inferior.h"
#include "regcache.h"
#include "regcache.h"
 
 
/* User interface:
/* User interface:
   reverse-step, reverse-next etc.  */
   reverse-step, reverse-next etc.  */
 
 
static void
static void
exec_direction_default (void *notused)
exec_direction_default (void *notused)
{
{
  /* Return execution direction to default state.  */
  /* Return execution direction to default state.  */
  execution_direction = EXEC_FORWARD;
  execution_direction = EXEC_FORWARD;
}
}
 
 
/* exec_reverse_once -- accepts an arbitrary gdb command (string),
/* exec_reverse_once -- accepts an arbitrary gdb command (string),
   and executes it with exec-direction set to 'reverse'.
   and executes it with exec-direction set to 'reverse'.
 
 
   Used to implement reverse-next etc. commands.  */
   Used to implement reverse-next etc. commands.  */
 
 
static void
static void
exec_reverse_once (char *cmd, char *args, int from_tty)
exec_reverse_once (char *cmd, char *args, int from_tty)
{
{
  char *reverse_command;
  char *reverse_command;
  enum exec_direction_kind dir = execution_direction;
  enum exec_direction_kind dir = execution_direction;
  struct cleanup *old_chain;
  struct cleanup *old_chain;
 
 
  if (dir == EXEC_ERROR)
  if (dir == EXEC_ERROR)
    error (_("Target %s does not support this command."), target_shortname);
    error (_("Target %s does not support this command."), target_shortname);
 
 
  if (dir == EXEC_REVERSE)
  if (dir == EXEC_REVERSE)
    error (_("Already in reverse mode.  Use '%s' or 'set exec-dir forward'."),
    error (_("Already in reverse mode.  Use '%s' or 'set exec-dir forward'."),
           cmd);
           cmd);
 
 
  if (!target_can_execute_reverse)
  if (!target_can_execute_reverse)
    error (_("Target %s does not support this command."), target_shortname);
    error (_("Target %s does not support this command."), target_shortname);
 
 
  reverse_command = xstrprintf ("%s %s", cmd, args ? args : "");
  reverse_command = xstrprintf ("%s %s", cmd, args ? args : "");
  old_chain = make_cleanup (exec_direction_default, NULL);
  old_chain = make_cleanup (exec_direction_default, NULL);
  make_cleanup (xfree, reverse_command);
  make_cleanup (xfree, reverse_command);
  execution_direction = EXEC_REVERSE;
  execution_direction = EXEC_REVERSE;
  execute_command (reverse_command, from_tty);
  execute_command (reverse_command, from_tty);
  do_cleanups (old_chain);
  do_cleanups (old_chain);
}
}
 
 
static void
static void
reverse_step (char *args, int from_tty)
reverse_step (char *args, int from_tty)
{
{
  exec_reverse_once ("step", args, from_tty);
  exec_reverse_once ("step", args, from_tty);
}
}
 
 
static void
static void
reverse_stepi (char *args, int from_tty)
reverse_stepi (char *args, int from_tty)
{
{
  exec_reverse_once ("stepi", args, from_tty);
  exec_reverse_once ("stepi", args, from_tty);
}
}
 
 
static void
static void
reverse_next (char *args, int from_tty)
reverse_next (char *args, int from_tty)
{
{
  exec_reverse_once ("next", args, from_tty);
  exec_reverse_once ("next", args, from_tty);
}
}
 
 
static void
static void
reverse_nexti (char *args, int from_tty)
reverse_nexti (char *args, int from_tty)
{
{
  exec_reverse_once ("nexti", args, from_tty);
  exec_reverse_once ("nexti", args, from_tty);
}
}
 
 
static void
static void
reverse_continue (char *args, int from_tty)
reverse_continue (char *args, int from_tty)
{
{
  exec_reverse_once ("continue", args, from_tty);
  exec_reverse_once ("continue", args, from_tty);
}
}
 
 
static void
static void
reverse_finish (char *args, int from_tty)
reverse_finish (char *args, int from_tty)
{
{
  exec_reverse_once ("finish", args, from_tty);
  exec_reverse_once ("finish", args, from_tty);
}
}
 
 
/* Data structures for a bookmark list.  */
/* Data structures for a bookmark list.  */
 
 
struct bookmark {
struct bookmark {
  struct bookmark *next;
  struct bookmark *next;
  int number;
  int number;
  CORE_ADDR pc;
  CORE_ADDR pc;
  struct symtab_and_line sal;
  struct symtab_and_line sal;
  gdb_byte *opaque_data;
  gdb_byte *opaque_data;
};
};
 
 
static struct bookmark *bookmark_chain;
static struct bookmark *bookmark_chain;
static int bookmark_count;
static int bookmark_count;
 
 
#define ALL_BOOKMARKS(B) for ((B) = bookmark_chain; (B); (B) = (B)->next)
#define ALL_BOOKMARKS(B) for ((B) = bookmark_chain; (B); (B) = (B)->next)
 
 
#define ALL_BOOKMARKS_SAFE(B,TMP)           \
#define ALL_BOOKMARKS_SAFE(B,TMP)           \
     for ((B) = bookmark_chain;             \
     for ((B) = bookmark_chain;             \
          (B) ? ((TMP) = (B)->next, 1) : 0; \
          (B) ? ((TMP) = (B)->next, 1) : 0; \
          (B) = (TMP))
          (B) = (TMP))
 
 
/* save_bookmark_command -- implement "bookmark" command.
/* save_bookmark_command -- implement "bookmark" command.
   Call target method to get a bookmark identifier.
   Call target method to get a bookmark identifier.
   Insert bookmark identifier into list.
   Insert bookmark identifier into list.
 
 
   Identifier will be a malloc string (gdb_byte *).
   Identifier will be a malloc string (gdb_byte *).
   Up to us to free it as required.  */
   Up to us to free it as required.  */
 
 
static void
static void
save_bookmark_command (char *args, int from_tty)
save_bookmark_command (char *args, int from_tty)
{
{
  /* Get target's idea of a bookmark.  */
  /* Get target's idea of a bookmark.  */
  gdb_byte *bookmark_id = target_get_bookmark (args, from_tty);
  gdb_byte *bookmark_id = target_get_bookmark (args, from_tty);
  struct bookmark *b, *b1;
  struct bookmark *b, *b1;
  struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
  struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
 
 
  /* CR should not cause another identical bookmark.  */
  /* CR should not cause another identical bookmark.  */
  dont_repeat ();
  dont_repeat ();
 
 
  if (bookmark_id == NULL)
  if (bookmark_id == NULL)
    error (_("target_get_bookmark failed."));
    error (_("target_get_bookmark failed."));
 
 
  /* Set up a bookmark struct.  */
  /* Set up a bookmark struct.  */
  b = xcalloc (1, sizeof (struct bookmark));
  b = xcalloc (1, sizeof (struct bookmark));
  b->number = ++bookmark_count;
  b->number = ++bookmark_count;
  init_sal (&b->sal);
  init_sal (&b->sal);
  b->pc = regcache_read_pc (get_current_regcache ());
  b->pc = regcache_read_pc (get_current_regcache ());
  b->sal = find_pc_line (b->pc, 0);
  b->sal = find_pc_line (b->pc, 0);
  b->sal.pspace = get_frame_program_space (get_current_frame ());
  b->sal.pspace = get_frame_program_space (get_current_frame ());
  b->opaque_data = bookmark_id;
  b->opaque_data = bookmark_id;
  b->next = NULL;
  b->next = NULL;
 
 
  /* Add this bookmark to the end of the chain, so that a list
  /* Add this bookmark to the end of the chain, so that a list
     of bookmarks will come out in order of increasing numbers.  */
     of bookmarks will come out in order of increasing numbers.  */
 
 
  b1 = bookmark_chain;
  b1 = bookmark_chain;
  if (b1 == 0)
  if (b1 == 0)
    bookmark_chain = b;
    bookmark_chain = b;
  else
  else
    {
    {
      while (b1->next)
      while (b1->next)
        b1 = b1->next;
        b1 = b1->next;
      b1->next = b;
      b1->next = b;
    }
    }
  printf_filtered (_("Saved bookmark %d at %s\n"), b->number,
  printf_filtered (_("Saved bookmark %d at %s\n"), b->number,
                     paddress (gdbarch, b->sal.pc));
                     paddress (gdbarch, b->sal.pc));
}
}
 
 
/* Implement "delete bookmark" command.  */
/* Implement "delete bookmark" command.  */
 
 
static int
static int
delete_one_bookmark (struct bookmark *b)
delete_one_bookmark (struct bookmark *b)
{
{
  struct bookmark *b1;
  struct bookmark *b1;
 
 
  /* Special case, first item in list.  */
  /* Special case, first item in list.  */
  if (b == bookmark_chain)
  if (b == bookmark_chain)
    bookmark_chain = b->next;
    bookmark_chain = b->next;
 
 
  /* Find bookmark preceeding "marked" one, so we can unlink.  */
  /* Find bookmark preceeding "marked" one, so we can unlink.  */
  if (b)
  if (b)
    {
    {
      ALL_BOOKMARKS (b1)
      ALL_BOOKMARKS (b1)
        if (b1->next == b)
        if (b1->next == b)
          {
          {
            /* Found designated bookmark.  Unlink and delete.  */
            /* Found designated bookmark.  Unlink and delete.  */
            b1->next = b->next;
            b1->next = b->next;
            break;
            break;
          }
          }
      xfree (b->opaque_data);
      xfree (b->opaque_data);
      xfree (b);
      xfree (b);
      return 1;         /* success */
      return 1;         /* success */
    }
    }
  return 0;              /* failure */
  return 0;              /* failure */
}
}
 
 
static void
static void
delete_all_bookmarks (void)
delete_all_bookmarks (void)
{
{
  struct bookmark *b, *b1;
  struct bookmark *b, *b1;
 
 
  ALL_BOOKMARKS_SAFE (b, b1)
  ALL_BOOKMARKS_SAFE (b, b1)
    {
    {
      xfree (b->opaque_data);
      xfree (b->opaque_data);
      xfree (b);
      xfree (b);
    }
    }
  bookmark_chain = NULL;
  bookmark_chain = NULL;
}
}
 
 
static void
static void
delete_bookmark_command (char *args, int from_tty)
delete_bookmark_command (char *args, int from_tty)
{
{
  struct bookmark *b, *b1;
  struct bookmark *b, *b1;
  unsigned long num;
  unsigned long num;
 
 
  if (bookmark_chain == NULL)
  if (bookmark_chain == NULL)
    {
    {
      warning (_("No bookmarks."));
      warning (_("No bookmarks."));
      return;
      return;
    }
    }
 
 
  if (args == NULL || args[0] == '\0')
  if (args == NULL || args[0] == '\0')
    {
    {
      if (from_tty && !query (_("Delete all bookmarks? ")))
      if (from_tty && !query (_("Delete all bookmarks? ")))
        return;
        return;
      delete_all_bookmarks ();
      delete_all_bookmarks ();
      return;
      return;
    }
    }
 
 
  num = strtoul (args, NULL, 0);
  num = strtoul (args, NULL, 0);
  /* Find bookmark with corresponding number.  */
  /* Find bookmark with corresponding number.  */
  ALL_BOOKMARKS (b)
  ALL_BOOKMARKS (b)
    if (b->number == num)
    if (b->number == num)
      break;
      break;
 
 
  if (!delete_one_bookmark (b))
  if (!delete_one_bookmark (b))
    /* Not found.  */
    /* Not found.  */
    error (_("delete bookmark: no bookmark found for '%s'."), args);
    error (_("delete bookmark: no bookmark found for '%s'."), args);
}
}
 
 
/* Implement "goto-bookmark" command.  */
/* Implement "goto-bookmark" command.  */
 
 
static void
static void
goto_bookmark_command (char *args, int from_tty)
goto_bookmark_command (char *args, int from_tty)
{
{
  struct bookmark *b;
  struct bookmark *b;
  unsigned long num;
  unsigned long num;
 
 
  if (args == NULL || args[0] == '\0')
  if (args == NULL || args[0] == '\0')
    error (_("Command requires an argument."));
    error (_("Command requires an argument."));
 
 
  if (strncmp (args, "start", strlen ("start")) == 0
  if (strncmp (args, "start", strlen ("start")) == 0
      || strncmp (args, "begin", strlen ("begin")) == 0
      || strncmp (args, "begin", strlen ("begin")) == 0
      || strncmp (args, "end",   strlen ("end")) == 0)
      || strncmp (args, "end",   strlen ("end")) == 0)
    {
    {
      /* Special case.  Give target opportunity to handle.  */
      /* Special case.  Give target opportunity to handle.  */
      target_goto_bookmark (args, from_tty);
      target_goto_bookmark (args, from_tty);
      return;
      return;
    }
    }
 
 
  if (args[0] == '\'' || args[0] == '\"')
  if (args[0] == '\'' || args[0] == '\"')
    {
    {
      /* Special case -- quoted string.  Pass on to target.  */
      /* Special case -- quoted string.  Pass on to target.  */
      if (args[strlen (args) - 1] != args[0])
      if (args[strlen (args) - 1] != args[0])
        error (_("Unbalanced quotes: %s"), args);
        error (_("Unbalanced quotes: %s"), args);
      target_goto_bookmark (args, from_tty);
      target_goto_bookmark (args, from_tty);
      return;
      return;
    }
    }
 
 
  /* General case.  Bookmark identified by bookmark number.  */
  /* General case.  Bookmark identified by bookmark number.  */
  num = strtoul (args, NULL, 0);
  num = strtoul (args, NULL, 0);
  ALL_BOOKMARKS (b)
  ALL_BOOKMARKS (b)
    if (b->number == num)
    if (b->number == num)
      break;
      break;
 
 
  if (b)
  if (b)
    {
    {
      /* Found.  Send to target method.  */
      /* Found.  Send to target method.  */
      target_goto_bookmark (b->opaque_data, from_tty);
      target_goto_bookmark (b->opaque_data, from_tty);
      return;
      return;
    }
    }
  /* Not found.  */
  /* Not found.  */
  error (_("goto-bookmark: no bookmark found for '%s'."), args);
  error (_("goto-bookmark: no bookmark found for '%s'."), args);
}
}
 
 
/* Implement "info bookmarks" command.  */
/* Implement "info bookmarks" command.  */
 
 
static void
static void
bookmarks_info (char *args, int from_tty)
bookmarks_info (char *args, int from_tty)
{
{
  struct bookmark *b;
  struct bookmark *b;
  int bnum = -1;
  int bnum = -1;
  struct gdbarch *gdbarch;
  struct gdbarch *gdbarch;
 
 
  if (args)
  if (args)
    bnum = parse_and_eval_long (args);
    bnum = parse_and_eval_long (args);
 
 
  if (!bookmark_chain)
  if (!bookmark_chain)
    {
    {
      printf_filtered (_("No bookmarks.\n"));
      printf_filtered (_("No bookmarks.\n"));
      return;
      return;
    }
    }
 
 
  gdbarch = get_regcache_arch (get_current_regcache ());
  gdbarch = get_regcache_arch (get_current_regcache ());
  printf_filtered (_("Bookmark    Address     Opaque\n"));
  printf_filtered (_("Bookmark    Address     Opaque\n"));
  printf_filtered (_("   ID                    Data \n"));
  printf_filtered (_("   ID                    Data \n"));
 
 
  ALL_BOOKMARKS (b)
  ALL_BOOKMARKS (b)
    printf_filtered ("   %d       %s    '%s'\n",
    printf_filtered ("   %d       %s    '%s'\n",
                     b->number,
                     b->number,
                     paddress (gdbarch, b->pc),
                     paddress (gdbarch, b->pc),
                     b->opaque_data);
                     b->opaque_data);
}
}
 
 
 
 
/* Provide a prototype to silence -Wmissing-prototypes.  */
/* Provide a prototype to silence -Wmissing-prototypes.  */
extern initialize_file_ftype _initialize_reverse;
extern initialize_file_ftype _initialize_reverse;
 
 
void
void
_initialize_reverse (void)
_initialize_reverse (void)
{
{
  add_com ("reverse-step", class_run, reverse_step, _("\
  add_com ("reverse-step", class_run, reverse_step, _("\
Step program backward until it reaches the beginning of another source line.\n\
Step program backward until it reaches the beginning of another source line.\n\
Argument N means do this N times (or till program stops for another reason).")
Argument N means do this N times (or till program stops for another reason).")
           );
           );
  add_com_alias ("rs", "reverse-step", class_alias, 1);
  add_com_alias ("rs", "reverse-step", class_alias, 1);
 
 
  add_com ("reverse-next", class_run, reverse_next, _("\
  add_com ("reverse-next", class_run, reverse_next, _("\
Step program backward, proceeding through subroutine calls.\n\
Step program backward, proceeding through subroutine calls.\n\
Like the \"reverse-step\" command as long as subroutine calls do not happen;\n\
Like the \"reverse-step\" command as long as subroutine calls do not happen;\n\
when they do, the call is treated as one instruction.\n\
when they do, the call is treated as one instruction.\n\
Argument N means do this N times (or till program stops for another reason).")
Argument N means do this N times (or till program stops for another reason).")
           );
           );
  add_com_alias ("rn", "reverse-next", class_alias, 1);
  add_com_alias ("rn", "reverse-next", class_alias, 1);
 
 
  add_com ("reverse-stepi", class_run, reverse_stepi, _("\
  add_com ("reverse-stepi", class_run, reverse_stepi, _("\
Step backward exactly one instruction.\n\
Step backward exactly one instruction.\n\
Argument N means do this N times (or till program stops for another reason).")
Argument N means do this N times (or till program stops for another reason).")
           );
           );
  add_com_alias ("rsi", "reverse-stepi", class_alias, 0);
  add_com_alias ("rsi", "reverse-stepi", class_alias, 0);
 
 
  add_com ("reverse-nexti", class_run, reverse_nexti, _("\
  add_com ("reverse-nexti", class_run, reverse_nexti, _("\
Step backward one instruction, but proceed through called subroutines.\n\
Step backward one instruction, but proceed through called subroutines.\n\
Argument N means do this N times (or till program stops for another reason).")
Argument N means do this N times (or till program stops for another reason).")
           );
           );
  add_com_alias ("rni", "reverse-nexti", class_alias, 0);
  add_com_alias ("rni", "reverse-nexti", class_alias, 0);
 
 
  add_com ("reverse-continue", class_run, reverse_continue, _("\
  add_com ("reverse-continue", class_run, reverse_continue, _("\
Continue program being debugged but run it in reverse.\n\
Continue program being debugged but run it in reverse.\n\
If proceeding from breakpoint, a number N may be used as an argument,\n\
If proceeding from breakpoint, a number N may be used as an argument,\n\
which means to set the ignore count of that breakpoint to N - 1 (so that\n\
which means to set the ignore count of that breakpoint to N - 1 (so that\n\
the breakpoint won't break until the Nth time it is reached)."));
the breakpoint won't break until the Nth time it is reached)."));
  add_com_alias ("rc", "reverse-continue", class_alias, 0);
  add_com_alias ("rc", "reverse-continue", class_alias, 0);
 
 
  add_com ("reverse-finish", class_run, reverse_finish, _("\
  add_com ("reverse-finish", class_run, reverse_finish, _("\
Execute backward until just before selected stack frame is called."));
Execute backward until just before selected stack frame is called."));
 
 
  add_com ("bookmark", class_bookmark, save_bookmark_command, _("\
  add_com ("bookmark", class_bookmark, save_bookmark_command, _("\
Set a bookmark in the program's execution history.\n\
Set a bookmark in the program's execution history.\n\
A bookmark represents a point in the execution history \n\
A bookmark represents a point in the execution history \n\
that can be returned to at a later point in the debug session."));
that can be returned to at a later point in the debug session."));
  add_info ("bookmarks", bookmarks_info, _("\
  add_info ("bookmarks", bookmarks_info, _("\
Status of user-settable bookmarks.\n\
Status of user-settable bookmarks.\n\
Bookmarks are user-settable markers representing a point in the \n\
Bookmarks are user-settable markers representing a point in the \n\
execution history that can be returned to later in the same debug \n\
execution history that can be returned to later in the same debug \n\
session."));
session."));
  add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\
  add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\
Delete a bookmark from the bookmark list.\n\
Delete a bookmark from the bookmark list.\n\
Argument is a bookmark number, or no argument to delete all bookmarks.\n"),
Argument is a bookmark number, or no argument to delete all bookmarks.\n"),
           &deletelist);
           &deletelist);
  add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\
  add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\
Go to an earlier-bookmarked point in the program's execution history.\n\
Go to an earlier-bookmarked point in the program's execution history.\n\
Argument is the bookmark number of a bookmark saved earlier by using \n\
Argument is the bookmark number of a bookmark saved earlier by using \n\
the 'bookmark' command, or the special arguments:\n\
the 'bookmark' command, or the special arguments:\n\
  start (beginning of recording)\n\
  start (beginning of recording)\n\
  end   (end of recording)\n"));
  end   (end of recording)\n"));
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.