|
|
9.9. Virtual Memory WatchpointsThe Solaris kernel implements virtual memory watchpoints within address spaces. A watchpoint is similar to a breakpoint, except that a watchpoint stops execution when an address location is read or modified, whereas a breakpoint stops execution when an instruction is executed at a specified location. Watchpoints also provide the ability to implement breakpoints through the watchpoint interface. You set and clear watchpoints through the /proc file system interface, by opening the control file for a process and then sending a PCWATCH command. The PCWATCH command is accompanied by a prwatch structure, which contains the address, the length of the area to be affected, and the type of watchpoint. typedef struct prwatch { uintptr_t pr_vaddr; /* virtual address of watched area */ size_t pr_size; /* size of watched area in bytes */ int pr_wflags; /* watch type flags */ } prwatch_t; See sys/watchpoint.h The pr_vaddr field specifies the virtual address of an area of memory to be watched in the controlled process; pr_size specifies the size of the area, in bytes, and pr_wflags specifies the type of memory access to be monitored as a bit-mask of the flags shown in Table 9.7.
If pr_wflags is nonzero, then a watched area is established for the virtual address range specified by pr_vaddr and pr_size. If pr_wflags is zero, then any previously established watched area starting at the specified virtual address is cleared; pr_size is ignored. A watchpoint is triggered when an LWP in the traced process makes a memory reference that covers at least one byte of a watched area and the memory reference is as specified in pr_wflags. When an LWP triggers a watchpoint, it incurs a watchpoint trap. If FLTWATCH is being traced, the LWP stops; otherwise, it is sent a SIGTRAP signal. If SIGTRAP is being traced and is not blocked, then the LWP stops. The watchpoint trap occurs before the instruction completes unless WA_TRAPAFTER was specified, in which case it occurs after the instruction completes. If the trap occurs before completion, the memory is not modified. If it occurs after completion, the memory is modified (if the access is a write access). A minimal example of how a watchpoint is established is shown below. The program creates a watchpoint for read and write access to the bytes occupied by the integer, test. #include <sys/types.h> #include <sys/fcntl.h> #include <procfs.h> typedef struct { long cmd; prwatch_t prwatch; } ctl_t; main(int argc, char **argv) { int ctlfd; ctl_t ctl; int test; if ((ctlfd = open("/proc/self/ctl", O_WRONLY)) < 0) { perror("open /proc"); exit (1); } ctl.cmd = PCWATCH; ctl.prwatch.pr_vaddr = (uintptr_t)&test; ctl.prwatch.pr_size = sizeof(int); ctl.prwatch.pr_wflags = WA_READ|WA_WRITE; if (write(ctlfd, &ctl, sizeof (ctl)) != sizeof (ctl)) { perror("Set PCWATCH"); exit (1); } test = 0; } When we attempt to write to the integer test, we TRigger a watchpoint and, by default, the process core dumps. sol8$ ./watchpoint Trace/Breakpoint Trap(coredump) The /proc process information file, prinfo, contains information pertinent to the watchpoint trap and can be read into a struct pr_info. In particular, the si_addr field contains the virtual address of the memory reference that triggered the watchpoint, and the si_code field contains one of TRAP_RWATCH, TRAP_WWATCH, or trAP_XWATCH, indicating read, write, or execute access, respectively. The si_trapafter field is zero unless WA_TRAPAFTER is in effect for this watched area; nonzero indicates that the current instruction is not the instruction that incurred the watchpoint trap. The si_pc field contains the virtual address of the instruction that incurred the trap. Figure 9.14 illustrates watchpoint data structures. Figure 9.14. Watchpoint Data Structures |
|
|