Source-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: src



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.




Home | Main Index | Thread Index | Old Index