Bug 10645

Summary: Watchpoints on unreadable memory need no singlestepping
Product: gdb Reporter: Jan Kratochvil <jan.kratochvil>
Component: breakpointsAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: enhancement CC: gdb-prs, jakub, ppluzhnikov, yuri
Priority: P3    
Version: 6.8   
Target Milestone: 6.8   
Host: x86_64-unknown-linux-gnu Target: x86_64-unknown-linux-gnu
Build: Last reconfirmed:
Attachments: Work in progress, not even a fix candidate.
A (failing now) testcase for possible kernel extensions.
Basic gdb/testsuite/ testcase.
Same patch as jank's, only adapted to the latest gdb tree.
Added more test cases.

Description Jan Kratochvil 2009-09-16 17:59:22 UTC
Currently GDB drops on unreadable watchpoint to PTRACE_SINGLESTEP.

It can use PTRACE_SYSCALL as any new memory area can appear at VMA only by a
kernel feature:
Better would be to setup address-specific mmap() trap (by prctl()?) or if kernel
would trigger DR debug registers on their hit by mmap().

Similar problem is about disappearing memory when inferior already runs with
PTRACE_CONT.  Currently GDB would have to always PTRACE_SYSCALL if any hardware
watchpoint is active.
kernel feature:
That would be better trapped by kernel on munmap() possibly checking the x86 DR
debug registers at the kernel level.

Feature is useful with default "set disable-randomization on" to watch memory
objects since the beginning of debuggee re-run (sort of record-replay by hand).

One should check also the case of `int **p = NULL;' with `watch **p'.

static int i, *p;
int main (void) {
  i = 1;
  i = 2;
  p = (void *) main;
  return 0;
(gdb) start
3	  i = 1;
(gdb) set debug infrun 1
(gdb) watch *p
Watchpoint 2: *p
(gdb) c
infrun: clear_proceed_status_thread (process 30884)
infrun: proceed (addr=0xffffffffffffffff, signal=144, step=0)
infrun: resume (step=1, signal=0), trap_expected=0
                     ^ step should be 0
PTRACE_SYSCALL should be used here, not PTRACE_SINGLESTEP.
Watchpoint 2: *p
Old value = <unreadable>
New value = -443987883
main () at /tmp/hwwatch.c:6
6	  return 0;
Comment 1 Jan Kratochvil 2009-09-16 18:00:36 UTC
Created attachment 4199 [details]
Work in progress, not even a fix candidate.
Comment 2 Jan Kratochvil 2009-09-23 14:45:37 UTC
Created attachment 4223 [details]
A (failing now) testcase for possible kernel extensions.

Made for a possible inclusion to:
Comment 3 Jan Kratochvil 2009-09-23 14:46:56 UTC
Created attachment 4224 [details]
Basic gdb/testsuite/ testcase.
Comment 4 Dragos Tatulea 2009-11-30 16:36:57 UTC
Created attachment 4429 [details]
Same patch as jank's, only adapted to the latest gdb tree.
Comment 5 Dragos Tatulea 2009-11-30 16:37:39 UTC
Created attachment 4430 [details]
Added more test cases.
Comment 6 Jan Kratochvil 2009-11-30 17:29:05 UTC
(a) There should be a GNU ChangeLog.  There should be some description text to
include whensubmitting it.  mmap_watchpoints_triggered() has no comment, also
the IMO-tricky fetch_watchpoint_value() call change and the reasons for
`mem_cnt' and `val' checking.  `if (step == 2)' or `else if (step == 1)' are not
acceptable - currently `int step' was a boolean, if it should be tri-state it
should become `enum' (or a new parameter/flag should be provided); this also
affects step_string().  `struct inferior'->trap_syscalls should be removed and
use the existing `catch syscall' infrastructure (I do not know it much so one
should follow it more closely than these comments of mine).  Is the custom
PT_SYSCALL still needed with the existing `catch syscall' infrastructure?

New parts I expected you could implement: (b) Catch also munmap()s.
(c) mmap_watchpoints_triggered() should trigger only on mmap-related syscalls as
detected by the existing `catch syscall' infrastructure.
Comment 7 Dragos Tatulea 2010-07-26 21:03:51 UTC
This patch: http://sourceware.org/ml/gdb-patches/2009-11/msg00429.html seems to 
change the behavior of watching an invalid area. Here's what happens now: 

GNU gdb (GDB)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
Reading symbols from /media/a/gdb/bugzilla/10645/simple...done.
(gdb) start
Temporary breakpoint 1 at 0x400478: file simple.c, line 4.
Starting program: /media/a/gdb/bugzilla/10645/simple 

Temporary breakpoint 1, main () at simple.c:4
4         i = 1;
(gdb) set debug infrun 1
(gdb) watch *p
Hardware watchpoint 2: *p
(gdb) c
infrun: clear_proceed_status_thread (process 13517)
infrun: proceed (addr=0xffffffffffffffff, signal=144, step=0)
infrun: resume (step=0, signal=0), trap_expected=0
infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
infrun: target_wait (-1, status) =
infrun:   13517 [process 13517],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: stop_pc = 0x400498
infrun: stopped by watchpoint
infrun: stopped data address = 0x600840
infrun: stop_stepping
Hardware watchpoint 2: *p

Old value = <unreadable>
New value = -443987883
main () at simple.c:7
7         return 0;

There's no single stepping anymore (at least for this particular case). Need to 
investigate why.
Comment 8 Paul Pluzhnikov 2011-07-31 19:08:32 UTC
*** Bug 12956 has been marked as a duplicate of this bug. ***