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