gdb/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 19 Jul 2010 17:51:25 +0000 (17:51 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 19 Jul 2010 17:51:25 +0000 (17:51 +0000)
Make core files the process_stratum.
* corefile.c (core_target): New variable.
(core_file_command): Remove variable t, use core_target.
* corelow.c (core_ops): Make it static.
(init_core_ops): Change to process_stratum.  Initialize CORE_TARGET.
* defs.h (make_cleanup_unpush_target): New prototype.
* gdbarch.h: Regenerate.
* gdbarch.sh (core_pid_to_str): Remove core_stratum from its comment.
* gdbcore.h (core_target): New declaration.
* inf-ptrace.c (inf_ptrace_create_inferior, inf_ptrace_attach): New
variables ops_already_pushed and back_to.  Use push_target,
make_cleanup_unpush_target and discard_cleanups calls.
* record.c (record_open): Replace core_stratum by a core_bfd check.
* target.c (target_is_pushed): New function.
(find_core_target): Remove.
* target.h (enum strata) <core_stratum>: Remove.
(target_is_pushed): New declaration.
(find_core_target): Remove declaration.
* tracepoint.c (init_tfile_ops) <to_stratum>: Remove comment.
* utils.c (do_unpush_target, make_cleanup_unpush_target): New functions.

gdb/doc/
Make core files the process_stratum.
* gdb.texinfo (Active Targets): Remove core_stratum.  Include
record_stratum example.

gdb/testsuite/
Make core files the process_stratum.
* gdb.base/corefile.exp (run: load core again)
(run: sanity check we see the core file, run: with core)
(run: core file is cleared, attach: load core again)
(attach: sanity check we see the core file, attach: with core)
(attach: core file is cleared): New tests.
* gdb.base/coremaker.c (main): New parameters.  Implement "sleep" argv.

18 files changed:
gdb/ChangeLog
gdb/corefile.c
gdb/corelow.c
gdb/defs.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/gdbcore.h
gdb/inf-ptrace.c
gdb/record.c
gdb/target.c
gdb/target.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/corefile.exp
gdb/testsuite/gdb.base/coremaker.c
gdb/tracepoint.c
gdb/utils.c

index ae0e58518b63ec1df22262801a73fab75639346e..0fd4ca2801a14e48992f5278684c67a931442226 100644 (file)
@@ -1,3 +1,26 @@
+2010-07-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       Make core files the process_stratum.
+       * corefile.c (core_target): New variable.
+       (core_file_command): Remove variable t, use core_target.
+       * corelow.c (core_ops): Make it static.
+       (init_core_ops): Change to process_stratum.  Initialize CORE_TARGET.
+       * defs.h (make_cleanup_unpush_target): New prototype.
+       * gdbarch.h: Regenerate.
+       * gdbarch.sh (core_pid_to_str): Remove core_stratum from its comment.
+       * gdbcore.h (core_target): New declaration.
+       * inf-ptrace.c (inf_ptrace_create_inferior, inf_ptrace_attach): New
+       variables ops_already_pushed and back_to.  Use push_target,
+       make_cleanup_unpush_target and discard_cleanups calls.
+       * record.c (record_open): Replace core_stratum by a core_bfd check.
+       * target.c (target_is_pushed): New function.
+       (find_core_target): Remove.
+       * target.h (enum strata) <core_stratum>: Remove.
+       (target_is_pushed): New declaration.
+       (find_core_target): Remove declaration.
+       * tracepoint.c (init_tfile_ops) <to_stratum>: Remove comment.
+       * utils.c (do_unpush_target, make_cleanup_unpush_target): New functions.
+
 2010-07-19  Hui Zhu  <teawater@gmail.com>
 
        * breakpoint.c (single_step_breakpoints_inserted): New
index 7c1db864f769a89c7177915217341e6d0c4d31b9..c6efba7da2583cd9af6d5063054e29ea45e19ff2 100644 (file)
@@ -59,6 +59,10 @@ static int exec_file_hook_count = 0; /* size of array */
 /* Binary file diddling handle for the core file.  */
 
 bfd *core_bfd = NULL;
+
+/* corelow.c target (if included for this gdb target).  */
+
+struct target_ops *core_target;
 \f
 
 /* Backward compatability with old way of specifying core files.  */
@@ -66,18 +70,15 @@ bfd *core_bfd = NULL;
 void
 core_file_command (char *filename, int from_tty)
 {
-  struct target_ops *t;
-
   dont_repeat ();              /* Either way, seems bogus. */
 
-  t = find_core_target ();
-  if (t == NULL)
+  if (core_target == NULL)
     error (_("GDB can't read core files on this machine."));
 
   if (!filename)
-    (t->to_detach) (t, filename, from_tty);
+    (core_target->to_detach) (core_target, filename, from_tty);
   else
-    (t->to_open) (filename, from_tty);
+    (core_target->to_open) (filename, from_tty);
 }
 \f
 
index 9523f3273192ab60b467fe5807ab334c294d36e7..e96d07253338c849c9f2a25626ca9010a90959b5 100644 (file)
@@ -100,7 +100,7 @@ static void init_core_ops (void);
 
 void _initialize_corelow (void);
 
-struct target_ops core_ops;
+static struct target_ops core_ops;
 
 /* An arbitrary identifier for the core inferior.  */
 #define CORELOW_PID 1
@@ -911,11 +911,17 @@ init_core_ops (void)
   core_ops.to_thread_alive = core_thread_alive;
   core_ops.to_read_description = core_read_description;
   core_ops.to_pid_to_str = core_pid_to_str;
-  core_ops.to_stratum = core_stratum;
+  core_ops.to_stratum = process_stratum;
   core_ops.to_has_memory = core_has_memory;
   core_ops.to_has_stack = core_has_stack;
   core_ops.to_has_registers = core_has_registers;
   core_ops.to_magic = OPS_MAGIC;
+
+  if (core_target)
+    internal_error (__FILE__, __LINE__, 
+                   _("init_core_ops: core target already exists (\"%s\")."),
+                   core_target->to_longname);
+  core_target = &core_ops;
 }
 
 void
