| 1 | # This testcase is part of GDB, the GNU debugger. |
| 2 | |
| 3 | # Copyright 2009, 2010 Free Software Foundation, Inc. |
| 4 | |
| 5 | # This program is free software; you can redistribute it and/or modify |
| 6 | # it under the terms of the GNU General Public License as published by |
| 7 | # the Free Software Foundation; either version 3 of the License, or |
| 8 | # (at your option) any later version. |
| 9 | # |
| 10 | # This program is distributed in the hope that it will be useful, |
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | # GNU General Public License for more details. |
| 14 | # |
| 15 | # You should have received a copy of the GNU General Public License |
| 16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | |
| 18 | # This test verifies that a local watchpoint isn't deleted when a |
| 19 | # thread other than the thread the local watchpoint was set in stops |
| 20 | # for a breakpoint. |
| 21 | |
| 22 | if [target_info exists gdb,no_hardware_watchpoints] { |
| 23 | return 0; |
| 24 | } |
| 25 | |
| 26 | set testfile "local-watch-wrong-thread" |
| 27 | set srcfile ${testfile}.c |
| 28 | set binfile ${objdir}/${subdir}/${testfile} |
| 29 | if {[gdb_compile_pthreads \ |
| 30 | "${srcdir}/${subdir}/${srcfile}" \ |
| 31 | "${binfile}" executable {debug} ] != "" } { |
| 32 | return -1 |
| 33 | } |
| 34 | |
| 35 | gdb_exit |
| 36 | gdb_start |
| 37 | gdb_reinitialize_dir $srcdir/$subdir |
| 38 | gdb_load ${binfile} |
| 39 | |
| 40 | gdb_test "set can-use-hw-watchpoints 1" "" "" |
| 41 | |
| 42 | if ![runto_main] then { |
| 43 | fail "Can't run to main" |
| 44 | return |
| 45 | } |
| 46 | |
| 47 | set inc_line_1 [gdb_get_line_number "Loop increment 1"] |
| 48 | set inc_line_2 [gdb_get_line_number "Loop increment 2"] |
| 49 | set bkpt_here [gdb_get_line_number "set breakpoint here"] |
| 50 | |
| 51 | # Run to the loop within thread_function0, so we can set our local |
| 52 | # watchpoint. |
| 53 | gdb_test "break ${srcfile}:${inc_line_1}" \ |
| 54 | "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ |
| 55 | "breakpoint on thread_function0" |
| 56 | |
| 57 | gdb_test "continue" \ |
| 58 | ".*Breakpoint 2.*thread_function0.*" \ |
| 59 | "continue to thread_function0" |
| 60 | |
| 61 | delete_breakpoints |
| 62 | |
| 63 | # Set the local watchpoint, and confirm that it traps as expected. |
| 64 | gdb_test "watch *myp" \ |
| 65 | "Hardware watchpoint 3\: \\*myp.*" \ |
| 66 | "set local watchpoint on *myp" |
| 67 | |
| 68 | gdb_test "continue" \ |
| 69 | "Hardware watchpoint.*Old value.*New value.*thread_function0.*" \ |
| 70 | "local watchpoint triggers" |
| 71 | |
| 72 | delete_breakpoints |
| 73 | |
| 74 | # Recreate the watchpoint, but this time with a condition we know |
| 75 | # won't trigger. This is so the watchpoint is inserted, and the |
| 76 | # target reports events, but GDB doesn't stop for them. We want to |
| 77 | # hit the breakpoints on the other thread, and make sure this |
| 78 | # watchpoint isn't deleted then. |
| 79 | gdb_test "watch *myp if trigger != 0" \ |
| 80 | "Hardware watchpoint 4\: \\*myp.*" \ |
| 81 | "set local watchpoint on *myp, with false conditional" |
| 82 | |
| 83 | # Run to a breakpoint on a different thread. The previous local |
| 84 | # watchpoint should not be deleted with the standard 'the program has |
| 85 | # left the block in which its expression is valid', because the |
| 86 | # thread_function0 thread should still be running in the loop. |
| 87 | gdb_test "break ${srcfile}:${inc_line_2}" \ |
| 88 | "Breakpoint 5 at .*: file .*${srcfile}, line .*" \ |
| 89 | "breakpoint on the other thread" |
| 90 | |
| 91 | gdb_test "continue" \ |
| 92 | "Breakpoint 5, thread_function1.*" \ |
| 93 | "the other thread stopped on breakpoint" |
| 94 | |
| 95 | # Delete the new breakpoint, we don't need it anymore. |
| 96 | gdb_test "delete 5" "" "" |
| 97 | |
| 98 | # Check if the local watchpoint hasn't been deleted (is still listed). |
| 99 | # This is simpler to check than expecting 'the program has left ...', |
| 100 | # and, is immune to string changes in that warning. |
| 101 | gdb_test "info breakpoints" \ |
| 102 | ".*4.*hw watchpoint.*keep.*y.*\\*myp.*" \ |
| 103 | "local watchpoint is still in breakpoint list" |
| 104 | |
| 105 | # Make the watchpoint condition eval true. |
| 106 | gdb_test_no_output "set trigger=1" "let local watchpoint trigger" |
| 107 | |
| 108 | gdb_test "continue" \ |
| 109 | "Hardware watchpoint.*Old value.*New value.*thread_function0.*" \ |
| 110 | "local watchpoint still triggers" |
| 111 | |
| 112 | # Confirm that the local watchpoint is indeed deleted when |
| 113 | # thread_function0 returns. |
| 114 | gdb_test_no_output "set *myp=0" "let thread_function0 return" |
| 115 | |
| 116 | gdb_test "break ${srcfile}:${bkpt_here}" \ |
| 117 | "Breakpoint 6 at .*: file .*${srcfile}, line .*" \ |
| 118 | "breakpoint on thread_function0's caller" |
| 119 | |
| 120 | gdb_test "continue" \ |
| 121 | ".*Watchpoint.*deleted.*" \ |
| 122 | "local watchpoint automatically deleted" |