[RFA] Unified watchpoints for x86 platforms

Eli Zaretskii eliz@delorie.com
Sat Mar 17 09:21:00 GMT 2001


This is the patch for the docs which adds a section about watchpoints
to gdbint.texinfo.  Please see if the description is clear and useful.

2001-03-17  Eli Zaretskii  <eliz@is.elta.co.il>

	* gdbint.texinfo (Algorithms): New section "Watchpoints" and new
	subsection "x86 Watchpoints".
	(Target Architecture Definition): Document
	I386_USE_GENERIC_WATCHPOINTS and TARGET_HAS_HARDWARE_WATCHPOINTS.
	(Native Debugging): Document I386_USE_GENERIC_WATCHPOINTS.


--- gdb/doc/gdbint.t~1	Sat Feb 10 22:35:34 2001
+++ gdb/doc/gdbint.texinfo	Sat Mar 17 16:20:18 2001
@@ -1,4 +1,4 @@
-\input texinfo
+\input texinfo   @c -*- texinfo -*-
 @setfilename gdbint.info
 @include gdb-cfg.texi
 @ifinfo
@@ -291,7 +291,11 @@
 
 Since they depend on hardware resources, hardware breakpoints may be
 limited in number; when the user asks for more, @value{GDBN} will
-start trying to set software breakpoints.
+start trying to set software breakpoints.  (On some architectures,
+notably the 32-bit x86 platforms, @value{GDBN} cannot alsways know
+whether there's enough hardware resources to insert all the hardware
+breakpoints and watchpoints.  On those platforms, @value{GDBN} prints
+an error message only when the program being debugged is continued.)
 
 @cindex software breakpoints
 Software breakpoints require @value{GDBN} to do somewhat more work.
@@ -350,6 +354,306 @@
 @file{tm-@var{target}.h} file.  Look in @file{tm-sun4os4.h} and
 @file{sparc-tdep.c} for examples of how to do this.
 
