Index: tests/kernel/arch/amd64/t_ptrace_wait.c =================================================================== RCS file: /cvsroot/src/tests/kernel/arch/amd64/t_ptrace_wait.c,v retrieving revision 1.11 diff -u -r1.11 t_ptrace_wait.c --- tests/kernel/arch/amd64/t_ptrace_wait.c 18 Jan 2017 05:14:34 -0000 1.11 +++ tests/kernel/arch/amd64/t_ptrace_wait.c 18 Jan 2017 12:52:58 -0000 @@ -431,7 +431,7 @@ printf("Before checking siginfo_t\n"); ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_HWWPT); - ATF_REQUIRE_EQ(info.psi_siginfo.si_trap2, 0); + ATF_REQUIRE_EQ_MSG(info.psi_siginfo.si_trap2, 0, "trap2 (%d) != 0", info.psi_siginfo.si_trap2); ATF_REQUIRE_EQ(info.psi_siginfo.si_trap3, X86_HW_WATCHPOINT_EVENT_FIRED); pw.pw_md.md_address = NULL; @@ -1579,6 +1579,120 @@ } #endif +#if defined(__HAVE_PTRACE_WATCHPOINTS) +ATF_TC(watchpoint_trap_code0_sstep); +ATF_TC_HEAD(watchpoint_trap_code0_sstep, 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_sstep, 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; + struct ptrace_siginfo info; + memset(&info, 0, sizeof(info)); + + 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_type = PTRACE_PW_TYPE_DBREGS; + 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_type=%#x\n", pw.pw_type); + 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); + + do { + printf("Before resuming the child process where it left off " + "and without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_STEP, 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 calling ptrace(2) with PT_GET_SIGINFO for " + "child\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) + != -1); + + printf("Signal traced to lwpid=%d\n", info.psi_lwpid); + printf("Signal properties: si_signo=%#x si_code=%#x " + "si_errno=%#x\n", + info.psi_siginfo.si_signo, info.psi_siginfo.si_code, + info.psi_siginfo.si_errno); +// } while(info.psi_siginfo.si_code != TRAP_HWWPT); + } while(info.psi_siginfo.si_trap3 != X86_HW_WATCHPOINT_EVENT_FIRED_AND_SSTEP); + + printf("Before checking siginfo_t\n"); + ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); + ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_HWWPT); + ATF_REQUIRE_EQ(info.psi_siginfo.si_trap2, 0); + ATF_REQUIRE_EQ(info.psi_siginfo.si_trap3, + X86_HW_WATCHPOINT_EVENT_FIRED_AND_SSTEP); + + 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 + ATF_TP_ADD_TCS(tp) { setvbuf(stdout, NULL, _IONBF, 0); @@ -1602,5 +1716,7 @@ ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_rw2); ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_data_rw3); + ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(tp, watchpoint_trap_code0_sstep); + return atf_no_error(); }