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);

Reply via email to