+@section Watchpoints
+@cindex watchpoints
+
+Watchpoints are a special kind of breakpoints (@pxref{Algorithms,
+breakpoints}) which break when data is accessed rather than when some
+instruction is executed.  When you have data which changes without
+your knowing what code does that, watchpoints are the silver bullet to
+hunt down and kill such bugs.
+
+@cindex hardware watchpoints
+@cindex software watchpoints
+Watchpoints can be either hardware-assisted or not; the latter type is
+known as ``software watchpoints.''  @value{GDBN} always uses
+hardware-assisted watchpoints if they are available, and falls back on
+software watchpoints otherwise.  Typical situations where @value{GDBN}
+will use software watchpoints are:
+
+@itemize @bullet
+@item
+The watched memory region is too large for the underlying hardware
+watchpoint support.  For example, each x86 debug register can watch up
+to 4 bytes of memory, so trying to watch data structures whose size is
+more than 16 bytes will cause @value{GDBN} to use software
+watchpoints.
+
+@item
+Too many different watchpoints requested.  (On some architectures,
+this situation is impossible to detect until the debugged program is
+resumed.)  Note that x86 debug registers are used both for hardware
+breakpoints and for watchpoints, so setting too many hardware
+breakpoints might cause watchpoint insertion to fail.
+
+@item
+No hardware-assisted watchpoints provided by the target
+implementation.
+@end itemize
+
+Software watchpoints are very slow, since @value{GDBN} needs to
+single-step the program being debugged and test the value of the
+watched expression(s) after each instruction.  The rest of this
+section is mostly irrelevant for software watchpoints.
+
+@value{GDBN} uses several macros and primitives to support hardware
+watchpoints:
+
+@table @code
+@findex TARGET_HAS_HARDWARE_WATCHPOINTS
+@item TARGET_HAS_HARDWARE_WATCHPOINTS
+If defined, the target supports hardware watchpoints.
+
+@findex TARGET_CAN_USE_HARDWARE_WATCHPOINT
+@item TARGET_CAN_USE_HARDWARE_WATCHPOINT (@var{type}, @var{count}, @var{other})
+Return the number of hardware watchpoints of type @var{type} that are
+possible to be set.  The value is positive if @var{count} watchpoints
+of this type can be set, zero if setting watchpoints of this type is
+not supported, and negative if @var{count} is more than the maximum
+number of watchpoints of type @var{type} that can be set.  @var{other}
+is non-zero if other types of watchpoints are currently enabled (there
+are architectures which cannot set watchpoints of different types).
+
+@findex TARGET_REGION_OK_FOR_HW_WATCHPOINT
+@item TARGET_REGION_OK_FOR_HW_WATCHPOINT (@var{addr}, @var{len})
+Return non-zero if hardware watchpoints can be used to watch a region
+whose address is @var{addr} and whose length in bytes is @var{len}.
+
+@findex TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT
+@item TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT (@var{size})
+Return non-zero if hardware watchpoints can be used to watch a region
+whose size is @var{size}.  @value{GDBN} only uses this macro as a
+fall-back, in case @code{TARGET_REGION_OK_FOR_HW_WATCHPOINT} is not
+defined.
+
+@findex TARGET_DISABLE_HW_WATCHPOINTS
+@item TARGET_DISABLE_HW_WATCHPOINTS (@var{pid})
+Disables watchpoints in the process identified by @var{pid}.  This is
+used, e.g., on HP-UX which provides operations to disable and enable
+the page-level memory protection that implements hardware watchpoints
+on that platform.
+
+@findex TARGET_ENABLE_HW_WATCHPOINTS
+@item TARGET_ENABLE_HW_WATCHPOINTS (@var{pid})
+Enables watchpoints in the process identified by @var{pid}.  This is
+used, e.g., on HP-UX which provides operations to disable and enable
+the page-level memory protection that implements hardware watchpoints
+on that platform.
+
+@findex TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT
+@item TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT (@var{pid},@var{start},@var{len})
+Some addresses may not be profitable to use hardware to watch, or may
+be difficult to understand when the addressed object is out of scope,
+and hence should not be watched with hardware watchpoints.  On some
+targets, this may have severe performance penalties, such that we
+might as well use regular watchpoints, and save (possibly precious)
+hardware watchpoints for other locations.
+
+@findex target_insert_watchpoint
+@findex target_remove_watchpoint
+@item target_insert_watchpoint (@var{addr}, @var{len}, @var{type})
+@itemx target_remove_watchpoint (@var{addr}, @var{len}, @var{type})
+Insert or remove a hardware watchpoint starting at @var{addr}, for
+@var{len} bytes.  @var{type} is the watchpoint type, one of the
+possible values of the enumerated data type @code{target_hw_bp_type},
+defined by @file{breakpoint.h} as follows:
+
+@example
+ enum target_hw_bp_type
+   @{
+     hw_write   = 0, /* Common (write) HW watchpoint */
+     hw_read    = 1, /* Read    HW watchpoint */
+     hw_access  = 2, /* Access (read or write) HW watchpoint */
+     hw_execute = 3  /* Execute HW breakpoint */
+   @};
+@end example
+
+@noindent
+These two macros should return 0 for success, non-zero for failure.
+
+@cindex insert or remove hardware breakpoint
+@findex target_remove_hw_breakpoint
+@findex target_insert_hw_breakpoint
+@item target_remove_hw_breakpoint (@var{addr}, @var{shadow})
+@itemx target_insert_hw_breakpoint (@var{addr}, @var{shadow})
+Insert or remove a hardware-assisted breakpoint at address @var{addr}.
+Returns zero for success, non-zero for failure.  @var{shadow} is the
+real contents of the byte where the breakpoint has been inserted; it
+is generally not valid when hardware breakpoints are used, but since
+no other code touches these values, the implementations of the above
+two macros can use them for their internal purposes.
+
+@findex target_stopped_data_address
+@item target_stopped_data_address ()
+If the inferior has some watchpoint that triggered, return the address
+associated with that watchpoint.  Otherwise, return zero.
+
+@findex DECR_PC_AFTER_HW_BREAK
+@item DECR_PC_AFTER_HW_BREAK
+If defined, @value{GDBN} decrements the program counter by the value
+of @code{DECR_PC_AFTER_HW_BREAK} after a hardware break-point.  This
+overrides the value of @code{DECR_PC_AFTER_BREAK} when hardware
+breakpoints are used.
+
+@findex HAVE_STEPPABLE_WATCHPOINT
+@item HAVE_STEPPABLE_WATCHPOINT
+If defined to a non-zero value, it is not necessary to disable a
+watchpoint to step over it.
+
+@findex HAVE_NONSTEPPABLE_WATCHPOINT
+@item HAVE_NONSTEPPABLE_WATCHPOINT
+If defined to a non-zero value, @value{GDBN} should disable a
+watchpoint to step the inferior over it.
+
+@findex HAVE_CONTINUABLE_WATCHPOINT
+@item HAVE_CONTINUABLE_WATCHPOINT
+If defined to a non-zero value, it is possible to continue the
+inferior after a watchpoint has been hit.
+
+@findex CANNOT_STEP_HW_WATCHPOINTS
+@item CANNOT_STEP_HW_WATCHPOINTS
+If this is defined to a non-zero value, @value{GDBN} will remove all
+watchpoints before stepping the inferior.
+
+@findex STOPPED_BY_WATCHPOINT
+@item STOPPED_BY_WATCHPOINT (@var{wait_status})
+Return non-zero if stopped by a watchpoint.  @var{wait_status} is of
+the type @code{struct target_waitstatus}, defined by @file{target.h}.
+@end table
+
+@subsection x86 Watchpoints
+@cindex x86 debug registers
+@cindex watchpoints, on x86
+
+The 32-bit Intel x86 (a.k.a.@: ia32) processors feature special debug
+registers designed to facilitate debugging.  @value{GDBN} provides a
+generic library of functions that x86-based ports can use to implement
+support for watchpoints and hardware-assisted breakpoints.  This
+subsection documents the x86 watchpoint facilities in @value{GDBN}.
+
+To use the generic x86 watchpoint support, a port should do the
+following:
+
+@itemize @bullet
+@findex I386_USE_GENERIC_WATCHPOINTS
+@item
+Define the macro @code{I386_USE_GENERIC_WATCHPOINTS} somewhere in the
+target-dependent headers.
+
+@item
+Include the @file{config/i386/nm-i386v.h} header file @emph{after}
+defining @code{I386_USE_GENERIC_WATCHPOINTS}.
+
+@item
+Add @file{i386-nat.o} to the value of the Make variable
+@code{NATDEPFILES} (@pxref{Native Debugging, NATDEPFILES}) or
+@code{TDEPFILES} (@pxref{Target Architecture Definition, TDEPFILES}).
+
+@item
+Provide implementations for the @code{I386_DR_LOW_*} macros described
+below.  Typically, each macro should call a target-specific function
+which does the real work.
+@end itemize
+
+The x86 watchpoint support works by maintaining mirror images of the
+debug registers.  Values are copied between the mirror images and the
+real debug registers via a set of macros which each target needs to
+provide:
+
+@table @code
+@findex I386_DR_LOW_SET_CONTROL
+@item I386_DR_LOW_SET_CONTROL (@var{val})
+Set the Debug Control (DR7) register to the value @var{val}.
+
+@findex I386_DR_LOW_SET_ADDR
+@item I386_DR_LOW_SET_ADDR (@var{idx}, @var{addr})
+Put the address @var{addr} into the debug register number @var{idx}.
+
+@findex I386_DR_LOW_RESET_ADDR
+@item I386_DR_LOW_RESET_ADDR (@var{idx})
+Reset (i.e. zero out) the address stored in the debug register number
+@var{idx}.
+
+@findex I386_DR_LOW_GET_STATUS
+@item I386_DR_LOW_GET_STATUS
+Return the value of the Debug Status (DR6) register.
+@end table
+
+For each one of the 4 debug registers (whose indices are from 0 to 3)
+that store addresses, a reference count is maintained by @value{GDBN},
+to allow sharing of debug registers by several watchpoints.  This
+allows the users to define several watchpoints which watch the same
+expression, but with different conditions and/or commands, without
+wasting debug registers which are in short supply.  @value{GDBN}
+maintains the reference counts internally, targets don't have to do
+anything to use this feature.
+
+The generic x86 watchpoint support provides the following API for the
+@value{GDBN}'s application code:
+
+@table @code
+@findex i386_region_ok_for_watchpoint
+@item i386_region_ok_for_watchpoint (@var{addr}, @var{len})
+The macro @code{TARGET_REGION_OK_FOR_HW_WATCHPOINT} is set to call
+this function.
+
+@findex i386_stopped_data_address
+@item i386_stopped_data_address (void)
+The macro @code{STOPPED_BY_WATCHPOINT} is set to call this function.
+The argument passed to @code{STOPPED_BY_WATCHPOINT} is ignored.
+
+@findex i386_stopped_data_address
+@item i386_stopped_data_address (void)
+The macro target_stopped_data_address is set to call this function.
+
+@findex i386_insert_watchpoint
+@findex i386_remove_watchpoint
+@item i386_insert_watchpoint (@var{addr}, @var{len}, @var{type})
+@itemx i386_remove_watchpoint (@var{addr}, @var{len}, @var{type})
+Insert or remove a watchpoint.  The macros
+@code{target_insert_watchpoint} and @code{target_remove_watchpoint}
+are set to call these functions.
+
+@findex i386_insert_hw_breakpoint
+@findex i386_remove_hw_breakpoint
+@item i386_insert_hw_breakpoint (@var{addr}, @var{shadow}
+@itemx i386_remove_hw_breakpoint (@var{addr}, @var{shadow})
+These functions insert and remove hardware-assisted breakpoints.  The
+macros @code{target_insert_hw_breakpoint} and
+@code{target_remove_hw_breakpoint} are set to call these functions.
+
+@findex i386_stopped_by_hwbp
+@item i386_stopped_by_hwbp (void)
+This function returns non-zero if the inferior has some watchpoint or
+hardware breakpoint that triggered.
+
+@findex i386_cleanup_dregs
+@item i386_cleanup_dregs (void)
+This function clears all the reference counts, addresses, and control
+bits in the mirror images of the debug registers.
+@end table
+
+@noindent
+@strong{Notes:}
+@enumerate 1
+@item
+x86 processors support setting watchpoints on I/O reads or writes.
+However, since no target supports this (as of March 2001), and since
+@code{enum target_hw_bp_type} doesn't even have an enumeration for I/O
+watchpoints, this feature is not yet available to @value{GDBN} running
+on x86.
+
+@item
+x86 processors can enable watchpoints locally, for the current task
+only, or globally, for all the tasks.  For each debug register,
+there's a bit in the DR7 control register that determines whether the
+associated address is watched locally or globally.  The current
+implementation of x86 watchpoint support in @value{GDBN} always sets
+watchpoints to be locally enabled, since global watchpoints might
+interfere with the underlying OS and are probably unavailable in many
+platforms.
+@end enumerate
+
 @node User Interface
 
 @chapter User Interface
@@ -374,7 +678,7 @@
 To add commands in general, use @code{add_cmd}.  @code{add_com} adds to
 the main command list, and should be used for those commands.  The usual
 place to add commands is in the @code{_initialize_@var{xyz}} routines at
-the ends of most source files. 
+the ends of most source files.
 
 @cindex deprecating commands
 @findex deprecate_cmd
@@ -1102,10 +1406,10 @@
 @code{BIG_ENDIAN} or @code{LITTLE_ENDIAN}.
 
 @item INT_MAX
-@item INT_MIN
-@item LONG_MAX
-@item UINT_MAX
-@item ULONG_MAX
+@itemx INT_MIN
+@itemx LONG_MAX
+@itemx UINT_MAX
+@itemx ULONG_MAX
 Values for host-side constants.
 
 @item ISATTY
@@ -1222,7 +1526,7 @@
 Define if this is not in a system header file (typically, @file{unistd.h}).
 
 @item SEEK_CUR
-@item SEEK_SET
+@itemx SEEK_SET
 Define these to appropriate value for the system @code{lseek}, if not already
 defined.
 
@@ -1990,6 +2294,10 @@
 feature-specific macros.  It was introduced in a haste and we are
 repenting at leisure.
 
+@item I386_USE_GENERIC_WATCHPOINTS
+An x86-based target can define this to use the generic x86 watchpoint
+support; see @ref{Algorithms, I386_USE_GENERIC_WATCHPOINTS}.
+
 @item SYMBOLS_CAN_START_WITH_DOLLAR
 @findex SYMBOLS_CAN_START_WITH_DOLLAR
 Some systems have routines whose names start with @samp{$}.  Giving this
@@ -2466,6 +2774,11 @@
 frame pointers are not used, a default definition simply returns 
 @code{FP_REGNUM}, with an offset of zero.
 
+@item TARGET_HAS_HARDWARE_WATCHPOINTS
+If non-zero, the target has support for hardware-assisted
+watchpoints.  @xref{Algorithms, watchpoints}, for more details and
+other related macros.
+
 @item USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type})
 @findex USE_STRUCT_CONVENTION
 If defined, this must be an expression that is nonzero if a value of the
@@ -2795,6 +3108,10 @@
 @code{CORE_ADDR *} as argument, and stores the target PC value through this
 pointer.  It examines the current state of the machine as needed.
 
+@item I386_USE_GENERIC_WATCHPOINTS
+An x86-based machine can define this to use the generic x86 watchpoint
+support; see @ref{Algorithms, I386_USE_GENERIC_WATCHPOINTS}.
+
 @item KERNEL_U_ADDR
 @findex KERNEL_U_ADDR
 Define this to the address of the @code{u} structure (the ``user



More information about the Gdb-patches mailing list