index 9b2decd879e3216b7887533d03a63d356b6654dd..c568a125d73c65bdd851fc971423e25d7172d621 100644 (file)
@@ -352,6 +352,9 @@ extern struct cleanup *make_cleanup_obstack_free (struct obstack *obstack);
 
 extern struct cleanup *make_cleanup_restore_integer (int *variable);
 
+struct target_ops;
+extern struct cleanup *make_cleanup_unpush_target (struct target_ops *ops);
+
 extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
 
 extern struct cleanup *make_my_cleanup (struct cleanup **,
index 6d0a3a48ac9e926040748c63c577154fca3ccd5f..dc2968cae837b7831f4849e897f6004747f817ca 100644 (file)
@@ -1,3 +1,10 @@
+2010-07-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
+           Eli Zaretskii  <eliz@gnu.org>
+
+       Make core files the process_stratum.
+       * gdb.texinfo (Active Targets): Remove core_stratum.  Include
+       record_stratum example.
+
 2010-07-13  Tom Tromey  <tromey@redhat.com>
 
        * gdb.texinfo (Index Files): New node.
index ba5ab75e676d24e41262d09224c857dd61adc441..bc4ca070903ff9a54bf6a7545fec045e61e4918f 100644 (file)
@@ -15391,33 +15391,20 @@ and @code{show architecture}.
 @cindex active targets
 @cindex multiple targets
 
-There are three classes of targets: processes, core files, and
-executable files.  @value{GDBN} can work concurrently on up to three
-active targets, one in each class.  This allows you to (for example)
-start a process and inspect its activity without abandoning your work on
-a core file.
-
-For example, if you execute @samp{gdb a.out}, then the executable file
-@code{a.out} is the only active target.  If you designate a core file as
-well---presumably from a prior run that crashed and coredumped---then
-@value{GDBN} has two active targets and uses them in tandem, looking
-first in the corefile target, then in the executable file, to satisfy
-requests for memory addresses.  (Typically, these two classes of target
-are complementary, since core files contain only a program's
-read-write memory---variables and so on---plus machine status, while
-executable files contain only the program text and initialized data.)
-
-When you type @code{run}, your executable file becomes an active process
-target as well.  When a process target is active, all @value{GDBN}
-commands requesting memory addresses refer to that target; addresses in
-an active core file or executable file target are obscured while the
-process target is active.
-
-Use the @code{core-file} and @code{exec-file} commands to select a new
-core file or executable target (@pxref{Files, ,Commands to Specify
-Files}).  To specify as a target a process that is already running, use
-the @code{attach} command (@pxref{Attach, ,Debugging an Already-running
-Process}).
+There are multiple classes of targets such, as: processes, executable files or
+recording sessions.  Core files belong to the process class, making core file
+and process mutually exclusive.  Otherwise, @value{GDBN} can work concurrently
+on multiple active targets, one in each class.  This allows you to (for
+example) start a process and inspect its activity, while still having access to
+the executable file after the process finishes.  Or if you start process
+recording (@pxref{Reverse Execution}) and @code{reverse-step} there, you are
+presented a virtual layer of the recording target, while the process target
+remains stopped at the chronologically last point of the process execution.
+
+Use the @code{core-file} and @code{exec-file} commands to select a new core
+file or executable target (@pxref{Files, ,Commands to Specify Files}).  To
+specify as a target a process that is already running, use the @code{attach}
+command (@pxref{Attach, ,Debugging an Already-running Process}).
 
 @node Target Commands
 @section Commands for Managing Targets
index cfc777ee1d6a576bfe99192ff937794b979c3e96..d2b0e5afec8b9adc74a62604f858d0401396d740 100644 (file)
@@ -672,8 +672,7 @@ typedef LONGEST (gdbarch_core_xfer_shared_libraries_ftype) (struct gdbarch *gdba
 extern LONGEST gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len);
 extern void set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries);
 
