diff --git a/tests/kernel/arch/amd64/t_ptrace_wait.c b/tests/kernel/arch/amd64/t_ptrace_wait.c index ad0317687a79..5b0accbff5de 100644 --- a/tests/kernel/arch/amd64/t_ptrace_wait.c +++ b/tests/kernel/arch/amd64/t_ptrace_wait.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_ptrace_wait.c,v 1.7 2016/12/13 13:09:00 kamil Exp $ */ +/* $NetBSD: t_ptrace_wait.c,v 1.8 2016/12/15 12:15:20 kamil Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include -__RCSID("$NetBSD: t_ptrace_wait.c,v 1.7 2016/12/13 13:09:00 kamil Exp $"); +__RCSID("$NetBSD: t_ptrace_wait.c,v 1.8 2016/12/15 12:15:20 kamil Exp $"); #include #include @@ -37,6 +37,7 @@ __RCSID("$NetBSD: t_ptrace_wait.c,v 1.7 2016/12/13 13:09:00 kamil Exp $"); #include #include #include +#include #include #include #include @@ -137,6 +138,1229 @@ ATF_TC_BODY(regs1, tc) } #endif +#if defined(__HAVE_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_count); +ATF_TC_HEAD(watchpoint_count, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and assert four available watchpoints"); +} + +ATF_TC_BODY(watchpoint_count, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + int N; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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 GETREGS for the child process\n"); + ATF_REQUIRE((N = ptrace(PT_COUNT_WATCHPOINTS, child, NULL, 0)) != -1); + printf("Reported %d watchpoints\n", N); + + ATF_REQUIRE_EQ_MSG(N, 4, "Expected 4 hw watchpoints - got %d", N); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_read); +ATF_TC_HEAD(watchpoint_read, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and assert four available watchpoints"); +} + +ATF_TC_BODY(watchpoint_read, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + int i, N; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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 GETREGS for the child process\n"); + ATF_REQUIRE((N = ptrace(PT_COUNT_WATCHPOINTS, child, NULL, 0)) != -1); + + ATF_REQUIRE_EQ_MSG(N, 4, "Expected 4 hw watchpoints - got %d", N); + + for (i = 0; i < N; i++) { + printf("Before reading watchpoint %d\n", i); + pw.pw_index = i; + ATF_REQUIRE(ptrace(PT_READ_WATCHPOINT, child, &pw, len) != -1); + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + } + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_write_unmodified); +ATF_TC_HEAD(watchpoint_write_unmodified, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and assert functional write of " + "unmodified data"); +} + +ATF_TC_BODY(watchpoint_write_unmodified, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + int i, N; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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 GETREGS for the child process\n"); + ATF_REQUIRE((N = ptrace(PT_COUNT_WATCHPOINTS, child, NULL, 0)) != -1); + + ATF_REQUIRE_EQ_MSG(N, 4, "Expected 4 hw watchpoints - got %d", N); + + for (i = 0; i < N; i++) { + printf("Before reading watchpoint %d\n", i); + pw.pw_index = i; + ATF_REQUIRE(ptrace(PT_READ_WATCHPOINT, child, &pw, len) != -1); + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d (unmodified)\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) + != -1); + } + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_code0); +ATF_TC_HEAD(watchpoint_trap_code0, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test code trap with watchpoint 0"); +} + +ATF_TC_BODY(watchpoint_trap_code0, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 0; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("check_happy(%d)=%d\n", watchme, check_happy(watchme)); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_lwpid = 0; + pw.pw_md.md_address = (void *)check_happy; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_EXECUTION; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + pw.pw_md.md_address = NULL; + printf("Before writing watchpoint %d (disable it)\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_code1); +ATF_TC_HEAD(watchpoint_trap_code1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test code trap with watchpoint 1"); +} + +ATF_TC_BODY(watchpoint_trap_code1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 1; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("check_happy(%d)=%d\n", watchme, check_happy(watchme)); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_lwpid = 0; + pw.pw_md.md_address = (void *)check_happy; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_EXECUTION; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + pw.pw_md.md_address = NULL; + printf("Before writing watchpoint %d (disable it)\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_code2); +ATF_TC_HEAD(watchpoint_trap_code2, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test code trap with watchpoint 2"); +} + +ATF_TC_BODY(watchpoint_trap_code2, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 2; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("check_happy(%d)=%d\n", watchme, check_happy(watchme)); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_lwpid = 0; + pw.pw_md.md_address = (void *)check_happy; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_EXECUTION; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + pw.pw_md.md_address = NULL; + printf("Before writing watchpoint %d (disable it)\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_code3); +ATF_TC_HEAD(watchpoint_trap_code3, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test code trap with watchpoint 3"); +} + +ATF_TC_BODY(watchpoint_trap_code3, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 3; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("check_happy(%d)=%d\n", watchme, check_happy(watchme)); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_lwpid = 0; + pw.pw_md.md_address = (void *)check_happy; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_EXECUTION; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + pw.pw_md.md_address = NULL; + printf("Before writing watchpoint %d (disable it)\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_write0); +ATF_TC_HEAD(watchpoint_trap_data_write0, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 0"); +} + +ATF_TC_BODY(watchpoint_trap_data_write0, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 0; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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); + + ++watchme; + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = 0; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_WRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_write1); +ATF_TC_HEAD(watchpoint_trap_data_write1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 1"); +} + +ATF_TC_BODY(watchpoint_trap_data_write1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 1; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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); + + ++watchme; + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_WRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_write2); +ATF_TC_HEAD(watchpoint_trap_data_write2, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 2"); +} + +ATF_TC_BODY(watchpoint_trap_data_write2, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 2; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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); + + ++watchme; + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_WRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_write3); +ATF_TC_HEAD(watchpoint_trap_data_write3, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 3"); +} + +ATF_TC_BODY(watchpoint_trap_data_write3, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 3; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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); + + ++watchme; + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_WRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_rw0); +ATF_TC_HEAD(watchpoint_trap_data_rw0, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 0"); +} + +ATF_TC_BODY(watchpoint_trap_data_rw0, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 0; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("watchme=%d\n", watchme); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_READWRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_rw1); +ATF_TC_HEAD(watchpoint_trap_data_rw1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 1"); +} + +ATF_TC_BODY(watchpoint_trap_data_rw1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 1; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("watchme=%d\n", watchme); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_READWRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_rw2); +ATF_TC_HEAD(watchpoint_trap_data_rw2, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 2"); +} + +ATF_TC_BODY(watchpoint_trap_data_rw2, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 2; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("watchme=%d\n", watchme); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_READWRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_data_rw3); +ATF_TC_HEAD(watchpoint_trap_data_rw3, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Call PT_COUNT_WATCHPOINTS and test write trap with watchpoint 3"); +} + +ATF_TC_BODY(watchpoint_trap_data_rw3, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + const int i = 3; + struct ptrace_watchpoint pw; + int len = sizeof(pw); + int watchme = 1234; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + 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("watchme=%d\n", watchme); + + 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("Preparing code watchpoint trap %d\n", i); + + pw.pw_index = i; + pw.pw_md.md_address = &watchme; + pw.pw_md.md_condition = X86_HW_WATCHPOINT_DR7_CONDITION_DATA_READWRITE; + pw.pw_md.md_length = X86_HW_WATCHPOINT_DR7_LENGTH_BYTE; + + printf("struct ptrace {\n"); + printf("\t.pw_index=%d\n", pw.pw_index); + printf("\t.pw_lwpid=%d\n", pw.pw_lwpid); + printf("\t.pw_md.md_address=%p\n", pw.pw_md.md_address); + printf("\t.pw_md.md_condition=%#x\n", pw.pw_md.md_condition); + printf("\t.pw_md.md_length=%#x\n", pw.pw_md.md_length); + printf("}\n"); + + printf("Before writing watchpoint %d\n", i); + ATF_REQUIRE(ptrace(PT_WRITE_WATCHPOINT, child, &pw, len) != -1); + + 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_stopped(status, SIGTRAP); + + 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 + ATF_TP_ADD_TCS(tp) { setvbuf(stdout, NULL, _IONBF, 0); @@ -144,5 +1368,21 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_count); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_read); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_write_unmodified); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_code0); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_code1); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_code2); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_code3); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_write0); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_write1); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_write2); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_write3); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_rw0); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_rw1); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_rw2); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_rw3); + return atf_no_error(); }