From e05fa6f9df82886043e1f1df30e0b9be3fee2d55 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Wed, 13 Dec 2017 22:36:42 -0500 Subject: [PATCH] (Ada) Add support for task switching when debugging core files 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. --- gdb/ChangeLog | 6 ++ gdb/ada-tasks.c | 34 ++------ gdb/testsuite/ChangeLog | 4 + gdb/testsuite/gdb.ada/task_switch_in_core.exp | 80 +++++++++++++++++++ .../gdb.ada/task_switch_in_core/crash.adb | 53 ++++++++++++ 5 files changed, 148 insertions(+), 29 deletions(-) create mode 100644 gdb/testsuite/gdb.ada/task_switch_in_core.exp create mode 100644 gdb/testsuite/gdb.ada/task_switch_in_core/crash.adb diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3a730c83bd9..cca1af9fc58 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2017-12-14 Joel Brobecker + + * 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 * location.h (string_to_event_location): Add match_type diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c index eac6c5be919..cd324b796a4 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 5dc7fc2cd18..53c37800094 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-12-14 Joel Brobecker + + * gdb.ada/task_switch_in_core: New testcase. + 2017-12-13 Simon Marchi * 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 00000000000..92e749f7635 --- /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 . + +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 00000000000..ae0170dae0e --- /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 . + +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; -- 2.30.2