Index: sys/arch/amd64/amd64/process_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/process_machdep.c,v retrieving revision 1.29 diff -u -r1.29 process_machdep.c --- sys/arch/amd64/amd64/process_machdep.c 15 Feb 2014 22:20:41 -0000 1.29 +++ sys/arch/amd64/amd64/process_machdep.c 10 Dec 2016 12:47:50 -0000 @@ -49,6 +49,15 @@ * * process_set_pc(proc) * Set the process's program counter. + * + * process_read_watchpoint(proc, index, watchpoint) + * Read hardware watchpoint of the given index. + * + * process_write_watchpoint(proc, index, watchpoint) + * Write hardware watchpoint of the given index. + * + * process_count_watchpoints(proc) + * Return the number of supported hardware watchpoints. */ @@ -157,3 +166,17 @@ return (0); } + +int +process_read_watchpoint(struct lwp *l, struct ptrace_watchpoint *wp) +{ + + + return (0); +} + +int +process_write_watchpoint(struct lwp *l, struct ptrace_watchpoint *wp) +{ + return (0); +} Index: sys/arch/amd64/conf/files.amd64 =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/conf/files.amd64,v retrieving revision 1.87 diff -u -r1.87 files.amd64 --- sys/arch/amd64/conf/files.amd64 6 Sep 2015 07:17:14 -0000 1.87 +++ sys/arch/amd64/conf/files.amd64 10 Dec 2016 12:47:50 -0000 @@ -49,6 +49,7 @@ file arch/amd64/amd64/process_machdep.c machdep file arch/amd64/amd64/trap.c machdep file arch/x86/x86/fpu.c machdep +file arch/x86/x86/dbregs.c machdep file arch/x86/x86/convert_xmm_s87.c machdep file arch/amd64/amd64/lock_stubs.S machdep file dev/cons.c machdep Index: sys/arch/amd64/include/proc.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/proc.h,v retrieving revision 1.19 diff -u -r1.19 proc.h --- sys/arch/amd64/include/proc.h 20 Feb 2014 18:19:10 -0000 1.19 +++ sys/arch/amd64/include/proc.h 10 Dec 2016 12:47:50 -0000 @@ -38,6 +38,7 @@ #include #include +#include /* * Machine-dependent part of the lwp structure for amd64. @@ -51,10 +52,12 @@ struct vm_page *md_gc_ptp; /* pages from pmap g/c */ int md_flags; /* machine-dependent flags */ volatile int md_astpending; + struct x86_hw_watchpoint md_watchpoint[X86_HW_WATCHPOINTS]; }; -#define MDL_COMPAT32 0x0008 /* i386, always return via iret */ -#define MDL_IRET 0x0010 /* force return via iret, not sysret */ +#define MDL_COMPAT32 0x0008 /* i386, always return via iret */ +#define MDL_IRET 0x0010 /* force return via iret, not sysret */ +#define MDL_X86_HW_WATCHPOINTS 0x0020 /* has hardware watchpoints */ struct mdproc { int md_flags; @@ -63,7 +66,7 @@ }; /* md_flags */ -#define MDP_USEDMTRR 0x0008 /* has set volatile MTRRs */ +#define MDP_USEDMTRR 0x0008 /* has set volatile MTRRs */ #else /* __x86_64__ */ Index: sys/arch/amd64/include/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/ptrace.h,v retrieving revision 1.7 diff -u -r1.7 ptrace.h --- sys/arch/amd64/include/ptrace.h 19 Oct 2016 09:44:00 -0000 1.7 +++ sys/arch/amd64/include/ptrace.h 10 Dec 2016 12:47:50 -0000 @@ -36,18 +36,24 @@ /* * i386-dependent ptrace definitions */ -#define PT_STEP (PT_FIRSTMACH + 0) -#define PT_GETREGS (PT_FIRSTMACH + 1) -#define PT_SETREGS (PT_FIRSTMACH + 2) -#define PT_GETFPREGS (PT_FIRSTMACH + 3) -#define PT_SETFPREGS (PT_FIRSTMACH + 4) +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) +#define PT_GETWATCHPOINT (PT_FIRSTMACH + 5) +#define PT_SETWATCHPOINT (PT_FIRSTMACH + 6) +#define PT_NUMWATCHPOINTS (PT_FIRSTMACH + 7) #define PT_MACHDEP_STRINGS \ "PT_STEP", \ "PT_GETREGS", \ "PT_SETREGS", \ "PT_GETFPREGS", \ - "PT_SETFPREGS", + "PT_SETFPREGS", \ + "PT_GETWATCHPOINT", \ + "PT_SETWATCHPOINT", \ + "PT_NUMWATCHPOINTS" #include #define PTRACE_REG_PC(r) (r)->regs[_REG_RIP] @@ -59,6 +65,31 @@ #define PTRACE_BREAKPOINT_SIZE 1 #define PTRACE_BREAKPOINT_ADJ 1 +#define __HAVE_PTRACE_WATCHPOINTS + +/* + * This MD structure translates into x86_hw_watchpoint + * + * pw_address - 0 represents disabled hardware watchpoint + * + * conditions: + * 0b00 - execution + * 0b01 - data write + * 0b10 - io read/write (not implemented) + * 0b11 - data read/write + * + * length: + * 0b00 - 1 byte + * 0b01 - 2 bytes + * 0b10 - undefined + * 0b11 - 4 bytes + */ +struct mdpw { + void *md_address; + int md_condition; + int md_length; +}; + #ifdef _KERNEL_OPT #include "opt_compat_netbsd32.h" Index: sys/arch/amd64/include/userret.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/userret.h,v retrieving revision 1.9 diff -u -r1.9 userret.h --- sys/arch/amd64/include/userret.h 28 Apr 2008 20:23:12 -0000 1.9 +++ sys/arch/amd64/include/userret.h 10 Dec 2016 12:47:50 -0000 @@ -67,6 +67,7 @@ */ #include +#include static __inline void userret(struct lwp *); @@ -77,7 +78,21 @@ static __inline void userret(struct lwp *l) { + size_t i; /* Invoke MI userret code */ mi_userret(l); + + if (l->l_md.md_flags & MDL_X86_HW_WATCHPOINTS) { + for (i = 0; i < X86_HW_WATCHPOINTS; i++) { + if (l->l_md.md_watchpoint[i].address != 0) { + set_x86_hw_watchpoint(i, + l->l_md.md_watchpoint[i].address, + l->l_md.md_watchpoint[i].condition, + l->l_md.md_watchpoint[i].length); + } + } + } else { + clear_x86_hw_watchpoints(); + } } Index: sys/arch/i386/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC,v retrieving revision 1.1143 diff -u -r1.1143 GENERIC --- sys/arch/i386/conf/GENERIC 9 Dec 2016 02:24:17 -0000 1.1143 +++ sys/arch/i386/conf/GENERIC 10 Dec 2016 12:47:53 -0000 @@ -31,6 +31,8 @@ options USER_LDT # user-settable LDT; used by WINE #options PAE # PAE mode (36 bits physical addressing) +options KSTACK_CHECK_DR0 + # CPU features acpicpu* at cpu? # ACPI CPU (including frequency scaling) coretemp* at cpu? # Intel on-die thermal sensor Index: sys/arch/i386/include/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/ptrace.h,v retrieving revision 1.15 diff -u -r1.15 ptrace.h --- sys/arch/i386/include/ptrace.h 25 Sep 2015 16:05:17 -0000 1.15 +++ sys/arch/i386/include/ptrace.h 10 Dec 2016 12:47:53 -0000 @@ -84,8 +84,11 @@ #define __HAVE_PROCFS_MACHDEP /* The machine-dependent ptrace(2) requests. */ -#define PT_GETXMMREGS (PT_FIRSTMACH + 5) -#define PT_SETXMMREGS (PT_FIRSTMACH + 6) +#define PT_GETXMMREGS (PT_FIRSTMACH + 5) +#define PT_SETXMMREGS (PT_FIRSTMACH + 6) +#define PT_GETWATCHPOINT (PT_FIRSTMACH + 7) +#define PT_SETWATCHPOINT (PT_FIRSTMACH + 8) +#define PT_NUMWATCHPOINTS (PT_FIRSTMACH + 9) #define PT_MACHDEP_STRINGS \ "PT_STEP", \ @@ -94,7 +97,10 @@ "PT_GETFPREGS", \ "PT_SETFPREGS", \ "PT_GETXMMREGS", \ - "PT_SETXMMREGS", + "PT_SETXMMREGS", \ + "PT_GETWATCHPOINT", \ + "PT_SETWATCHPOINT", \ + "PT_NUMWATCHPOINTS" #include #define PTRACE_REG_PC(r) (r)->r_eip @@ -106,6 +112,31 @@ #define PTRACE_BREAKPOINT_SIZE 1 #define PTRACE_BREAKPOINT_ADJ sizeof(PTRACE_BREAKPOINT) +#define __HAVE_PTRACE_WATCHPOINTS + +/* + * This MD structure translates into x86_hw_watchpoint + * + * pw_address - 0 represents disabled hardware watchpoint + * + * conditions: + * 0b00 - execution + * 0b01 - data write + * 0b10 - io read/write (not implemented) + * 0b11 - data read/write + * + * length: + * 0b00 - 1 byte + * 0b01 - 2 bytes + * 0b10 - undefined + * 0b11 - 4 bytes + */ +struct mdpw { + void *md_address; + int md_condition; + int md_length; +}; + #ifdef _KERNEL /* Index: sys/arch/x86/include/Makefile =================================================================== RCS file: /cvsroot/src/sys/arch/x86/include/Makefile,v retrieving revision 1.20 diff -u -r1.20 Makefile --- sys/arch/x86/include/Makefile 27 Feb 2016 00:09:45 -0000 1.20 +++ sys/arch/x86/include/Makefile 10 Dec 2016 12:47:56 -0000 @@ -11,6 +11,7 @@ cpu_ucode.h \ cputypes.h \ cpuvar.h \ + dbregs.h \ float.h \ fpu.h \ ieee.h ieeefp.h \ Index: sys/arch/x86/include/dbregs.h =================================================================== RCS file: /cvsroot/src/sys/arch/x86/include/dbregs.h,v retrieving revision 1.1 diff -u -r1.1 dbregs.h --- sys/arch/x86/include/dbregs.h 27 Nov 2016 14:49:21 -0000 1.1 +++ sys/arch/x86/include/dbregs.h 10 Dec 2016 12:47:56 -0000 @@ -32,14 +32,85 @@ #ifdef _KERNEL -struct lwp; -struct dbreg; +#include +#include -void reset_dbregs(void); +/* + * CPU Debug Register 7 bits + * + * LOCAL_EXACT_BREAKPOINT and GLOBAL_EXACT_BREAKPOINT are no longer used since + * the P6 processor family - portable code should set these bits + * unconditionally in oder to get exact breakpoints + */ +#define X86_HW_WATCHPOINT_LOCAL_DR0_BREAKPOINT __BIT(0) +#define X86_HW_WATCHPOINT_GLOBAL_DR0_BREAKPOINT __BIT(1) +#define X86_HW_WATCHPOINT_LOCAL_DR1_BREAKPOINT __BIT(2) +#define X86_HW_WATCHPOINT_GLOBAL_DR1_BREAKPOINT __BIT(3) +#define X86_HW_WATCHPOINT_LOCAL_DR2_BREAKPOINT __BIT(4) +#define X86_HW_WATCHPOINT_GLOBAL_DR2_BREAKPOINT __BIT(5) +#define X86_HW_WATCHPOINT_LOCAL_DR3_BREAKPOINT __BIT(6) +#define X86_HW_WATCHPOINT_GLOBAL_DR3_BREAKPOINT __BIT(7) +#define X86_HW_WATCHPOINT_LOCAL_EXACT_BREAKPOINT __BIT(8) +#define X86_HW_WATCHPOINT_GLOBAL_EXACT_BREAKPOINT __BIT(9) +/* undefined __BIT(10) */ +#define X86_HW_WATCHPOINT_RESTRICTED_TRANSACTIONAL_MEMORY __BIT(11) +/* undefined __BIT(12) */ +#define X86_HW_WATCHPOINT_GENERAL_DETECT_ENABLE __BIT(13) +/* undefined __BITS(14,15) */ -int process_write_dbregs(struct lwp *lwp, const struct dbreg *regs); -int process_read_dbregs(struct lwp *lwp, struct dbreg *regs); +#define X86_HW_WATCHPOINT_DR0_CONDITION_MASK __BITS(16, 17) +#define X86_HW_WATCHPOINT_DR0_LENGTH_MASK __BITS(18, 19) +#define X86_HW_WATCHPOINT_DR1_CONDITION_MASK __BITS(20, 21) +#define X86_HW_WATCHPOINT_DR1_LENGTH_MASK __BITS(22, 23) +#define X86_HW_WATCHPOINT_DR2_CONDITION_MASK __BITS(24, 25) +#define X86_HW_WATCHPOINT_DR2_LENGTH_MASK __BITS(26, 27) +#define X86_HW_WATCHPOINT_DR3_CONDITION_MASK __BITS(28, 29) +#define X86_HW_WATCHPOINT_DR3_LENGTH_MASK __BITS(30, 31) + +/* + * X86_HW_WATCHPOINT_CONDITION_IO_READWRITE is unused + * it requires DE (debug extension) flag in control register CR4 set + * not all CPUs support it + */ +enum x86_hw_watchpoint_condition { + X86_HW_WATCHPOINT_CONDITION_EXECUTION = 0x0, + X86_HW_WATCHPOINT_CONDITION_DATA_WRITE = 0x1, + X86_HW_WATCHPOINT_CONDITION_IO_READWRITE = 0x2, + X86_HW_WATCHPOINT_CONDITION_DATA_READWRITE = 0x3 +}; + +enum x86_hw_watchpoint_length { + X86_HW_WATCHPOINT_LENGTH_BYTE = 0x0, + X86_HW_WATCHPOINT_LENGTH_TWOBYTES = 0x1, + /* 0x2 undefined */ + X86_HW_WATCHPOINT_LENGTH_FOURBYTES = 0x3 +}; + +/* The number of available watchpoint registers available since Intel 80386 */ +#define X86_HW_WATCHPOINTS 4 + +/* + * lwpid - 0 means all LWPs in the process + * address - 0 means that watchpoint is disabled + */ +struct x86_hw_watchpoint { + vaddr_t address; + enum x86_hw_watchpoint_condition condition; + enum x86_hw_watchpoint_length length; +}; + +/* + * Set CPU Debug Registers - to be used before entering user-land context + */ +void set_x86_hw_watchpoint(size_t idx, vaddr_t address, + enum x86_hw_watchpoint_condition condition, + enum x86_hw_watchpoint_length length); + +/* + * Reset CPU Debug Registers - to be used after entering kernel context + */ +void clear_x86_hw_watchpoints(void); #endif -#endif /* _X86_FPU_H_ */ +#endif /* _X86_DBREGS_H_ */ Index: sys/arch/x86/x86/dbregs.c =================================================================== RCS file: sys/arch/x86/x86/dbregs.c diff -N sys/arch/x86/x86/dbregs.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/x86/x86/dbregs.c 10 Dec 2016 12:47:56 -0000 @@ -0,0 +1,103 @@ +/* $NetBSD: dbregs.h,v 1.1 2016/11/27 14:49:21 kamil Exp $ */ + +/*- + * Copyright (c) 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +void +set_x86_hw_watchpoint(size_t idx, vaddr_t address, + enum x86_hw_watchpoint_condition condition, + enum x86_hw_watchpoint_length length) +{ + register_t dr; + + KASSERT(address < VM_MAXUSER_ADDRESS); + + /* Read the original DR7 value in order to save existing watchpoints */ + dr = rdr7(); + + switch (idx) { + case 0: + ldr0(address); + dr |= X86_HW_WATCHPOINT_GLOBAL_DR0_BREAKPOINT; + dr |= __SHIFTIN(condition, + X86_HW_WATCHPOINT_DR0_CONDITION_MASK); + dr |= __SHIFTIN(length, + X86_HW_WATCHPOINT_DR0_LENGTH_MASK); + break; + case 1: + ldr1(address); + dr |= X86_HW_WATCHPOINT_GLOBAL_DR1_BREAKPOINT; + dr |= __SHIFTIN(condition, + X86_HW_WATCHPOINT_DR1_CONDITION_MASK); + dr |= __SHIFTIN(length, + X86_HW_WATCHPOINT_DR1_LENGTH_MASK); + break; + case 2: + ldr2(address); + dr |= X86_HW_WATCHPOINT_GLOBAL_DR2_BREAKPOINT; + dr |= __SHIFTIN(condition, + X86_HW_WATCHPOINT_DR2_CONDITION_MASK); + dr |= __SHIFTIN(length, + X86_HW_WATCHPOINT_DR2_LENGTH_MASK); + break; + case 3: + ldr3(address); + dr |= X86_HW_WATCHPOINT_GLOBAL_DR3_BREAKPOINT; + dr |= __SHIFTIN(condition, + X86_HW_WATCHPOINT_DR3_CONDITION_MASK); + dr |= __SHIFTIN(length, + X86_HW_WATCHPOINT_DR3_LENGTH_MASK); + break; + } + + ldr7(dr); +} + +void +clear_x86_hw_watchpoints(void) +{ + + /* + * It's sufficient to just disable Debug Control Register bits to + * deactivate hardware watchpoints + */ + ldr7(0); + /* + * However at some point we need to clear also other Debug Registers + * do it now + */ + ldr0(0); + ldr1(0); + ldr2(0); + ldr3(0); + ldr6(0); +} Index: sys/compat/netbsd32/netbsd32_ptrace.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_ptrace.c,v retrieving revision 1.2 diff -u -r1.2 netbsd32_ptrace.c --- sys/compat/netbsd32/netbsd32_ptrace.c 2 Nov 2016 00:11:59 -0000 1.2 +++ sys/compat/netbsd32/netbsd32_ptrace.c 10 Dec 2016 12:47:57 -0000 @@ -58,6 +58,8 @@ static void netbsd32_copyoutpiod(const struct ptrace_io_desc *, void *); static int netbsd32_doregs(struct lwp *, struct lwp *, struct uio *); static int netbsd32_dofpregs(struct lwp *, struct lwp *, struct uio *); +static int netbsd32_dowatchpoint(struct lwp *, struct lwp *, int, + struct ptrace_watchpoint *); static int @@ -165,11 +167,32 @@ #endif } +static int +netbsd32_dowatchpoint(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + int write, struct ptrace_watchpoint *pw) +{ + +#ifdef __HAVE_PTRACE_WATCHPOINTS + process_watchpoint32 pw32; + + /* unimplemented */ + + if (write == 0) + return process_write_watchpoint32(l, &pw32); + else + return process_read_watchpoint32(l, &pw32); +#else + return EINVAL; +#endif +} + static struct ptrace_methods netbsd32_ptm = { .ptm_copyinpiod = netbsd32_copyinpiod, .ptm_copyoutpiod = netbsd32_copyoutpiod, .ptm_doregs = netbsd32_doregs, - .ptm_dofpregs = netbsd32_dofpregs + .ptm_dofpregs = netbsd32_dofpregs, + .ptm_dowatchpoint = netbsd32_dowatchpoint }; Index: sys/kern/sys_ptrace_common.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_ptrace_common.c,v retrieving revision 1.6 diff -u -r1.6 sys_ptrace_common.c --- sys/kern/sys_ptrace_common.c 5 Dec 2016 22:07:16 -0000 1.6 +++ sys/kern/sys_ptrace_common.c 10 Dec 2016 12:48:01 -0000 @@ -202,6 +202,11 @@ #ifdef PT_SETFPREGS case PT_SETFPREGS: #endif +#ifdef __HAVE_PTRACE_WATCHPOINTS + case PT_GETWATCHPOINT: + case PT_SETWATCHPOINT: + case PT_NUMWATCHPOINTS: +#endif case PT_SET_EVENT_MASK: case PT_GET_EVENT_MASK: case PT_GET_PROCESS_STATE: @@ -295,6 +300,9 @@ struct ptrace_event pe; struct ptrace_state ps; struct ptrace_lwpinfo pl; +#ifdef __HAVE_PTRACE_WATCHPOINTS + struct ptrace_watchpoint pw; +#endif struct vmspace *vm; int error, write, tmp, pheld; int signo = 0; @@ -405,6 +413,11 @@ #ifdef PT_SETFPREGS case PT_SETFPREGS: #endif +#ifdef __HAVE_PTRACE_WATCHPOINTS + case PT_GETWATCHPOINT: + case PT_SETWATCHPOINT: + case PT_NUMWATCHPOINTS: +#endif #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES #endif @@ -993,6 +1006,44 @@ break; #endif +#ifdef __HAVE_PTRACE_WATCHPOINTS + case PT_SETWATCHPOINT: + write = 1; + case PT_GETWATCHPOINT: + /* write = 0 done above */ + + if (data != sizeof(pw)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, + data, sizeof(pe))); + error = EINVAL; + break; + } + error = copyin(addr, &pw, sizeof(pw)); + if (error) + break; + tmp = pw.pw_lwpid; + if (tmp != 0 && t->p_nlwps > 1) { + lwp_delref(lt); + mutex_enter(t->p_lock); + lt = lwp_find(t, tmp); + if (lt == NULL) { + mutex_exit(t->p_lock); + error = ESRCH; + break; + } + lwp_addref(lt); + mutex_exit(t->p_lock); + } + if (!process_validwatchpoint(lt)) + error = EINVAL; + else { + lwp_lock(lt); + error = ptm->ptm_dowatchpoint(l, lt, write, &pw); + lwp_unlock(lt); + } + break; +#endif + #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES error = ptrace_machdep_dorequest(l, lt, req, addr, data); @@ -1135,6 +1186,33 @@ #endif return 0; } + +int +process_dowatchpoint(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + int write, struct ptrace_watchpoint *wp) +{ + +#ifdef __HAVE_PTRACE_WATCHPOINTS + if (write) + return process_write_watchpoint(l, wp); + else + return process_read_watchpoint(l, wp); +#else + return EINVAL; +#endif +} + +int +process_validwatchpoint(struct lwp *l) +{ + +#ifdef __HAVE_PTRACE_WATCHPOINTS + return (l->l_flag & LW_SYSTEM) == 0; +#else + return 0; +#endif +} #endif /* PTRACE */ MODULE(MODULE_CLASS_EXEC, ptrace_common, ""); @@ -1158,4 +1236,3 @@ } return error; } - Index: sys/sys/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/sys/ptrace.h,v retrieving revision 1.49 diff -u -r1.49 ptrace.h --- sys/sys/ptrace.h 4 Nov 2016 18:14:04 -0000 1.49 +++ sys/sys/ptrace.h 10 Dec 2016 12:48:05 -0000 @@ -118,6 +118,19 @@ #define PL_EVENT_NONE 0 #define PL_EVENT_SIGNAL 1 +#ifdef __HAVE_PTRACE_WATCHPOINTS +/* + * Hardware Watchpoints + * + * MD code handles switch informing whether a particular watchpoint is enabled + */ +typedef struct ptrace_watchpoint { + int pw_index; /* HW Watchpoint ID (count from 0) */ + lwpid_t pw_lwpid; /* LWP described */ + struct mdpw pw_md; /* MD fields */ +} ptrace_watchpoint_t; +#endif + #ifdef _KERNEL #if defined(PT_GETREGS) || defined(PT_SETREGS) @@ -138,12 +151,22 @@ #define process_fpreg64 struct fpreg #endif #endif +#ifdef __HAVE_PTRACE_WATCHPOINTS +#ifndef process_watchpoint32 +#define process_watchpoint32 struct ptrace_watchpoint +#endif +#ifndef process_watchpoint64 +#define process_watchpoint64 struct ptrace_watchpoint +#endif +#endif struct ptrace_methods { int (*ptm_copyinpiod)(struct ptrace_io_desc *, const void *); void (*ptm_copyoutpiod)(const struct ptrace_io_desc *, void *); int (*ptm_doregs)(struct lwp *, struct lwp *, struct uio *); int (*ptm_dofpregs)(struct lwp *, struct lwp *, struct uio *); + int (*ptm_dowatchpoint)(struct lwp *, struct lwp *, int, + struct ptrace_watchpoint *); }; int ptrace_init(void); @@ -156,6 +179,10 @@ int process_dofpregs(struct lwp *, struct lwp *, struct uio *); int process_validfpregs(struct lwp *); +int process_dowatchpoint(struct lwp *, struct lwp *, int, + struct ptrace_watchpoint *); +int process_validwatchpoint(struct lwp *); + int process_domem(struct lwp *, struct lwp *, struct uio *); void process_stoptrace(void); @@ -211,6 +238,32 @@ #endif #endif +#ifdef __HAVE_PTRACE_WATCHPOINTS +int process_read_watchpoint(struct lwp *, struct ptrace_watchpoint *); +#ifndef process_read_watchpoint32 +#define process_read_watchpoint32 process_read_watchpoint +#endif +#ifndef process_read_watchpoint64 +#define process_read_watchpoint64 process_read_watchpoint +#endif + +int process_write_watchpoint(struct lwp *, struct ptrace_watchpoint *); +#ifndef process_write_watchpoint32 +#define process_write_watchpoint32 process_write_watchpoint +#endif +#ifndef process_write_watchpoint64 +#define process_write_watchpoint64 process_write_watchpoint +#endif + +int process_count_watchpoints(struct lwp *); +#ifndef process_count_watchpoints32 +#define process_count_watchpoints32 process_count_watchpoints +#endif +#ifndef process_count_watchpoints64 +#define process_count_watchpoints64 process_count_watchpoints +#endif +#endif + #ifdef __HAVE_PROCFS_MACHDEP int ptrace_machdep_dorequest(struct lwp *, struct lwp *, int, void *, int);