-/* How the core_stratum layer converts a PTID from a core file to a
-   string. */
+/* How the core target converts a PTID from a core file to a string. */
 
 extern int gdbarch_core_pid_to_str_p (struct gdbarch *gdbarch);
 
index eece393c990cc5a2b04a6190c209e3c0675aa94b..49022e50c5a62662f0b4262d95899f99c326762f 100755 (executable)
@@ -611,8 +611,7 @@ v:struct core_regset_section *:core_regset_sections:const char *name, int len:::
 # core file into buffer READBUF with length LEN.
 M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len
 
-# How the core_stratum layer converts a PTID from a core file to a
-# string.
+# How the core target converts a PTID from a core file to a string.
 M:char *:core_pid_to_str:ptid_t ptid:ptid
 
 # BFD target to use when generating a core file.
index 4b36d6968aa535b0b2fedd803d348ebf3f918726..82c0946366fa9c33e91dd56e4e570b6ba533d082 100644 (file)
@@ -108,6 +108,8 @@ extern void specify_exec_file_hook (void (*hook) (char *filename));
 
 extern bfd *core_bfd;
 
+extern struct target_ops *core_target;
+
 /* Whether to open exec and core files read-only or read-write.  */
 
 extern int write_files;
index ba9d8a8aec9e863cf6c416744b7569a4c47f2f63..82dfc343fc4f789f9e2849ac454190bb60443b38 100644 (file)
@@ -121,10 +121,23 @@ inf_ptrace_create_inferior (struct target_ops *ops,
 {
   int pid;
 
+  /* Do not change either targets above or the same target if already present.
+     The reason is the target stack is shared across multiple inferiors.  */
+  int ops_already_pushed = target_is_pushed (ops);
+  struct cleanup *back_to;
+
+  if (! ops_already_pushed)
+    {
+      /* Clear possible core file with its process_stratum.  */
+      push_target (ops);
+      back_to = make_cleanup_unpush_target (ops);
+    }
+
   pid = fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL,
                       NULL, NULL);
 
-  push_target (ops);
+  if (! ops_already_pushed)
+    discard_cleanups (back_to);
 
   /* On some targets, there must be some explicit synchronization
      between the parent and child processes after the debugger
@@ -189,11 +202,24 @@ inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
   pid_t pid;
   struct inferior *inf;
 
+  /* Do not change either targets above or the same target if already present.
+     The reason is the target stack is shared across multiple inferiors.  */
+  int ops_already_pushed = target_is_pushed (ops);
+  struct cleanup *back_to;
+
   pid = parse_pid_to_attach (args);
 
   if (pid == getpid ())                /* Trying to masturbate?  */
     error (_("I refuse to debug myself!"));
 
+  if (! ops_already_pushed)
+    {
+      /* target_pid_to_str already uses the target.  Also clear possible core
+        file with its process_stratum.  */
+      push_target (ops);
+      back_to = make_cleanup_unpush_target (ops);
+    }
+
   if (from_tty)
     {
       exec_file = get_exec_file (0);
@@ -226,7 +252,8 @@ inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
      target, it should decorate the ptid later with more info.  */
   add_thread_silent (inferior_ptid);
 
-  push_target(ops);
+  if (! ops_already_pushed)
+    discard_cleanups (back_to);
 }
 
 #ifdef PT_GET_PROCESS_STATE
index cd64c7adf55fe2aefcd86ad67515028abf259fe2..0b4924bbd94288999d5caa73a74a1ef7b8fda6a1 100644 (file)
@@ -962,7 +962,7 @@ record_open (char *name, int from_tty)
   record_beneath_to_stopped_by_watchpoint = tmp_to_stopped_by_watchpoint;
   record_beneath_to_stopped_data_address = tmp_to_stopped_data_address;
 
-  if (current_target.to_stratum == core_stratum)
+  if (core_bfd)
     record_core_open_1 (name, from_tty);
   else
     record_open_1 (name, from_tty);
index 4cabcbd501d52bac4169cdf160d8ab0a1f436208..2c65a88f2ad8457f1387489e47b0491356aa8e05 100644 (file)
@@ -1037,6 +1037,30 @@ pop_all_targets (int quitting)
   pop_all_targets_above (dummy_stratum, quitting);
 }
 
