[pushed/Ada] Add support for task switching when debugging core files

Message ID 1513224700-93241-1-git-send-email-brobecker@adacore.com
State New, archived
Headers

Commit Message

Joel Brobecker Dec. 14, 2017, 4:11 a.m. UTC
  Hello,

The reasons for not supporting task switching when debugging core files
appear to now mostly be OBE. In particular, on GNU/Linux, the thread
layer is now able to retrieve the same thread info as in the live
process. So, this patch is mostly about just removing the guard
that limited the use of task switching to live processes.

gdb/ChangeLog:

        * ada-tasks.c (read_atcb): Properly set task_info->ptid
        when !target_has_execution as well.
        (task_command): Remove error when !target_has_execution.

gdb/testsuite/ChangeLog:

        * gdb.ada/task_switch_in_core: New testcase.

Tested on x86_64-linux, and then pushed to master.

Thank you,
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3a730c8..cca1af9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@ 
+2017-12-14  Joel Brobecker  <brobecker@adacore.com>
+
+	* ada-tasks.c (read_atcb): Properly set task_info->ptid
+	when !target_has_execution as well.
+	(task_command): Remove error when !target_has_execution.
+
 2017-12-13  Simon Marchi  <simon.marchi@ericsson.com>
 
 	* location.h (string_to_event_location): Add match_type
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index eac6c5b..cd324b7 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -783,18 +783,10 @@  read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
     = value_as_long (value_field (common_value,
 				  pspace_data->atcb_fieldno.base_cpu));
 
-  /* And finally, compute the task ptid.  Note that there are situations
-     where this cannot be determined:
-       - The task is no longer alive - the ptid is irrelevant;
-       - We are debugging a core file - the thread is not always
-         completely preserved for us to link back a task to its
-         underlying thread.  Since we do not support task switching
-         when debugging core files anyway, we don't need to compute
-         that task ptid.
-     In either case, we don't need that ptid, and it is just good enough
-     to set it to null_ptid.  */
-
-  if (target_has_execution && ada_task_is_alive (task_info))
+  /* And finally, compute the task ptid.  Note that there is not point
+     in computing it if the task is no longer alive, in which case
+     it is good enough to set its ptid to the null_ptid.  */
+  if (ada_task_is_alive (task_info))
     task_info->ptid = ptid_from_atcb_common (common_value);
   else
     task_info->ptid = null_ptid;
@@ -1366,23 +1358,7 @@  task_command (const char *taskno_str, int from_tty)
   if (taskno_str == NULL || taskno_str[0] == '\0')
     display_current_task_id ();
   else
-    {
-      /* Task switching in core files doesn't work, either because:
-           1. Thread support is not implemented with core files
-           2. Thread support is implemented, but the thread IDs created
-              after having read the core file are not the same as the ones
-              that were used during the program life, before the crash.
-              As a consequence, there is no longer a way for the debugger
-              to find the associated thead ID of any given Ada task.
-         So, instead of attempting a task switch without giving the user
-         any clue as to what might have happened, just error-out with
-         a message explaining that this feature is not supported.  */
-      if (!target_has_execution)
-        error (_("\
-Task switching not supported when debugging from core files\n\
-(use thread support instead)"));
-      task_command_1 (taskno_str, from_tty, current_inferior ());
-    }
+    task_command_1 (taskno_str, from_tty, current_inferior ());
 }
 
 /* Indicate that the given inferior's task list may have changed,
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 5dc7fc2..53c3780 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@ 
+2017-12-14  Joel Brobecker  <brobecker@adacore.com>
+
+	* gdb.ada/task_switch_in_core: New testcase.
+
 2017-12-13  Simon Marchi  <simon.marchi@ericsson.com>
 
 	* gdb.python/py-breakpoint.c (foo_ns::multiply): New function.
diff --git a/gdb/testsuite/gdb.ada/task_switch_in_core.exp b/gdb/testsuite/gdb.ada/task_switch_in_core.exp
new file mode 100644
index 0000000..92e749f
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/task_switch_in_core.exp
@@ -0,0 +1,80 @@ 
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+standard_ada_testfile crash
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" } {
+  return -1
+}
+
+clean_restart ${testfile}
+
+# Run the program to a certain point, and then use the gcore command
+# to generate a core file. The only objective of this part of this
+# testcase is to generate this core file, so we can then exercise
+# task-switching when debugging from core files.
+
+if { ![runto request_for_crash ]} then {
+    untested "couldn't run to Request_For_Crash"
+    return -1
+}
+
+set corefile [standard_output_file crash.gcore]
+set core_supported [gdb_gcore_cmd "$corefile" "save a corefile"]
+if {!$core_supported} {
+  return -1
+}
+
+# Now taht the core file has been created, we can start the real
+# part of this testcase, which is to debug using that core file.
+# Restart GDB and load that core file.
+
+clean_restart ${testfile}
+
+set core_loaded [gdb_core_cmd "$corefile" "re-load generated corefile"]
+if { $core_loaded == -1 } {
+    # No use proceeding from here.
+    return
+}
+
+# First, switch to task 1.
+
+gdb_test "task 1" \
+         "crash\\.request_for_crash \\(\\) at .*crash\\.adb:$decimal.*"
+
+
+gdb_test "info tasks" \
+         [multi_line "\\s+ID\\s+TID\\s+P-ID\\s+Pri\\s+State\\s+Name" \
+                     "\\*\\s+1\\s+.*main_task" \
+                     "\\s+2.*my_t"] \
+         "info tasks after switching to task 1"
+
+# Switch to task 2. Unlike in the case where we tested the switch to
+# task 1, don't check the location where the debugger says the program
+# is, as this might depend on the runtime, and in particular it might
+# depend on whether the runtime is built with debugging information
+# or not. Just check that we get the "switching to task" message, and
+# we will verify right after with an additional test that the current
+# task is now task 2.
+gdb_test "task 2" \
+         "\\\[Switching to task 2\\\].*"
+
+gdb_test "info tasks" \
+         [multi_line "\\s+ID\\s+TID\\s+P-ID\\s+Pri\\s+State\\s+Name" \
+                     "\\s+1\\s+.*main_task" \
+                     "\\*\\s+2.*my_t"] \
+         "info tasks after switching to task 2"
diff --git a/gdb/testsuite/gdb.ada/task_switch_in_core/crash.adb b/gdb/testsuite/gdb.ada/task_switch_in_core/crash.adb
new file mode 100644
index 0000000..ae0170d
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/task_switch_in_core/crash.adb
@@ -0,0 +1,53 @@ 
+--  Copyright 2017 Free Software Foundation, Inc.
+--
+--  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 3 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, see <http://www.gnu.org/licenses/>.
+
+with Ada.Text_IO; use Ada.Text_IO;
+
+procedure Crash is
+
+   procedure Request_For_Crash is
+   begin
+      null; -- Just an anchor for the debugger...
+   end Request_For_Crash;
+
+   task type T is
+      entry Done;
+   end T;
+
+   task body T is
+   begin
+      accept Done do
+         null;
+      end Done;
+      Put_Line ("Task T: Rendez-vous completed.");
+   end T;
+
+   My_T : T;
+
+begin
+
+   --  Give some time for the task to be created, and start its execution,
+   --  so that it reaches the accept statement.
+   delay 0.01;
+
+   Request_For_Crash;
+
+   delay 0.01;
+   Put_Line ("*** We didn't crash !?!");
+
+   --  Complete the rendez-vous with our task, so it can complete.
+   My_T.Done;
+
+end Crash;