Source-Changes-HG archive

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

[src/trunk]: src/tests/kernel/arch/amd64 Add new tests dbregs[2345] in MD arc...



details:   https://anonhg.NetBSD.org/src/rev/a30d3d5b2fe0
branches:  trunk
changeset: 349250:a30d3d5b2fe0
user:      kamil <kamil%NetBSD.org@localhost>
date:      Fri Dec 02 06:49:00 2016 +0000

description:
Add new tests dbregs[2345] in MD arch/amd64/ t_ptrace_wait{,3,4,6,id,pid}

dbregs2:
    Verify that setting DR0 is preserved across ptrace(2) calls

dbregs3:
    Verify that setting DR1 is preserved across ptrace(2) calls

dbregs4:
    Verify that setting DR2 is preserved across ptrace(2) calls

dbregs5:
    Verify that setting DR3 is preserved across ptrace(2) calls

These tests are deliberately fine-grained as they are expected to penetrate
precisely each functional aspect of CPU Debug Registers on amd64 one after
another.

These tests (and MI ones) might be generated or merged with helper
functions, however in order to copy-and-paste them out of a test-suite and
quickly port to other platform (in order to compare results) it's useful to
keep them as stand-alone as they are.

Code from these tests might be shared with other ports in future, for the
same reason keep them currently as they are.

Sponsored by <The NetBSD Foundation>

diffstat:

 tests/kernel/arch/amd64/t_ptrace_wait.c |  344 +++++++++++++++++++++++++++++++-
 1 files changed, 342 insertions(+), 2 deletions(-)

diffs (truncated from 371 to 300 lines):

diff -r 28d2c6b90518 -r a30d3d5b2fe0 tests/kernel/arch/amd64/t_ptrace_wait.c
--- a/tests/kernel/arch/amd64/t_ptrace_wait.c   Fri Dec 02 06:19:50 2016 +0000
+++ b/tests/kernel/arch/amd64/t_ptrace_wait.c   Fri Dec 02 06:49:00 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: t_ptrace_wait.c,v 1.1 2016/12/02 05:54:15 kamil Exp $  */
+/*     $NetBSD: t_ptrace_wait.c,v 1.2 2016/12/02 06:49:00 kamil Exp $  */
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: t_ptrace_wait.c,v 1.1 2016/12/02 05:54:15 kamil Exp $");
+__RCSID("$NetBSD: t_ptrace_wait.c,v 1.2 2016/12/02 06:49:00 kamil Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -111,12 +111,352 @@
 }
 #endif
 
