From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eli Zaretskii To: gdb-patches@sources.redhat.com Subject: Re: [RFA] Unified watchpoints for x86 platforms Date: Sat, 17 Mar 2001 09:21:00 -0000 Message-id: <200103171721.MAA13098@indy.delorie.com> References: <200103141310.f2EDAnZ04186@debye.wins.uva.nl> X-SW-Source: 2001-03/msg00318.html 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 * 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