+/* Return 1 if T is now pushed in the target stack.  Return 0 otherwise.  */
+
+int
+target_is_pushed (struct target_ops *t)
+{
+  struct target_ops **cur;
+
+  /* Check magic number.  If wrong, it probably means someone changed
+     the struct definition, but not all the places that initialize one.  */
+  if (t->to_magic != OPS_MAGIC)
+    {
+      fprintf_unfiltered (gdb_stderr,
+                         "Magic number of %s target struct wrong\n",
+                         t->to_shortname);
+      internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+    }
+
+  for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
+    if (*cur == t)
+      return 1;
+
+  return 0;
+}
+
 /* Using the objfile specified in OBJFILE, find the address for the
    current thread's thread-local storage with offset OFFSET.  */
 CORE_ADDR
@@ -2770,31 +2794,6 @@ find_run_target (void)
   return (count == 1 ? runable : NULL);
 }
 
-/* Find a single core_stratum target in the list of targets and return it.
-   If for some reason there is more than one, return NULL.  */
-
-struct target_ops *
-find_core_target (void)
-{
-  struct target_ops **t;
-  struct target_ops *runable = NULL;
-  int count;
-
-  count = 0;
-
-  for (t = target_structs; t < target_structs + target_struct_size;
-       ++t)
-    {
-      if ((*t)->to_stratum == core_stratum)
-       {
-         runable = *t;
-         ++count;
-       }
-    }
-
-  return (count == 1 ? runable : NULL);
-}
-
 /*
  * Find the next target down the stack from the specified target.
  */
