From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eli Zaretskii To: gdb@sources.redhat.com Subject: [RFC] Unified watchpoints for x86 platforms Date: Sat, 10 Feb 2001 07:34:00 -0000 Message-id: <200102101533.KAA10417@indy.delorie.com> References: <200009070855.EAA00749@albacore> <200009071500.LAA07756@indy.delorie.com> <200009081529.e88FTjx15960@debye.wins.uva.nl> X-SW-Source: 2001-02/msg00104.html [Yes, I know: it's been a looong time since I promised to make this happen. Still, it's better late than never ;-)] I started working on the unified support for hardware-assisted breakpoints and watchpoints on x86 platforms (see TODO). Since I don't feel I know enough about all the aspects of this on any platform but DJGPP, I thought I'd better get the framework agreed to before I start coding. Here's the API I suggest for use by higher-level GDB code: (Note: I'm not good at inventing names, so please suggest better ones if you want.) int i386_hwbp_insert (int pid, CORE_ADDR addr, int len, int kind); This function inserts a breakpoint or watchpoint to watch memory region starting at address ADDR whose length is LEN bytes. The watchpoint will watch said memory region for accesses whose type is defined by KIND: HW_READ break if the region is accessed for reading[1] HW_WRITE break if the region is accessed for writing HW_ACCESS break if the region is accessed for either reading or writing HW_IO_ACCESS same as HW_ACCESS type, but for I/O read/write access[2] HW_EXECUTE instruction execution breakpoint The function returns 0 upon success, else -1. Notes: [1] Since x86 doesn't support read data watchpoints, HW_READ will actually be implemented as a read/write watchpoint, and relies on higher-level GDB code to distinguish between reads and writes. The infrastructure to support this is already in place in breakpoint.c, since GDB 5.0. [2] I/O watchpoints are not currently supported (AFAIK) by GDB on any x86 platform. I can provide the code to handle it, but do people think we should define a command to access this feature? If so, should we provide separate read, write, and access types of watchpoints, or a single access type (the only one supported by x86's debug registers) is enough? Note that I/O watchpoints require that the DE (debug extensions) flag in the CR4 register be set. I don't know what platforms set it and under what circumstances. int i386_hwbp_remove (int pid, CORE_ADDR addr, int len, int kind); This function removes a breakpoint of watchpoint at address ADDR which watches a memory region of LEN bytes and whose type is given by KIND. It returns 0 upon success, else -1. int i386_hwbp_region_ok (CORE_ADDR addr, int len); This function tests whether a memory region of LEN bytes starting at ADDR can be watched with debug registers. It returns 1 if the region can be watched, 0 otherwise. int i386_hwbp_stopped_by_watchpoint (int pid); This function returns the address of a breakpoint or watchpoint which could have stopped the debuggee. If no watchpoint triggered, it returns 0. To actually insert and remove breakpoints and watchpoints, I need low-level system-dependent functions. Here's the API I suggest for this low-levwl layer. (These are macros so that targets could define them on their nm-*.h files. On a typical Unix or GNU/Linux system, each of these macros will call `ptrace' with suitable arguments.) void HWBP_SET_ADDR (int pid, int dr_num, CORE_ADDR addr); This macro sets the debug register DR_NUM in the inferior to watch the address ADDR. DR_NUM can be in the range [0..3]. void HWBP_SET_CONTROL (int pid, unsigned int val); This macro sets the DR7 debug control register in the inferior to the value VAL. unsigned int HWBP_GET_STATUS (int pid); This macro returns the value of the DR6 debug status register from the inferior. In the discussion we had back in September, Mark said that the status register should be per thread. Does that mean that we need an additional argument (int tid?) to pass to HWBP_GET_STATUS? If so, how will this argument get into the i386_hwbp_* functions which will call these macros? Or maybe the target end can figure out the thread id by itself with some TIDGET(pid) magic? Comments? Suggestions? Flames?