Sun Dec 4 03:38:58 2016 UTC ()
Add dbregs_dr[0123]_trap_variable in arch/amd64/t_ptrace_wait*

Add new preliminary tests for testing that CPU Debug Registers can be used
to trap on a variable (write operation).

dbregs_dr0_trap_variable:
    Verify that setting trap with DR0 triggers SIGTRAP

dbregs_dr1_trap_variable:
    Verify that setting trap with DR1 triggers SIGTRAP

dbregs_dr2_trap_variable:
    Verify that setting trap with DR2 triggers SIGTRAP

dbregs_dr3_trap_variable:
    Verify that setting trap with DR3 triggers SIGTRAP

Sponsored by <The NetBSD Foundation>


(kamil)
diff -r1.3 -r1.4 src/tests/kernel/arch/amd64/t_ptrace_wait.c

cvs diff -r1.3 -r1.4 src/tests/kernel/arch/amd64/Attic/t_ptrace_wait.c (expand / switch to unified diff)

--- src/tests/kernel/arch/amd64/Attic/t_ptrace_wait.c 2016/12/03 01:41:15 1.3
+++ src/tests/kernel/arch/amd64/Attic/t_ptrace_wait.c 2016/12/04 03:38:58 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: t_ptrace_wait.c,v 1.3 2016/12/03 01:41:15 kamil Exp $ */ 1/* $NetBSD: t_ptrace_wait.c,v 1.4 2016/12/04 03:38:58 kamil Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2016 The NetBSD Foundation, Inc. 4 * Copyright (c) 2016 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,52 +17,84 @@ @@ -17,52 +17,84 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__RCSID("$NetBSD: t_ptrace_wait.c,v 1.3 2016/12/03 01:41:15 kamil Exp $"); 30__RCSID("$NetBSD: t_ptrace_wait.c,v 1.4 2016/12/04 03:38:58 kamil Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/types.h> 33#include <sys/types.h>
34#include <sys/ptrace.h> 34#include <sys/ptrace.h>
35#include <sys/resource.h> 35#include <sys/resource.h>
36#include <sys/stat.h> 36#include <sys/stat.h>
37#include <sys/sysctl.h> 37#include <sys/sysctl.h>
38#include <sys/wait.h> 38#include <sys/wait.h>
39#include <machine/reg.h> 39#include <machine/reg.h>
40#include <err.h> 40#include <err.h>
41#include <errno.h> 41#include <errno.h>
42#include <sched.h> 42#include <sched.h>
43#include <signal.h> 43#include <signal.h>
44#include <stdint.h> 44#include <stdint.h>
45#include <stdio.h> 45#include <stdio.h>
46#include <stdlib.h> 46#include <stdlib.h>
47#include <strings.h> 47#include <strings.h>
48#include <unistd.h> 48#include <unistd.h>
49 49
50#include <atf-c.h> 50#include <atf-c.h>
51 51
52#include "../../../h_macros.h" 52#include "../../../h_macros.h"
53 53
54#include "../../t_ptrace_wait.h" 54#include "../../t_ptrace_wait.h"
55 55
 56
 57union u {
 58 long raw;
 59 struct {
 60 long local_dr0_breakpoint : 1; /* 0 */
 61 long global_dr0_breakpoint : 1; /* 1 */
 62 long local_dr1_breakpoint : 1; /* 2 */
 63 long global_dr1_breakpoint : 1; /* 3 */
 64 long local_dr2_breakpoint : 1; /* 4 */
 65 long global_dr2_breakpoint : 1; /* 5 */
 66 long local_dr3_breakpoint : 1; /* 6 */
 67 long global_dr3_breakpoint : 1; /* 7 */
 68 long local_exact_breakpt : 1; /* 8 */
 69 long global_exact_breakpt : 1; /* 9 */
 70 long reserved_10 : 1; /* 10 */
 71 long rest_trans_memory : 1; /* 11 */
 72 long reserved_12 : 1; /* 12 */
 73 long general_detect_enable : 1; /* 13 */
 74 long reserved_14 : 1; /* 14 */
 75 long reserved_15 : 1; /* 15 */
 76 long condition_dr0 : 2; /* 16-17 */
 77 long len_dr0 : 2; /* 18-19 */
 78 long condition_dr1 : 2; /* 20-21 */
 79 long len_dr1 : 2; /* 22-23 */
 80 long condition_dr2 : 2; /* 24-25 */
 81 long len_dr2 : 2; /* 26-27 */
 82 long condition_dr3 : 2; /* 28-29 */
 83 long len_dr3 : 2; /* 30-31 */
 84 } bits;
 85};
 86
 87
