t_ptrace_wait.h revision 1.42 1 /* $NetBSD: t_ptrace_wait.h,v 1.42 2025/05/09 01:32:25 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) == 15)
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 errx(EXIT_FAILURE, "%s:%d %s(): failed", \
230 __FILE__, __LINE__, __func__); \
231 } while (/*CONSTCOND*/0)
232
233 #define FORKEE_ASSERTX(x) \
234 do { \
235 int ret = (x); \
236 if (!ret) \
237 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
238 __FILE__, __LINE__, __func__, #x); \
239 } while (/*CONSTCOND*/0)
240
241 #define FORKEE_ASSERT(x) \
242 do { \
243 int ret = (x); \
244 if (!ret) \
245 err(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
246 __FILE__, __LINE__, __func__, #x); \
247 } while (/*CONSTCOND*/0)
248
249 #define FORKEE_PTHREAD(x) \
250 do { \
251 int _forkee_pthread_error = (x); \
252 if (_forkee_pthread_error) { \
253 errno = _forkee_pthread_error; \
254 err(EXIT_FAILURE, "%s:%d %s(): %s", __FILE__, __LINE__, \
255 __func__, #x); \
256 } \
257 } while (/*CONSTCOND*/0)
258
259 /*
260 * Simplify logic for functions using general purpose registers add HAVE_GPREGS
261 *
262 * For platforms that do not implement all needed calls for simplicity assume
263 * that they are unsupported at all.
264 */
265 #if defined(PT_GETREGS) \
266 && defined(PT_SETREGS) \
267 && defined(PTRACE_REG_PC) \
268 && defined(PTRACE_REG_SET_PC) \
269 && defined(PTRACE_REG_SP) \
270 && defined(PTRACE_REG_INTRV)
271 #define HAVE_GPREGS
272 #endif
273
274 /* Add guards for floating point registers */
275 #if defined(PT_GETFPREGS) \
276 && defined(PT_SETFPREGS)
277 #define HAVE_FPREGS
278 #endif
279
280 /* Add guards for cpu debug registers */
281 #if defined(PT_GETDBREGS) \
282 && defined(PT_SETDBREGS)
283 #define HAVE_DBREGS
284 #endif
285
286 /*
287 * If waitid(2) returns because one or more processes have a state change to
288 * report, 0 is returned. If an error is detected, a value of -1 is returned
289 * and errno is set to indicate the error. If WNOHANG is specified and there
290 * are no stopped, continued or exited children, 0 is returned.
291 */
292 #if defined(TWAIT_WAITID)
293 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), 0)
294 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1)
295 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, 0)
296 #define FORKEE_REQUIRE_FAILURE(a,b) \
297 FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
298 #else
299 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), (b))
300 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1)
301 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, b)
302 #define FORKEE_REQUIRE_FAILURE(a,b) \
303 FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
304 #endif
305
306 /*
307 * Helper tools to verify whether status reports exited value
308 */
309 #if TWAIT_HAVE_STATUS
310 static void __used
311 validate_status_exited(int status, int expected)
312 {
313 ATF_REQUIRE_MSG(WIFEXITED(status), "Reported !exited process");
314 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
315 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
316 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
317
318 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(status), expected,
319 "The process has exited with invalid value %d != %d",
320 WEXITSTATUS(status), expected);
321 }
322
323 static void __used
324 forkee_status_exited(int status, int expected)
325 {
326 FORKEE_ASSERTX(WIFEXITED(status));
327 FORKEE_ASSERTX(!WIFCONTINUED(status));
328 FORKEE_ASSERTX(!WIFSIGNALED(status));
329 FORKEE_ASSERTX(!WIFSTOPPED(status));
330
331 FORKEE_ASSERT_EQ(WEXITSTATUS(status), expected);
332 }
333
334 static void __used
335 validate_status_continued(int status)
336 {
337 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
338 ATF_REQUIRE_MSG(WIFCONTINUED(status), "Reported !continued process");
339 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
340 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
341 }
342
343 static void __used
344 forkee_status_continued(int status)
345 {
346 FORKEE_ASSERTX(!WIFEXITED(status));
347 FORKEE_ASSERTX(WIFCONTINUED(status));
348 FORKEE_ASSERTX(!WIFSIGNALED(status));
349 FORKEE_ASSERTX(!WIFSTOPPED(status));
350 }
351
352 static void __used
353 validate_status_signaled(int status, int expected_termsig, int expected_core)
354 {
355 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
356 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
357 ATF_REQUIRE_MSG(WIFSIGNALED(status), "Reported !signaled process");
358 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
359
360 ATF_REQUIRE_EQ_MSG(WTERMSIG(status), expected_termsig,
361 "Unexpected signal received");
362
363 ATF_REQUIRE_EQ_MSG(!!WCOREDUMP(status), expected_core,
364 "Unexpectedly core file %s generated", expected_core ? "not" : "");
365 }
366
367 static void __used
368 forkee_status_signaled(int status, int expected_termsig, int expected_core)
369 {
370 FORKEE_ASSERTX(!WIFEXITED(status));
371 FORKEE_ASSERTX(!WIFCONTINUED(status));
372 FORKEE_ASSERTX(WIFSIGNALED(status));
373 FORKEE_ASSERTX(!WIFSTOPPED(status));
374
375 FORKEE_ASSERT_EQ(WTERMSIG(status), expected_termsig);
376 FORKEE_ASSERT_EQ(!!WCOREDUMP(status), expected_core);
377 }
378
379 static void __used
380 validate_status_stopped(int status, int expected)
381 {
382 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
383 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
384 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
385 ATF_REQUIRE_MSG(WIFSTOPPED(status), "Reported !stopped process");
386
387 char st[128], ex[128];
388 strlcpy(st, strsignal(WSTOPSIG(status)), sizeof(st));
389 strlcpy(ex, strsignal(expected), sizeof(ex));
390
391 ATF_REQUIRE_EQ_MSG(WSTOPSIG(status), expected,
392 "Unexpected stop signal received [%s] != [%s]", st, ex);
393 }
394
395 static void __used
396 forkee_status_stopped(int status, int expected)
397 {
398 FORKEE_ASSERTX(!WIFEXITED(status));
399 FORKEE_ASSERTX(!WIFCONTINUED(status));
400 FORKEE_ASSERTX(!WIFSIGNALED(status));
401 FORKEE_ASSERTX(WIFSTOPPED(status));
402
403 FORKEE_ASSERT_EQ(WSTOPSIG(status), expected);
404 }
405 #else
406 #define validate_status_exited(a,b)
407 #define forkee_status_exited(a,b)
408 #define validate_status_continued(a,b)
409 #define forkee_status_continued(a,b)
410 #define validate_status_signaled(a,b,c)
411 #define forkee_status_signaled(a,b,c)
412 #define validate_status_stopped(a,b)
413 #define forkee_status_stopped(a,b)
414 #endif
415
416 /* This function is currently designed to be run in the main/parent process */
417 static void __used
418 await_zombie_raw(pid_t process, useconds_t ms)
419 {
420 struct kinfo_proc2 p;
421 size_t len = sizeof(p);
422
423 const int name[] = {
424 [0] = CTL_KERN,
425 [1] = KERN_PROC2,
426 [2] = KERN_PROC_PID,
427 [3] = process,
428 [4] = sizeof(p),
429 [5] = 1
430 };
431
432 const size_t namelen = __arraycount(name);
433
434 /* Await the process becoming a zombie */
435 while(1) {
436 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
437
438 if (p.p_stat == LSZOMB)
439 break;
440
441 if (ms > 0) {
442 ATF_REQUIRE(usleep(ms) == 0);
443 }
444 }
445 }
446
447 static void __used
448 await_zombie(pid_t process)
449 {
450
451 await_zombie_raw(process, 1000);
452 }
453
454 static void __used
455 await_stopped(pid_t process)
456 {
457 struct kinfo_proc2 p;
458 size_t len = sizeof(p);
459
460 const int name[] = {
461 [0] = CTL_KERN,
462 [1] = KERN_PROC2,
463 [2] = KERN_PROC_PID,
464 [3] = process,
465 [4] = sizeof(p),
466 [5] = 1
467 };
468
469 const size_t namelen = __arraycount(name);
470
471 /* Await the process becoming a zombie */
472 while(1) {
473 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
474
475 if (p.p_stat == LSSTOP)
476 break;
477
478 ATF_REQUIRE(usleep(1000) == 0);
479 }
480 }
481
482 static pid_t __used
483 await_stopped_child(pid_t process)
484 {
485 struct kinfo_proc2 *p = NULL;
486 size_t i, len;
487 pid_t child = -1;
488
489 int name[] = {
490 [0] = CTL_KERN,
491 [1] = KERN_PROC2,
492 [2] = KERN_PROC_ALL,
493 [3] = 0,
494 [4] = sizeof(struct kinfo_proc2),
495 [5] = 0
496 };
497
498 const size_t namelen = __arraycount(name);
499
500 /* Await the process becoming a zombie */
501 while(1) {
502 name[5] = 0;
503
504 FORKEE_ASSERT_EQ(sysctl(name, namelen, 0, &len, NULL, 0), 0);
505
506 FORKEE_ASSERT_EQ(reallocarr(&p,
507 len,
508 sizeof(struct kinfo_proc2)), 0);
509
510 name[5] = len;
511
512 FORKEE_ASSERT_EQ(sysctl(name, namelen, p, &len, NULL, 0), 0);
513
514 for (i = 0; i < len/sizeof(struct kinfo_proc2); i++) {
515 if (p[i].p_pid == getpid())
516 continue;
517 if (p[i].p_ppid != process)
518 continue;
519 if (p[i].p_stat != LSSTOP)
520 continue;
521 child = p[i].p_pid;
522 break;
523 }
524
525 if (child != -1)
526 break;
527
528 FORKEE_ASSERT_EQ(usleep(1000), 0);
529 }
530
531 /* Free the buffer */
532 FORKEE_ASSERT_EQ(reallocarr(&p, 0, sizeof(struct kinfo_proc2)), 0);
533
534 return child;
535 }
536
537 static void __used
538 await_collected(pid_t process)
539 {
540 struct kinfo_proc2 p;
541 size_t len = sizeof(p);
542
543 const int name[] = {
544 [0] = CTL_KERN,
545 [1] = KERN_PROC2,
546 [2] = KERN_PROC_PID,
547 [3] = process,
548 [4] = sizeof(p),
549 [5] = 1
550 };
551
552 const size_t namelen = __arraycount(name);
553
554 /* Await the process to disappear */
555 while(1) {
556 FORKEE_ASSERT_EQ(sysctl(name, namelen, &p, &len, NULL, 0), 0);
557 if (len == 0)
558 break;
559
560 ATF_REQUIRE(usleep(1000) == 0);
561 }
562 }
563
564 /* Happy number sequence -- this function is used to just consume cpu cycles */
565 #define HAPPY_NUMBER 1
566
567 /* If n is not happy then its sequence ends in the cycle:
568 * 4, 16, 37, 58, 89, 145, 42, 20, 4, ... */
569 #define SAD_NUMBER 4
570
571 /* Calculate the sum of the squares of the digits of n */
572 static unsigned __used
573 dsum(unsigned n)
574 {
575 unsigned sum, x;
576 for (sum = 0; n; n /= 10) {
577 x = n % 10;
578 sum += x * x;
579 }
580 return sum;
581 }
582
583 /*
584 * XXX: Disabled optimization is required to make tests for hardware assisted
585 * traps in .text functional
586 *
587 * Tested with GCC 5.4 on NetBSD 7.99.47 amd64
588 */
589 static int __used
590 #ifdef __clang__
591 __attribute__((__optnone__))
592 #else
593 __attribute__((__optimize__("O0")))
594 #endif
595 check_happy(unsigned n)
596 {
597 for (;;) {
598 unsigned total = dsum(n);
599
600 if (total == HAPPY_NUMBER)
601 return 1;
602 if (total == SAD_NUMBER)
603 return 0;
604
605 n = total;
606 }
607 }
608
609 static void * __used
610 infinite_thread(void *arg __unused)
611 {
612
613 while (true)
614 continue;
615
616 __unreachable();
617 }
618
619 static int __used
620 clone_func(void *arg)
621 {
622 int ret;
623
624 ret = (int)(intptr_t)arg;
625
626 return ret;
627 }
628
629 #if defined(HAVE_DBREGS)
630 static bool __used
631 can_we_set_dbregs(void)
632 {
633 static long euid = -1;
634 static int user_set_dbregs = -1;
635 size_t user_set_dbregs_len = sizeof(user_set_dbregs);
636
637 if (euid == -1)
638 euid = geteuid();
639
640 if (euid == 0)
641 return true;
642
643 if (user_set_dbregs == -1) {
644 if (sysctlbyname("security.models.extensions.user_set_dbregs",
645 &user_set_dbregs, &user_set_dbregs_len, NULL, 0)
646 == -1) {
647 return false;
648 }
649 }
650
651 if (user_set_dbregs > 0)
652 return true;
653 else
654 return false;
655 }
656 #endif
657
658 static bool __used
659 get_user_va0_disable(void)
660 {
661 static int user_va0_disable = -1;
662 size_t user_va0_disable_len = sizeof(user_va0_disable);
663
664 if (user_va0_disable == -1) {
665 if (sysctlbyname("vm.user_va0_disable",
666 &user_va0_disable, &user_va0_disable_len, NULL, 0)
667 == -1) {
668 return true;
669 }
670 }
671
672 if (user_va0_disable > 0)
673 return true;
674 else
675 return false;
676 }
677
678 static bool __used
679 can_we_write_to_text(pid_t pid)
680 {
681 int mib[3];
682 int paxflags;
683 size_t len = sizeof(int);
684
685 mib[0] = CTL_PROC;
686 mib[1] = pid;
687 mib[2] = PROC_PID_PAXFLAGS;
688
689 if (sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)
690 return false;
691
692 return !(paxflags & CTL_PROC_PAXFLAGS_MPROTECT);
693 }
694
695 static void __used
696 trigger_trap(void)
697 {
698
699 /* Software breakpoint causes CPU trap, translated to SIGTRAP */
700 #ifdef PTRACE_BREAKPOINT_ASM
701 PTRACE_BREAKPOINT_ASM;
702 #else
703 /* port me */
704 #endif
705 }
706
707 static void __used
708 trigger_segv(void)
709 {
710 static volatile char *ptr = NULL;
711
712 /* Access to unmapped memory causes CPU trap, translated to SIGSEGV */
713 *ptr = 1;
714 }
715
716 static void __used
717 trigger_ill(void)
718 {
719
720 /* Illegal instruction causes CPU trap, translated to SIGILL */
721 #ifdef PTRACE_ILLEGAL_ASM
722 #ifndef __mips__ /* To avoid GXemul crash */
723 PTRACE_ILLEGAL_ASM;
724 #endif
725 #else
726 /* port me */
727 #endif
728 }
729
730 #include <fenv.h>
731
732 #if (__arm__ && !__SOFTFP__) || __aarch64__
733 #include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
734
735 static bool __used
736 are_fpu_exceptions_supported(void)
737 {
738 /*
739 * Some NEON fpus do not trap on IEEE 754 FP exceptions.
740 * Skip these tests if running on them and compiled for
741 * hard float.
742 */
743 if (0 == fpsetmask(fpsetmask(FP_X_INV)))
744 return false;
745 return true;
746 }
747 #elif defined __riscv__
748 #define are_fpu_exceptions_supported() 0
749 #else
750 #define are_fpu_exceptions_supported() 1
751 #endif
752
753 volatile double ignore_result;
754
755 static void __used
756 trigger_fpe(void)
757 {
758 #if __i386__ || __x86_64__
759 /*
760 * XXX
761 * Hack for QEMU bug #1668041, by which floating-point division by
762 * zero is not trapped correctly. Also, assertions for si_code in
763 * ptrace_signal_wait.h are commented out. Clean them up after the
764 * bug is fixed.
765 */
766 volatile int a, b;
767 #else
768 volatile double a, b;
769 #endif
770
771 a = getpid();
772 b = atoi("0");
773
774 #ifdef __HAVE_FENV
775 feenableexcept(FE_ALL_EXCEPT);
776 #endif
777
778 /* Division by zero causes CPU trap, translated to SIGFPE */
779 ignore_result = (int)(a / b);
780 }
781
782 static void __used
783 trigger_bus(void)
784 {
785 FILE *fp;
786 char *p;
787
788 /* Open an empty file for writing. */
789 fp = tmpfile();
790 FORKEE_ASSERT_NEQ((uintptr_t)fp, (uintptr_t)NULL);
791
792 /*
793 * Map an empty file with mmap(2) to a pointer.
794 *
795 * PROT_READ handles read-modify-write sequences emitted for
796 * certain combinations of CPUs and compilers (e.g. Alpha AXP).
797 */
798 p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
799 FORKEE_ASSERT_NEQ((uintptr_t)p, (uintptr_t)MAP_FAILED);
800
801 /* Invalid memory access causes CPU trap, translated to SIGBUS */
802 *p = 'a';
803 }
804
805 struct lwp_event_count {
806 lwpid_t lec_lwp;
807 int lec_count;
808 };
809
810 static int * __used
811 find_event_count(struct lwp_event_count list[], lwpid_t lwp, size_t max_lwps)
812 {
813 size_t i;
814
815 for (i = 0; i < max_lwps; i++) {
816 if (list[i].lec_lwp == 0)
817 list[i].lec_lwp = lwp;
818 if (list[i].lec_lwp == lwp)
819 return &list[i].lec_count;
820 }
821
822 atf_tc_fail("More LWPs reported than expected");
823 }
824
825 #define FIND_EVENT_COUNT(list, lwp) \
826 find_event_count(list, lwp, __arraycount(list))
827
828 #if defined(TWAIT_HAVE_PID)
829 #define ATF_TP_ADD_TC_HAVE_PID(a,b) ATF_TP_ADD_TC(a,b)
830 #else
831 #define ATF_TP_ADD_TC_HAVE_PID(a,b)
832 #endif
833
834 #if defined(TWAIT_HAVE_STATUS)
835 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b) ATF_TP_ADD_TC(a,b)
836 #else
837 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b)
838 #endif
839
840 #if defined(TWAIT_HAVE_STATUS) && (defined(__i386__) || defined(__x86_64__))
841 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b) ATF_TP_ADD_TC(a,b)
842 #else
843 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b)
844 #endif
845
846 #if defined(HAVE_GPREGS)
847 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b) ATF_TP_ADD_TC(a,b)
848 #else
849 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b)
850 #endif
851
852 #if defined(HAVE_FPREGS)
853 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b) ATF_TP_ADD_TC(a,b)
854 #else
855 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b)
856 #endif
857
858 #if defined(HAVE_DBREGS)
859 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b) ATF_TP_ADD_TC(a,b)
860 #else
861 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b)
862 #endif
863
864 #if defined(PT_STEP)
865 #define ATF_TP_ADD_TC_PT_STEP(a,b) ATF_TP_ADD_TC(a,b)
866 #else
867 #define ATF_TP_ADD_TC_PT_STEP(a,b)
868 #endif
869