Fix "is a record target open" checks.
authorPedro Alves <palves@redhat.com>
Tue, 14 Jan 2014 16:12:19 +0000 (16:12 +0000)
committerPedro Alves <palves@redhat.com>
Tue, 14 Jan 2014 16:12:19 +0000 (16:12 +0000)
RECORD_IS_USED and record_full_open look at current_target.to_stratum
to determine whether a record target is in use.  This is wrong because
arch_stratum is greater than record_stratum, so if an arch_stratum
target is pushed, RECORD_IS_USED and record_full_open will miss it.

To fix this, we can use the existing find_record_target instead, which
looks up for a record stratum target across the target stack.  Since
that means exporting find_record_target in record.h, RECORD_IS_USED
ends up redundant, so the patch eliminates it.

That exercise then reveals other issues:

- adjust_pc_after_break is gating record_full_... calls based on
RECORD_IS_USED.  But, record_full_ calls shouldn't be made when
recording with the record-btrace target.  So this adds a new
record_full_is_used predicate to be used in that spot.

- record_full_open says "Process record target already running", even
if the recording target is record-btrace ("process record" is the
original complete name of the record-full target).  record_btrace_open
only says "The process is already being recorded." and does not
suggest "record stop", like record-full does.  The patch factors out
and merges that error to a new record_preopen function that all record
targets call in their open routine.

Tested on x86_64 Fedora 17.

gdb/
2014-01-14  Pedro Alves  <palves@redhat.com>
    Tom Tromey  <tromey@redhat.com>

* infrun.c (use_displaced_stepping): Use find_record_target
instead of RECORD_IS_USED.
(adjust_pc_after_break): Use record_full_is_used instead of
RECORD_IS_USED.
* record-btrace.c (record_btrace_open): Call record_preopen
instead of checking RECORD_IS_USED.
* record-full.c (record_full_shortname)
(record_full_core_shortname): New globals.
(record_full_is_used): New function.
(find_full_open): Call record_preopen instead of checking
RECORD_IS_USED.
(init_record_full_ops): Set the target's shortname to
record_full_shortname.
(init_record_full_core_ops): Set the target's shortname to
record_full_core_shortname.
* record-full.h (record_full_is_used): Declare.
* record.c (find_record_target): Make extern.
(record_preopen): New function.
* record.h (RECORD_IS_USED): Delete macro.
(find_record_target, record_preopen): Declare functions.

gdb/ChangeLog
gdb/infrun.c
gdb/record-btrace.c
gdb/record-full.c
gdb/record-full.h
gdb/record.c
gdb/record.h

index 40e703f9b9e395be93a3f2f3ef7712c75eb1b370..3daf77fa4eec66669e34fbb5d62518079415878b 100644 (file)
@@ -1,3 +1,27 @@
+2014-01-14  Pedro Alves  <palves@redhat.com>
+           Tom Tromey  <tromey@redhat.com>
+
+       * infrun.c (use_displaced_stepping): Use find_record_target
+       instead of RECORD_IS_USED.
+       (adjust_pc_after_break): Use record_full_is_used instead of
+       RECORD_IS_USED.
+       * record-btrace.c (record_btrace_open): Call record_preopen
+       instead of checking RECORD_IS_USED.
+       * record-full.c (record_full_shortname)
+       (record_full_core_shortname): New globals.
+       (record_full_is_used): New function.
+       (find_full_open): Call record_preopen instead of checking
+       RECORD_IS_USED.
+       (init_record_full_ops): Set the target's shortname to
+       record_full_shortname.
+       (init_record_full_core_ops): Set the target's shortname to
+       record_full_core_shortname.
+       * record-full.h (record_full_is_used): Declare.
+       * record.c (find_record_target): Make extern.
+       (record_preopen): New function.
+       * record.h (RECORD_IS_USED): Delete macro.
+       (find_record_target, record_preopen): Declare functions.
+
 2014-01-14  Yao Qi  <yao@codesourcery.com>
 
        * gdbarch.sh (core_xfer_shared_libraries): Change its argument
index 73038a396eda36b5c97543243f326c05b8c9b663..311bf9c4359b92cbf574b06bec814c4a1e4f5448 100644 (file)
@@ -1240,7 +1240,7 @@ use_displaced_stepping (struct gdbarch *gdbarch)
   return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO && non_stop)
           || can_use_displaced_stepping == AUTO_BOOLEAN_TRUE)
          && gdbarch_displaced_step_copy_insn_p (gdbarch)
-         && !RECORD_IS_USED);
+         && find_record_target () == NULL);
 }
 
 /* Clean out any stray displaced stepping state.  */