56#if defined(HAVE_DBREGS) 88#if defined(HAVE_DBREGS)
57ATF_TC(dbregs_print); 89ATF_TC(dbregs_print);
58ATF_TC_HEAD(dbregs_print, tc) 90ATF_TC_HEAD(dbregs_print, tc)
59{ 91{
60 atf_tc_set_md_var(tc, "descr", 92 atf_tc_set_md_var(tc, "descr",
61 "Verify plain PT_GETDBREGS with printing Debug Registers"); 93 "Verify plain PT_GETDBREGS with printing Debug Registers");
62} 94}
63 95
64ATF_TC_BODY(dbregs_print, tc) 96ATF_TC_BODY(dbregs_print, tc)
65{ 97{
66 const int exitval = 5; 98 const int exitval = 5;
67 const int sigval = SIGSTOP; 99 const int sigval = SIGSTOP;
68 pid_t child, wpid; 100 pid_t child, wpid;
@@ -79,27 +111,27 @@ ATF_TC_BODY(dbregs_print, tc) @@ -79,27 +111,27 @@ ATF_TC_BODY(dbregs_print, tc)
79 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 111 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
80 112
81 printf("Before raising %s from child\n", strsignal(sigval)); 113 printf("Before raising %s from child\n", strsignal(sigval));
82 FORKEE_ASSERT(raise(sigval) == 0); 114 FORKEE_ASSERT(raise(sigval) == 0);
83 115
84 printf("Before exiting of the child process\n"); 116 printf("Before exiting of the child process\n");
85 _exit(exitval); 117 _exit(exitval);
86 } 118 }
87 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); 119 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
88 120
89 printf("Before calling %s() for the child\n", TWAIT_FNAME); 121 printf("Before calling %s() for the child\n", TWAIT_FNAME);
90 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 122 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
91 123
92 validate_status_stopped(status, sigval); 124 validate_status_stopped(status, sigval);
93 125
94 printf("Call GETDBREGS for the child process\n"); 126 printf("Call GETDBREGS for the child process\n");
95 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r, 0) != -1); 127 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r, 0) != -1);
96 128
97 printf("State of the debug registers:\n"); 129 printf("State of the debug registers:\n");
98 for (i = 0; i < __arraycount(r.dbregs); i++) 130 for (i = 0; i < __arraycount(r.dbregs); i++)
99 printf("r[%zu]=%#lx\n", i, r.dbregs[i]); 131 printf("r[%zu]=%#lx\n", i, r.dbregs[i]);
100 132
101 printf("Before resuming the child process where it left off and " 133 printf("Before resuming the child process where it left off and "
102 "without signal to be sent\n"); 134 "without signal to be sent\n");
103 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 135 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
104 136
105 printf("Before calling %s() for the child\n", TWAIT_FNAME); 137 printf("Before calling %s() for the child\n", TWAIT_FNAME);
@@ -1182,37 +1214,486 @@ ATF_TC_BODY(dbregs_preserve_dr3_continue @@ -1182,37 +1214,486 @@ ATF_TC_BODY(dbregs_preserve_dr3_continue
1182 "without signal to be sent\n"); 1214 "without signal to be sent\n");
1183 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1215 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1184 1216
1185 printf("Before calling %s() for the child\n", TWAIT_FNAME); 1217 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1186 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1218 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1187 1219
1188 validate_status_exited(status, exitval); 1220 validate_status_exited(status, exitval);
1189 1221
1190 printf("Before calling %s() for the child\n", TWAIT_FNAME); 1222 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1191 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1223 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1192} 1224}
1193#endif 1225#endif
1194 1226
 1227#if defined(HAVE_DBREGS)
 1228ATF_TC(dbregs_dr0_trap_variable);
 1229ATF_TC_HEAD(dbregs_dr0_trap_variable, tc)
 1230{
 1231 atf_tc_set_md_var(tc, "descr",
 1232 "Verify that setting trap with DR0 triggers SIGTRAP");
 1233}
 1234
 1235ATF_TC_BODY(dbregs_dr0_trap_variable, tc)
 1236{
 1237 const int exitval = 5;
 1238 const int sigval = SIGSTOP;
 1239 pid_t child, wpid;
 1240#if defined(TWAIT_HAVE_STATUS)
 1241 int status;
 1242#endif
 1243 struct dbreg r1;
 1244 struct dbreg r2;
 1245 /* Number of available CPU Debug Registers on AMD64 */
 1246 const size_t len = 16;
 1247 size_t i;
 1248 volatile int watchme;
 1249 union u dr7;
 1250
 1251 dr7.raw = 0;
 1252 dr7.bits.global_dr0_breakpoint = 1;
 1253 dr7.bits.condition_dr0 = 3; /* 0b11 -- break on data write&read */
 1254 dr7.bits.len_dr0 = 3; /* 0b11 -- 4 bytes */
 1255
 1256 printf("Assert that known number of Debug Registers (%zu) is valid\n",
 1257 len);
 1258 ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);
 1259 ATF_REQUIRE_EQ(__arraycount(r2.dbregs), len);
 1260
 1261 printf("Before forking process PID=%d\n", getpid());
 1262 child = atf_utils_fork();
 1263 if (child == 0) {
 1264 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
 1265 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
 1266
 1267 printf("Before raising %s from child\n", strsignal(sigval));
 1268 FORKEE_ASSERT(raise(sigval) == 0);
 1269
 1270 watchme = 1;
 1271
 1272 printf("Before raising %s from child\n", strsignal(sigval));
 1273 FORKEE_ASSERT(raise(sigval) == 0);
 1274
 1275 printf("Before exiting of the child process\n");
 1276 _exit(exitval);
 1277 }
 1278 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
 1279
 1280 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1281 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1282
 1283 validate_status_stopped(status, sigval);
 1284
 1285 printf("Call GETDBREGS for the child process (r1)\n");
 1286 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
 1287
 1288 printf("State of the debug registers (r1):\n");
 1289 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1290 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1291
 1292 r1.dbregs[0] = (long)(intptr_t)&watchme;
 1293 printf("Set DR0 (r1.dbregs[0]) to new value %#lx\n", r1.dbregs[0]);
 1294
 1295 r1.dbregs[7] = dr7.raw;
 1296 printf("Set DR7 (r1.dbregs[7]) to new value %#lx\n", r1.dbregs[7]);
 1297
 1298 printf("New state of the debug registers (r1):\n");
 1299 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1300 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1301
 1302 printf("Call SETDBREGS for the child process (r1)\n");
 1303 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
 1304
 1305 printf("Call CONTINUE for the child process\n");
 1306 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1307
 1308 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1309 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1310
 1311 validate_status_stopped(status, SIGTRAP);
 1312
 1313 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1314 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1315
 1316 validate_status_stopped(status, sigval);
 1317
 1318 printf("Call GETDBREGS for the child process (r2)\n");
 1319 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
 1320
 1321 printf("Assert that (r1) and (r2) are the same\n");
 1322 ATF_REQUIRE(memcmp(&r1, &r2, len) == 0);
 1323
 1324 printf("Before resuming the child process where it left off and "
 1325 "without signal to be sent\n");
 1326 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1327
 1328 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1329 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1330
 1331 validate_status_exited(status, exitval);
 1332
 1333 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1334 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 1335}
 1336#endif
 1337
 1338#if defined(HAVE_DBREGS)
 1339ATF_TC(dbregs_dr1_trap_variable);
 1340ATF_TC_HEAD(dbregs_dr1_trap_variable, tc)
 1341{
 1342 atf_tc_set_md_var(tc, "descr",
 1343 "Verify that setting trap with DR1 triggers SIGTRAP");
 1344}
 1345
 1346ATF_TC_BODY(dbregs_dr1_trap_variable, tc)
 1347{
 1348 const int exitval = 5;
 1349 const int sigval = SIGSTOP;
 1350 pid_t child, wpid;
 1351#if defined(TWAIT_HAVE_STATUS)
 1352 int status;
 1353#endif
 1354 struct dbreg r1;
 1355 struct dbreg r2;
 1356 /* Number of available CPU Debug Registers on AMD64 */
 1357 const size_t len = 16;
 1358 size_t i;
 1359 volatile int watchme;
 1360 union u dr7;
 1361
 1362 dr7.raw = 0;
 1363 dr7.bits.global_dr1_breakpoint = 1;
 1364 dr7.bits.condition_dr1 = 3; /* 0b11 -- break on data write&read */
 1365 dr7.bits.len_dr1 = 3; /* 0b11 -- 4 bytes */
 1366
 1367 printf("Assert that known number of Debug Registers (%zu) is valid\n",
 1368 len);
 1369 ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);
 1370 ATF_REQUIRE_EQ(__arraycount(r2.dbregs), len);
 1371
 1372 printf("Before forking process PID=%d\n", getpid());
 1373 child = atf_utils_fork();
 1374 if (child == 0) {
 1375 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
 1376 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
 1377
 1378 printf("Before raising %s from child\n", strsignal(sigval));
 1379 FORKEE_ASSERT(raise(sigval) == 0);
 1380
 1381 watchme = 1;
 1382
 1383 printf("Before raising %s from child\n", strsignal(sigval));
 1384 FORKEE_ASSERT(raise(sigval) == 0);
 1385
 1386 printf("Before exiting of the child process\n");
 1387 _exit(exitval);
 1388 }
 1389 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
 1390
 1391 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1392 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1393
 1394 validate_status_stopped(status, sigval);
 1395
 1396 printf("Call GETDBREGS for the child process (r1)\n");
 1397 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
 1398
 1399 printf("State of the debug registers (r1):\n");
 1400 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1401 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1402
 1403 r1.dbregs[1] = (long)(intptr_t)&watchme;
 1404 printf("Set DR1 (r1.dbregs[1]) to new value %#lx\n", r1.dbregs[1]);
 1405
 1406 r1.dbregs[7] = dr7.raw;
 1407 printf("Set DR7 (r1.dbregs[7]) to new value %#lx\n", r1.dbregs[7]);
 1408
 1409 printf("New state of the debug registers (r1):\n");
 1410 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1411 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1412
 1413 printf("Call SETDBREGS for the child process (r1)\n");
 1414 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
 1415
 1416 printf("Call CONTINUE for the child process\n");
 1417 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1418
 1419 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1420 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1421
 1422 validate_status_stopped(status, SIGTRAP);
 1423
 1424 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1425 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1426
 1427 validate_status_stopped(status, sigval);
 1428
 1429 printf("Call GETDBREGS for the child process (r2)\n");
 1430 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
 1431
 1432 printf("Assert that (r1) and (r2) are the same\n");
 1433 ATF_REQUIRE(memcmp(&r1, &r2, len) == 0);
 1434
 1435 printf("Before resuming the child process where it left off and "
 1436 "without signal to be sent\n");
 1437 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1438
 1439 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1440 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1441
 1442 validate_status_exited(status, exitval);
 1443
 1444 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1445 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 1446}
 1447#endif
 1448
 1449#if defined(HAVE_DBREGS)
 1450ATF_TC(dbregs_dr2_trap_variable);
 1451ATF_TC_HEAD(dbregs_dr2_trap_variable, tc)
 1452{
 1453 atf_tc_set_md_var(tc, "descr",
 1454 "Verify that setting trap with DR2 triggers SIGTRAP");
 1455}
 1456
 1457ATF_TC_BODY(dbregs_dr2_trap_variable, tc)
 1458{
 1459 const int exitval = 5;
 1460 const int sigval = SIGSTOP;
 1461 pid_t child, wpid;
 1462#if defined(TWAIT_HAVE_STATUS)
 1463 int status;
 1464#endif
 1465 struct dbreg r1;
 1466 struct dbreg r2;
 1467 /* Number of available CPU Debug Registers on AMD64 */
 1468 const size_t len = 16;
 1469 size_t i;
 1470 volatile int watchme;
 1471 union u dr7;
 1472
 1473 dr7.raw = 0;
 1474 dr7.bits.global_dr2_breakpoint = 1;
 1475 dr7.bits.condition_dr2 = 3; /* 0b11 -- break on data write&read */
 1476 dr7.bits.len_dr2 = 3; /* 0b11 -- 4 bytes */
 1477
 1478 printf("Assert that known number of Debug Registers (%zu) is valid\n",
 1479 len);
 1480 ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);
 1481 ATF_REQUIRE_EQ(__arraycount(r2.dbregs), len);
 1482
 1483 printf("Before forking process PID=%d\n", getpid());
 1484 child = atf_utils_fork();
 1485 if (child == 0) {
 1486 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
 1487 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
 1488
 1489 printf("Before raising %s from child\n", strsignal(sigval));
 1490 FORKEE_ASSERT(raise(sigval) == 0);
 1491
 1492 watchme = 1;
 1493
 1494 printf("Before raising %s from child\n", strsignal(sigval));
 1495 FORKEE_ASSERT(raise(sigval) == 0);
 1496
 1497 printf("Before exiting of the child process\n");
 1498 _exit(exitval);
 1499 }
 1500 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
 1501
 1502 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1503 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1504
 1505 validate_status_stopped(status, sigval);
 1506
 1507 printf("Call GETDBREGS for the child process (r1)\n");
 1508 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
 1509
 1510 printf("State of the debug registers (r1):\n");
 1511 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1512 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1513
 1514 r1.dbregs[2] = (long)(intptr_t)&watchme;
 1515 printf("Set DR2 (r1.dbregs[2]) to new value %#lx\n", r1.dbregs[2]);
 1516
 1517 r1.dbregs[7] = dr7.raw;
 1518 printf("Set DR7 (r1.dbregs[7]) to new value %#lx\n", r1.dbregs[7]);
 1519
 1520 printf("New state of the debug registers (r1):\n");
 1521 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1522 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1523
 1524 printf("Call SETDBREGS for the child process (r1)\n");
 1525 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
 1526
 1527 printf("Call CONTINUE for the child process\n");
 1528 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1529
 1530 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1531 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1532
 1533 validate_status_stopped(status, SIGTRAP);
 1534
 1535 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1536 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1537
 1538 validate_status_stopped(status, sigval);
 1539
 1540 printf("Call GETDBREGS for the child process (r2)\n");
 1541 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
 1542
 1543 printf("Assert that (r1) and (r2) are the same\n");
 1544 ATF_REQUIRE(memcmp(&r1, &r2, len) == 0);
 1545
 1546 printf("Before resuming the child process where it left off and "
 1547 "without signal to be sent\n");
 1548 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1549
 1550 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1551 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1552
 1553 validate_status_exited(status, exitval);
 1554
 1555 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1556 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 1557}
 1558#endif
 1559
 1560#if defined(HAVE_DBREGS)
 1561ATF_TC(dbregs_dr3_trap_variable);
 1562ATF_TC_HEAD(dbregs_dr3_trap_variable, tc)
 1563{
 1564 atf_tc_set_md_var(tc, "descr",
 1565 "Verify that setting trap with DR3 triggers SIGTRAP");
 1566}
 1567
 1568ATF_TC_BODY(dbregs_dr3_trap_variable, tc)
 1569{
 1570 const int exitval = 5;
 1571 const int sigval = SIGSTOP;
 1572 pid_t child, wpid;
 1573#if defined(TWAIT_HAVE_STATUS)
 1574 int status;
 1575#endif
 1576 struct dbreg r1;
 1577 struct dbreg r2;
 1578 /* Number of available CPU Debug Registers on AMD64 */
 1579 const size_t len = 16;
 1580 size_t i;
 1581 volatile int watchme;
 1582 union u dr7;
 1583
 1584 dr7.raw = 0;
 1585 dr7.bits.global_dr3_breakpoint = 1;
 1586 dr7.bits.condition_dr3 = 3; /* 0b11 -- break on data write&read */
 1587 dr7.bits.len_dr3 = 3; /* 0b11 -- 4 bytes */
 1588
 1589 printf("Assert that known number of Debug Registers (%zu) is valid\n",
 1590 len);
 1591 ATF_REQUIRE_EQ(__arraycount(r1.dbregs), len);
 1592 ATF_REQUIRE_EQ(__arraycount(r2.dbregs), len);
 1593
 1594 printf("Before forking process PID=%d\n", getpid());
 1595 child = atf_utils_fork();
 1596 if (child == 0) {
 1597 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
 1598 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
 1599
 1600 printf("Before raising %s from child\n", strsignal(sigval));
 1601 FORKEE_ASSERT(raise(sigval) == 0);
 1602
 1603 watchme = 1;
 1604
 1605 printf("Before raising %s from child\n", strsignal(sigval));
 1606 FORKEE_ASSERT(raise(sigval) == 0);
 1607
 1608 printf("Before exiting of the child process\n");
 1609 _exit(exitval);
 1610 }
 1611 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
 1612
 1613 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1614 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1615
 1616 validate_status_stopped(status, sigval);
 1617
 1618 printf("Call GETDBREGS for the child process (r1)\n");
 1619 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
 1620
 1621 printf("State of the debug registers (r1):\n");
 1622 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1623 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1624
 1625 r1.dbregs[3] = (long)(intptr_t)&watchme;
 1626 printf("Set DR3 (r1.dbregs[3]) to new value %#lx\n", r1.dbregs[3]);
 1627
 1628 r1.dbregs[7] = dr7.raw;
 1629 printf("Set DR7 (r1.dbregs[7]) to new value %#lx\n", r1.dbregs[7]);
 1630
 1631 printf("New state of the debug registers (r1):\n");
 1632 for (i = 0; i < __arraycount(r1.dbregs); i++)
 1633 printf("r1[%zu]=%#lx\n", i, r1.dbregs[i]);
 1634
 1635 printf("Call SETDBREGS for the child process (r1)\n");
 1636 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
 1637
 1638 printf("Call CONTINUE for the child process\n");
 1639 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1640
 1641 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1642 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1643
 1644 validate_status_stopped(status, SIGTRAP);
 1645
 1646 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1647 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1648
 1649 validate_status_stopped(status, sigval);
 1650
 1651 printf("Call GETDBREGS for the child process (r2)\n");
 1652 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
 1653
 1654 printf("Assert that (r1) and (r2) are the same\n");
 1655 ATF_REQUIRE(memcmp(&r1, &r2, len) == 0);
 1656
 1657 printf("Before resuming the child process where it left off and "
 1658 "without signal to be sent\n");
 1659 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 1660
 1661 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1662 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
 1663
 1664 validate_status_exited(status, exitval);
 1665
 1666 printf("Before calling %s() for the child\n", TWAIT_FNAME);
 1667 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 1668}
 1669#endif
 1670
1195ATF_TP_ADD_TCS(tp) 1671ATF_TP_ADD_TCS(tp)
1196{ 1672{
1197 setvbuf(stdout, NULL, _IONBF, 0); 1673 setvbuf(stdout, NULL, _IONBF, 0);
1198 setvbuf(stderr, NULL, _IONBF, 0); 1674 setvbuf(stderr, NULL, _IONBF, 0);
1199 1675
1200 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_print); 1676 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_print);
1201 1677
1202 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0); 1678 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0);
1203 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1); 1679 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1);
1204 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2); 1680 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2);
1205 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3); 1681 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3);
1206 1682
1207 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_yield); 1683 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_yield);
1208 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_yield); 1684 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_yield);
1209 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_yield); 1685 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_yield);
1210 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_yield); 1686 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_yield);
1211 1687
1212 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_continued); 1688 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_continued);
1213 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_continued); 1689 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_continued);
1214 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_continued); 1690 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_continued);
1215 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_continued); 1691 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_continued);
1216 1692
 1693 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable);
 1694 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable);
 1695 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable);
 1696 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable);
 1697
1217 return atf_no_error(); 1698 return atf_no_error();
1218} 1699}