windows-nat: Cleanups in get_windows_debug_event
[deliverable/binutils-gdb.git] / gdb / record-full.c
index d35165b90a705620453b5e17292b59e8b81bef8c..43e8be23b6c775618df0e3b8c2e274995002a426 100644 (file)
@@ -1,6 +1,6 @@
 /* Process record and replay target for GDB, the GNU debugger.
 
-   Copyright (C) 2013-2014 Free Software Foundation, Inc.
+   Copyright (C) 2013-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,7 +22,6 @@
 #include "regcache.h"
 #include "gdbthread.h"
 #include "event-top.h"
-#include "exceptions.h"
 #include "completer.h"
 #include "arch-utils.h"
 #include "gdbcore.h"
@@ -35,6 +34,7 @@
 #include "inf-loop.h"
 #include "gdb_bfd.h"
 #include "observer.h"
+#include "infrun.h"
 
 #include <signal.h>
 
@@ -688,7 +688,8 @@ record_full_gdb_operation_disable_set (void)
 }
 
 /* Flag set to TRUE for target_stopped_by_watchpoint.  */
-static int record_full_hw_watchpoint = 0;
+static enum target_stop_reason record_full_stop_reason
+  = TARGET_STOPPED_BY_NO_REASON;
 
 /* Execute one instruction from the record log.  Each instruction in
    the log will be represented by an arbitrary sequence of register
@@ -766,7 +767,7 @@ record_full_exec_insn (struct regcache *regcache,
                    if (hardware_watchpoint_inserted_in_range
                        (get_regcache_aspace (regcache),
                         entry->u.mem.addr, entry->u.mem.len))
-                     record_full_hw_watchpoint = 1;
+                     record_full_stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
                  }
               }
           }
@@ -791,7 +792,7 @@ record_full_async_inferior_event_handler (gdb_client_data data)
 /* Open the process record target.  */
 
 static void