+#if defined(HAVE_DBREGS)
+ATF_TC(dbregs2);
+ATF_TC_HEAD(dbregs2, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Verify that setting DR0 is preserved across ptrace(2) calls");
+}
+
+ATF_TC_BODY(dbregs2, tc)
+{
+       const int exitval = 5;
+       const int sigval = SIGSTOP;
+       pid_t child, wpid;
+#if defined(TWAIT_HAVE_STATUS)
+       int status;
+#endif
+       struct dbreg r1;
+       struct dbreg r2;
+       /* Number of available CPU Debug Registers on AMD64 */
+       const size_t len = 16;
+       size_t i;
+       int watchme;
+
+       printf("Assert that known number of Debug Registers (%zu) is valid\n",
+           len);
+       ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);
+       ATF_REQUIRE_EQ(__arraycount(r2.dbregs), len);
+
+       printf("Before forking process PID=%d\n", getpid());
+       child = atf_utils_fork();
+       if (child == 0) {
+               printf("Before calling PT_TRACE_ME from child %d\n", getpid());
+               FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
+
+               printf("Before raising %s from child\n", strsignal(sigval));
+               FORKEE_ASSERT(raise(sigval) == 0);
+
+               printf("Before exiting of the child process\n");
+               _exit(exitval);
+       }
+       printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_stopped(status, sigval);
+
+       printf("Call GETDBREGS for the child process (r1)\n");
+       ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
+
+       printf("State of the debug registers (r1):\n");
+       for (i = 0; i < __arraycount(r1.dbregs); i++)
+               printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
+
+       r1.dbregs[0] = (long)(intptr_t)&watchme;
+       printf("Set DR0 (r1.dbregs[0]) to new value %#lx\n", r1.dbregs[0]);
+
+       printf("New state of the debug registers (r1):\n");
+       for (i = 0; i < __arraycount(r1.dbregs); i++)
+               printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
+
+       printf("Call SETDBREGS for the child process (r1)\n");
+       ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
+
+       printf("Call GETDBREGS for the child process (r2)\n");
+       ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
+
+       printf("Assert that (r1) and (r2) are the same\n");
+       ATF_REQUIRE(memcmp(&r1, &r2, len) == 0);
+
+       printf("Before resuming the child process where it left off and "
+           "without signal to be sent\n");
+       ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_exited(status, exitval);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+}
+#endif
+
+#if defined(HAVE_DBREGS)
+ATF_TC(dbregs3);
+ATF_TC_HEAD(dbregs3, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Verify that setting DR1 is preserved across ptrace(2) calls");
+}
+
+ATF_TC_BODY(dbregs3, tc)
+{
+       const int exitval = 5;
+       const int sigval = SIGSTOP;
+       pid_t child, wpid;
+#if defined(TWAIT_HAVE_STATUS)
+       int status;
+#endif
+       struct dbreg r1;
+       struct dbreg r2;
+       /* Number of available CPU Debug Registers on AMD64 */
+       const size_t len = 16;
+       size_t i;
+       int watchme;
+
+       printf("Assert that known number of Debug Registers (%zu) is valid\n",
+           len);
+       ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);
+       ATF_REQUIRE_EQ(__arraycount(r2.dbregs), len);
+
+       printf("Before forking process PID=%d\n", getpid());
+       child = atf_utils_fork();
+       if (child == 0) {
+               printf("Before calling PT_TRACE_ME from child %d\n", getpid());
+               FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
+
+               printf("Before raising %s from child\n", strsignal(sigval));
+               FORKEE_ASSERT(raise(sigval) == 0);
+
+               printf("Before exiting of the child process\n");
+               _exit(exitval);
+       }
+       printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_stopped(status, sigval);
+
+       printf("Call GETDBREGS for the child process (r1)\n");
+       ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
+
+       printf("State of the debug registers (r1):\n");
+       for (i = 0; i < __arraycount(r1.dbregs); i++)
+               printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
+
+       r1.dbregs[1] = (long)(intptr_t)&watchme;
+       printf("Set DR1 (r1.dbregs[1]) to new value %#lx\n", r1.dbregs[1]);
+
+       printf("New state of the debug registers (r1):\n");
+       for (i = 0; i < __arraycount(r1.dbregs); i++)
+               printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
+
+       printf("Call SETDBREGS for the child process (r1)\n");
+       ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
+
+       printf("Call GETDBREGS for the child process (r2)\n");
+       ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
+
+       printf("Assert that (r1) and (r2) are the same\n");
+       ATF_REQUIRE(memcmp(&r1, &r2, len) == 0);
+
+       printf("Before resuming the child process where it left off and "
+           "without signal to be sent\n");
+       ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_exited(status, exitval);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+}
+#endif
+
+#if defined(HAVE_DBREGS)
+ATF_TC(dbregs4);
+ATF_TC_HEAD(dbregs4, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Verify that setting DR2 is preserved across ptrace(2) calls");
+}
+
+ATF_TC_BODY(dbregs4, tc)
+{
+       const int exitval = 5;
+       const int sigval = SIGSTOP;
+       pid_t child, wpid;
+#if defined(TWAIT_HAVE_STATUS)
+       int status;
+#endif
+       struct dbreg r1;
+       struct dbreg r2;
+       /* Number of available CPU Debug Registers on AMD64 */
+       const size_t len = 16;
+       size_t i;
+       int watchme;
+
+       printf("Assert that known number of Debug Registers (%zu) is valid\n",
+           len);
+       ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);
+       ATF_REQUIRE_EQ(__arraycount(r2.dbregs), len);
+
+       printf("Before forking process PID=%d\n", getpid());
+       child = atf_utils_fork();
+       if (child == 0) {
+               printf("Before calling PT_TRACE_ME from child %d\n", getpid());
+               FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
+
+               printf("Before raising %s from child\n", strsignal(sigval));
+               FORKEE_ASSERT(raise(sigval) == 0);
+
+               printf("Before exiting of the child process\n");
+               _exit(exitval);
+       }
+       printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_stopped(status, sigval);
+
+       printf("Call GETDBREGS for the child process (r1)\n");
+       ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
+
+       printf("State of the debug registers (r1):\n");
+       for (i = 0; i < __arraycount(r1.dbregs); i++)
+               printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
+
+       r1.dbregs[2] = (long)(intptr_t)&watchme;
+       printf("Set DR2 (r1.dbregs[2]) to new value %#lx\n", r1.dbregs[2]);
+
+       printf("New state of the debug registers (r1):\n");
+       for (i = 0; i < __arraycount(r1.dbregs); i++)
+               printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
+
+       printf("Call SETDBREGS for the child process (r1)\n");
+       ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
+
+       printf("Call GETDBREGS for the child process (r2)\n");
+       ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
+
+       printf("Assert that (r1) and (r2) are the same\n");
+       ATF_REQUIRE(memcmp(&r1, &r2, len) == 0);
+
+       printf("Before resuming the child process where it left off and "
+           "without signal to be sent\n");
+       ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_exited(status, exitval);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+}
+#endif
+
+#if defined(HAVE_DBREGS)
+ATF_TC(dbregs5);
+ATF_TC_HEAD(dbregs5, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Verify that setting DR3 is preserved across ptrace(2) calls");
+}
+
+ATF_TC_BODY(dbregs5, tc)
+{
+       const int exitval = 5;
+       const int sigval = SIGSTOP;
+       pid_t child, wpid;
+#if defined(TWAIT_HAVE_STATUS)
+       int status;
+#endif
+       struct dbreg r1;
+       struct dbreg r2;
+       /* Number of available CPU Debug Registers on AMD64 */
+       const size_t len = 16;
+       size_t i;
+       int watchme;
+
+       printf("Assert that known number of Debug Registers (%zu) is valid\n",
+           len);
+       ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);



Home | Main Index | Thread Index | Old Index