@@ -3048,7 +3048,7 @@ adjust_pc_after_break (struct execution_control_state *ecs)
     {
       struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
 
-      if (RECORD_IS_USED)
+      if (record_full_is_used ())
        record_full_gdb_operation_disable_set ();
 
       /* When using hardware single-step, a SIGTRAP is reported for both
index 5fd26e257cc41e4193a27070ac20726f5a66274f..c3330e937205267e063dd3eaff46487d22174772 100644 (file)
@@ -142,8 +142,7 @@ record_btrace_open (char *args, int from_tty)
 
   DEBUG ("open");
 
-  if (RECORD_IS_USED)
-    error (_("The process is already being recorded."));
+  record_preopen ();
 
   if (!target_has_execution)
     error (_("The program is not being run."));
index a9fc018ff0f29190d8f68ae9b17fa03cb8324ead..a93418c4e52ad1c832339b1aa520bd3dc7462dd3 100644 (file)
@@ -208,6 +208,19 @@ static ULONGEST record_full_insn_count;
 static struct target_ops record_full_ops;
 static struct target_ops record_full_core_ops;
 
+/* See record-full.h.  */
+
+int
+record_full_is_used (void)
+{
+  struct target_ops *t;
+
+  t = find_record_target ();
+  return (t == &record_full_ops
+         || t == &record_full_core_ops);
+}
+
+
 /* Command lists for "set/show record full".  */
 static struct cmd_list_element *set_record_full_cmdlist;
 static struct cmd_list_element *show_record_full_cmdlist;
@@ -907,10 +920,7 @@ record_full_open (char *name, int from_tty)
   if (record_debug)
     fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n");
 
-  /* Check if record target is already running.  */
-  if (current_target.to_stratum == record_stratum)
-    error (_("Process record target already running.  Use \"record stop\" to "
-             "stop record target first."));
+  record_preopen ();
 
   /* Reset the tmp beneath pointers.  */
   tmp_to_resume_ops = NULL;
index 517d786c2f005bcc5e558837329448c462adf2fb..ef3b3870832fc39eee4270521d9e59054c0743c8 100644 (file)
@@ -25,6 +25,10 @@ extern int record_full_memory_query;
 extern int record_full_arch_list_add_reg (struct regcache *regcache, int num);
 extern int record_full_arch_list_add_mem (CORE_ADDR addr, int len);
 extern int record_full_arch_list_add_end (void);
+
+/* Returns true if the process record target is open.  */
+extern int record_full_is_used (void);
+
 extern struct cleanup *record_full_gdb_operation_disable_set (void);
 
 #endif /* RECORD_FULL_H */
index e0df6b1cdd3b9ceee6da0752497ba03ad0cbb5e3..f2cfcc86d90067292471de866e6a355c059e44db 100644 (file)
@@ -57,9 +57,9 @@ struct cmd_list_element *info_record_cmdlist = NULL;
   if (record_debug)                                                    \
     fprintf_unfiltered (gdb_stdlog, "record: " msg "\n", ##args)
 
-/* Find the record target in the target stack.  */
+/* See record.h.  */
 
-static struct target_ops *
+struct target_ops *
 find_record_target (void)
 {
   struct target_ops *t;
@@ -88,6 +88,17 @@ require_record_target (void)
 
 /* See record.h.  */
 
+void
+record_preopen (void)
+{
+  /* Check if a record target is already running.  */
+  if (find_record_target () != NULL)
+    error (_("The process is already being recorded.  Use \"record stop\" to "
+            "stop recording first."));
+}
+
+/* See record.h.  */
+
 int
 record_read_memory (struct gdbarch *gdbarch,
                    CORE_ADDR memaddr, gdb_byte *myaddr,
index ab5ea4bd5870dd12d89cd68d207f8f0ce39a7cab..962e3826d9cd9e14727b2a8ff9d50f01e8637eda 100644 (file)
@@ -22,8 +22,6 @@
 
 struct cmd_list_element;
 
-#define RECORD_IS_USED (current_target.to_stratum == record_stratum)
-
 extern unsigned int record_debug;
 
 /* Allow record targets to add their own sub-commands.  */
@@ -63,4 +61,12 @@ extern void record_mourn_inferior (struct target_ops *);
 /* The default "to_kill" target method for record targets.  */
 extern void record_kill (struct target_ops *);
 
+/* Find the record_stratum target in the current target stack.
+   Returns NULL if none is found.  */
+extern struct target_ops *find_record_target (void);
+
+/* This is to be called by record_stratum targets' open routine before
+   it does anything.  */
+extern void record_preopen (void);
+
 #endif /* _RECORD_H_ */