Message ID | 20240422230700.1173173-3-thiago.bauermann@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Add testcase for libc memory operations | expand |
On Mon, 22 Apr 2024 20:07:00 -0300 Thiago Jung Bauermann <thiago.bauermann@linaro.org> wrote: > +set saw_watch_trigger 0 > +set saw_function 0 > +set is_supported 1 > +set message "continue until memcpy watchpoint hits" > +set watch_trigger \ > + [multi_line \ > + "Continuing\\." \ > + "" \ > + "(Hardware w|W)atchpoint ${decimal}: -location b\\\[28\\\]" \ > + "" \ > + "Old value = 101 'e'" \ > + "New value = 114 'r'"] > +gdb_test_multiple "continue" $message { > + -re $watch_trigger { > + set saw_watch_trigger 1 > + exp_continue > + } > + -re ".*memcpy.* \\(\\) at .*:$decimal\r\n" { > + set saw_function 1 > + exp_continue > + } > + -re ".*memcpy.* \\(\\) from .*libc\[^\r\n\]+\r\n" { > + set saw_function 1 > + exp_continue > + } > + -re "in \\?\\? \\(\\) from .*libc\[^\r\n\]+\r\n" { > + set is_supported 0 > + unsupported "symbol for memcpy not found" > + exp_continue > + } > + -re "$gdb_prompt $" { > + if { $is_supported } { > + setup_kfail breakpoints/31665 arm*-*-linux* > + gdb_assert { $saw_watch_trigger && $saw_function } $message > + } > + } > +} For this test, on Fedora 39 x86_64 without glibc debuginfo, I see: continue Continuing. Hardware watchpoint 3: -location b[28] Old value = 101 'e' New value = 114 'r' 0x00007ffff7e34b19 in __memmove_avx_unaligned () from /lib64/libc.so.6 (gdb) FAIL: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits When I run it on Fedora 39 x86_64 w/ glibc debuginfo, I see the expected PASS: continue Continuing. Hardware watchpoint 3: -location b[28] Old value = 101 'e' New value = 114 'r' __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:226 226 VMOVU %VMM(1), -VEC_SIZE(%rdi,%rdx) (gdb) PASS: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits I think you can fix the FAIL for the no-glibc-debuginfo case by tweaking the RE in the same way that you did for the memmove test. I also have Fedora 39 (Asahi Remix) running on an M1 macbook. When I try this test on that machine, I see some timeouts... (gdb) watch -location a[28] Hardware watchpoint 2: -location a[28] (gdb) PASS: gdb.base/memops-watchpoint.exp: set watch on a watch -location b[28] Hardware watchpoint 3: -location b[28] (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on b watch -location c[28] Hardware watchpoint 4: -location c[28] (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on c continue Continuing. Hardware watchpoint 2: -location a[28] Old value = 104 'h' New value = 0 '\000' __GI___memset_generic () at ../sysdeps/aarch64/memset.S:67 67 tbz count, 5, 1f (gdb) PASS: gdb.base/memops-watchpoint.exp: continue until memset watchpoint hits continue Continuing. FAIL: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits (timeout) continue FAIL: gdb.base/memops-watchpoint.exp: continue until memmove watchpoint hits (timeout) testcase /ironwood1/sourceware-git/macbook-review/bld/../../worktree-review/gdb/testsuite/gdb.base/memops-watchpoint.exp completed in 20 seconds === gdb Summary === # of expected passes 4 # of unexpected failures 2 Is this demonstrating the bug (31484) ? Kevin
Kevin Buettner <kevinb@redhat.com> writes: > On Mon, 22 Apr 2024 20:07:00 -0300 > Thiago Jung Bauermann <thiago.bauermann@linaro.org> wrote: > >> +set saw_watch_trigger 0 >> +set saw_function 0 >> +set is_supported 1 >> +set message "continue until memcpy watchpoint hits" >> +set watch_trigger \ >> + [multi_line \ >> + "Continuing\\." \ >> + "" \ >> + "(Hardware w|W)atchpoint ${decimal}: -location b\\\[28\\\]" \ >> + "" \ >> + "Old value = 101 'e'" \ >> + "New value = 114 'r'"] >> +gdb_test_multiple "continue" $message { >> + -re $watch_trigger { >> + set saw_watch_trigger 1 >> + exp_continue >> + } >> + -re ".*memcpy.* \\(\\) at .*:$decimal\r\n" { >> + set saw_function 1 >> + exp_continue >> + } >> + -re ".*memcpy.* \\(\\) from .*libc\[^\r\n\]+\r\n" { >> + set saw_function 1 >> + exp_continue >> + } >> + -re "in \\?\\? \\(\\) from .*libc\[^\r\n\]+\r\n" { >> + set is_supported 0 >> + unsupported "symbol for memcpy not found" >> + exp_continue >> + } >> + -re "$gdb_prompt $" { >> + if { $is_supported } { >> + setup_kfail breakpoints/31665 arm*-*-linux* >> + gdb_assert { $saw_watch_trigger && $saw_function } $message >> + } >> + } >> +} > > For this test, on Fedora 39 x86_64 without glibc debuginfo, I see: > > continue > Continuing. > > Hardware watchpoint 3: -location b[28] > > Old value = 101 'e' > New value = 114 'r' > 0x00007ffff7e34b19 in __memmove_avx_unaligned () from /lib64/libc.so.6 > (gdb) FAIL: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits > > > When I run it on Fedora 39 x86_64 w/ glibc debuginfo, I see the expected PASS: > > continue > Continuing. > > Hardware watchpoint 3: -location b[28] > > Old value = 101 'e' > New value = 114 'r' > __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:226 > 226 VMOVU %VMM(1), -VEC_SIZE(%rdi,%rdx) > (gdb) PASS: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits > > I think you can fix the FAIL for the no-glibc-debuginfo case by > tweaking the RE in the same way that you did for the memmove test. That's true. Thanks! I'll make the change for v4. > I also have Fedora 39 (Asahi Remix) running on an M1 macbook. When > I try this test on that machine, I see some timeouts... > > (gdb) watch -location a[28] > Hardware watchpoint 2: -location a[28] > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watch on a > watch -location b[28] > Hardware watchpoint 3: -location b[28] > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on b > watch -location c[28] > Hardware watchpoint 4: -location c[28] > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on c > continue > Continuing. > > Hardware watchpoint 2: -location a[28] > > Old value = 104 'h' > New value = 0 '\000' > __GI___memset_generic () at ../sysdeps/aarch64/memset.S:67 > 67 tbz count, 5, 1f > (gdb) PASS: gdb.base/memops-watchpoint.exp: continue until memset watchpoint hits > continue > Continuing. > FAIL: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits (timeout) > continue > FAIL: gdb.base/memops-watchpoint.exp: continue until memmove watchpoint hits (timeout) > testcase /ironwood1/sourceware-git/macbook-review/bld/../../worktree-review/gdb/testsuite/gdb.base/memops-watchpoint.exp completed in 20 seconds > > === gdb Summary === > > # of expected passes 4 > # of unexpected failures 2 > > Is this demonstrating the bug (31484) ? Hm. Probably. I haven't seen this behaviour in my tests. It's hard to say why GDB hung. Can you try to "set debug infrun on" at that point? diff --git a/gdb/testsuite/gdb.base/memops-watchpoint.exp b/gdb/testsuite/gdb.base/memops-watchpoint.exp index 4005b1eecf85..5920608453a4 100644 --- a/gdb/testsuite/gdb.base/memops-watchpoint.exp +++ b/gdb/testsuite/gdb.base/memops-watchpoint.exp @@ -82,6 +82,8 @@ gdb_test_multiple "continue" $message { } } +gdb_test_no_output "set debug infrun on" + set saw_watch_trigger 0 set saw_function 0 set is_supported 1
On Wed, 24 Apr 2024 14:05:31 -0300 Thiago Jung Bauermann <thiago.bauermann@linaro.org> wrote: > > I also have Fedora 39 (Asahi Remix) running on an M1 macbook. When > > I try this test on that machine, I see some timeouts... > > > > (gdb) watch -location a[28] > > Hardware watchpoint 2: -location a[28] > > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watch on a > > watch -location b[28] > > Hardware watchpoint 3: -location b[28] > > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on b > > watch -location c[28] > > Hardware watchpoint 4: -location c[28] > > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on c > > continue > > Continuing. > > > > Hardware watchpoint 2: -location a[28] > > > > Old value = 104 'h' > > New value = 0 '\000' > > __GI___memset_generic () at ../sysdeps/aarch64/memset.S:67 > > 67 tbz count, 5, 1f > > (gdb) PASS: gdb.base/memops-watchpoint.exp: continue until memset watchpoint hits > > continue > > Continuing. > > FAIL: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits (timeout) > > continue > > FAIL: gdb.base/memops-watchpoint.exp: continue until memmove watchpoint hits (timeout) > > testcase /ironwood1/sourceware-git/macbook-review/bld/../../worktree-review/gdb/testsuite/gdb.base/memops-watchpoint.exp completed in 20 seconds > > > > === gdb Summary === > > > > # of expected passes 4 > > # of unexpected failures 2 > > > > Is this demonstrating the bug (31484) ? > > Hm. Probably. I haven't seen this behaviour in my tests. It's hard to > say why GDB hung. Can you try to "set debug infrun on" at that point? I tried running the test again on my macbook and can no longer reproduce that failure. I'm seeing 6 passes now. (No reboots or updates either. uptime shows that it's been up for 111 days.) Kevin
Kevin Buettner <kevinb@redhat.com> writes: > On Wed, 24 Apr 2024 14:05:31 -0300 > Thiago Jung Bauermann <thiago.bauermann@linaro.org> wrote: > >> > I also have Fedora 39 (Asahi Remix) running on an M1 macbook. When >> > I try this test on that machine, I see some timeouts... >> > >> > (gdb) watch -location a[28] >> > Hardware watchpoint 2: -location a[28] >> > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watch on a >> > watch -location b[28] >> > Hardware watchpoint 3: -location b[28] >> > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on b >> > watch -location c[28] >> > Hardware watchpoint 4: -location c[28] >> > (gdb) PASS: gdb.base/memops-watchpoint.exp: set watchpoint on c >> > continue >> > Continuing. >> > >> > Hardware watchpoint 2: -location a[28] >> > >> > Old value = 104 'h' >> > New value = 0 '\000' >> > __GI___memset_generic () at ../sysdeps/aarch64/memset.S:67 >> > 67 tbz count, 5, 1f >> > (gdb) PASS: gdb.base/memops-watchpoint.exp: continue until memset watchpoint hits >> > continue >> > Continuing. >> > FAIL: gdb.base/memops-watchpoint.exp: continue until memcpy watchpoint hits (timeout) >> > continue >> > FAIL: gdb.base/memops-watchpoint.exp: continue until memmove watchpoint hits (timeout) >> > testcase /ironwood1/sourceware-git/macbook-review/bld/../../worktree-review/gdb/testsuite/gdb.base/memops-watchpoint.exp completed in 20 seconds >> > >> > === gdb Summary === >> > >> > # of expected passes 4 >> > # of unexpected failures 2 >> > >> > Is this demonstrating the bug (31484) ? >> >> Hm. Probably. I haven't seen this behaviour in my tests. It's hard to >> say why GDB hung. Can you try to "set debug infrun on" at that point? > > I tried running the test again on my macbook and can no longer > reproduce that failure. I'm seeing 6 passes now. (No reboots or > updates either. uptime shows that it's been up for 111 days.) Ah, interesting. I think it's unlikely to be an issue related to this testcase then. I expect problems with watchpoints triggering with memset/memcpy/memmove to be deterministic. E.g., the kernel doesn't report a close enough data address because the hand-optimized memcpy used some very specialized instruction with a very wide data access range, and thus GDB doesn't recognize why the SIGTRAP happened. As an example, this test did uncover a problem in arm-linux-gnueabihf, and it manifested as the watchpoints triggering when the inferior program is exiting: continue Continuing. b = 'This is a relatively long string...' c = 'This is a relatively long string...' Hardware watchpoint 2: -location a[28] Old value = 104 'h' New value = 128 '\200' 0xf7fc27de in _dl_fini () at dl-fini.c:51 warning: 51 dl-fini.c: No such file or directory (gdb) KFAIL: gdb.base/memops-watchpoint.exp: continue until memset watchpoint hits (PRMS: breakpoints/31665)
diff --git a/gdb/testsuite/gdb.base/memops-watchpoint.c b/gdb/testsuite/gdb.base/memops-watchpoint.c new file mode 100644 index 000000000000..0255cfb43404 --- /dev/null +++ b/gdb/testsuite/gdb.base/memops-watchpoint.c @@ -0,0 +1,45 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2024 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/>. */ + +#include <stdio.h> +#include <string.h> + +int +main (void) +{ + /* Some targets need 4-byte alignment for hardware watchpoints. */ + char s[40] __attribute__ ((aligned (4))) + = "This is a relatively long string..."; + char a[40] __attribute__ ((aligned (4))) + = "String to be overwritten with zeroes"; + char b[40] __attribute__ ((aligned (4))) + = "Another string to be memcopied..."; + char c[40] __attribute__ ((aligned (4))) + = "Another string to be memmoved..."; + + /* Break here. */ + memset (a, 0, sizeof (a)); + + memcpy (b, s, sizeof (b)); + + memmove (c, s, sizeof (c)); + + printf ("b = '%s'\n", b); + printf ("c = '%s'\n", c); + + return 0; +} diff --git a/gdb/testsuite/gdb.base/memops-watchpoint.exp b/gdb/testsuite/gdb.base/memops-watchpoint.exp new file mode 100644 index 000000000000..4005b1eecf85 --- /dev/null +++ b/gdb/testsuite/gdb.base/memops-watchpoint.exp @@ -0,0 +1,160 @@ +# Copyright 2024 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/>. + +# Test a binary that uses standard libc memory operation functions. They are +# frequently optimized with specialized instructions, so make sure GDB behaves +# correctly in their presence. + +standard_testfile +set options "-fno-builtin-memset -fno-builtin-memcpy -fno-builtin-memmove" +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + [list debug additional_flags=$options]] } { + return -1 +} + +set linespec ${srcfile}:[gdb_get_line_number "Break here"] +if ![runto ${linespec}] { + return -1 +} + +gdb_test "watch -location a\[28\]" \ + "(Hardware w|W)atchpoint ${decimal}: -location a\\\[28\\\]" \ + "set watch on a" +gdb_test "watch -location b\[28\]" \ + "(Hardware w|W)atchpoint ${decimal}: -location b\\\[28\\\]" \ + "set watchpoint on b" +gdb_test "watch -location c\[28\]" \ + "(Hardware w|W)atchpoint ${decimal}: -location c\\\[28\\\]" \ + "set watchpoint on c" + +# For the tests below, split the pattern matching in two parts: one for the +# watchpoint trigger, and another for the line showing the function name. +# This is to allow the tests to work if there's a properly named symbol for +# the function, even if there's no libc debug info. + +set saw_watch_trigger 0 +set saw_function 0 +set is_supported 1 +set message "continue until memset watchpoint hits" +set watch_trigger \ + [multi_line \ + "Continuing\\." \ + "" \ + "(Hardware w|W)atchpoint ${decimal}: -location a\\\[28\\\]" \ + "" \ + "Old value = 104 'h'" \ + "New value = 0 '\\\\000'"] +gdb_test_multiple "continue" $message { + -re $watch_trigger { + set saw_watch_trigger 1 + exp_continue + } + -re ".*memset.* \\(\\) at .*:$decimal\r\n" { + set saw_function 1 + exp_continue + } + -re ".*memset.* \\(\\) from .*libc\[^\r\n\]+\r\n" { + set saw_function 1 + exp_continue + } + -re "in \\?\\? \\(\\) from .*libc\[^\r\n\]+\r\n" { + set is_supported 0 + unsupported "symbol for memset not found" + exp_continue + } + -re "$gdb_prompt $" { + if { $is_supported } { + setup_kfail breakpoints/31665 arm*-*-linux* + gdb_assert { $saw_watch_trigger && $saw_function } $message + } + } +} + +set saw_watch_trigger 0 +set saw_function 0 +set is_supported 1 +set message "continue until memcpy watchpoint hits" +set watch_trigger \ + [multi_line \ + "Continuing\\." \ + "" \ + "(Hardware w|W)atchpoint ${decimal}: -location b\\\[28\\\]" \ + "" \ + "Old value = 101 'e'" \ + "New value = 114 'r'"] +gdb_test_multiple "continue" $message { + -re $watch_trigger { + set saw_watch_trigger 1 + exp_continue + } + -re ".*memcpy.* \\(\\) at .*:$decimal\r\n" { + set saw_function 1 + exp_continue + } + -re ".*memcpy.* \\(\\) from .*libc\[^\r\n\]+\r\n" { + set saw_function 1 + exp_continue + } + -re "in \\?\\? \\(\\) from .*libc\[^\r\n\]+\r\n" { + set is_supported 0 + unsupported "symbol for memcpy not found" + exp_continue + } + -re "$gdb_prompt $" { + if { $is_supported } { + setup_kfail breakpoints/31665 arm*-*-linux* + gdb_assert { $saw_watch_trigger && $saw_function } $message + } + } +} + +# Note: Some architectures use memcpy for memmove. +set saw_watch_trigger 0 +set saw_function 0 +set is_supported 1 +set message "continue until memmove watchpoint hits" +set watch_trigger \ + [multi_line \ + "Continuing\\." \ + "" \ + "(Hardware w|W)atchpoint ${decimal}: -location c\\\[28\\\]" \ + "" \ + "Old value = 100 'd'" \ + "New value = 114 'r'"] +gdb_test_multiple "continue" $message { + -re $watch_trigger { + set saw_watch_trigger 1 + exp_continue + } + -re ".*(memmove|memcpy).* \\(\\) at .*:$decimal\r\n" { + set saw_function 1 + exp_continue + } + -re ".*(memmove|memcpy).* \\(\\) from .*libc\[^\r\n\]+\r\n" { + set saw_function 1 + exp_continue + } + -re "in \\?\\? \\(\\) from .*libc\[^\r\n\]+\r\n" { + set is_supported 0 + unsupported "symbol for memmove not found" + exp_continue + } + -re "$gdb_prompt $" { + if { $is_supported } { + setup_kfail breakpoints/31665 arm*-*-linux* + gdb_assert { $saw_watch_trigger && $saw_function } $message + } + } +}