summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libc/amd64/sys/Makefile.inc6
-rw-r--r--lib/libc/i386/sys/Makefile.inc6
-rw-r--r--lib/libc/i386/sys/i386_clr_watch.c50
-rw-r--r--lib/libc/i386/sys/i386_set_watch.3103
-rw-r--r--lib/libc/i386/sys/i386_set_watch.c88
-rw-r--r--sys/amd64/include/reg.h6
-rw-r--r--sys/amd64/include/sysarch.h4
-rw-r--r--sys/i386/include/reg.h6
-rw-r--r--sys/i386/include/sysarch.h4
9 files changed, 269 insertions, 4 deletions
diff --git a/lib/libc/amd64/sys/Makefile.inc b/lib/libc/amd64/sys/Makefile.inc
index c1c3d2d..f670705 100644
--- a/lib/libc/amd64/sys/Makefile.inc
+++ b/lib/libc/amd64/sys/Makefile.inc
@@ -1,8 +1,8 @@
# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp
# $FreeBSD$
-SRCS+= i386_get_ioperm.c i386_get_ldt.c i386_set_ioperm.c i386_set_ldt.c \
- i386_vm86.c
+SRCS+= i386_clr_watch.c i386_get_ioperm.c i386_get_ldt.c i386_set_ioperm.c \
+ i386_set_ldt.c i386_set_watch.c i386_vm86.c
MDASM= Ovfork.S brk.S cerror.S exect.S fork.S pipe.S ptrace.S reboot.S \
rfork.S sbrk.S setlogin.S sigreturn.S syscall.S
@@ -22,7 +22,9 @@ PSEUDOR= _exit.o
.if ${LIB} == "c"
MAN2+= i386_get_ioperm.2 i386_get_ldt.2 i386_vm86.2
+MAN3+= i386_set_watch.3
MLINKS+=i386_get_ioperm.2 i386_set_ioperm.2
MLINKS+=i386_get_ldt.2 i386_set_ldt.2
+MLINKS+=i386_set_watch.3 i386_clr_watch.3
.endif
diff --git a/lib/libc/i386/sys/Makefile.inc b/lib/libc/i386/sys/Makefile.inc
index c1c3d2d..f670705 100644
--- a/lib/libc/i386/sys/Makefile.inc
+++ b/lib/libc/i386/sys/Makefile.inc
@@ -1,8 +1,8 @@
# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp
# $FreeBSD$
-SRCS+= i386_get_ioperm.c i386_get_ldt.c i386_set_ioperm.c i386_set_ldt.c \
- i386_vm86.c
+SRCS+= i386_clr_watch.c i386_get_ioperm.c i386_get_ldt.c i386_set_ioperm.c \
+ i386_set_ldt.c i386_set_watch.c i386_vm86.c
MDASM= Ovfork.S brk.S cerror.S exect.S fork.S pipe.S ptrace.S reboot.S \
rfork.S sbrk.S setlogin.S sigreturn.S syscall.S
@@ -22,7 +22,9 @@ PSEUDOR= _exit.o
.if ${LIB} == "c"
MAN2+= i386_get_ioperm.2 i386_get_ldt.2 i386_vm86.2
+MAN3+= i386_set_watch.3
MLINKS+=i386_get_ioperm.2 i386_set_ioperm.2
MLINKS+=i386_get_ldt.2 i386_set_ldt.2
+MLINKS+=i386_set_watch.3 i386_clr_watch.3
.endif
diff --git a/lib/libc/i386/sys/i386_clr_watch.c b/lib/libc/i386/sys/i386_clr_watch.c
new file mode 100644
index 0000000..0320634
--- /dev/null
+++ b/lib/libc/i386/sys/i386_clr_watch.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000 Brian S. Dean <bsd@bsdhome.com>
+ * 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 BRIAN S. DEAN ``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 BRIAN S. DEAN 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.
+ *
+ */
+
+/*
+ * $FreeBSD$
+ */
+
+
+#include <machine/reg.h>
+#include <machine/sysarch.h>
+
+
+int
+i386_clr_watch(int watchnum, struct dbreg * d)
+{
+
+ if (watchnum < 0 || watchnum >= 4)
+ return -1;
+
+ d->dr7 = d->dr7 & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+ DBREG_DRX(d,watchnum) = 0;
+
+ return 0;
+}
diff --git a/lib/libc/i386/sys/i386_set_watch.3 b/lib/libc/i386/sys/i386_set_watch.3
new file mode 100644
index 0000000..a85ae85
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_watch.3
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2000 Brian S. Dean
+.\" All rights reserved.
+.\"
+.\" This man-page is based on a similar man-page by Jonathan Lemon
+.\" which is copyrighted under the following conditions:
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 24, 2000
+.Os
+.Dt I386_SET_WATCH 3
+.Sh NAME
+.Nm i386_clr_watch ,
+.Nm i386_set_watch
+.Nd manage i386 debug register values
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <machine/reg.h>
+.Fd #include <machine/sysarch.h>
+.Ft int
+.Fn i386_clr_watch "int watchnum" "struct dbreg *d"
+.Ft int
+.Fn i386_set_watch "int watchnum" "unsigned int watchaddr" "int size" "int access" "struct dbreg *d"
+.Sh DESCRIPTION
+.Fn i386_clr_watch
+will disable the indicated watch point within the specified debug
+register set.
+.Pp
+.Fn i386_set_watch
+will set up the specified debug registers as indicated by the
+parameters. The
+.Fa watchnum
+argument specifies which watch register is used, 0, 1, 2, 3, or -1. If
+.Fa watchnum
+is -1, a free watch register is found and used. If there are no free
+watch registers, an error code of -1 is returned.
+.Fa Watchaddr
+specifies the watch address,
+.Fa size
+specifies the size in bytes of the area to be watched (1, 2, or 4 bytes),
+and
+.Fa access
+specifes the type of watch point:
+.Pp
+.Bd -literal -offset indent -compact
+DBREG_DR7_EXEC An execution breakpoint.
+DBREG_DR7_WRONLY Break only when the watch area is written to.
+DBREG_DR7_RDWR Break when the watch area is read from or written
+ to.
+.Ed
+.Pp
+Note that these functions do not actually set or clear breakpoints;
+they manipulate the indicated debug register set. You must use
+.Xr ptrace 2
+to retrieve and install the debug register values for a process.
+.Sh RETURN VALUES
+.Fn i386_clr_watch
+returns 0 on success, or -1 if
+.Fa watchnum
+is invalid (not in the range of 0-3).
+.Pp
+.Fn i386_set_watch
+will return the
+.Fa watchnum
+argument, or the watchnum actually used in the case that
+.Fa watchnum
+is -1 on success. On error,
+.Fn i386_set_watch
+will return -1 indicating that the watchpoint could not be set up
+because either no more watchpoints are available, or
+.Fa watchnum ,
+.Fa size ,
+or
+.Fa access
+is invalid.
+.Sh SEE ALSO
+.Xr ptrace 2 ,
+.Xr procfs 5
+.Sh AUTHORS
+This man page was written by
+.An Brian S. Dean .
diff --git a/lib/libc/i386/sys/i386_set_watch.c b/lib/libc/i386/sys/i386_set_watch.c
new file mode 100644
index 0000000..bb710dc
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_watch.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000 Brian S. Dean <bsd@bsdhome.com>
+ * 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 BRIAN S. DEAN ``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 BRIAN S. DEAN 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.
+ *
+ */
+
+/*
+ * $FreeBSD$
+ */
+
+
+#include <machine/reg.h>
+#include <machine/sysarch.h>
+
+
+int
+i386_set_watch(int watchnum, unsigned int watchaddr, int size,
+ int access, struct dbreg * d)
+{
+ int i;
+ unsigned int mask;
+
+ if (watchnum == -1) {
+ for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
+ if ((d->dr7 & mask) == 0)
+ break;
+ if (i < 4)
+ watchnum = i;
+ else
+ return -1;
+ }
+
+ switch (access) {
+ case DBREG_DR7_EXEC:
+ size = 1; /* size must be 1 for an execution breakpoint */
+ /* fall through */
+ case DBREG_DR7_WRONLY:
+ case DBREG_DR7_RDWR:
+ break;
+ default : return -1; break;
+ }
+
+ /*
+ * we can watch a 1, 2, or 4 byte sized location
+ */
+ switch (size) {
+ case 1 : mask = 0x00; break;
+ case 2 : mask = 0x01 << 2; break;
+ case 4 : mask = 0x03 << 2; break;
+ default : return -1; break;
+ }
+
+ mask |= access;
+
+ /* clear the bits we are about to affect */
+ d->dr7 &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+
+ /* set drN register to the address, N=watchnum */
+ DBREG_DRX(d,watchnum) = watchaddr;
+
+ /* enable the watchpoint */
+ d->dr7 |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16));
+
+ return watchnum;
+}
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index 6effd1a..47856a3 100644
--- a/sys/amd64/include/reg.h
+++ b/sys/amd64/include/reg.h
@@ -132,6 +132,12 @@ struct dbreg {
unsigned int dr7; /* debug control register */
};
+#define DBREG_DR7_EXEC 0x00 /* break on execute */
+#define DBREG_DR7_WRONLY 0x01 /* break on write */
+#define DBREG_DR7_RDWR 0x03 /* break on read or write */
+#define DBREG_DRX(d,x) ((&d->dr0)[x]) /* reference dr0 - dr7 by
+ register number */
+
#ifdef _KERNEL
/*
diff --git a/sys/amd64/include/sysarch.h b/sys/amd64/include/sysarch.h
index 01e63c5..7e355af 100644
--- a/sys/amd64/include/sysarch.h
+++ b/sys/amd64/include/sysarch.h
@@ -68,6 +68,7 @@ struct i386_vm86_args {
#include <sys/cdefs.h>
union descriptor;
+struct dbreg;
__BEGIN_DECLS
int i386_get_ldt __P((int, union descriptor *, int));
@@ -75,6 +76,9 @@ int i386_set_ldt __P((int, union descriptor *, int));
int i386_get_ioperm __P((unsigned int, unsigned int *, int *));
int i386_set_ioperm __P((unsigned int, unsigned int, int));
int i386_vm86 __P((int, void *));
+int i386_set_watch __P((int watchnum, unsigned int watchaddr, int size,
+ int access, struct dbreg * d));
+int i386_clr_watch __P((int watchnum, struct dbreg * d));
__END_DECLS
#endif
diff --git a/sys/i386/include/reg.h b/sys/i386/include/reg.h
index 6effd1a..47856a3 100644
--- a/sys/i386/include/reg.h
+++ b/sys/i386/include/reg.h
@@ -132,6 +132,12 @@ struct dbreg {
unsigned int dr7; /* debug control register */
};
+#define DBREG_DR7_EXEC 0x00 /* break on execute */
+#define DBREG_DR7_WRONLY 0x01 /* break on write */
+#define DBREG_DR7_RDWR 0x03 /* break on read or write */
+#define DBREG_DRX(d,x) ((&d->dr0)[x]) /* reference dr0 - dr7 by
+ register number */
+
#ifdef _KERNEL
/*
diff --git a/sys/i386/include/sysarch.h b/sys/i386/include/sysarch.h
index 01e63c5..7e355af 100644
--- a/sys/i386/include/sysarch.h
+++ b/sys/i386/include/sysarch.h
@@ -68,6 +68,7 @@ struct i386_vm86_args {
#include <sys/cdefs.h>
union descriptor;
+struct dbreg;
__BEGIN_DECLS
int i386_get_ldt __P((int, union descriptor *, int));
@@ -75,6 +76,9 @@ int i386_set_ldt __P((int, union descriptor *, int));
int i386_get_ioperm __P((unsigned int, unsigned int *, int *));
int i386_set_ioperm __P((unsigned int, unsigned int, int));
int i386_vm86 __P((int, void *));
+int i386_set_watch __P((int watchnum, unsigned int watchaddr, int size,
+ int access, struct dbreg * d));
+int i386_clr_watch __P((int watchnum, struct dbreg * d));
__END_DECLS
#endif
OpenPOWER on IntegriCloud