t_ptrace_wait.h revision 1.40 1 /* $NetBSD: t_ptrace_wait.h,v 1.40 2025/05/02 02:52:40 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2016, 2017, 2018, 2019 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 /* Detect plain wait(2) use-case */
30 #if !defined(TWAIT_WAITPID) && \
31 !defined(TWAIT_WAITID) && \
32 !defined(TWAIT_WAIT3) && \
33 !defined(TWAIT_WAIT4) && \
34 !defined(TWAIT_WAIT6)
35 #define TWAIT_WAIT
36 #endif
37
38 /*
39 * There are two classes of wait(2)-like functions:
40 * - wait4(2)-like accepting pid_t, optional options parameter, struct rusage*
41 * - wait6(2)-like accepting idtype_t, id_t, struct wrusage, mandatory options
42 *
43 * The TWAIT_FNAME value is to be used for convenience in debug messages.
44 *
45 * The TWAIT_GENERIC() macro is designed to reuse the same unmodified
46 * code with as many wait(2)-like functions as possible.
47 *
48 * In a common use-case wait4(2) and wait6(2)-like function can work the almost
49 * the same way, however there are few important differences:
50 * wait6(2) must specify P_PID for idtype to match wpid from wait4(2).
51 * To behave like wait4(2), wait6(2) the 'options' to wait must include
52 * WEXITED|WTRUNCATED.
53 *
54 * There are two helper macros (they purpose it to mach more than one
55 * wait(2)-like function):
56 * The TWAIT_HAVE_STATUS - specifies whether a function can retrieve
57 * status (as integer value).
58 * The TWAIT_HAVE_PID - specifies whether a function can request
59 * exact process identifier
60 * The TWAIT_HAVE_RUSAGE - specifies whether a function can request
61 * the struct rusage value
62 *
63 */
64
65 #if defined(TWAIT_WAIT)
66 # define TWAIT_FNAME "wait"
67 # define TWAIT_WAIT4TYPE(a,b,c,d) wait((b))
68 # define TWAIT_GENERIC(a,b,c) wait((b))
69 # define TWAIT_HAVE_STATUS 1
70 #elif defined(TWAIT_WAITPID)
71 # define TWAIT_FNAME "waitpid"
72 # define TWAIT_WAIT4TYPE(a,b,c,d) waitpid((a),(b),(c))
73 # define TWAIT_GENERIC(a,b,c) waitpid((a),(b),(c))
74 # define TWAIT_HAVE_PID 1
75 # define TWAIT_HAVE_STATUS 1
76 # define TWAIT_HAVE_OPTIONS 1
77 #elif defined(TWAIT_WAITID)
78 # define TWAIT_FNAME "waitid"
79 # define TWAIT_GENERIC(a,b,c) \
80 waitid(P_PID,(a),NULL,(c)|WEXITED|WTRAPPED)
81 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) waitid((a),(b),(f),(d))
82 # define TWAIT_HAVE_PID 1
83 # define TWAIT_HAVE_OPTIONS 1
84 #elif defined(TWAIT_WAIT3)
85 # define TWAIT_FNAME "wait3"
86 # define TWAIT_WAIT4TYPE(a,b,c,d) wait3((b),(c),(d))
87 # define TWAIT_GENERIC(a,b,c) wait3((b),(c),NULL)
88 # define TWAIT_HAVE_STATUS 1
89 # define TWAIT_HAVE_RUSAGE 1
90 # define TWAIT_HAVE_OPTIONS 1
91 #elif defined(TWAIT_WAIT4)
92 # define TWAIT_FNAME "wait4"
93 # define TWAIT_WAIT4TYPE(a,b,c,d) wait4((a),(b),(c),(d))
94 # define TWAIT_GENERIC(a,b,c) wait4((a),(b),(c),NULL)
95 # define TWAIT_HAVE_PID 1
96 # define TWAIT_HAVE_STATUS 1
97 # define TWAIT_HAVE_RUSAGE 1
98 # define TWAIT_HAVE_OPTIONS 1
99 #elif defined(TWAIT_WAIT6)
100 # define TWAIT_FNAME "wait6"
101 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) wait6((a),(b),(c),(d),(e),(f))
102 # define TWAIT_GENERIC(a,b,c) \
103 wait6(P_PID,(a),(b),(c)|WEXITED|WTRAPPED,NULL,NULL)
104 # define TWAIT_HAVE_PID 1
105 # define TWAIT_HAVE_STATUS 1
106 # define TWAIT_HAVE_OPTIONS 1
107 #endif
108
109 /*
110 * There are 3 groups of tests:
111 * - TWAIT_GENERIC() (wait, wait2, waitpid, wait3, wait4, wait6)
112 * - TWAIT_WAIT4TYPE() (wait2, waitpid, wait3, wait4)
113 * - TWAIT_WAIT6TYPE() (waitid, wait6)
114 *
115 * Tests only in the above categories are allowed. However some tests are not
116 * possible in the context requested functionality to be verified, therefore
117 * there are helper macros:
118 * - TWAIT_HAVE_PID (wait2, waitpid, waitid, wait4, wait6)
119 * - TWAIT_HAVE_STATUS (wait, wait2, waitpid, wait3, wait4, wait6)
120 * - TWAIT_HAVE_RUSAGE (wait3, wait4)
121 * - TWAIT_HAVE_RETPID (wait, wait2, waitpid, wait3, wait4, wait6)
122 *
123 * If there is an intention to test e.g. wait6(2) specific features in the
124 * ptrace(2) context, find the most matching group and with #ifdefs reduce
125 * functionality of less featured than wait6(2) interface (TWAIT_WAIT6TYPE).
126 *
127 * For clarity never use negative preprocessor checks, like:
128 * #if !defined(TWAIT_WAIT4)
129 * always refer to checks for positive values.
130 */
131
132 #define TEST_REQUIRE_EQ(x, y) \
133 do { \
134 uintmax_t vx = (x); \
135 uintmax_t vy = (y); \
136 int ret = vx == vy; \
137 if (!ret) \
138 ATF_REQUIRE_EQ_MSG(vx, vy, \
139 "%s(%ju=0x%jx) == %s(%ju=0x%jx)", \
140 #x, vx, vx, #y, vy, vy); \
141 } while (/*CONSTCOND*/0)
142
143 #define TEST_CHECK_EQ(x, y) \
144 do { \
145 uintmax_t vx = (x); \
146 uintmax_t vy = (y); \
147 int ret = vx == vy; \
148 if (!ret) \
149 ATF_CHECK_EQ_MSG(vx, vy, \
150 "%s(%ju=0x%jx) == %s(%ju=0x%jx)", \
151 #x, vx, vx, #y, vy, vy); \
152 } while (/*CONSTCOND*/0)
153
154 #define TEST_CHECK_MEMEQ(x, y, n) \
155 do { \
156 const void *vx = (x); \
157 const void *vy = (y); \
158 const size_t vn = (n); \
159 if (__predict_true(memcmp(vx, vy, vn) == 0)) \
160 break; \
161 hexdump(#x, vx, vn); \
162 hexdump(#y, vy, vn); \
163 atf_tc_fail_nonfatal("%s != %s (%s = %zu bytes)", \
164 #x, #y, #n, vn); \
165 } while (/*CONSTCOND*/0)
166
167 /*
168 * A child process cannot call atf functions and expect them to magically
169 * work like in the parent.
170 * The printf(3) messaging from a child will not work out of the box as well
171 * without establishing a communication protocol with its parent. To not
172 * overcomplicate the tests - do not log from a child and use err(3)/errx(3)
173 * wrapped with FORKEE_ASSERT()/FORKEE_ASSERTX() as that is guaranteed to work.
174 */
175 #define FORKEE_ASSERT_EQ(x, y) \
176 do { \
177 uintmax_t vx = (x); \
178 uintmax_t vy = (y); \
179 int ret = vx == vy; \
180 if (!ret) \
181 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
182 "%s(%jd=0x%jx) == %s(%jd=0x%jx)", \
183 __FILE__, __LINE__, __func__, \
184 #x, vx, vx, #y, vy, vy); \
185 } while (/*CONSTCOND*/0)
186
187 #define FORKEE_ASSERT_NEQ(x, y) \
188 do { \
189 uintmax_t vx = (x); \
190 uintmax_t vy = (y); \
191 int ret = vx != vy; \
192 if (!ret) \
193 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
194 "%s(%ju=0x%jx) != %s(%ju=0x%jx)", \
195 __FILE__, __LINE__, __func__, \
196 #x, vx, vx, #y, vy, vy); \
197 } while (/*CONSTCOND*/0)
198
199 __unused /* used by FORKEE_ASSERT_MEMEQ, otherwise not used */
200 static void
201 hexdump(const char *title, const void *buf, size_t len)
202 {
203 const unsigned char *p = buf;
204 size_t i;
205
206 fprintf(stderr, "%s (%zu bytes)\n", title, len);
207 for (i = 0; i < len; i++) {
208 if ((i % 8) == 0)
209 fprintf(stderr, " ");
210 fprintf(stderr, "%02hhx", p[i]);
211 if ((i % 16) == 0)
212 fprintf(stderr, "\n");
213 }
214 if (i % 16)
215 fprintf(stderr, "\n");
216 }
217
218 #define FORKEE_ASSERT_MEMEQ(x, y, n) \
219 do { \
220 const void *const vx = (x); \
221 const void *const vy = (y); \
222 const size_t vn = (n); \
223 \
224 if (__predict_true(memcmp(vx, vy, vn) == 0)) \
225 break; \
226 fprintf(stderr, "%s != %s (%s = %zu bytes)\n", #x, #y, #n, vn); \
227 hexdump(#x, vx, vn); \
228 hexdump(#y, vy, vn); \
229 } while (/*CONSTCOND*/0)
230
231 #define FORKEE_ASSERTX(x) \
232 do { \
233 int ret = (x); \
234 if (!ret) \
235 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
236 __FILE__, __LINE__, __func__, #x); \
237 } while (/*CONSTCOND*/0)
238
239 #define FORKEE_ASSERT(x) \
240 do { \
241 int ret = (x); \
242 if (!ret) \
243 err(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
244 __FILE__, __LINE__, __func__, #x); \
245 } while (/*CONSTCOND*/0)
246
247 #define FORKEE_PTHREAD(x) \
248 do { \
249 int _forkee_pthread_error = (x); \
250 if (_forkee_pthread_error) { \
251 errno = _forkee_pthread_error; \
252 err(EXIT_FAILURE, "%s:%d %s(): %s", __FILE__, __LINE__, \
253 __func__, #x); \
254 } \
255 } while (/*CONSTCOND*/0)
256
257 /*
258 * Simplify logic for functions using general purpose registers add HAVE_GPREGS
259 *
260 * For platforms that do not implement all needed calls for simplicity assume
261 * that they are unsupported at all.
262 */
263 #if defined(PT_GETREGS) \
264 && defined(PT_SETREGS) \
265 && defined(PTRACE_REG_PC) \
266 && defined(PTRACE_REG_SET_PC) \
267 && defined(PTRACE_REG_SP) \
268 && defined(PTRACE_REG_INTRV)
269 #define HAVE_GPREGS
270 #endif
271
272 /* Add guards for floating point registers */
273 #if defined(PT_GETFPREGS) \
274 && defined(PT_SETFPREGS)
275 #define HAVE_FPREGS
276 #endif
277
278 /* Add guards for cpu debug registers */
279 #if defined(PT_GETDBREGS) \
280 && defined(PT_SETDBREGS)
281 #define HAVE_DBREGS
282 #endif
283
284 /*
285 * If waitid(2) returns because one or more processes have a state change to
286 * report, 0 is returned. If an error is detected, a value of -1 is returned
287 * and errno is set to indicate the error. If WNOHANG is specified and there
288 * are no stopped, continued or exited children, 0 is returned.
289 */
290 #if defined(TWAIT_WAITID)
291 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), 0)
292 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1)
293 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, 0)
294 #define FORKEE_REQUIRE_FAILURE(a,b) \
295 FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
296 #else
297 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), (b))
298 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1)
299 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, b)
300 #define FORKEE_REQUIRE_FAILURE(a,b) \
301 FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
302 #endif
303
304 /*
305 * Helper tools to verify whether status reports exited value
306 */
307 #if TWAIT_HAVE_STATUS
308 static void __used
309 validate_status_exited(int status, int expected)
310 {
311 ATF_REQUIRE_MSG(WIFEXITED(status), "Reported !exited process");
312 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
313 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
314 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
315
316 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(status), expected,
317 "The process has exited with invalid value %d != %d",
318 WEXITSTATUS(status), expected);
319 }
320
321 static void __used
322 forkee_status_exited(int status, int expected)
323 {
324 FORKEE_ASSERTX(WIFEXITED(status));
325 FORKEE_ASSERTX(!WIFCONTINUED(status));
326 FORKEE_ASSERTX(!WIFSIGNALED(status));
327 FORKEE_ASSERTX(!WIFSTOPPED(status));
328
329 FORKEE_ASSERT_EQ(WEXITSTATUS(status), expected);
330 }
331
332 static void __used
333 validate_status_continued(int status)
334 {
335 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
336 ATF_REQUIRE_MSG(WIFCONTINUED(status), "Reported !continued process");
337 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
338 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
339 }
340
341 static void __used
342 forkee_status_continued(int status)
343 {
344 FORKEE_ASSERTX(!WIFEXITED(status));
345 FORKEE_ASSERTX(WIFCONTINUED(status));
346 FORKEE_ASSERTX(!WIFSIGNALED(status));
347 FORKEE_ASSERTX(!WIFSTOPPED(status));
348 }
349
350 static void __used
351 validate_status_signaled(int status, int expected_termsig, int expected_core)
352 {
353 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
354 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
355 ATF_REQUIRE_MSG(WIFSIGNALED(status), "Reported !signaled process");
356 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
357
358 ATF_REQUIRE_EQ_MSG(WTERMSIG(status), expected_termsig,
359 "Unexpected signal received");
360
361 ATF_REQUIRE_EQ_MSG(!!WCOREDUMP(status), expected_core,
362 "Unexpectedly core file %s generated", expected_core ? "not" : "");
363 }
364
365 static void __used
366 forkee_status_signaled(int status, int expected_termsig, int expected_core)
367 {
368 FORKEE_ASSERTX(!WIFEXITED(status));
369 FORKEE_ASSERTX(!WIFCONTINUED(status));
370 FORKEE_ASSERTX(WIFSIGNALED(status));
371 FORKEE_ASSERTX(!WIFSTOPPED(status));
372
373 FORKEE_ASSERT_EQ(WTERMSIG(status), expected_termsig);
374 FORKEE_ASSERT_EQ(!!WCOREDUMP(status), expected_core);
375 }
376
377 static void __used
378 validate_status_stopped(int status, int expected)
379 {
380 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
381 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
382 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
383 ATF_REQUIRE_MSG(WIFSTOPPED(status), "Reported !stopped process");
384
385 char st[128], ex[128];
386 strlcpy(st, strsignal(WSTOPSIG(status)), sizeof(st));
387 strlcpy(ex, strsignal(expected), sizeof(ex));
388
389 ATF_REQUIRE_EQ_MSG(WSTOPSIG(status), expected,
390 "Unexpected stop signal received [%s] != [%s]", st, ex);
391 }
392
393 static void __used
394 forkee_status_stopped(int status, int expected)
395 {
396 FORKEE_ASSERTX(!WIFEXITED(status));
397 FORKEE_ASSERTX(!WIFCONTINUED(status));
398 FORKEE_ASSERTX(!WIFSIGNALED(status));
399 FORKEE_ASSERTX(WIFSTOPPED(status));
400
401 FORKEE_ASSERT_EQ(WSTOPSIG(status), expected);
402 }
403 #else
404 #define validate_status_exited(a,b)
405 #define forkee_status_exited(a,b)
406 #define validate_status_continued(a,b)
407 #define forkee_status_continued(a,b)
408 #define validate_status_signaled(a,b,c)
409 #define forkee_status_signaled(a,b,c)
410 #define validate_status_stopped(a,b)
411 #define forkee_status_stopped(a,b)
412 #endif
413
414 /* This function is currently designed to be run in the main/parent process */
415 static void __used
416 await_zombie_raw(pid_t process, useconds_t ms)
417 {
418 struct kinfo_proc2 p;
419 size_t len = sizeof(p);
420
421 const int name[] = {
422 [0] = CTL_KERN,
423 [1] = KERN_PROC2,
424 [2] = KERN_PROC_PID,
425 [3] = process,
426 [4] = sizeof(p),
427 [5] = 1
428 };
429
430 const size_t namelen = __arraycount(name);
431
432 /* Await the process becoming a zombie */
433 while(1) {
434 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
435
436 if (p.p_stat == LSZOMB)
437 break;
438
439 if (ms > 0) {
440 ATF_REQUIRE(usleep(ms) == 0);
441 }
442 }
443 }
444
445 static void __used
446 await_zombie(pid_t process)
447 {
448
449 await_zombie_raw(process, 1000);
450 }
451
452 static void __used
453 await_stopped(pid_t process)
454 {
455 struct kinfo_proc2 p;
456 size_t len = sizeof(p);
457
458 const int name[] = {
459 [0] = CTL_KERN,
460 [1] = KERN_PROC2,
461 [2] = KERN_PROC_PID,
462 [3] = process,
463 [4] = sizeof(p),
464 [5] = 1
465 };
466
467 const size_t namelen = __arraycount(name);
468
469 /* Await the process becoming a zombie */
470 while(1) {
471 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
472
473 if (p.p_stat == LSSTOP)
474 break;
475
476 ATF_REQUIRE(usleep(1000) == 0);
477 }
478 }
479
480 static pid_t __used
481 await_stopped_child(pid_t process)
482 {
483 struct kinfo_proc2 *p = NULL;
484 size_t i, len;
485 pid_t child = -1;
486
487 int name[] = {
488 [0] = CTL_KERN,
489 [1] = KERN_PROC2,
490 [2] = KERN_PROC_ALL,
491 [3] = 0,
492 [4] = sizeof(struct kinfo_proc2),
493 [5] = 0
494 };
495
496 const size_t namelen = __arraycount(name);
497
498 /* Await the process becoming a zombie */
499 while(1) {
500 name[5] = 0;
501
502 FORKEE_ASSERT_EQ(sysctl(name, namelen, 0, &len, NULL, 0), 0);
503
504 FORKEE_ASSERT_EQ(reallocarr(&p,
505 len,
506 sizeof(struct kinfo_proc2)), 0);
507
508 name[5] = len;
509
510 FORKEE_ASSERT_EQ(sysctl(name, namelen, p, &len, NULL, 0), 0);
511
512 for (i = 0; i < len/sizeof(struct kinfo_proc2); i++) {
513 if (p[i].p_pid == getpid())
514 continue;
515 if (p[i].p_ppid != process)
516 continue;
517 if (p[i].p_stat != LSSTOP)
518 continue;
519 child = p[i].p_pid;
520 break;
521 }
522
523 if (child != -1)
524 break;
525
526 FORKEE_ASSERT_EQ(usleep(1000), 0);
527 }
528
529 /* Free the buffer */
530 FORKEE_ASSERT_EQ(reallocarr(&p, 0, sizeof(struct kinfo_proc2)), 0);
531
532 return child;
533 }
534
535 static void __used
536 await_collected(pid_t process)
537 {
538 struct kinfo_proc2 p;
539 size_t len = sizeof(p);
540
541 const int name[] = {
542 [0] = CTL_KERN,
543 [1] = KERN_PROC2,
544 [2] = KERN_PROC_PID,
545 [3] = process,
546 [4] = sizeof(p),
547 [5] = 1
548 };
549
550 const size_t namelen = __arraycount(name);
551
552 /* Await the process to disappear */
553 while(1) {
554 FORKEE_ASSERT_EQ(sysctl(name, namelen, &p, &len, NULL, 0), 0);
555 if (len == 0)
556 break;
557
558 ATF_REQUIRE(usleep(1000) == 0);
559 }
560 }
561
562 /* Happy number sequence -- this function is used to just consume cpu cycles */
563 #define HAPPY_NUMBER 1
564
565 /* If n is not happy then its sequence ends in the cycle:
566 * 4, 16, 37, 58, 89, 145, 42, 20, 4, ... */
567 #define SAD_NUMBER 4
568
569 /* Calculate the sum of the squares of the digits of n */
570 static unsigned __used
571 dsum(unsigned n)
572 {
573 unsigned sum, x;
574 for (sum = 0; n; n /= 10) {
575 x = n % 10;
576 sum += x * x;
577 }
578 return sum;
579 }
580
581 /*
582 * XXX: Disabled optimization is required to make tests for hardware assisted
583 * traps in .text functional
584 *
585 * Tested with GCC 5.4 on NetBSD 7.99.47 amd64
586 */
587 static int __used
588 #ifdef __clang__
589 __attribute__((__optnone__))
590 #else
591 __attribute__((__optimize__("O0")))
592 #endif
593 check_happy(unsigned n)
594 {
595 for (;;) {
596 unsigned total = dsum(n);
597
598 if (total == HAPPY_NUMBER)
599 return 1;
600 if (total == SAD_NUMBER)
601 return 0;
602
603 n = total;
604 }
605 }
606
607 static void * __used
608 infinite_thread(void *arg __unused)
609 {
610
611 while (true)
612 continue;
613
614 __unreachable();
615 }
616
617 static int __used
618 clone_func(void *arg)
619 {
620 int ret;
621
622 ret = (int)(intptr_t)arg;
623
624 return ret;
625 }
626
627 #if defined(HAVE_DBREGS)
628 static bool __used
629 can_we_set_dbregs(void)
630 {
631 static long euid = -1;
632 static int user_set_dbregs = -1;
633 size_t user_set_dbregs_len = sizeof(user_set_dbregs);
634
635 if (euid == -1)
636 euid = geteuid();
637
638 if (euid == 0)
639 return true;
640
641 if (user_set_dbregs == -1) {
642 if (sysctlbyname("security.models.extensions.user_set_dbregs",
643 &user_set_dbregs, &user_set_dbregs_len, NULL, 0)
644 == -1) {
645 return false;
646 }
647 }
648
649 if (user_set_dbregs > 0)
650 return true;
651 else
652 return false;
653 }
654 #endif
655
656 static bool __used
657 get_user_va0_disable(void)
658 {
659 static int user_va0_disable = -1;
660 size_t user_va0_disable_len = sizeof(user_va0_disable);
661
662 if (user_va0_disable == -1) {
663 if (sysctlbyname("vm.user_va0_disable",
664 &user_va0_disable, &user_va0_disable_len, NULL, 0)
665 == -1) {
666 return true;
667 }
668 }
669
670 if (user_va0_disable > 0)
671 return true;
672 else
673 return false;
674 }
675
676 static bool __used
677 can_we_write_to_text(pid_t pid)
678 {
679 int mib[3];
680 int paxflags;
681 size_t len = sizeof(int);
682
683 mib[0] = CTL_PROC;
684 mib[1] = pid;
685 mib[2] = PROC_PID_PAXFLAGS;
686
687 if (sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)
688 return false;
689
690 return !(paxflags & CTL_PROC_PAXFLAGS_MPROTECT);
691 }
692
693 static void __used
694 trigger_trap(void)
695 {
696
697 /* Software breakpoint causes CPU trap, translated to SIGTRAP */
698 #ifdef PTRACE_BREAKPOINT_ASM
699 PTRACE_BREAKPOINT_ASM;
700 #else
701 /* port me */
702 #endif
703 }
704
705 static void __used
706 trigger_segv(void)
707 {
708 static volatile char *ptr = NULL;
709
710 /* Access to unmapped memory causes CPU trap, translated to SIGSEGV */
711 *ptr = 1;
712 }
713
714 static void __used
715 trigger_ill(void)
716 {
717
718 /* Illegal instruction causes CPU trap, translated to SIGILL */
719 #ifdef PTRACE_ILLEGAL_ASM
720 #ifndef __mips__ /* To avoid GXemul crash */
721 PTRACE_ILLEGAL_ASM;
722 #endif
723 #else
724 /* port me */
725 #endif
726 }
727
728 #include <fenv.h>
729
730 #if (__arm__ && !__SOFTFP__) || __aarch64__
731 #include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
732
733 static bool __used
734 are_fpu_exceptions_supported(void)
735 {
736 /*
737 * Some NEON fpus do not trap on IEEE 754 FP exceptions.
738 * Skip these tests if running on them and compiled for
739 * hard float.
740 */
741 if (0 == fpsetmask(fpsetmask(FP_X_INV)))
742 return false;
743 return true;
744 }
745 #elif defined __riscv__
746 #define are_fpu_exceptions_supported() 0
747 #else
748 #define are_fpu_exceptions_supported() 1
749 #endif
750
751 volatile double ignore_result;
752
753 static void __used
754 trigger_fpe(void)
755 {
756 #if __i386__ || __x86_64__
757 /*
758 * XXX
759 * Hack for QEMU bug #1668041, by which floating-point division by
760 * zero is not trapped correctly. Also, assertions for si_code in
761 * ptrace_signal_wait.h are commented out. Clean them up after the
762 * bug is fixed.
763 */
764 volatile int a, b;
765 #else
766 volatile double a, b;
767 #endif
768
769 a = getpid();
770 b = atoi("0");
771
772 #ifdef __HAVE_FENV
773 feenableexcept(FE_ALL_EXCEPT);
774 #endif
775
776 /* Division by zero causes CPU trap, translated to SIGFPE */
777 ignore_result = (int)(a / b);
778 }
779
780 static void __used
781 trigger_bus(void)
782 {
783 FILE *fp;
784 char *p;
785
786 /* Open an empty file for writing. */
787 fp = tmpfile();
788 FORKEE_ASSERT_NEQ((uintptr_t)fp, (uintptr_t)NULL);
789
790 /*
791 * Map an empty file with mmap(2) to a pointer.
792 *
793 * PROT_READ handles read-modify-write sequences emitted for
794 * certain combinations of CPUs and compilers (e.g. Alpha AXP).
795 */
796 p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
797 FORKEE_ASSERT_NEQ((uintptr_t)p, (uintptr_t)MAP_FAILED);
798
799 /* Invalid memory access causes CPU trap, translated to SIGBUS */
800 *p = 'a';
801 }
802
803 struct lwp_event_count {
804 lwpid_t lec_lwp;
805 int lec_count;
806 };
807
808 static int * __used
809 find_event_count(struct lwp_event_count list[], lwpid_t lwp, size_t max_lwps)
810 {
811 size_t i;
812
813 for (i = 0; i < max_lwps; i++) {
814 if (list[i].lec_lwp == 0)
815 list[i].lec_lwp = lwp;
816 if (list[i].lec_lwp == lwp)
817 return &list[i].lec_count;
818 }
819
820 atf_tc_fail("More LWPs reported than expected");
821 }
822
823 #define FIND_EVENT_COUNT(list, lwp) \
824 find_event_count(list, lwp, __arraycount(list))
825
826 #if defined(TWAIT_HAVE_PID)
827 #define ATF_TP_ADD_TC_HAVE_PID(a,b) ATF_TP_ADD_TC(a,b)
828 #else
829 #define ATF_TP_ADD_TC_HAVE_PID(a,b)
830 #endif
831
832 #if defined(TWAIT_HAVE_STATUS)
833 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b) ATF_TP_ADD_TC(a,b)
834 #else
835 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b)
836 #endif
837
838 #if defined(TWAIT_HAVE_STATUS) && (defined(__i386__) || defined(__x86_64__))
839 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b) ATF_TP_ADD_TC(a,b)
840 #else
841 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b)
842 #endif
843
844 #if defined(HAVE_GPREGS)
845 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b) ATF_TP_ADD_TC(a,b)
846 #else
847 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b)
848 #endif
849
850 #if defined(HAVE_FPREGS)
851 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b) ATF_TP_ADD_TC(a,b)
852 #else
853 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b)
854 #endif
855
856 #if defined(HAVE_DBREGS)
857 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b) ATF_TP_ADD_TC(a,b)
858 #else
859 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b)
860 #endif
861
862 #if defined(PT_STEP)
863 #define ATF_TP_ADD_TC_PT_STEP(a,b) ATF_TP_ADD_TC(a,b)
864 #else
865 #define ATF_TP_ADD_TC_PT_STEP(a,b)
866 #endif
867