-record_full_core_open_1 (char *name, int from_tty)
+record_full_core_open_1 (const char *name, int from_tty)
 {
   struct regcache *regcache = get_current_regcache ();
   int regnum = gdbarch_num_regs (get_regcache_arch (regcache));
@@ -821,7 +822,7 @@ record_full_core_open_1 (char *name, int from_tty)
 /* "to_open" target method for 'live' processes.  */
 
 static void
-record_full_open_1 (char *name, int from_tty)
+record_full_open_1 (const char *name, int from_tty)
 {
   if (record_debug)
     fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n");
@@ -845,7 +846,7 @@ static void record_full_init_record_breakpoints (void);
 /* "to_open" target method.  Open the process record target.  */
 
 static void
-record_full_open (char *name, int from_tty)
+record_full_open (const char *name, int from_tty)
 {
   struct target_ops *t;
 
@@ -910,6 +911,19 @@ record_full_close (struct target_ops *self)
     delete_async_event_handler (&record_full_async_inferior_event_token);
 }
 
+/* "to_async" target method.  */
+
+static void
+record_full_async (struct target_ops *ops, int enable)
+{
+  if (enable)
+    mark_async_event_handler (record_full_async_inferior_event_token);
+  else
+    clear_async_event_handler (record_full_async_inferior_event_token);
+
+  ops->beneath->to_async (ops->beneath, enable);
+}
+
 static int record_full_resume_step = 0;
 
 /* True if we've been resumed, and so each record_full_wait call should
@@ -960,7 +974,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
           else
             {
               /* This arch support soft sigle step.  */
-              if (single_step_breakpoints_inserted ())
+              if (thread_has_single_step_breakpoints_set (inferior_thread ()))
                 {
                   /* This is a soft single step.  */
                   record_full_resume_step = 1;
@@ -989,12 +1003,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
   /* We are about to start executing the inferior (or simulate it),
      let's register it with the event loop.  */
   if (target_can_async_p ())
-    {
-      target_async (inferior_event_handler, 0);
-      /* Notify the event loop there's an event to wait for.  We do
-        most of the work in record_full_wait.  */
-      mark_async_event_handler (record_full_async_inferior_event_token);
-    }
+    target_async (1);
 }
 
 static int record_full_get_sig = 0;
@@ -1068,6 +1077,8 @@ record_full_wait_1 (struct target_ops *ops,
   record_full_get_sig = 0;
   signal (SIGINT, record_full_sig_handler);
 
+  record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON;
+
   if (!RECORD_FULL_IS_REPLAY && ops != &record_full_core_ops)
     {
       if (record_full_resume_step)
@@ -1084,6 +1095,8 @@ record_full_wait_1 (struct target_ops *ops,
 
          while (1)
            {
+             struct thread_info *tp;
+
              ret = ops->beneath->to_wait (ops->beneath, ptid, status, options);
              if (status->kind == TARGET_WAITKIND_IGNORE)
                {
@@ -1094,8 +1107,8 @@ record_full_wait_1 (struct target_ops *ops,
                  return ret;
                }
 
-              if (single_step_breakpoints_inserted ())
-                remove_single_step_breakpoints ();
+             ALL_NON_EXITED_THREADS (tp)
+                delete_single_step_breakpoints (tp);
 
              if (record_full_resume_step)
                return ret;
@@ -1106,6 +1119,8 @@ record_full_wait_1 (struct target_ops *ops,
                {
                  struct regcache *regcache;
                  struct address_space *aspace;
+                 enum target_stop_reason *stop_reason_p
+                   = &record_full_stop_reason;
 
                  /* Yes -- this is likely our single-step finishing,
                     but check if there's any reason the core would be
@@ -1120,20 +1135,11 @@ record_full_wait_1 (struct target_ops *ops,
                    {
                      /* Always interested in watchpoints.  */
                    }
-                 else if (breakpoint_inserted_here_p (aspace, tmp_pc))
+                 else if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
+                                                              stop_reason_p))
                    {
                      /* There is a breakpoint here.  Let the core
                         handle it.  */
-                     if (software_breakpoint_inserted_here_p (aspace, tmp_pc))
-                       {
-                         struct gdbarch *gdbarch
-                           = get_regcache_arch (regcache);
-                         CORE_ADDR decr_pc_after_break
-                           = target_decr_pc_after_break (gdbarch);
-                         if (decr_pc_after_break)
-                           regcache_write_pc (regcache,
-                                              tmp_pc + decr_pc_after_break);
-                       }
                    }
                  else
                    {
@@ -1192,27 +1198,20 @@ record_full_wait_1 (struct target_ops *ops,
        = make_cleanup (record_full_wait_cleanups, 0);
       CORE_ADDR tmp_pc;
 
-      record_full_hw_watchpoint = 0;
+      record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON;
       status->kind = TARGET_WAITKIND_STOPPED;
 
       /* Check breakpoint when forward execute.  */
       if (execution_direction == EXEC_FORWARD)
        {
          tmp_pc = regcache_read_pc (regcache);
-         if (breakpoint_inserted_here_p (aspace, tmp_pc))
+         if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
+                                                 &record_full_stop_reason))
            {
-             int decr_pc_after_break = target_decr_pc_after_break (gdbarch);
-
              if (record_debug)
                fprintf_unfiltered (gdb_stdlog,
                                    "Process record: break at %s.\n",
                                    paddress (gdbarch, tmp_pc));
-
-             if (decr_pc_after_break
-                 && !record_full_resume_step
-                 && software_breakpoint_inserted_here_p (aspace, tmp_pc))
-               regcache_write_pc (regcache,
-                                  tmp_pc + decr_pc_after_break);
              goto replay_out;
            }
        }
@@ -1280,27 +1279,19 @@ record_full_wait_1 (struct target_ops *ops,
 
                  /* check breakpoint */
                  tmp_pc = regcache_read_pc (regcache);
-                 if (breakpoint_inserted_here_p (aspace, tmp_pc))
+                 if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
+                                                         &record_full_stop_reason))
                    {
-                     int decr_pc_after_break
-                       = target_decr_pc_after_break (gdbarch);
-
                      if (record_debug)
                        fprintf_unfiltered (gdb_stdlog,
                                            "Process record: break "
                                            "at %s.\n",
                                            paddress (gdbarch, tmp_pc));
-                     if (decr_pc_after_break
-                         && execution_direction == EXEC_FORWARD
-                         && !record_full_resume_step
-                         && software_breakpoint_inserted_here_p (aspace,
-                                                                 tmp_pc))
-                       regcache_write_pc (regcache,
-                                          tmp_pc + decr_pc_after_break);
+
                      continue_flag = 0;
                    }
 
-                 if (record_full_hw_watchpoint)
+                 if (record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT)
                    {
                      if (record_debug)
                        fprintf_unfiltered (gdb_stdlog,
@@ -1371,7 +1362,7 @@ static int
 record_full_stopped_by_watchpoint (struct target_ops *ops)
 {
   if (RECORD_FULL_IS_REPLAY)
-    return record_full_hw_watchpoint;
+    return record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
   else
     return ops->beneath->to_stopped_by_watchpoint (ops->beneath);
 }
@@ -1385,6 +1376,40 @@ record_full_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
     return ops->beneath->to_stopped_data_address (ops->beneath, addr_p);
 }
 
+/* The to_stopped_by_sw_breakpoint method of target record-full.  */
+
+static int
+record_full_stopped_by_sw_breakpoint (struct target_ops *ops)
+{
+  return record_full_stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
+}
+
+/* The to_supports_stopped_by_sw_breakpoint method of target
+   record-full.  */
+
+static int
+record_full_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
+{
+  return 1;
+}
+
+/* The to_stopped_by_hw_breakpoint method of target record-full.  */
+
+static int
+record_full_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+  return record_full_stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
+}
+
+/* The to_supports_stopped_by_sw_breakpoint method of target
+   record-full.  */
+
+static int
+record_full_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+  return 1;
+}
+
 /* Record registers change (by user or by GDB) to list as an instruction.  */
 
 static void
@@ -1702,7 +1727,8 @@ record_full_can_execute_reverse (struct target_ops *self)
 /* "to_get_bookmark" method for process record and prec over core.  */
 
 static gdb_byte *
-record_full_get_bookmark (struct target_ops *self, char *args, int from_tty)
+record_full_get_bookmark (struct target_ops *self, const char *args,
+                         int from_tty)
 {
   char *ret = NULL;
 
@@ -1726,9 +1752,10 @@ record_full_get_bookmark (struct target_ops *self, char *args, int from_tty)
 
 static void
 record_full_goto_bookmark (struct target_ops *self,
-                          gdb_byte *raw_bookmark, int from_tty)
+                          const gdb_byte *raw_bookmark, int from_tty)
 {
-  char *bookmark = (char *) raw_bookmark;
+  const char *bookmark = (const char *) raw_bookmark;
+  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
 
   if (record_debug)
     fprintf_unfiltered (gdb_stdlog,
@@ -1736,32 +1763,20 @@ record_full_goto_bookmark (struct target_ops *self,
 
   if (bookmark[0] == '\'' || bookmark[0] == '\"')
     {
+      char *copy;
+
       if (bookmark[strlen (bookmark) - 1] != bookmark[0])
        error (_("Unbalanced quotes: %s"), bookmark);
 
-      /* Strip trailing quote.  */
-      bookmark[strlen (bookmark) - 1] = '\0';
-      /* Strip leading quote.  */
-      bookmark++;
-      /* Pass along to cmd_record_full_goto.  */
-    }
 
-  cmd_record_goto (bookmark, from_tty);
-  return;
-}
+      copy = savestring (bookmark + 1, strlen (bookmark) - 2);
+      make_cleanup (xfree, copy);
+      bookmark = copy;
+    }
 
-static int
-record_full_can_async_p (struct target_ops *ops)
-{
-  /* We only enable async when the user specifically asks for it.  */
-  return target_async_permitted;
-}
+  record_goto (bookmark);
 
-static int
-record_full_is_async_p (struct target_ops *ops)
-{
-  /* We only enable async when the user specifically asks for it.  */
-  return target_async_permitted;
+  do_cleanups (cleanup);
 }
 
 static enum exec_direction_kind
@@ -1910,26 +1925,32 @@ init_record_full_ops (void)
     "Log program while executing and replay execution from log.";
   record_full_ops.to_open = record_full_open;
   record_full_ops.to_close = record_full_close;
+  record_full_ops.to_async = record_full_async;
   record_full_ops.to_resume = record_full_resume;
   record_full_ops.to_wait = record_full_wait;
   record_full_ops.to_disconnect = record_disconnect;
   record_full_ops.to_detach = record_detach;
   record_full_ops.to_mourn_inferior = record_mourn_inferior;
   record_full_ops.to_kill = record_kill;
-  record_full_ops.to_create_inferior = find_default_create_inferior;
   record_full_ops.to_store_registers = record_full_store_registers;
   record_full_ops.to_xfer_partial = record_full_xfer_partial;
   record_full_ops.to_insert_breakpoint = record_full_insert_breakpoint;
   record_full_ops.to_remove_breakpoint = record_full_remove_breakpoint;
   record_full_ops.to_stopped_by_watchpoint = record_full_stopped_by_watchpoint;
   record_full_ops.to_stopped_data_address = record_full_stopped_data_address;
+  record_full_ops.to_stopped_by_sw_breakpoint
+    = record_full_stopped_by_sw_breakpoint;
+  record_full_ops.to_supports_stopped_by_sw_breakpoint
+    = record_full_supports_stopped_by_sw_breakpoint;
+  record_full_ops.to_stopped_by_hw_breakpoint
+    = record_full_stopped_by_hw_breakpoint;
+  record_full_ops.to_supports_stopped_by_hw_breakpoint
+    = record_full_supports_stopped_by_hw_breakpoint;
   record_full_ops.to_can_execute_reverse = record_full_can_execute_reverse;
   record_full_ops.to_stratum = record_stratum;
   /* Add bookmark target methods.  */
   record_full_ops.to_get_bookmark = record_full_get_bookmark;
   record_full_ops.to_goto_bookmark = record_full_goto_bookmark;
-  record_full_ops.to_can_async_p = record_full_can_async_p;
-  record_full_ops.to_is_async_p = record_full_is_async_p;
   record_full_ops.to_execution_direction = record_full_execution_direction;
   record_full_ops.to_info_record = record_full_info;
   record_full_ops.to_save_record = record_full_save;
@@ -1954,12 +1975,7 @@ record_full_core_resume (struct target_ops *ops, ptid_t ptid, int step,
   /* We are about to start executing the inferior (or simulate it),
      let's register it with the event loop.  */
   if (target_can_async_p ())
-    {
-      target_async (inferior_event_handler, 0);
-
-      /* Notify the event loop there's an event to wait for.  */
-      mark_async_event_handler (record_full_async_inferior_event_token);
-    }
+    target_async (1);
 }
 
 /* "to_kill" method for prec over corefile.  */
@@ -2152,6 +2168,7 @@ init_record_full_core_ops (void)
     "Log program while executing and replay execution from log.";
   record_full_core_ops.to_open = record_full_open;
   record_full_core_ops.to_close = record_full_close;
+  record_full_core_ops.to_async = record_full_async;
   record_full_core_ops.to_resume = record_full_core_resume;
   record_full_core_ops.to_wait = record_full_wait;
   record_full_core_ops.to_kill = record_full_core_kill;
@@ -2167,6 +2184,14 @@ init_record_full_core_ops (void)
     = record_full_stopped_by_watchpoint;
   record_full_core_ops.to_stopped_data_address
     = record_full_stopped_data_address;
+  record_full_core_ops.to_stopped_by_sw_breakpoint
+    = record_full_stopped_by_sw_breakpoint;
+  record_full_core_ops.to_supports_stopped_by_sw_breakpoint
+    = record_full_supports_stopped_by_sw_breakpoint;
+  record_full_core_ops.to_stopped_by_hw_breakpoint
+    = record_full_stopped_by_hw_breakpoint;
+  record_full_core_ops.to_supports_stopped_by_hw_breakpoint
+    = record_full_supports_stopped_by_hw_breakpoint;
   record_full_core_ops.to_can_execute_reverse
     = record_full_can_execute_reverse;
   record_full_core_ops.to_has_execution = record_full_core_has_execution;
@@ -2174,8 +2199,6 @@ init_record_full_core_ops (void)
   /* Add bookmark target methods.  */
   record_full_core_ops.to_get_bookmark = record_full_get_bookmark;
   record_full_core_ops.to_goto_bookmark = record_full_goto_bookmark;
-  record_full_core_ops.to_can_async_p = record_full_can_async_p;
-  record_full_core_ops.to_is_async_p = record_full_is_async_p;
   record_full_core_ops.to_execution_direction
     = record_full_execution_direction;
   record_full_core_ops.to_info_record = record_full_info;
This page took 0.029854 seconds and 4 git commands to generate.