| # Copyright 2009-2023 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" |
| load_lib "gdb-guile.exp" |
| load_lib "gdb-python.exp" |
| |
| require allow_ada_tests |
| |
| standard_ada_testfile foo |
| |
| if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } { |
| return -1 |
| } |
| |
| clean_restart ${testfile} |
| |
| set bp_location [gdb_get_line_number "STOP_HERE" ${testdir}/foo.adb] |
| runto "foo.adb:$bp_location" |
| |
| # Make sure that all tasks appear in the "info tasks" listing, and |
| # that the active task is the environment task. |
| gdb_test "info tasks" \ |
| [join {" +ID +TID P-ID Pri State +Name" \ |
| "\\* +1 .* main_task" \ |
| " +2 .* task_list\\(1\\)" \ |
| " +3 .* task_list\\(2\\)" \ |
| " +4 .* task_list\\(3\\)"} \ |
| "\r\n"] \ |
| "info tasks before inserting breakpoint" |
| |
| # Confirm that the "info threads" output lines up with the tasks list. |
| gdb_test "info threads" \ |
| [multi_line \ |
| "\\*\\s+1\\s+\[^\r\n\]+\\s\"foo\"\\s\[^\r\n\]+" \ |
| "\\s+2\\s+\[^\r\n\]+\\s\"task_list\\(1\\)\"\\s\[^\r\n\]+" \ |
| "\\s+3\\s+\[^\r\n\]+\\s\"task_list\\(2\\)\"\\s\[^\r\n\]+" \ |
| "\\s+4\\s+\[^\r\n\]+\\s\"task_list\\(3\\)\"\\s\[^\r\n\]+"] |
| |
| # Check that multiple uses of the 'task' keyword will give an error. |
| gdb_test "break break_me task 1 task 3" "You can specify only one task\\." |
| gdb_test "watch j task 1 task 3" "You can specify only one task\\." |
| |
| # Check that attempting to combine 'task' and 'thread' gives an error. |
| gdb_test "break break_me task 1 thread 1" \ |
| "You can specify only one of thread or task\\." |
| gdb_test "break break_me thread 1 task 1" \ |
| "You can specify only one of thread or task\\." |
| gdb_test "watch j task 1 thread 1" \ |
| "You can specify only one of thread or task\\." |
| gdb_test "watch j thread 1 task 1" \ |
| "You can specify only one of thread or task\\." |
| |
| # Insert a breakpoint that should stop only if task 1 stops. Since |
| # task 1 never calls break_me, this shouldn't actually ever trigger. |
| # The fact that this breakpoint is created _before_ the next one |
| # matters. GDB used to have a bug where it would report the first |
| # breakpoint in the list that matched the triggered-breakpoint's |
| # address, no matter which task it was specific to. |
| gdb_test "break break_me task 1" "Breakpoint .* at .*" |
| set bp_number [get_integer_valueof "\$bpnum" "INVALID" \ |
| "get number of breakpoint for task 1"] |
| gdb_test "info breakpoints" "foo.adb:${decimal}\r\n\\s+stop only in task 1" \ |
| "check info breakpoints for task 1 breakpoint" |
| |
| # Now, insert a breakpoint that should stop only if task 3 stops, and |
| # extract its number. Use gdb_test here so that we can validate that |
| # the 'Breakpoint ... also set at' line correctly includes the task |
| # number of the previous breakpoint. |
| gdb_test "break break_me task 3" \ |
| [multi_line \ |
| "Note: breakpoint $bp_number \\(task 1\\) also set at pc $hex\\." \ |
| "Breakpoint $decimal at $hex: \[^\r\n\]+"] |
| set bp_number [get_integer_valueof "\$bpnum" "INVALID" \ |
| "get number of breakpoint for task 3"] |
| gdb_test "info breakpoints" "foo.adb:${decimal}\r\n\\s+stop only in task 3" \ |
| "check info breakpoints for task 3 breakpoint" |
| |
| # Test the Python API for the breakpoint task attribute. |
| if {[allow_python_tests]} { |
| gdb_test_no_output "python bp = gdb.breakpoints()\[$bp_number - 1\]" \ |
| "get gdb.Breakpoint from list" |
| gdb_test "python print(bp.task)" "3" |
| gdb_test "python print(bp.thread)" "None" |
| gdb_test "python bp.thread = 1" \ |
| [multi_line \ |
| "RuntimeError: Cannot set both task and thread attributes\\." \ |
| "Error while executing Python code\\."] \ |
| "try setting the thread, but expect an error" |
| gdb_test_no_output "python bp.task = None" |
| gdb_test_no_output "python bp.thread = 1" |
| gdb_test "python bp.task = 3" \ |
| [multi_line \ |
| "RuntimeError: Cannot set both task and thread attributes\\." \ |
| "Error while executing Python code\\."] \ |
| "try setting the task, but expect an error" |
| |
| # Reset the breakpoint to the state required for the rest of this |
| # test. |
| gdb_test_no_output "python bp.thread = None" |
| gdb_test_no_output "python bp.task = 3" |
| } |
| |
| # Test the Guile API for the breakpoint task attribute. |
| if {[allow_guile_tests]} { |
| gdb_install_guile_utils |
| gdb_install_guile_module |
| |
| gdb_scm_test_silent_cmd "guile (define blist (breakpoints))" \ |
| "get breakpoint list" |
| gdb_scm_test_silent_cmd "guile (define bp (list-ref blist (- $bp_number 1)))" \ |
| "get <gdb:breakpoint> from list" |
| gdb_test "guile (print (breakpoint-task bp))" "= 3" |
| gdb_test "guile (print (breakpoint-thread bp))" "= #f" |
| gdb_test "guile (set-breakpoint-thread! bp 1)" \ |
| [multi_line \ |
| "ERROR: In procedure set-breakpoint-thread!:" \ |
| "(ERROR: )?In procedure gdbscm_set_breakpoint_thread_x:\ |
| cannot set both task and thread attributes" \ |
| "Error while executing Scheme code."] \ |
| "attempt to set thread, but expect an error" |
| |
| gdb_scm_test_silent_cmd "guile (set-breakpoint-task! bp #f)" \ |
| "clear breakpoint task attribute" |
| gdb_scm_test_silent_cmd "guile (set-breakpoint-thread! bp 1)" \ |
| "set breakpoint thread now task is unset" |
| gdb_test "guile (set-breakpoint-task! bp 1)" \ |
| [multi_line \ |
| "ERROR: In procedure set-breakpoint-task!:" \ |
| "(ERROR: )?In procedure gdbscm_set_breakpoint_task_x:\ |
| cannot set both task and thread attributes" \ |
| "Error while executing Scheme code."] \ |
| "attempt to set task, but expect an error" |
| |
| # Reset the breakpoint to the state required for the rest of this |
| # test. |
| gdb_scm_test_silent_cmd "guile (set-breakpoint-thread! bp #f)" \ |
| "clear breakpoint thread attribute" |
| gdb_scm_test_silent_cmd "guile (set-breakpoint-task! bp 3)" \ |
| "restore breakpoint task attribute" |
| } |
| |
| # Continue to that breakpoint. Task 2 should hit it first, and GDB |
| # is expected to ignore that hit and resume the execution. Only then |
| # task 3 will hit our breakpoint, and GDB is expected to stop at that |
| # point. Also make sure that GDB reports the correct breakpoint number. |
| gdb_test "continue" \ |
| ".*Breakpoint $bp_number, foo.break_me \\(\\).*" \ |
| "continue to breakpoint" |
| |
| # Check that it is indeed task 3 that hit the breakpoint by checking |
| # which is the active task. |
| gdb_test "info tasks" \ |
| [join {" +ID +TID P-ID Pri State +Name" \ |
| " +1 .* main_task" \ |
| " +2 .* task_list\\(1\\)" \ |
| "\\* +3 .* task_list\\(2\\)" \ |
| " +4 .* task_list\\(3\\)"} \ |
| "\r\n"] \ |
| "info tasks after hitting breakpoint" |
| |
| # Now, resume the execution and make sure that GDB does not stop when |
| # task 4 hits the breakpoint. Continuing thus results in our program |
| # running to completion. |
| set bp_location [gdb_get_line_number "STOP_HERE_2" ${testdir}/foo.adb] |
| gdb_breakpoint foo.adb:$bp_location |
| gdb_continue_to_breakpoint second ".*foo.adb:$bp_location.*null; -- STOP_HERE_2" |
| |
| # A regression test for a crash caused by trying to find the thread |
| # for a terminated task. |
| gdb_test "interpreter-exec mi \"-ada-task-info\"" ".*" |