Module Name: src Committed By: mgorny Date: Thu Feb 13 15:27:25 UTC 2020
Modified Files: src/tests/lib/libc/sys: t_ptrace_wait.c t_ptrace_x86_wait.h Log Message: Extend concurrent events test to watchpoints To generate a diff of this commit: cvs rdiff -u -r1.160 -r1.161 src/tests/lib/libc/sys/t_ptrace_wait.c cvs rdiff -u -r1.20 -r1.21 src/tests/lib/libc/sys/t_ptrace_x86_wait.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/lib/libc/sys/t_ptrace_wait.c diff -u src/tests/lib/libc/sys/t_ptrace_wait.c:1.160 src/tests/lib/libc/sys/t_ptrace_wait.c:1.161 --- src/tests/lib/libc/sys/t_ptrace_wait.c:1.160 Thu Feb 13 15:27:05 2020 +++ src/tests/lib/libc/sys/t_ptrace_wait.c Thu Feb 13 15:27:25 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: t_ptrace_wait.c,v 1.160 2020/02/13 15:27:05 mgorny Exp $ */ +/* $NetBSD: t_ptrace_wait.c,v 1.161 2020/02/13 15:27:25 mgorny Exp $ */ /*- * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: t_ptrace_wait.c,v 1.160 2020/02/13 15:27:05 mgorny Exp $"); +__RCSID("$NetBSD: t_ptrace_wait.c,v 1.161 2020/02/13 15:27:25 mgorny Exp $"); #define __LEGACY_PT_LWPINFO @@ -8622,6 +8622,7 @@ ATF_TC_BODY(core_dump_procinfo, tc) #define THREAD_CONCURRENT_BREAKPOINT_NUM 50 #define THREAD_CONCURRENT_SIGNALS_NUM 50 +#define THREAD_CONCURRENT_WATCHPOINT_NUM 50 /* List of signals to use for the test */ const int thread_concurrent_signals_list[] = { @@ -8647,6 +8648,7 @@ enum thread_concurrent_signal_handling { static pthread_barrier_t thread_concurrent_barrier; static pthread_key_t thread_concurrent_key; +static uint32_t thread_concurrent_watchpoint_var = 0; static void * thread_concurrent_breakpoint_thread(void *arg) @@ -8687,10 +8689,20 @@ thread_concurrent_signals_thread(void *a return NULL; } +static void * +thread_concurrent_watchpoint_thread(void *arg) +{ + pthread_barrier_wait(&thread_concurrent_barrier); + DPRINTF("Before modifying var from LWP %d\n", _lwp_self()); + thread_concurrent_watchpoint_var = 1; + return NULL; +} + #if defined(__i386__) || defined(__x86_64__) enum thread_concurrent_sigtrap_event { TCSE_UNKNOWN, - TCSE_BREAKPOINT + TCSE_BREAKPOINT, + TCSE_WATCHPOINT }; static void @@ -8701,7 +8713,7 @@ thread_concurrent_handle_sigtrap(pid_t c static void thread_concurrent_test(enum thread_concurrent_signal_handling signal_handle, - int breakpoint_threads, int signal_threads) + int breakpoint_threads, int signal_threads, int watchpoint_threads) { const int exitval = 5; const int sigval = SIGSTOP; @@ -8711,6 +8723,8 @@ thread_concurrent_test(enum thread_concu = {{0, 0}}; struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] = {{0, 0}}; + struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] + = {{0, 0}}; ptrace_event_t event; int i; @@ -8722,12 +8736,14 @@ thread_concurrent_test(enum thread_concu /* Protect against out-of-bounds array access. */ ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM); ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM); + ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM); DPRINTF("Before forking process PID=%d\n", getpid()); SYSCALL_REQUIRE((child = fork()) != -1); if (child == 0) { pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM]; pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM]; + pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM]; DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); @@ -8757,7 +8773,8 @@ thread_concurrent_test(enum thread_concu DPRINTF("Before starting threads from the child\n"); FORKEE_ASSERT(pthread_barrier_init( &thread_concurrent_barrier, NULL, - breakpoint_threads + signal_threads) == 0); + breakpoint_threads + signal_threads + watchpoint_threads) + == 0); FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL) == 0); @@ -8770,8 +8787,15 @@ thread_concurrent_test(enum thread_concu FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL, thread_concurrent_breakpoint_thread, NULL) == 0); } + for (i = 0; i < watchpoint_threads; i++) { + FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL, + thread_concurrent_watchpoint_thread, NULL) == 0); + } DPRINTF("Before joining threads from the child\n"); + for (i = 0; i < watchpoint_threads; i++) { + FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0); + } for (i = 0; i < breakpoint_threads; i++) { FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0); } @@ -8852,6 +8876,10 @@ thread_concurrent_test(enum thread_concu *FIND_EVENT_COUNT(bp_counts, info.psi_lwpid) += 1; break; + case TCSE_WATCHPOINT: + *FIND_EVENT_COUNT(wp_counts, + info.psi_lwpid) += 1; + break; } #else ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n", @@ -8883,10 +8911,19 @@ thread_concurrent_test(enum thread_concu "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d", i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); + for (i = 0; i < watchpoint_threads; i++) + ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1, + "wp_counts[%d].lec_count=%d; lec_lwp=%d", + i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); + for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++) + ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0, + "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d", + i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); + validate_status_exited(status, exitval); } -#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, descr) \ +#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \ ATF_TC(test); \ ATF_TC_HEAD(test, tc) \ { \ @@ -8895,24 +8932,27 @@ ATF_TC_HEAD(test, tc) \ \ ATF_TC_BODY(test, tc) \ { \ - thread_concurrent_test(sig_hdl, bps, sigs); \ + thread_concurrent_test(sig_hdl, bps, sigs, wps); \ } THREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD, - 0, THREAD_CONCURRENT_SIGNALS_NUM, + 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, "Verify that concurrent signals issued to a single thread are reported " "correctly"); THREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN, - 0, THREAD_CONCURRENT_SIGNALS_NUM, + 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, "Verify that concurrent signals issued to a single thread are reported " "correctly and passed back to SIG_IGN handler"); THREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER, - 0, THREAD_CONCURRENT_SIGNALS_NUM, + 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, "Verify that concurrent signals issued to a single thread are reported " "correctly and passed back to a handler function"); THREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD, - THREAD_CONCURRENT_BREAKPOINT_NUM, 0, + THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0, + "Verify that concurrent breakpoints are reported correctly"); +THREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD, + 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, "Verify that concurrent breakpoints are reported correctly"); #endif /*defined(TWAIT_HAVE_STATUS)*/ @@ -9509,6 +9549,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, thread_concurrent_signals_handler); #if defined(__i386__) || defined(__x86_64__) ATF_TP_ADD_TC(tp, thread_concurrent_breakpoints); + ATF_TP_ADD_TC(tp, thread_concurrent_watchpoints); #endif #endif Index: src/tests/lib/libc/sys/t_ptrace_x86_wait.h diff -u src/tests/lib/libc/sys/t_ptrace_x86_wait.h:1.20 src/tests/lib/libc/sys/t_ptrace_x86_wait.h:1.21 --- src/tests/lib/libc/sys/t_ptrace_x86_wait.h:1.20 Thu Feb 13 15:27:05 2020 +++ src/tests/lib/libc/sys/t_ptrace_x86_wait.h Thu Feb 13 15:27:25 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: t_ptrace_x86_wait.h,v 1.20 2020/02/13 15:27:05 mgorny Exp $ */ +/* $NetBSD: t_ptrace_x86_wait.h,v 1.21 2020/02/13 15:27:25 mgorny Exp $ */ /*- * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. @@ -3572,9 +3572,15 @@ thread_concurrent_lwp_setup(pid_t child, dr7.bits.global_dr0_breakpoint = 1; dr7.bits.condition_dr0 = 0; /* exec */ dr7.bits.len_dr0 = 0; + /* use DR1 for watchpoints */ + dr7.bits.global_dr1_breakpoint = 1; + dr7.bits.condition_dr1 = 1; /* write */ + dr7.bits.len_dr1 = 3; /* 4 bytes */ r.dr[7] = dr7.raw; r.dr[0] = (long)(intptr_t)check_happy; + r.dr[1] = (long)(intptr_t)&thread_concurrent_watchpoint_var; DPRINTF("dr0=%" PRIxREGISTER "\n", r.dr[0]); + DPRINTF("dr1=%" PRIxREGISTER "\n", r.dr[1]); DPRINTF("dr7=%" PRIxREGISTER "\n", r.dr[7]); DPRINTF("Call SETDBREGS for LWP %d\n", lwpid); @@ -3597,9 +3603,12 @@ thread_concurrent_handle_sigtrap(pid_t c DPRINTF("dr6=%" PRIxREGISTER ", dr7=%" PRIxREGISTER "\n", r.dr[6], r.dr[7]); - ATF_CHECK_MSG(r.dr[6] & 1, "lwp=%d, got DR6=%" PRIxREGISTER, + ATF_CHECK_MSG(r.dr[6] & 3, "lwp=%d, got DR6=%" PRIxREGISTER, info->psi_lwpid, r.dr[6]); + /* Handle only one event at a time, we should get + * a separate SIGTRAP for the other one. + */ if (r.dr[6] & 1) { r.dr[6] &= ~1; @@ -3613,6 +3622,9 @@ thread_concurrent_handle_sigtrap(pid_t c r.dr[7] = dr7.raw; ret = TCSE_BREAKPOINT; + } else if (r.dr[6] & 2) { + r.dr[6] &= ~2; + ret = TCSE_WATCHPOINT; } DPRINTF("Call SETDBREGS for LWP %d\n", info->psi_lwpid);