- hardware-assisted breakpoints and watchpoints, testing if
- one or more of the watchpoints triggered and at what address,
- checking whether a given region can be watched, etc.
-
- A target which wants to use these functions should define
- several macros, such as `target_insert_watchpoint' and
- `target_stopped_data_address', listed in target.h, to call
- the appropriate functions below. It should also define
- I386_USE_GENERIC_WATCHPOINTS in its tm.h file.
-
- In addition, each target should provide several low-level
- macros that will be called to insert watchpoints and hardware
- breakpoints into the inferior, remove them, and check their
- status. These macros are:
-
- I386_DR_LOW_SET_CONTROL -- set the debug control (DR7)
- register to a given value
-
- I386_DR_LOW_SET_ADDR -- put an address into one debug
- register
-
- I386_DR_LOW_RESET_ADDR -- reset the address stored in
- one debug register
-
- I386_DR_LOW_GET_STATUS -- return the value of the debug
- status (DR6) register.
-
- The functions below implement debug registers sharing by
- reference counts, and allow to watch regions up to 16 bytes
- long. */
-
-#ifdef I386_USE_GENERIC_WATCHPOINTS
-
-/* Debug registers' indices. */
-#define DR_NADDR 4 /* the number of debug address registers */
-#define DR_STATUS 6 /* index of debug status register (DR6) */
-#define DR_CONTROL 7 /* index of debug control register (DR7) */
-
-/* DR7 Debug Control register fields. */
-
-/* How many bits to skip in DR7 to get to R/W and LEN fields. */
-#define DR_CONTROL_SHIFT 16
-/* How many bits in DR7 per R/W and LEN field for each watchpoint. */
-#define DR_CONTROL_SIZE 4
-
-/* Watchpoint/breakpoint read/write fields in DR7. */
-#define DR_RW_EXECUTE (0x0) /* break on instruction execution */
-#define DR_RW_WRITE (0x1) /* break on data writes */
-#define DR_RW_READ (0x3) /* break on data reads or writes */
-
-/* This is here for completeness. No platform supports this
- functionality yet (as of Mar-2001). Note that the DE flag in the
- CR4 register needs to be set to support this. */
-#ifndef DR_RW_IORW
-#define DR_RW_IORW (0x2) /* break on I/O reads or writes */
-#endif
-
-/* Watchpoint/breakpoint length fields in DR7. The 2-bit left shift
- is so we could OR this with the read/write field defined above. */
-#define DR_LEN_1 (0x0 << 2) /* 1-byte region watch or breakpt */
-#define DR_LEN_2 (0x1 << 2) /* 2-byte region watch */
-#define DR_LEN_4 (0x3 << 2) /* 4-byte region watch */
-
-/* Local and Global Enable flags in DR7.
-
- When the Local Enable flag is set, the breakpoint/watchpoint is
- enabled only for the current task; the processor automatically
- clears this flag on every task switch. When the Global Enable
- flag is set, the breakpoint/watchpoint is enabled for all tasks;
- the processor never clears this flag.
-
- Currently, all watchpoint are locally enabled. If you need to
- enable them globally, read the comment which pertains to this in
- i386_insert_aligned_watchpoint below. */
-#define DR_LOCAL_ENABLE_SHIFT 0 /* extra shift to the local enable bit */
-#define DR_GLOBAL_ENABLE_SHIFT 1 /* extra shift to the global enable bit */
-#define DR_ENABLE_SIZE 2 /* 2 enable bits per debug register */
-
-/* Local and global exact breakpoint enable flags (a.k.a. slowdown
- flags). These are only required on i386, to allow detection of the
- exact instruction which caused a watchpoint to break; i486 and
- later processors do that automatically. We set these flags for
- back compatibility. */
-#define DR_LOCAL_SLOWDOWN (0x100)
-#define DR_GLOBAL_SLOWDOWN (0x200)
-
-/* Fields reserved by Intel. This includes the GD (General Detect
- Enable) flag, which causes a debug exception to be generated when a
- MOV instruction accesses one of the debug registers.
-
- FIXME: My Intel manual says we should use 0xF800, not 0xFC00. */
-#define DR_CONTROL_RESERVED (0xFC00)
-
-/* Auxiliary helper macros. */
-
-/* A value that masks all fields in DR7 that are reserved by Intel. */
-#define I386_DR_CONTROL_MASK (~DR_CONTROL_RESERVED)
-
-/* The I'th debug register is vacant if its Local and Global Enable
- bits are reset in the Debug Control register. */
-#define I386_DR_VACANT(i) \
- ((dr_control_mirror & (3 << (DR_ENABLE_SIZE * (i)))) == 0)
-
-/* Locally enable the break/watchpoint in the I'th debug register. */
-#define I386_DR_LOCAL_ENABLE(i) \
- dr_control_mirror |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i)))
-
-/* Globally enable the break/watchpoint in the I'th debug register. */
-#define I386_DR_GLOBAL_ENABLE(i) \
- dr_control_mirror |= (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i)))
-
-/* Disable the break/watchpoint in the I'th debug register. */
-#define I386_DR_DISABLE(i) \
- dr_control_mirror &= ~(3 << (DR_ENABLE_SIZE * (i)))