Module Name: src Committed By: kamil Date: Thu Feb 23 03:34:23 UTC 2017
Modified Files: src/distrib/sets/lists/comp: md.amd64 md.i386 src/sys/arch/amd64/amd64: machdep.c netbsd32_machdep.c process_machdep.c trap.c src/sys/arch/amd64/include: netbsd32_machdep.h pcb.h proc.h ptrace.h reg.h userret.h src/sys/arch/i386/i386: machdep.c process_machdep.c trap.c src/sys/arch/i386/include: pcb.h proc.h ptrace.h reg.h userret.h src/sys/arch/x86/include: dbregs.h src/sys/arch/x86/x86: dbregs.c vm_machdep.c src/sys/compat/netbsd32: netbsd32_ptrace.c src/sys/kern: sys_ptrace.c sys_ptrace_common.c src/sys/sys: proc.h ptrace.h Log Message: Introduce PT_GETDBREGS and PT_SETDBREGS in ptrace(2) on i386 and amd64 This interface is modeled after FreeBSD API with the usage. This replaced previous watchpoint API. The previous one was introduced recently in NetBSD-current and remove its spurs without any backward-compatibility. Design choices for Debug Register accessors: - exec() (TRAP_EXEC event) must remove debug registers from LWP - debug registers are only per-LWP, not per-process globally - debug registers must not be inherited after (v)forking a process - debug registers must not be inherited after forking a thread - a debugger is responsible to set global watchpoints/breakpoints with the debug registers, to achieve this PTRACE_LWP_CREATE/PTRACE_LWP_EXIT event monitoring function is designed to be used - debug register traps must generate SIGTRAP with si_code TRAP_DBREG - debugger is responsible to retrieve debug register state to distinguish the exact debug register trap (DR6 is Status Register on x86) - kernel must not remove debug register traps after triggering a trap event a debugger is responsible to detach this trap with appropriate PT_SETDBREGS call (DR7 is Control Register on x86) - debug registers must not be exposed in mcontext - userland must not be allowed to set a trap on the kernel Implementation notes on i386 and amd64: - the initial state of debug register is retrieved on boot and this value is stored in a local copy (initdbregs), this value is used to initialize dbreg context after PT_GETDBREGS - struct dbregs is stored in pcb as a pointer and by default not initialized - reserved registers (DR4-DR5, DR9-DR15) are ignored Further ideas: - restrict this interface with securelevel Tested on real hardware i386 (Intel Pentium IV) and amd64 (Intel i7). This commit enables 390 debug register ATF tests in kernel/arch/x86. All tests are passing. This commit does not cover netbsd32 compat code. Currently other interface PT_GET_SIGINFO/PT_SET_SIGINFO is required in netbsd32 compat code in order to validate reliably PT_GETDBREGS/PT_SETDBREGS. This implementation does not cover FreeBSD specific defines in their <x86/reg.h>: DBREG_DR7_LOCAL_ENABLE, DBREG_DR7_GLOBAL_ENABLE, DBREG_DR7_LEN_1 etc. These values tend to be reinvented by each tracer on its own. GNU Debugger (GDB) works with NetBSD debug registers after adding this patch: --- gdb/amd64bsd-nat.c.orig 2016-02-10 03:19:39.000000000 +0000 +++ gdb/amd64bsd-nat.c @@ -167,6 +167,10 @@ amd64bsd_target (void) #ifdef HAVE_PT_GETDBREGS +#ifndef DBREG_DRX +#define DBREG_DRX(d,x) ((d)->dr[(x)]) +#endif + static unsigned long amd64bsd_dr_get (ptid_t ptid, int regnum) { Another reason to stop introducing unpopular defines covering machine specific register macros is that these value varies across generations of the same CPU family. GDB demo: (gdb) c Continuing. Watchpoint 2: traceme Old value = 0 New value = 16 main (argc=1, argv=0x7f7fff79fe30) at test.c:8 8 printf("traceme=%d\n", traceme); (Currently the GDB interface is not reliable due to NetBSD support bugs) Sponsored by <The NetBSD Foundation> To generate a diff of this commit: cvs rdiff -u -r1.242 -r1.243 src/distrib/sets/lists/comp/md.amd64 cvs rdiff -u -r1.162 -r1.163 src/distrib/sets/lists/comp/md.i386 cvs rdiff -u -r1.251 -r1.252 src/sys/arch/amd64/amd64/machdep.c cvs rdiff -u -r1.103 -r1.104 src/sys/arch/amd64/amd64/netbsd32_machdep.c cvs rdiff -u -r1.31 -r1.32 src/sys/arch/amd64/amd64/process_machdep.c cvs rdiff -u -r1.91 -r1.92 src/sys/arch/amd64/amd64/trap.c cvs rdiff -u -r1.21 -r1.22 src/sys/arch/amd64/include/netbsd32_machdep.h cvs rdiff -u -r1.25 -r1.26 src/sys/arch/amd64/include/pcb.h cvs rdiff -u -r1.20 -r1.21 src/sys/arch/amd64/include/proc.h cvs rdiff -u -r1.9 -r1.10 src/sys/arch/amd64/include/ptrace.h \ src/sys/arch/amd64/include/reg.h cvs rdiff -u -r1.11 -r1.12 src/sys/arch/amd64/include/userret.h cvs rdiff -u -r1.779 -r1.780 src/sys/arch/i386/i386/machdep.c cvs rdiff -u -r1.88 -r1.89 src/sys/arch/i386/i386/process_machdep.c cvs rdiff -u -r1.283 -r1.284 src/sys/arch/i386/i386/trap.c cvs rdiff -u -r1.54 -r1.55 src/sys/arch/i386/include/pcb.h cvs rdiff -u -r1.43 -r1.44 src/sys/arch/i386/include/proc.h cvs rdiff -u -r1.17 -r1.18 src/sys/arch/i386/include/ptrace.h cvs rdiff -u -r1.19 -r1.20 src/sys/arch/i386/include/reg.h cvs rdiff -u -r1.13 -r1.14 src/sys/arch/i386/include/userret.h cvs rdiff -u -r1.3 -r1.4 src/sys/arch/x86/include/dbregs.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/x86/x86/dbregs.c cvs rdiff -u -r1.27 -r1.28 src/sys/arch/x86/x86/vm_machdep.c cvs rdiff -u -r1.3 -r1.4 src/sys/compat/netbsd32/netbsd32_ptrace.c cvs rdiff -u -r1.3 -r1.4 src/sys/kern/sys_ptrace.c cvs rdiff -u -r1.16 -r1.17 src/sys/kern/sys_ptrace_common.c cvs rdiff -u -r1.337 -r1.338 src/sys/sys/proc.h cvs rdiff -u -r1.57 -r1.58 src/sys/sys/ptrace.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.