t_ptrace_x86_wait.h revision 1.1 1 /* $NetBSD: t_ptrace_x86_wait.h,v 1.1 2017/04/02 21:44:00 kamil Exp $ */
2
3 /*-
4 * Copyright (c) 2016 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
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
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #if defined(__i386__) || defined(__x86_64__)
30 union u {
31 unsigned long raw;
32 struct {
33 unsigned long local_dr0_breakpoint : 1; /* 0 */
34 unsigned long global_dr0_breakpoint : 1; /* 1 */
35 unsigned long local_dr1_breakpoint : 1; /* 2 */
36 unsigned long global_dr1_breakpoint : 1; /* 3 */
37 unsigned long local_dr2_breakpoint : 1; /* 4 */
38 unsigned long global_dr2_breakpoint : 1; /* 5 */
39 unsigned long local_dr3_breakpoint : 1; /* 6 */
40 unsigned long global_dr3_breakpoint : 1; /* 7 */
41 unsigned long local_exact_breakpt : 1; /* 8 */
42 unsigned long global_exact_breakpt : 1; /* 9 */
43 unsigned long reserved_10 : 1; /* 10 */
44 unsigned long rest_trans_memory : 1; /* 11 */
45 unsigned long reserved_12 : 1; /* 12 */
46 unsigned long general_detect_enable : 1; /* 13 */
47 unsigned long reserved_14 : 1; /* 14 */
48 unsigned long reserved_15 : 1; /* 15 */
49 unsigned long condition_dr0 : 2; /* 16-17 */
50 unsigned long len_dr0 : 2; /* 18-19 */
51 unsigned long condition_dr1 : 2; /* 20-21 */
52 unsigned long len_dr1 : 2; /* 22-23 */
53 unsigned long condition_dr2 : 2; /* 24-25 */
54 unsigned long len_dr2 : 2; /* 26-27 */
55 unsigned long condition_dr3 : 2; /* 28-29 */
56 unsigned long len_dr3 : 2; /* 30-31 */
57 } bits;
58 };
59
60 ATF_TC(dbregs_print);
61 ATF_TC_HEAD(dbregs_print, tc)
62 {
63 atf_tc_set_md_var(tc, "descr",
64 "Verify plain PT_GETDBREGS with printing Debug Registers");
65 }
66
67 ATF_TC_BODY(dbregs_print, tc)
68 {
69 const int exitval = 5;
70 const int sigval = SIGSTOP;
71 pid_t child, wpid;
72 #if defined(TWAIT_HAVE_STATUS)
73 int status;
74 #endif
75 struct dbreg r;
76 size_t i;
77
78 printf("Before forking process PID=%d\n", getpid());
79 ATF_REQUIRE((child = fork()) != -1);
80 if (child == 0) {
81 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
82 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
83
84 printf("Before raising %s from child\n", strsignal(sigval));
85 FORKEE_ASSERT(raise(sigval) == 0);
86
87 printf("Before exiting of the child process\n");
88 _exit(exitval);
89 }
90 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
91
92 printf("Before calling %s() for the child\n", TWAIT_FNAME);
93 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
94
95 validate_status_stopped(status, sigval);
96
97 printf("Call GETDBREGS for the child process\n");
98 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r, 0) != -1);
99
100 printf("State of the debug registers:\n");
101 for (i = 0; i < __arraycount(r.dr); i++)
102 printf("r[%zu]=%" PRIxREGISTER "\n", i, r.dr[i]);
103
104 printf("Before resuming the child process where it left off and "
105 "without signal to be sent\n");
106 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
107
108 printf("Before calling %s() for the child\n", TWAIT_FNAME);
109 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
110
111 validate_status_exited(status, exitval);
112
113 printf("Before calling %s() for the child\n", TWAIT_FNAME);
114 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
115 }
116
117
118 enum dbreg_preserve_mode {
119 dbreg_preserve_mode_none,
120 dbreg_preserve_mode_yield,
121 dbreg_preserve_mode_continued
122 };
123
124 static void
125 dbreg_preserve(int reg, enum dbreg_preserve_mode mode)
126 {
127 const int exitval = 5;
128 const int sigval = SIGSTOP;
129 pid_t child, wpid;
130 #if defined(TWAIT_HAVE_STATUS)
131 int status;
132 #endif
133 struct dbreg r1;
134 struct dbreg r2;
135 size_t i;
136 int watchme;
137
138 printf("Before forking process PID=%d\n", getpid());
139 ATF_REQUIRE((child = fork()) != -1);
140 if (child == 0) {
141 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
142 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
143
144 printf("Before raising %s from child\n", strsignal(sigval));
145 FORKEE_ASSERT(raise(sigval) == 0);
146
147 if (mode == dbreg_preserve_mode_continued) {
148 printf("Before raising %s from child\n",
149 strsignal(sigval));
150 FORKEE_ASSERT(raise(sigval) == 0);
151 }
152
153 printf("Before exiting of the child process\n");
154 _exit(exitval);
155 }
156 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
157
158 printf("Before calling %s() for the child\n", TWAIT_FNAME);
159 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
160
161 validate_status_stopped(status, sigval);
162
163 printf("Call GETDBREGS for the child process (r1)\n");
164 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
165
166 printf("State of the debug registers (r1):\n");
167 for (i = 0; i < __arraycount(r1.dr); i++)
168 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
169
170 r1.dr[reg] = (long)(intptr_t)&watchme;
171 printf("Set DR0 (r1.dr[%d]) to new value %" PRIxREGISTER "\n",
172 reg, r1.dr[reg]);
173
174 printf("New state of the debug registers (r1):\n");
175 for (i = 0; i < __arraycount(r1.dr); i++)
176 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
177
178 printf("Call SETDBREGS for the child process (r1)\n");
179 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
180
181 switch (mode) {
182 case dbreg_preserve_mode_none:
183 break;
184 case dbreg_preserve_mode_yield:
185 printf("Yields a processor voluntarily and gives other "
186 "threads a chance to run without waiting for an "
187 "involuntary preemptive switch\n");
188 sched_yield();
189 break;
190 case dbreg_preserve_mode_continued:
191 printf("Call CONTINUE for the child process\n");
192 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
193
194 printf("Before calling %s() for the child\n", TWAIT_FNAME);
195 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
196
197 validate_status_stopped(status, sigval);
198 break;
199 }
200
201 printf("Call GETDBREGS for the child process (r2)\n");
202 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
203
204 printf("Assert that (r1) and (r2) are the same\n");
205 ATF_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) == 0);
206
207 printf("Before resuming the child process where it left off and "
208 "without signal to be sent\n");
209 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
210
211 printf("Before calling %s() for the child\n", TWAIT_FNAME);
212 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
213
214 validate_status_exited(status, exitval);
215
216 printf("Before calling %s() for the child\n", TWAIT_FNAME);
217 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
218 }
219
220
221 ATF_TC(dbregs_preserve_dr0);
222 ATF_TC_HEAD(dbregs_preserve_dr0, tc)
223 {
224 atf_tc_set_md_var(tc, "descr",
225 "Verify that setting DR0 is preserved across ptrace(2) calls");
226 }
227
228 ATF_TC_BODY(dbregs_preserve_dr0, tc)
229 {
230 dbreg_preserve(0, dbreg_preserve_mode_none);
231 }
232
233 ATF_TC(dbregs_preserve_dr1);
234 ATF_TC_HEAD(dbregs_preserve_dr1, tc)
235 {
236 atf_tc_set_md_var(tc, "descr",
237 "Verify that setting DR1 is preserved across ptrace(2) calls");
238 }
239
240 ATF_TC_BODY(dbregs_preserve_dr1, tc)
241 {
242 dbreg_preserve(1, dbreg_preserve_mode_none);
243 }
244
245 ATF_TC(dbregs_preserve_dr2);
246 ATF_TC_HEAD(dbregs_preserve_dr2, tc)
247 {
248 atf_tc_set_md_var(tc, "descr",
249 "Verify that setting DR2 is preserved across ptrace(2) calls");
250 }
251
252 ATF_TC_BODY(dbregs_preserve_dr2, tc)
253 {
254 dbreg_preserve(2, dbreg_preserve_mode_none);
255 }
256
257 ATF_TC(dbregs_preserve_dr3);
258 ATF_TC_HEAD(dbregs_preserve_dr3, tc)
259 {
260 atf_tc_set_md_var(tc, "descr",
261 "Verify that setting DR3 is preserved across ptrace(2) calls");
262 }
263
264 ATF_TC_BODY(dbregs_preserve_dr3, tc)
265 {
266 dbreg_preserve(3, dbreg_preserve_mode_none);
267 }
268
269 ATF_TC(dbregs_preserve_dr0_yield);
270 ATF_TC_HEAD(dbregs_preserve_dr0_yield, tc)
271 {
272 atf_tc_set_md_var(tc, "descr",
273 "Verify that setting DR0 is preserved across ptrace(2) calls with "
274 "scheduler yield");
275 }
276
277 ATF_TC_BODY(dbregs_preserve_dr0_yield, tc)
278 {
279 dbreg_preserve(0, dbreg_preserve_mode_yield);
280 }
281
282 ATF_TC(dbregs_preserve_dr1_yield);
283 ATF_TC_HEAD(dbregs_preserve_dr1_yield, tc)
284 {
285 atf_tc_set_md_var(tc, "descr",
286 "Verify that setting DR1 is preserved across ptrace(2) calls with "
287 "scheduler yield");
288 }
289
290 ATF_TC_BODY(dbregs_preserve_dr1_yield, tc)
291 {
292 dbreg_preserve(0, dbreg_preserve_mode_yield);
293 }
294
295 ATF_TC(dbregs_preserve_dr2_yield);
296 ATF_TC_HEAD(dbregs_preserve_dr2_yield, tc)
297 {
298 atf_tc_set_md_var(tc, "descr",
299 "Verify that setting DR2 is preserved across ptrace(2) calls with "
300 "scheduler yield");
301 }
302
303 ATF_TC_BODY(dbregs_preserve_dr2_yield, tc)
304 {
305 dbreg_preserve(0, dbreg_preserve_mode_yield);
306 }
307
308
309 ATF_TC(dbregs_preserve_dr3_yield);
310 ATF_TC_HEAD(dbregs_preserve_dr3_yield, tc)
311 {
312 atf_tc_set_md_var(tc, "descr",
313 "Verify that setting DR3 is preserved across ptrace(2) calls with "
314 "scheduler yield");
315 }
316
317 ATF_TC_BODY(dbregs_preserve_dr3_yield, tc)
318 {
319 dbreg_preserve(3, dbreg_preserve_mode_yield);
320 }
321
322 ATF_TC(dbregs_preserve_dr0_continued);
323 ATF_TC_HEAD(dbregs_preserve_dr0_continued, tc)
324 {
325 atf_tc_set_md_var(tc, "descr",
326 "Verify that setting DR0 is preserved across ptrace(2) calls and "
327 "with continued child");
328 }
329
330 ATF_TC_BODY(dbregs_preserve_dr0_continued, tc)
331 {
332 dbreg_preserve(0, dbreg_preserve_mode_continued);
333 }
334
335 ATF_TC(dbregs_preserve_dr1_continued);
336 ATF_TC_HEAD(dbregs_preserve_dr1_continued, tc)
337 {
338 atf_tc_set_md_var(tc, "descr",
339 "Verify that setting DR1 is preserved across ptrace(2) calls and "
340 "with continued child");
341 }
342
343 ATF_TC_BODY(dbregs_preserve_dr1_continued, tc)
344 {
345 dbreg_preserve(1, dbreg_preserve_mode_continued);
346 }
347
348 ATF_TC(dbregs_preserve_dr2_continued);
349 ATF_TC_HEAD(dbregs_preserve_dr2_continued, tc)
350 {
351 atf_tc_set_md_var(tc, "descr",
352 "Verify that setting DR2 is preserved across ptrace(2) calls and "
353 "with continued child");
354 }
355
356 ATF_TC_BODY(dbregs_preserve_dr2_continued, tc)
357 {
358 dbreg_preserve(2, dbreg_preserve_mode_continued);
359 }
360
361 ATF_TC(dbregs_preserve_dr3_continued);
362 ATF_TC_HEAD(dbregs_preserve_dr3_continued, tc)
363 {
364 atf_tc_set_md_var(tc, "descr",
365 "Verify that setting DR3 is preserved across ptrace(2) calls and "
366 "with continued child");
367 }
368
369 ATF_TC_BODY(dbregs_preserve_dr3_continued, tc)
370 {
371 dbreg_preserve(3, dbreg_preserve_mode_continued);
372 }
373
374
375 static void
376 dbregs_trap_variable(int reg, int cond, int len, bool write)
377 {
378 const int exitval = 5;
379 const int sigval = SIGSTOP;
380 pid_t child, wpid;
381 #if defined(TWAIT_HAVE_STATUS)
382 int status;
383 #endif
384 struct dbreg r1;
385 size_t i;
386 volatile int watchme = 0;
387 union u dr7;
388
389 struct ptrace_siginfo info;
390 memset(&info, 0, sizeof(info));
391
392 dr7.raw = 0;
393 switch (reg) {
394 case 0:
395 dr7.bits.global_dr0_breakpoint = 1;
396 dr7.bits.condition_dr0 = cond;
397 dr7.bits.len_dr0 = len;
398 case 1:
399 dr7.bits.global_dr1_breakpoint = 1;
400 dr7.bits.condition_dr1 = cond;
401 dr7.bits.len_dr1 = len;
402 case 2:
403 dr7.bits.global_dr2_breakpoint = 1;
404 dr7.bits.condition_dr2 = cond;
405 dr7.bits.len_dr2 = len;
406 case 3:
407 dr7.bits.global_dr3_breakpoint = 1;
408 dr7.bits.condition_dr3 = cond;
409 dr7.bits.len_dr3 = len;
410 break;
411 }
412
413 printf("Before forking process PID=%d\n", getpid());
414 ATF_REQUIRE((child = fork()) != -1);
415 if (child == 0) {
416 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
417 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
418
419 printf("Before raising %s from child\n", strsignal(sigval));
420 FORKEE_ASSERT(raise(sigval) == 0);
421
422 if (write)
423 watchme = 1;
424 else
425 printf("watchme=%d\n", watchme);
426
427 printf("Before raising %s from child\n", strsignal(sigval));
428 FORKEE_ASSERT(raise(sigval) == 0);
429
430 printf("Before exiting of the child process\n");
431 _exit(exitval);
432 }
433 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
434
435 printf("Before calling %s() for the child\n", TWAIT_FNAME);
436 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
437
438 validate_status_stopped(status, sigval);
439
440 printf("Call GETDBREGS for the child process (r1)\n");
441 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
442
443 printf("State of the debug registers (r1):\n");
444 for (i = 0; i < __arraycount(r1.dr); i++)
445 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
446
447 r1.dr[reg] = (long)(intptr_t)&watchme;
448 printf("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n",
449 reg, reg, r1.dr[reg]);
450
451 r1.dr[7] = dr7.raw;
452 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
453 r1.dr[7]);
454
455 printf("New state of the debug registers (r1):\n");
456 for (i = 0; i < __arraycount(r1.dr); i++)
457 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
458
459 printf("Call SETDBREGS for the child process (r1)\n");
460 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
461
462 printf("Call CONTINUE for the child process\n");
463 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
464
465 printf("Before calling %s() for the child\n", TWAIT_FNAME);
466 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
467
468 validate_status_stopped(status, SIGTRAP);
469
470 printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
471 ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
472
473 printf("Signal traced to lwpid=%d\n", info.psi_lwpid);
474 printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
475 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
476 info.psi_siginfo.si_errno);
477
478 printf("Before checking siginfo_t\n");
479 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
480 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
481
482 printf("Call CONTINUE for the child process\n");
483 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
484
485 printf("Before calling %s() for the child\n", TWAIT_FNAME);
486 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
487
488 validate_status_stopped(status, sigval);
489
490 printf("Before resuming the child process where it left off and "
491 "without signal to be sent\n");
492 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
493
494 printf("Before calling %s() for the child\n", TWAIT_FNAME);
495 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
496
497 validate_status_exited(status, exitval);
498
499 printf("Before calling %s() for the child\n", TWAIT_FNAME);
500 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
501 }
502
503 ATF_TC(dbregs_dr0_trap_variable_writeonly_byte);
504 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_byte, tc)
505 {
506 atf_tc_set_md_var(tc, "descr",
507 "Verify that setting trap with DR0 triggers SIGTRAP "
508 "(break on data writes only and 1 byte mode)");
509 }
510
511 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_byte, tc)
512 {
513 /* 0b01 -- break on data write only */
514 /* 0b00 -- 1 byte */
515
516 dbregs_trap_variable(0, 1, 0, true);
517 }
518
519 ATF_TC(dbregs_dr1_trap_variable_writeonly_byte);
520 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_byte, tc)
521 {
522 atf_tc_set_md_var(tc, "descr",
523 "Verify that setting trap with DR1 triggers SIGTRAP "
524 "(break on data writes only and 1 byte mode)");
525 }
526
527 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_byte, tc)
528 {
529 /* 0b01 -- break on data write only */
530 /* 0b00 -- 1 byte */
531
532 dbregs_trap_variable(1, 1, 0, true);
533 }
534
535 ATF_TC(dbregs_dr2_trap_variable_writeonly_byte);
536 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_byte, tc)
537 {
538 atf_tc_set_md_var(tc, "descr",
539 "Verify that setting trap with DR2 triggers SIGTRAP "
540 "(break on data writes only and 1 byte mode)");
541 }
542
543 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_byte, tc)
544 {
545 /* 0b01 -- break on data write only */
546 /* 0b00 -- 1 byte */
547
548 dbregs_trap_variable(2, 1, 0, true);
549 }
550
551 ATF_TC(dbregs_dr3_trap_variable_writeonly_byte);
552 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_byte, tc)
553 {
554 atf_tc_set_md_var(tc, "descr",
555 "Verify that setting trap with DR3 triggers SIGTRAP "
556 "(break on data writes only and 1 byte mode)");
557 }
558
559 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_byte, tc)
560 {
561 /* 0b01 -- break on data write only */
562 /* 0b00 -- 1 byte */
563
564 dbregs_trap_variable(3, 1, 0, true);
565 }
566
567 ATF_TC(dbregs_dr0_trap_variable_writeonly_2bytes);
568 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_2bytes, tc)
569 {
570 atf_tc_set_md_var(tc, "descr",
571 "Verify that setting trap with DR0 triggers SIGTRAP "
572 "(break on data writes only and 2 bytes mode)");
573 }
574
575 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_2bytes, tc)
576 {
577 /* 0b01 -- break on data write only */
578 /* 0b01 -- 2 bytes */
579
580 dbregs_trap_variable(0, 1, 1, true);
581 }
582
583 ATF_TC(dbregs_dr1_trap_variable_writeonly_2bytes);
584 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_2bytes, tc)
585 {
586 atf_tc_set_md_var(tc, "descr",
587 "Verify that setting trap with DR1 triggers SIGTRAP "
588 "(break on data writes only and 2 bytes mode)");
589 }
590
591 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_2bytes, tc)
592 {
593 /* 0b01 -- break on data write only */
594 /* 0b01 -- 2 bytes */
595
596 dbregs_trap_variable(1, 1, 1, true);
597 }
598
599 ATF_TC(dbregs_dr2_trap_variable_writeonly_2bytes);
600 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_2bytes, tc)
601 {
602 atf_tc_set_md_var(tc, "descr",
603 "Verify that setting trap with DR2 triggers SIGTRAP "
604 "(break on data writes only and 2 bytes mode)");
605 }
606
607 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_2bytes, tc)
608 {
609 /* 0b01 -- break on data write only */
610 /* 0b01 -- 2 bytes */
611
612 dbregs_trap_variable(2, 1, 1, true);
613 }
614
615 ATF_TC(dbregs_dr3_trap_variable_writeonly_2bytes);
616 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_2bytes, tc)
617 {
618 atf_tc_set_md_var(tc, "descr",
619 "Verify that setting trap with DR3 triggers SIGTRAP "
620 "(break on data writes only and 2 bytes mode)");
621 }
622
623 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_2bytes, tc)
624 {
625 /* 0b01 -- break on data write only */
626 /* 0b01 -- 2 bytes */
627
628 dbregs_trap_variable(3, 1, 1, true);
629 }
630
631 ATF_TC(dbregs_dr0_trap_variable_writeonly_4bytes);
632 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_4bytes, tc)
633 {
634 atf_tc_set_md_var(tc, "descr",
635 "Verify that setting trap with DR0 triggers SIGTRAP "
636 "(break on data writes only and 4 bytes mode)");
637 }
638
639 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_4bytes, tc)
640 {
641 /* 0b01 -- break on data write only */
642 /* 0b11 -- 4 bytes */
643
644 dbregs_trap_variable(0, 1, 3, true);
645 }
646
647 ATF_TC(dbregs_dr1_trap_variable_writeonly_4bytes);
648 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_4bytes, tc)
649 {
650 atf_tc_set_md_var(tc, "descr",
651 "Verify that setting trap with DR1 triggers SIGTRAP "
652 "(break on data writes only and 4 bytes mode)");
653 }
654
655 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_4bytes, tc)
656 {
657 /* 0b01 -- break on data write only */
658 /* 0b11 -- 4 bytes */
659
660 dbregs_trap_variable(1, 1, 3, true);
661 }
662
663 ATF_TC(dbregs_dr2_trap_variable_writeonly_4bytes);
664 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_4bytes, tc)
665 {
666 atf_tc_set_md_var(tc, "descr",
667 "Verify that setting trap with DR2 triggers SIGTRAP "
668 "(break on data writes only and 4 bytes mode)");
669 }
670
671 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_4bytes, tc)
672 {
673 /* 0b01 -- break on data write only */
674 /* 0b11 -- 4 bytes */
675
676 dbregs_trap_variable(2, 1, 3, true);
677 }
678
679 ATF_TC(dbregs_dr3_trap_variable_writeonly_4bytes);
680 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_4bytes, tc)
681 {
682 atf_tc_set_md_var(tc, "descr",
683 "Verify that setting trap with DR3 triggers SIGTRAP "
684 "(break on data writes only and 4 bytes mode)");
685 }
686
687 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_4bytes, tc)
688 {
689 /* 0b01 -- break on data write only */
690 /* 0b11 -- 4 bytes */
691
692 dbregs_trap_variable(3, 1, 3, true);
693 }
694
695 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_byte);
696 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_byte, tc)
697 {
698 atf_tc_set_md_var(tc, "descr",
699 "Verify that setting trap with DR0 triggers SIGTRAP "
700 "(break on data read/write trap in read 1 byte mode)");
701 }
702
703 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_byte, tc)
704 {
705 /* 0b11 -- break on data write&read */
706 /* 0b00 -- 1 byte */
707
708 dbregs_trap_variable(0, 3, 0, true);
709 }
710
711 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_byte);
712 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_byte, tc)
713 {
714 atf_tc_set_md_var(tc, "descr",
715 "Verify that setting trap with DR1 triggers SIGTRAP "
716 "(break on data read/write trap in read 1 byte mode)");
717 }
718
719 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_byte, tc)
720 {
721 /* 0b11 -- break on data write&read */
722 /* 0b00 -- 1 byte */
723
724 dbregs_trap_variable(1, 3, 0, true);
725 }
726
727 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_byte);
728 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_byte, tc)
729 {
730 atf_tc_set_md_var(tc, "descr",
731 "Verify that setting trap with DR2 triggers SIGTRAP "
732 "(break on data read/write trap in read 1 byte mode)");
733 }
734
735 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_byte, tc)
736 {
737 /* 0b11 -- break on data write&read */
738 /* 0b00 -- 1 byte */
739
740 dbregs_trap_variable(2, 3, 0, true);
741 }
742
743 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_byte);
744 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_byte, tc)
745 {
746 atf_tc_set_md_var(tc, "descr",
747 "Verify that setting trap with DR3 triggers SIGTRAP "
748 "(break on data read/write trap in read 1 byte mode)");
749 }
750
751 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_byte, tc)
752 {
753 /* 0b11 -- break on data write&read */
754 /* 0b00 -- 1 byte */
755
756 dbregs_trap_variable(3, 3, 0, true);
757 }
758
759 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_2bytes);
760 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_2bytes, tc)
761 {
762 atf_tc_set_md_var(tc, "descr",
763 "Verify that setting trap with DR0 triggers SIGTRAP "
764 "(break on data read/write trap in read 2 bytes mode)");
765 }
766
767 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_2bytes, tc)
768 {
769 /* 0b11 -- break on data write&read */
770 /* 0b01 -- 2 bytes */
771
772 dbregs_trap_variable(0, 3, 1, true);
773 }
774
775 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_2bytes);
776 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_2bytes, tc)
777 {
778 atf_tc_set_md_var(tc, "descr",
779 "Verify that setting trap with DR1 triggers SIGTRAP "
780 "(break on data read/write trap in read 2 bytes mode)");
781 }
782
783 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_2bytes, tc)
784 {
785 /* 0b11 -- break on data write&read */
786 /* 0b01 -- 2 bytes */
787
788 dbregs_trap_variable(1, 3, 1, true);
789 }
790
791 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_2bytes);
792 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_2bytes, tc)
793 {
794 atf_tc_set_md_var(tc, "descr",
795 "Verify that setting trap with DR2 triggers SIGTRAP "
796 "(break on data read/write trap in read 2 bytes mode)");
797 }
798
799 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_2bytes, tc)
800 {
801 /* 0b11 -- break on data write&read */
802 /* 0b01 -- 2 bytes */
803
804 dbregs_trap_variable(2, 3, 1, true);
805 }
806
807 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_2bytes);
808 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_2bytes, tc)
809 {
810 atf_tc_set_md_var(tc, "descr",
811 "Verify that setting trap with DR3 triggers SIGTRAP "
812 "(break on data read/write trap in read 2 bytes mode)");
813 }
814
815 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_2bytes, tc)
816 {
817 /* 0b11 -- break on data write&read */
818 /* 0b01 -- 2 bytes */
819
820 dbregs_trap_variable(3, 3, 1, true);
821 }
822
823 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_4bytes);
824 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_4bytes, tc)
825 {
826 atf_tc_set_md_var(tc, "descr",
827 "Verify that setting trap with DR0 triggers SIGTRAP "
828 "(break on data read/write trap in read 4 bytes mode)");
829 }
830
831 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_4bytes, tc)
832 {
833 /* 0b11 -- break on data write&read */
834 /* 0b11 -- 4 bytes */
835
836 dbregs_trap_variable(0, 3, 3, true);
837 }
838
839 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_4bytes);
840 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_4bytes, tc)
841 {
842 atf_tc_set_md_var(tc, "descr",
843 "Verify that setting trap with DR1 triggers SIGTRAP "
844 "(break on data read/write trap in read 4 bytes mode)");
845 }
846
847 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_4bytes, tc)
848 {
849 /* 0b11 -- break on data write&read */
850 /* 0b11 -- 4 bytes */
851
852 dbregs_trap_variable(1, 3, 3, true);
853 }
854
855 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_4bytes);
856 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_4bytes, tc)
857 {
858 atf_tc_set_md_var(tc, "descr",
859 "Verify that setting trap with DR2 triggers SIGTRAP "
860 "(break on data read/write trap in read 4 bytes mode)");
861 }
862
863 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_4bytes, tc)
864 {
865 /* 0b11 -- break on data write&read */
866 /* 0b11 -- 4 bytes */
867
868 dbregs_trap_variable(2, 3, 3, true);
869 }
870
871 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_4bytes);
872 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_4bytes, tc)
873 {
874 atf_tc_set_md_var(tc, "descr",
875 "Verify that setting trap with DR3 triggers SIGTRAP "
876 "(break on data read/write trap in read 4 bytes mode)");
877 }
878
879 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_4bytes, tc)
880 {
881 /* 0b11 -- break on data write&read */
882 /* 0b11 -- 4 bytes */
883
884 dbregs_trap_variable(3, 3, 3, true);
885 }
886
887 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_byte);
888 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_byte, tc)
889 {
890 atf_tc_set_md_var(tc, "descr",
891 "Verify that setting trap with DR0 triggers SIGTRAP "
892 "(break on data read/write trap in write 1 byte mode)");
893 }
894
895 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_byte, tc)
896 {
897 /* 0b11 -- break on data write&read */
898 /* 0b00 -- 1 byte */
899
900 dbregs_trap_variable(0, 3, 0, false);
901 }
902
903 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_byte);
904 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_byte, tc)
905 {
906 atf_tc_set_md_var(tc, "descr",
907 "Verify that setting trap with DR1 triggers SIGTRAP "
908 "(break on data read/write trap in write 1 byte mode)");
909 }
910
911 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_byte, tc)
912 {
913 /* 0b11 -- break on data write&read */
914 /* 0b00 -- 1 byte */
915
916 dbregs_trap_variable(1, 3, 0, false);
917 }
918
919 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_byte);
920 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_byte, tc)
921 {
922 atf_tc_set_md_var(tc, "descr",
923 "Verify that setting trap with DR2 triggers SIGTRAP "
924 "(break on data read/write trap in write 1 byte mode)");
925 }
926
927 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_byte, tc)
928 {
929 /* 0b11 -- break on data write&read */
930 /* 0b00 -- 1 byte */
931
932 dbregs_trap_variable(2, 3, 0, false);
933 }
934
935 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_byte);
936 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_byte, tc)
937 {
938 atf_tc_set_md_var(tc, "descr",
939 "Verify that setting trap with DR3 triggers SIGTRAP "
940 "(break on data read/write trap in write 1 byte mode)");
941 }
942
943 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_byte, tc)
944 {
945 /* 0b11 -- break on data write&read */
946 /* 0b00 -- 1 byte */
947
948 dbregs_trap_variable(3, 3, 0, false);
949 }
950
951 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_2bytes);
952 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_2bytes, tc)
953 {
954 atf_tc_set_md_var(tc, "descr",
955 "Verify that setting trap with DR0 triggers SIGTRAP "
956 "(break on data read/write trap in write 2 bytes mode)");
957 }
958
959 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_2bytes, tc)
960 {
961 /* 0b11 -- break on data write&read */
962 /* 0b01 -- 2 bytes */
963
964 dbregs_trap_variable(0, 3, 1, false);
965 }
966
967 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_2bytes);
968 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_2bytes, tc)
969 {
970 atf_tc_set_md_var(tc, "descr",
971 "Verify that setting trap with DR1 triggers SIGTRAP "
972 "(break on data read/write trap in write 2 bytes mode)");
973 }
974
975 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_2bytes, tc)
976 {
977 /* 0b11 -- break on data write&read */
978 /* 0b01 -- 2 bytes */
979
980 dbregs_trap_variable(1, 3, 1, false);
981 }
982
983 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_2bytes);
984 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_2bytes, tc)
985 {
986 atf_tc_set_md_var(tc, "descr",
987 "Verify that setting trap with DR2 triggers SIGTRAP "
988 "(break on data read/write trap in write 2 bytes mode)");
989 }
990
991 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_2bytes, tc)
992 {
993 /* 0b11 -- break on data write&read */
994 /* 0b01 -- 2 bytes */
995
996 dbregs_trap_variable(2, 3, 1, false);
997 }
998
999 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_2bytes);
1000 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_2bytes, tc)
1001 {
1002 atf_tc_set_md_var(tc, "descr",
1003 "Verify that setting trap with DR3 triggers SIGTRAP "
1004 "(break on data read/write trap in write 2 bytes mode)");
1005 }
1006
1007 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_2bytes, tc)
1008 {
1009 /* 0b11 -- break on data write&read */
1010 /* 0b01 -- 2 bytes */
1011
1012 dbregs_trap_variable(3, 3, 1, false);
1013 }
1014
1015 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_4bytes);
1016 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_4bytes, tc)
1017 {
1018 atf_tc_set_md_var(tc, "descr",
1019 "Verify that setting trap with DR0 triggers SIGTRAP "
1020 "(break on data read/write trap in write 4 bytes mode)");
1021 }
1022
1023 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_4bytes, tc)
1024 {
1025 /* 0b11 -- break on data write&read */
1026 /* 0b11 -- 4 bytes */
1027
1028 dbregs_trap_variable(0, 3, 3, false);
1029 }
1030
1031 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_4bytes);
1032 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_4bytes, tc)
1033 {
1034 atf_tc_set_md_var(tc, "descr",
1035 "Verify that setting trap with DR1 triggers SIGTRAP "
1036 "(break on data read/write trap in write 4 bytes mode)");
1037 }
1038
1039 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_4bytes, tc)
1040 {
1041 /* 0b11 -- break on data write&read */
1042 /* 0b11 -- 4 bytes */
1043
1044 dbregs_trap_variable(1, 3, 3, false);
1045 }
1046
1047 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_4bytes);
1048 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_4bytes, tc)
1049 {
1050 atf_tc_set_md_var(tc, "descr",
1051 "Verify that setting trap with DR2 triggers SIGTRAP "
1052 "(break on data read/write trap in write 4 bytes mode)");
1053 }
1054
1055 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_4bytes, tc)
1056 {
1057 /* 0b11 -- break on data write&read */
1058 /* 0b11 -- 4 bytes */
1059
1060 dbregs_trap_variable(2, 3, 3, false);
1061 }
1062
1063 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_4bytes);
1064 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_4bytes, tc)
1065 {
1066 atf_tc_set_md_var(tc, "descr",
1067 "Verify that setting trap with DR3 triggers SIGTRAP "
1068 "(break on data read/write trap in write 4 bytes mode)");
1069 }
1070
1071 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_4bytes, tc)
1072 {
1073 /* 0b11 -- break on data write&read */
1074 /* 0b11 -- 4 bytes */
1075
1076 dbregs_trap_variable(3, 3, 3, false);
1077 }
1078
1079 #if defined(HAVE_DBREGS)
1080 ATF_TC(dbregs_dr0_trap_code);
1081 ATF_TC_HEAD(dbregs_dr0_trap_code, tc)
1082 {
1083 atf_tc_set_md_var(tc, "descr",
1084 "Verify that setting trap with DR0 triggers SIGTRAP "
1085 "(break on code execution trap)");
1086 }
1087
1088 ATF_TC_BODY(dbregs_dr0_trap_code, tc)
1089 {
1090 const int exitval = 5;
1091 const int sigval = SIGSTOP;
1092 pid_t child, wpid;
1093 #if defined(TWAIT_HAVE_STATUS)
1094 int status;
1095 #endif
1096 struct dbreg r1;
1097 size_t i;
1098 volatile int watchme = 1;
1099 union u dr7;
1100
1101 struct ptrace_siginfo info;
1102 memset(&info, 0, sizeof(info));
1103
1104 dr7.raw = 0;
1105 dr7.bits.global_dr0_breakpoint = 1;
1106 dr7.bits.condition_dr0 = 0; /* 0b00 -- break on code execution */
1107 dr7.bits.len_dr0 = 0; /* 0b00 -- 1 byte */
1108
1109 printf("Before forking process PID=%d\n", getpid());
1110 ATF_REQUIRE((child = fork()) != -1);
1111 if (child == 0) {
1112 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
1113 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1114
1115 printf("Before raising %s from child\n", strsignal(sigval));
1116 FORKEE_ASSERT(raise(sigval) == 0);
1117
1118 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1119
1120 printf("Before raising %s from child\n", strsignal(sigval));
1121 FORKEE_ASSERT(raise(sigval) == 0);
1122
1123 printf("Before exiting of the child process\n");
1124 _exit(exitval);
1125 }
1126 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1127
1128 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1129 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1130
1131 validate_status_stopped(status, sigval);
1132
1133 printf("Call GETDBREGS for the child process (r1)\n");
1134 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1135
1136 printf("State of the debug registers (r1):\n");
1137 for (i = 0; i < __arraycount(r1.dr); i++)
1138 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1139
1140 r1.dr[0] = (long)(intptr_t)check_happy;
1141 printf("Set DR0 (r1.dr[0]) to new value %" PRIxREGISTER "\n",
1142 r1.dr[0]);
1143
1144 r1.dr[7] = dr7.raw;
1145 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1146 r1.dr[7]);
1147
1148 printf("New state of the debug registers (r1):\n");
1149 for (i = 0; i < __arraycount(r1.dr); i++)
1150 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1151
1152 printf("Call SETDBREGS for the child process (r1)\n");
1153 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1154
1155 printf("Call CONTINUE for the child process\n");
1156 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1157
1158 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1159 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1160
1161 validate_status_stopped(status, SIGTRAP);
1162
1163 printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1164 ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1165
1166 printf("Signal traced to lwpid=%d\n", info.psi_lwpid);
1167 printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1168 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1169 info.psi_siginfo.si_errno);
1170
1171 printf("Before checking siginfo_t\n");
1172 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1173 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1174
1175 printf("Remove code trap from check_happy=%p\n", check_happy);
1176 dr7.bits.global_dr0_breakpoint = 0;
1177 r1.dr[7] = dr7.raw;
1178 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1179 r1.dr[7]);
1180
1181 printf("Call SETDBREGS for the child process (r1)\n");
1182 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1183
1184 printf("Call CONTINUE for the child process\n");
1185 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1186
1187 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1188 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1189
1190 validate_status_stopped(status, sigval);
1191
1192 printf("Before resuming the child process where it left off and "
1193 "without signal to be sent\n");
1194 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1195
1196 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1197 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1198
1199 validate_status_exited(status, exitval);
1200
1201 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1202 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1203 }
1204 #endif
1205
1206 #if defined(HAVE_DBREGS)
1207 ATF_TC(dbregs_dr1_trap_code);
1208 ATF_TC_HEAD(dbregs_dr1_trap_code, tc)
1209 {
1210 atf_tc_set_md_var(tc, "descr",
1211 "Verify that setting trap with DR1 triggers SIGTRAP "
1212 "(break on code execution trap)");
1213 }
1214
1215 ATF_TC_BODY(dbregs_dr1_trap_code, tc)
1216 {
1217 const int exitval = 5;
1218 const int sigval = SIGSTOP;
1219 pid_t child, wpid;
1220 #if defined(TWAIT_HAVE_STATUS)
1221 int status;
1222 #endif
1223 struct dbreg r1;
1224 size_t i;
1225 volatile int watchme = 1;
1226 union u dr7;
1227
1228 struct ptrace_siginfo info;
1229 memset(&info, 0, sizeof(info));
1230
1231 dr7.raw = 0;
1232 dr7.bits.global_dr1_breakpoint = 1;
1233 dr7.bits.condition_dr1 = 0; /* 0b00 -- break on code execution */
1234 dr7.bits.len_dr1 = 0; /* 0b00 -- 1 byte */
1235
1236 printf("Before forking process PID=%d\n", getpid());
1237 ATF_REQUIRE((child = fork()) != -1);
1238 if (child == 0) {
1239 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
1240 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1241
1242 printf("Before raising %s from child\n", strsignal(sigval));
1243 FORKEE_ASSERT(raise(sigval) == 0);
1244
1245 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1246
1247 printf("Before raising %s from child\n", strsignal(sigval));
1248 FORKEE_ASSERT(raise(sigval) == 0);
1249
1250 printf("Before exiting of the child process\n");
1251 _exit(exitval);
1252 }
1253 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1254
1255 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1256 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1257
1258 validate_status_stopped(status, sigval);
1259
1260 printf("Call GETDBREGS for the child process (r1)\n");
1261 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1262
1263 printf("State of the debug registers (r1):\n");
1264 for (i = 0; i < __arraycount(r1.dr); i++)
1265 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1266
1267 r1.dr[1] = (long)(intptr_t)check_happy;
1268 printf("Set DR1 (r1.dr[1]) to new value %" PRIxREGISTER "\n",
1269 r1.dr[1]);
1270
1271 r1.dr[7] = dr7.raw;
1272 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1273 r1.dr[7]);
1274
1275 printf("New state of the debug registers (r1):\n");
1276 for (i = 0; i < __arraycount(r1.dr); i++)
1277 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1278
1279 printf("Call SETDBREGS for the child process (r1)\n");
1280 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1281
1282 printf("Call CONTINUE for the child process\n");
1283 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1284
1285 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1286 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1287
1288 validate_status_stopped(status, SIGTRAP);
1289
1290 printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1291 ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1292
1293 printf("Signal traced to lwpid=%d\n", info.psi_lwpid);
1294 printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1295 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1296 info.psi_siginfo.si_errno);
1297
1298 printf("Before checking siginfo_t\n");
1299 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1300 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1301
1302 printf("Remove code trap from check_happy=%p\n", check_happy);
1303 dr7.bits.global_dr1_breakpoint = 0;
1304 r1.dr[7] = dr7.raw;
1305 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1306 r1.dr[7]);
1307
1308 printf("Call SETDBREGS for the child process (r1)\n");
1309 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1310
1311 printf("Call CONTINUE for the child process\n");
1312 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1313
1314 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1315 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1316
1317 validate_status_stopped(status, sigval);
1318
1319 printf("Before resuming the child process where it left off and "
1320 "without signal to be sent\n");
1321 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1322
1323 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1324 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1325
1326 validate_status_exited(status, exitval);
1327
1328 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1329 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1330 }
1331 #endif
1332
1333 #if defined(HAVE_DBREGS)
1334 ATF_TC(dbregs_dr2_trap_code);
1335 ATF_TC_HEAD(dbregs_dr2_trap_code, tc)
1336 {
1337 atf_tc_set_md_var(tc, "descr",
1338 "Verify that setting trap with DR2 triggers SIGTRAP "
1339 "(break on code execution trap)");
1340 }
1341
1342 ATF_TC_BODY(dbregs_dr2_trap_code, tc)
1343 {
1344 const int exitval = 5;
1345 const int sigval = SIGSTOP;
1346 pid_t child, wpid;
1347 #if defined(TWAIT_HAVE_STATUS)
1348 int status;
1349 #endif
1350 struct dbreg r1;
1351 size_t i;
1352 volatile int watchme = 1;
1353 union u dr7;
1354
1355 struct ptrace_siginfo info;
1356 memset(&info, 0, sizeof(info));
1357
1358 dr7.raw = 0;
1359 dr7.bits.global_dr2_breakpoint = 1;
1360 dr7.bits.condition_dr2 = 0; /* 0b00 -- break on code execution */
1361 dr7.bits.len_dr2 = 0; /* 0b00 -- 1 byte */
1362
1363 printf("Before forking process PID=%d\n", getpid());
1364 ATF_REQUIRE((child = fork()) != -1);
1365 if (child == 0) {
1366 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
1367 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1368
1369 printf("Before raising %s from child\n", strsignal(sigval));
1370 FORKEE_ASSERT(raise(sigval) == 0);
1371
1372 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1373
1374 printf("Before raising %s from child\n", strsignal(sigval));
1375 FORKEE_ASSERT(raise(sigval) == 0);
1376
1377 printf("Before exiting of the child process\n");
1378 _exit(exitval);
1379 }
1380 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1381
1382 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1383 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1384
1385 validate_status_stopped(status, sigval);
1386
1387 printf("Call GETDBREGS for the child process (r1)\n");
1388 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1389
1390 printf("State of the debug registers (r1):\n");
1391 for (i = 0; i < __arraycount(r1.dr); i++)
1392 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1393
1394 r1.dr[2] = (long)(intptr_t)check_happy;
1395 printf("Set DR2 (r1.dr[2]) to new value %" PRIxREGISTER "\n",
1396 r1.dr[2]);
1397
1398 r1.dr[7] = dr7.raw;
1399 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1400 r1.dr[7]);
1401
1402 printf("New state of the debug registers (r1):\n");
1403 for (i = 0; i < __arraycount(r1.dr); i++)
1404 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1405
1406 printf("Call SETDBREGS for the child process (r1)\n");
1407 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1408
1409 printf("Call CONTINUE for the child process\n");
1410 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1411
1412 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1413 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1414
1415 validate_status_stopped(status, SIGTRAP);
1416
1417 printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1418 ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1419
1420 printf("Signal traced to lwpid=%d\n", info.psi_lwpid);
1421 printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1422 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1423 info.psi_siginfo.si_errno);
1424
1425 printf("Before checking siginfo_t\n");
1426 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1427 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1428
1429 printf("Remove code trap from check_happy=%p\n", check_happy);
1430 dr7.bits.global_dr2_breakpoint = 0;
1431 r1.dr[7] = dr7.raw;
1432 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1433 r1.dr[7]);
1434
1435 printf("Call SETDBREGS for the child process (r1)\n");
1436 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1437
1438 printf("Call CONTINUE for the child process\n");
1439 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1440
1441 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1442 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1443
1444 validate_status_stopped(status, sigval);
1445
1446 printf("Before resuming the child process where it left off and "
1447 "without signal to be sent\n");
1448 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1449
1450 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1451 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1452
1453 validate_status_exited(status, exitval);
1454
1455 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1456 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1457 }
1458 #endif
1459
1460 #if defined(HAVE_DBREGS)
1461 ATF_TC(dbregs_dr3_trap_code);
1462 ATF_TC_HEAD(dbregs_dr3_trap_code, tc)
1463 {
1464 atf_tc_set_md_var(tc, "descr",
1465 "Verify that setting trap with DR3 triggers SIGTRAP "
1466 "(break on code execution trap)");
1467 }
1468
1469 ATF_TC_BODY(dbregs_dr3_trap_code, tc)
1470 {
1471 const int exitval = 5;
1472 const int sigval = SIGSTOP;
1473 pid_t child, wpid;
1474 #if defined(TWAIT_HAVE_STATUS)
1475 int status;
1476 #endif
1477 struct dbreg r1;
1478 size_t i;
1479 volatile int watchme = 1;
1480 union u dr7;
1481
1482 struct ptrace_siginfo info;
1483 memset(&info, 0, sizeof(info));
1484
1485 dr7.raw = 0;
1486 dr7.bits.global_dr3_breakpoint = 1;
1487 dr7.bits.condition_dr3 = 0; /* 0b00 -- break on code execution */
1488 dr7.bits.len_dr3 = 0; /* 0b00 -- 1 byte */
1489
1490 printf("Before forking process PID=%d\n", getpid());
1491 ATF_REQUIRE((child = fork()) != -1);
1492 if (child == 0) {
1493 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
1494 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1495
1496 printf("Before raising %s from child\n", strsignal(sigval));
1497 FORKEE_ASSERT(raise(sigval) == 0);
1498
1499 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1500
1501 printf("Before raising %s from child\n", strsignal(sigval));
1502 FORKEE_ASSERT(raise(sigval) == 0);
1503
1504 printf("Before exiting of the child process\n");
1505 _exit(exitval);
1506 }
1507 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1508
1509 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1510 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1511
1512 validate_status_stopped(status, sigval);
1513
1514 printf("Call GETDBREGS for the child process (r1)\n");
1515 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1516
1517 printf("State of the debug registers (r1):\n");
1518 for (i = 0; i < __arraycount(r1.dr); i++)
1519 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1520
1521 r1.dr[3] = (long)(intptr_t)check_happy;
1522 printf("Set DR3 (r1.dr[3]) to new value %" PRIxREGISTER "\n",
1523 r1.dr[3]);
1524
1525 r1.dr[7] = dr7.raw;
1526 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1527 r1.dr[7]);
1528
1529 printf("New state of the debug registers (r1):\n");
1530 for (i = 0; i < __arraycount(r1.dr); i++)
1531 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1532
1533 printf("Call SETDBREGS for the child process (r1)\n");
1534 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1535
1536 printf("Call CONTINUE for the child process\n");
1537 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1538
1539 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1540 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1541
1542 validate_status_stopped(status, SIGTRAP);
1543
1544 printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1545 ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1546
1547 printf("Signal traced to lwpid=%d\n", info.psi_lwpid);
1548 printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1549 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1550 info.psi_siginfo.si_errno);
1551
1552 printf("Before checking siginfo_t\n");
1553 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1554 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1555
1556 printf("Remove code trap from check_happy=%p\n", check_happy);
1557 dr7.bits.global_dr3_breakpoint = 0;
1558 r1.dr[7] = dr7.raw;
1559 printf("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1560 r1.dr[7]);
1561
1562 printf("Call SETDBREGS for the child process (r1)\n");
1563 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1564
1565 printf("Call CONTINUE for the child process\n");
1566 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1567
1568 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1569 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1570
1571 validate_status_stopped(status, sigval);
1572
1573 printf("Before resuming the child process where it left off and "
1574 "without signal to be sent\n");
1575 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1576
1577 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1578 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1579
1580 validate_status_exited(status, exitval);
1581
1582 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1583 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1584 }
1585 #endif
1586
1587 volatile lwpid_t x86_the_lwp_id = 0;
1588
1589 static void __used
1590 x86_lwp_main_func(void *arg)
1591 {
1592 x86_the_lwp_id = _lwp_self();
1593 _lwp_exit();
1594 }
1595
1596 static void
1597 dbregs_dont_inherit_lwp(int reg)
1598 {
1599 const int exitval = 5;
1600 const int sigval = SIGSTOP;
1601 pid_t child, wpid;
1602 #if defined(TWAIT_HAVE_STATUS)
1603 int status;
1604 #endif
1605 ptrace_state_t state;
1606 const int slen = sizeof(state);
1607 ptrace_event_t event;
1608 const int elen = sizeof(event);
1609 ucontext_t uc;
1610 lwpid_t lid;
1611 static const size_t ssize = 16*1024;
1612 void *stack;
1613 size_t i;
1614 struct dbreg r1;
1615 struct dbreg r2;
1616
1617 printf("Before forking process PID=%d\n", getpid());
1618 ATF_REQUIRE((child = fork()) != -1);
1619 if (child == 0) {
1620 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
1621 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1622
1623 printf("Before raising %s from child\n", strsignal(sigval));
1624 FORKEE_ASSERT(raise(sigval) == 0);
1625
1626 printf("Before allocating memory for stack in child\n");
1627 FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
1628
1629 printf("Before making context for new lwp in child\n");
1630 _lwp_makecontext(&uc, x86_lwp_main_func, NULL, NULL, stack,
1631 ssize);
1632
1633 printf("Before creating new in child\n");
1634 FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
1635
1636 printf("Before waiting for lwp %d to exit\n", lid);
1637 FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
1638
1639 printf("Before verifying that reported %d and running lid %d "
1640 "are the same\n", lid, x86_the_lwp_id);
1641 FORKEE_ASSERT_EQ(lid, x86_the_lwp_id);
1642
1643 printf("Before exiting of the child process\n");
1644 _exit(exitval);
1645 }
1646 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1647
1648 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1649 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1650
1651 validate_status_stopped(status, sigval);
1652
1653 printf("Set empty EVENT_MASK for the child %d\n", child);
1654 event.pe_set_event = PTRACE_LWP_CREATE;
1655 ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
1656
1657 printf("Call GETDBREGS for the child process (r1)\n");
1658 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1659
1660 printf("State of the debug registers (r1):\n");
1661 for (i = 0; i < __arraycount(r1.dr); i++)
1662 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1663
1664 r1.dr[reg] = (long)(intptr_t)check_happy;
1665 printf("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n",
1666 reg, reg, r1.dr[0]);
1667
1668 printf("New state of the debug registers (r1):\n");
1669 for (i = 0; i < __arraycount(r1.dr); i++)
1670 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1671
1672 printf("Call SETDBREGS for the child process (r1)\n");
1673 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1674
1675 printf("Before resuming the child process where it left off and "
1676 "without signal to be sent\n");
1677 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1678
1679 printf("Before calling %s() for the child - expected stopped "
1680 "SIGTRAP\n", TWAIT_FNAME);
1681 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1682
1683 validate_status_stopped(status, SIGTRAP);
1684
1685 ATF_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
1686
1687 ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
1688
1689 lid = state.pe_lwp;
1690 printf("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
1691
1692 printf("Call GETDBREGS for the child process new lwp (r2)\n");
1693 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, lid) != -1);
1694
1695 printf("State of the debug registers (r2):\n");
1696 for (i = 0; i < __arraycount(r2.dr); i++)
1697 printf("r2[%zu]=%" PRIxREGISTER "\n", i, r2.dr[i]);
1698
1699 printf("Assert that (r1) and (r2) are not the same\n");
1700 ATF_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) != 0);
1701
1702 printf("Before resuming the child process where it left off and "
1703 "without signal to be sent\n");
1704 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1705
1706 printf("Before calling %s() for the child - expected exited\n",
1707 TWAIT_FNAME);
1708 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1709
1710 validate_status_exited(status, exitval);
1711
1712 printf("Before calling %s() for the child - expected no process\n",
1713 TWAIT_FNAME);
1714 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1715 }
1716
1717 ATF_TC(dbregs_dr0_dont_inherit_lwp);
1718 ATF_TC_HEAD(dbregs_dr0_dont_inherit_lwp, tc)
1719 {
1720 atf_tc_set_md_var(tc, "descr",
1721 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1722 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 0 from "
1723 "the forker thread is not inherited");
1724 }
1725
1726 ATF_TC_BODY(dbregs_dr0_dont_inherit_lwp, tc)
1727 {
1728 dbregs_dont_inherit_lwp(0);
1729 }
1730
1731 ATF_TC(dbregs_dr1_dont_inherit_lwp);
1732 ATF_TC_HEAD(dbregs_dr1_dont_inherit_lwp, tc)
1733 {
1734 atf_tc_set_md_var(tc, "descr",
1735 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1736 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 1 from "
1737 "the forker thread is not inherited");
1738 }
1739
1740 ATF_TC_BODY(dbregs_dr1_dont_inherit_lwp, tc)
1741 {
1742 dbregs_dont_inherit_lwp(1);
1743 }
1744
1745 ATF_TC(dbregs_dr2_dont_inherit_lwp);
1746 ATF_TC_HEAD(dbregs_dr2_dont_inherit_lwp, tc)
1747 {
1748 atf_tc_set_md_var(tc, "descr",
1749 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1750 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 2 from "
1751 "the forker thread is not inherited");
1752 }
1753
1754 ATF_TC_BODY(dbregs_dr2_dont_inherit_lwp, tc)
1755 {
1756 dbregs_dont_inherit_lwp(2);
1757 }
1758
1759 ATF_TC(dbregs_dr3_dont_inherit_lwp);
1760 ATF_TC_HEAD(dbregs_dr3_dont_inherit_lwp, tc)
1761 {
1762 atf_tc_set_md_var(tc, "descr",
1763 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1764 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 3 from "
1765 "the forker thread is not inherited");
1766 }
1767
1768 ATF_TC_BODY(dbregs_dr3_dont_inherit_lwp, tc)
1769 {
1770 dbregs_dont_inherit_lwp(3);
1771 }
1772
1773 static void
1774 dbregs_dont_inherit_execve(int reg)
1775 {
1776 const int sigval = SIGTRAP;
1777 pid_t child, wpid;
1778 #if defined(TWAIT_HAVE_STATUS)
1779 int status;
1780 #endif
1781 size_t i;
1782 struct dbreg r1;
1783 struct dbreg r2;
1784
1785 struct ptrace_siginfo info;
1786 memset(&info, 0, sizeof(info));
1787
1788 printf("Before forking process PID=%d\n", getpid());
1789 ATF_REQUIRE((child = fork()) != -1);
1790 if (child == 0) {
1791 printf("Before calling PT_TRACE_ME from child %d\n", getpid());
1792 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1793
1794 printf("Before raising %s from child\n", strsignal(sigval));
1795 FORKEE_ASSERT(raise(sigval) == 0);
1796
1797 printf("Before calling execve(2) from child\n");
1798 execlp("/bin/echo", "/bin/echo", NULL);
1799
1800 FORKEE_ASSERT(0 && "Not reached");
1801 }
1802 printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1803
1804 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1805 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1806
1807 validate_status_stopped(status, sigval);
1808
1809 printf("Call GETDBREGS for the child process (r1)\n");
1810 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1811
1812 printf("State of the debug registers (r1):\n");
1813 for (i = 0; i < __arraycount(r1.dr); i++)
1814 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1815
1816 r1.dr[reg] = (long)(intptr_t)check_happy;
1817 printf("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n",
1818 reg, reg, r1.dr[reg]);
1819
1820 printf("New state of the debug registers (r1):\n");
1821 for (i = 0; i < __arraycount(r1.dr); i++)
1822 printf("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1823
1824 printf("Call SETDBREGS for the child process (r1)\n");
1825 ATF_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1826
1827 printf("Before resuming the child process where it left off and "
1828 "without signal to be sent\n");
1829 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1830
1831 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1832 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1833
1834 validate_status_stopped(status, sigval);
1835
1836 printf("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1837 ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1838
1839 printf("Signal traced to lwpid=%d\n", info.psi_lwpid);
1840 printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1841 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1842 info.psi_siginfo.si_errno);
1843
1844 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1845 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
1846
1847 printf("Call GETDBREGS for the child process after execve(2)\n");
1848 ATF_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
1849
1850 printf("State of the debug registers (r2):\n");
1851 for (i = 0; i < __arraycount(r2.dr); i++)
1852 printf("r2[%zu]=%" PRIxREGISTER "\n", i, r2.dr[i]);
1853
1854 printf("Assert that (r1) and (r2) are not the same\n");
1855 ATF_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) != 0);
1856
1857 printf("Before resuming the child process where it left off and "
1858 "without signal to be sent\n");
1859 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1860
1861 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1862 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1863
1864 printf("Before calling %s() for the child\n", TWAIT_FNAME);
1865 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1866 }
1867
1868 ATF_TC(dbregs_dr0_dont_inherit_execve);
1869 ATF_TC_HEAD(dbregs_dr0_dont_inherit_execve, tc)
1870 {
1871 atf_tc_set_md_var(tc, "descr",
1872 "Verify that execve(2) is intercepted by tracer and Debug "
1873 "Register 0 is reset");
1874 }
1875
1876 ATF_TC_BODY(dbregs_dr0_dont_inherit_execve, tc)
1877 {
1878 dbregs_dont_inherit_execve(0);
1879 }
1880
1881 ATF_TC(dbregs_dr1_dont_inherit_execve);
1882 ATF_TC_HEAD(dbregs_dr1_dont_inherit_execve, tc)
1883 {
1884 atf_tc_set_md_var(tc, "descr",
1885 "Verify that execve(2) is intercepted by tracer and Debug "
1886 "Register 1 is reset");
1887 }
1888
1889 ATF_TC_BODY(dbregs_dr1_dont_inherit_execve, tc)
1890 {
1891 dbregs_dont_inherit_execve(1);
1892 }
1893
1894 ATF_TC(dbregs_dr2_dont_inherit_execve);
1895 ATF_TC_HEAD(dbregs_dr2_dont_inherit_execve, tc)
1896 {
1897 atf_tc_set_md_var(tc, "descr",
1898 "Verify that execve(2) is intercepted by tracer and Debug "
1899 "Register 2 is reset");
1900 }
1901
1902 ATF_TC_BODY(dbregs_dr2_dont_inherit_execve, tc)
1903 {
1904 dbregs_dont_inherit_execve(2);
1905 }
1906
1907 ATF_TC(dbregs_dr3_dont_inherit_execve);
1908 ATF_TC_HEAD(dbregs_dr3_dont_inherit_execve, tc)
1909 {
1910 atf_tc_set_md_var(tc, "descr",
1911 "Verify that execve(2) is intercepted by tracer and Debug "
1912 "Register 3 is reset");
1913 }
1914
1915 ATF_TC_BODY(dbregs_dr3_dont_inherit_execve, tc)
1916 {
1917 dbregs_dont_inherit_execve(3);
1918 }
1919 #define ATF_TP_ADD_TCS_PTRACE_WAIT_X86() \
1920 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_print); \
1921 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0); \
1922 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1); \
1923 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2); \
1924 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3); \
1925 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_yield); \
1926 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_yield); \
1927 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_yield); \
1928 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_yield); \
1929 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_continued); \
1930 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_continued); \
1931 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_continued); \
1932 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_continued); \
1933 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_byte); \
1934 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_byte); \
1935 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_byte); \
1936 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_byte); \
1937 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_2bytes); \
1938 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_2bytes); \
1939 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_2bytes); \
1940 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_2bytes); \
1941 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_4bytes); \
1942 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_4bytes); \
1943 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_4bytes); \
1944 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_4bytes); \
1945 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_byte); \
1946 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_byte); \
1947 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_byte); \
1948 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_byte); \
1949 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_2bytes); \
1950 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_2bytes); \
1951 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_2bytes); \
1952 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_2bytes); \
1953 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_4bytes); \
1954 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_4bytes); \
1955 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_4bytes); \
1956 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_4bytes); \
1957 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_byte); \
1958 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_byte); \
1959 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_byte); \
1960 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_byte); \
1961 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_2bytes); \
1962 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_2bytes); \
1963 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_2bytes); \
1964 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_2bytes); \
1965 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_4bytes); \
1966 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_4bytes); \
1967 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_4bytes); \
1968 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_4bytes); \
1969 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_code); \
1970 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_code); \
1971 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_code); \
1972 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_code); \
1973 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_dont_inherit_lwp); \
1974 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_dont_inherit_lwp); \
1975 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_lwp); \
1976 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_lwp); \
1977 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_dont_inherit_execve); \
1978 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_dont_inherit_execve); \
1979 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_execve); \
1980 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_execve);
1981 #else
1982 #define ATF_TP_ADD_TCS_PTRACE_WAIT_X86()
1983 #endif
1984