index 3c8c017489cefc893f3fd61b91ac0144959b67b5..e493d9d1492e0b9c73f68bea7b70b2de5b8c43d3 100644 (file)
@@ -68,8 +68,7 @@ enum strata
   {
     dummy_stratum,             /* The lowest of the low */
     file_stratum,              /* Executable files, etc */
-    core_stratum,              /* Core dump files */
-    process_stratum,           /* Executing processes */
+    process_stratum,           /* Executing processes or core dump files */
     thread_stratum,            /* Executing threads */
     record_stratum,            /* Support record debugging */
     arch_stratum               /* Architecture overrides */
@@ -1485,6 +1484,8 @@ extern void pop_all_targets (int quitting);
    strictly above ABOVE_STRATUM.  */
 extern void pop_all_targets_above (enum strata above_stratum, int quitting);
 
+extern int target_is_pushed (struct target_ops *t);
+
 extern CORE_ADDR target_translate_tls_address (struct objfile *objfile,
                                               CORE_ADDR offset);
 
@@ -1546,8 +1547,6 @@ extern void find_default_create_inferior (struct target_ops *,
 
 extern struct target_ops *find_run_target (void);
 
-extern struct target_ops *find_core_target (void);
-
 extern struct target_ops *find_target_beneath (struct target_ops *);
 
 /* Read OS data object of type TYPE from the target, and return it in
index e657676d2a85bfe4abcf82ca25ea8d00ff9c3783..e821f0e3f257d4d32f808893769c5d67d80180cb 100644 (file)
@@ -1,3 +1,13 @@
+2010-07-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       Make core files the process_stratum.
+       * gdb.base/corefile.exp (run: load core again)
+       (run: sanity check we see the core file, run: with core)
+       (run: core file is cleared, attach: load core again)
+       (attach: sanity check we see the core file, attach: with core)
+       (attach: core file is cleared): New tests.
+       * gdb.base/coremaker.c (main): New parameters.  Implement "sleep" argv.
+
 2010-07-14  Ken Werner  <ken.werner@de.ibm.com>
 
        * gdb.arch/altivec-abi.exp: New tests.
index 61040a6cb83949f079df96bc03397ff5ef389df4..09204e85a39998ecae62ef5a27928a9ef4b239c9 100644 (file)
@@ -177,3 +177,62 @@ gdb_load ${binfile}
 gdb_test "up" "#\[0-9\]* *\[0-9xa-fH'\]* in .* \\(.*\\).*" "up in corefile.exp (reinit)"
 
 gdb_test "core" "No core file now."
+
+
+# Test a run (start) command will clear any loaded core file.
+
+gdb_test "core-file $corefile" "Core was generated by .*" "run: load core again"
+gdb_test "info files" "\r\nLocal core dump file:\r\n.*" "run: sanity check we see the core file"
+
+set test "run: with core"
+if [runto_main] {
+    pass $test
+} else {
+    fail $test
+}
+
+set test "run: core file is cleared"
+gdb_test_multiple "info files" $test {
+    -re "\r\nLocal core dump file:\r\n.*\r\n$gdb_prompt $" {
+       fail $test
+    }
+    -re "\r\n$gdb_prompt $" {
+       pass $test
+    }
+}
+
+gdb_exit
+
+
+# Test an attach command will clear any loaded core file.
+
+if ![is_remote target] {
+    set test "attach: spawn sleep"
+    set res [remote_spawn host "$binfile sleep"];
+    if { $res < 0 || $res == "" } {
+       fail $test
+       return
+    }
+    set pid [exp_pid -i $res]
+    # We don't care whether the program is still in the startup phase when we
+    # attach.
+
+    gdb_start
+
+    gdb_test "core-file $corefile" "Core was generated by .*" "attach: load core again"
+    gdb_test "info files" "\r\nLocal core dump file:\r\n.*" "attach: sanity check we see the core file"
+
+    gdb_test "attach $pid" "Attaching to process $pid\r\n.*" "attach: with core"
+
+    set test "attach: core file is cleared"
+    gdb_test_multiple "info files" $test {
+       -re "\r\nLocal core dump file:\r\n.*\r\n$gdb_prompt $" {
+           fail $test
+       }
+       -re "\r\n$gdb_prompt $" {
+           pass $test
+       }
+    }
+
+    gdb_exit
+}
index f3363891b391fcc97906b316c37be628476ebc0e..81ca4d5f9a7bbf78ed23dbd392333f17cda025ca 100644 (file)
@@ -133,8 +133,14 @@ func1 ()
   func2 ();
 }
 
-int main ()
+int
+main (int argc, char **argv)
 {
+  if (argc == 2 && strcmp (argv[1], "sleep") == 0)
+    {
+      sleep (60);
+      return 0;
+    }
   mmapdata ();
   func1 ();
   return 0;
index 28ba55027c90c5885a1d4fd591e909e4382099e8..80be63eb7675db2badf1d28d842e0065e788d7ec 100644 (file)
@@ -4098,8 +4098,6 @@ init_tfile_ops (void)
   tfile_ops.to_get_trace_status = tfile_get_trace_status;
   tfile_ops.to_trace_find = tfile_trace_find;
   tfile_ops.to_get_trace_state_variable_value = tfile_get_trace_state_variable_value;
-  /* core_stratum might seem more logical, but GDB doesn't like having
-     more than one core_stratum vector.  */
   tfile_ops.to_stratum = process_stratum;
   tfile_ops.to_has_all_memory = tfile_has_all_memory;
   tfile_ops.to_has_memory = tfile_has_memory;
index a8beb379dc10dfe12a264caebb4223ce6f3dd379..0eaa050ce04d30824839ae29a35f2c67b09689ba 100644 (file)
@@ -352,6 +352,24 @@ make_cleanup_restore_integer (int *variable)
                           xfree);
 }
 
+/* Helper for make_cleanup_unpush_target.  */
+
+static void
+do_unpush_target (void *arg)
+{
+  struct target_ops *ops = arg;
+
+  unpush_target (ops);
+}
+
+/* Return a new cleanup that unpushes OPS.  */
+
+struct cleanup *
+make_cleanup_unpush_target (struct target_ops *ops)
+{
+  return make_my_cleanup (&cleanup_chain, do_unpush_target, ops);
+}
+
 struct cleanup *
 make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
                  void *arg,  void (*free_arg) (void *))