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