xref: /netbsd-src/tests/lib/libc/sys/t_ptrace_amd64_wait.h (revision f3cfa6f6ce31685c6c4a758bc430e69eb99f50a4)
1 /*	$NetBSD: t_ptrace_amd64_wait.h,v 1.10 2019/05/10 16:24:35 mgorny 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 #if defined(__x86_64__)
30 
31 /// ----------------------------------------------------------------------------
32 
33 ATF_TC(x86_64_regs1);
34 ATF_TC_HEAD(x86_64_regs1, tc)
35 {
36 	atf_tc_set_md_var(tc, "descr",
37 	    "Call PT_GETREGS and iterate over General Purpose registers");
38 }
39 
40 ATF_TC_BODY(x86_64_regs1, tc)
41 {
42 	const int exitval = 5;
43 	const int sigval = SIGSTOP;
44 	pid_t child, wpid;
45 #if defined(TWAIT_HAVE_STATUS)
46 	int status;
47 #endif
48 	struct reg r;
49 
50 	DPRINTF("Before forking process PID=%d\n", getpid());
51 	SYSCALL_REQUIRE((child = fork()) != -1);
52 	if (child == 0) {
53 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55 
56 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57 		FORKEE_ASSERT(raise(sigval) == 0);
58 
59 		DPRINTF("Before exiting of the child process\n");
60 		_exit(exitval);
61 	}
62 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63 
64 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66 
67 	validate_status_stopped(status, sigval);
68 
69 	DPRINTF("Call GETREGS for the child process\n");
70 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
71 
72 	DPRINTF("RAX=%#" PRIxREGISTER "\n", r.regs[_REG_RAX]);
73 	DPRINTF("RBX=%#" PRIxREGISTER "\n", r.regs[_REG_RBX]);
74 	DPRINTF("RCX=%#" PRIxREGISTER "\n", r.regs[_REG_RCX]);
75 	DPRINTF("RDX=%#" PRIxREGISTER "\n", r.regs[_REG_RDX]);
76 
77 	DPRINTF("RDI=%#" PRIxREGISTER "\n", r.regs[_REG_RDI]);
78 	DPRINTF("RSI=%#" PRIxREGISTER "\n", r.regs[_REG_RSI]);
79 
80 	DPRINTF("GS=%#" PRIxREGISTER "\n", r.regs[_REG_GS]);
81 	DPRINTF("FS=%#" PRIxREGISTER "\n", r.regs[_REG_FS]);
82 	DPRINTF("ES=%#" PRIxREGISTER "\n", r.regs[_REG_ES]);
83 	DPRINTF("DS=%#" PRIxREGISTER "\n", r.regs[_REG_DS]);
84 	DPRINTF("CS=%#" PRIxREGISTER "\n", r.regs[_REG_CS]);
85 	DPRINTF("SS=%#" PRIxREGISTER "\n", r.regs[_REG_SS]);
86 
87 	DPRINTF("RSP=%#" PRIxREGISTER "\n", r.regs[_REG_RSP]);
88 	DPRINTF("RIP=%#" PRIxREGISTER "\n", r.regs[_REG_RIP]);
89 
90 	DPRINTF("RFLAGS=%#" PRIxREGISTER "\n", r.regs[_REG_RFLAGS]);
91 
92 	DPRINTF("R8=%#" PRIxREGISTER "\n", r.regs[_REG_R8]);
93 	DPRINTF("R9=%#" PRIxREGISTER "\n", r.regs[_REG_R9]);
94 	DPRINTF("R10=%#" PRIxREGISTER "\n", r.regs[_REG_R10]);
95 	DPRINTF("R11=%#" PRIxREGISTER "\n", r.regs[_REG_R11]);
96 	DPRINTF("R12=%#" PRIxREGISTER "\n", r.regs[_REG_R12]);
97 	DPRINTF("R13=%#" PRIxREGISTER "\n", r.regs[_REG_R13]);
98 	DPRINTF("R14=%#" PRIxREGISTER "\n", r.regs[_REG_R14]);
99 	DPRINTF("R15=%#" PRIxREGISTER "\n", r.regs[_REG_R15]);
100 
101 	DPRINTF("Before resuming the child process where it left off and "
102 	    "without signal to be sent\n");
103 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
104 
105 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
106 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
107 
108 	validate_status_exited(status, exitval);
109 
110 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
111 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
112 }
113 
114 ATF_TC(x86_64_regs_gp_read);
115 ATF_TC_HEAD(x86_64_regs_gp_read, tc)
116 {
117 	atf_tc_set_md_var(tc, "descr",
118 		"Set general-purpose reg values from debugged program and read "
119 		"them via PT_GETREGS, comparing values against expected.");
120 }
121 
122 ATF_TC_BODY(x86_64_regs_gp_read, tc)
123 {
124 	const int exitval = 5;
125 	pid_t child, wpid;
126 #if defined(TWAIT_HAVE_STATUS)
127 	const int sigval = SIGTRAP;
128 	int status;
129 #endif
130 	struct reg gpr;
131 
132 	const uint64_t rax = 0x0001020304050607;
133 	const uint64_t rbx = 0x1011121314151617;
134 	const uint64_t rcx = 0x2021222324252627;
135 	const uint64_t rdx = 0x3031323334353637;
136 	const uint64_t rsi = 0x4041424344454647;
137 	const uint64_t rdi = 0x5051525354555657;
138 	const uint64_t rsp = 0x6061626364656667;
139 	const uint64_t rbp = 0x7071727374757677;
140 
141 	DPRINTF("Before forking process PID=%d\n", getpid());
142 	SYSCALL_REQUIRE((child = fork()) != -1);
143 	if (child == 0) {
144 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
145 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
146 
147 		DPRINTF("Before running assembly from child\n");
148 
149 		__asm__ __volatile__(
150 			/* rbp & rbp are a bit tricky, we must not clobber them */
151 			"movq    %%rsp, %%r8\n\t"
152 			"movq    %%rbp, %%r9\n\t"
153 			"movq    %6, %%rsp\n\t"
154 			"movq    %7, %%rbp\n\t"
155 			"\n\t"
156 			"int3\n\t"
157 			"\n\t"
158 			"movq    %%r8, %%rsp\n\t"
159 			"movq    %%r9, %%rbp\n\t"
160 			:
161 			: "a"(rax), "b"(rbx), "c"(rcx), "d"(rdx), "S"(rsi), "D"(rdi),
162 			  "i"(rsp), "i"(rbp)
163 			: "%r8", "%r9"
164 		);
165 
166 		DPRINTF("Before exiting of the child process\n");
167 		_exit(exitval);
168 	}
169 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
170 
171 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
172 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
173 
174 	validate_status_stopped(status, sigval);
175 
176 	DPRINTF("Call GETREGS for the child process\n");
177 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
178 
179 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RAX], rax);
180 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBX], rbx);
181 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RCX], rcx);
182 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDX], rdx);
183 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSI], rsi);
184 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDI], rdi);
185 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSP], rsp);
186 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBP], rbp);
187 
188 	DPRINTF("Before resuming the child process where it left off and "
189 	    "without signal to be sent\n");
190 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
191 
192 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
193 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
194 
195 	validate_status_exited(status, exitval);
196 
197 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
198 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
199 }
200 
201 ATF_TC(x86_64_regs_gp_write);
202 ATF_TC_HEAD(x86_64_regs_gp_write, tc)
203 {
204 	atf_tc_set_md_var(tc, "descr",
205 		"Set general-purpose reg values into a debugged program via "
206 		"PT_SETREGS and compare the result against expected.");
207 }
208 
209 ATF_TC_BODY(x86_64_regs_gp_write, tc)
210 {
211 	const int exitval = 5;
212 	pid_t child, wpid;
213 #if defined(TWAIT_HAVE_STATUS)
214 	const int sigval = SIGTRAP;
215 	int status;
216 #endif
217 	struct reg gpr;
218 
219 	const uint64_t rax = 0x0001020304050607;
220 	const uint64_t rbx = 0x1011121314151617;
221 	const uint64_t rcx = 0x2021222324252627;
222 	const uint64_t rdx = 0x3031323334353637;
223 	const uint64_t rsi = 0x4041424344454647;
224 	const uint64_t rdi = 0x5051525354555657;
225 	const uint64_t rsp = 0x6061626364656667;
226 	const uint64_t rbp = 0x7071727374757677;
227 
228 	DPRINTF("Before forking process PID=%d\n", getpid());
229 	SYSCALL_REQUIRE((child = fork()) != -1);
230 	if (child == 0) {
231 		const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
232 		uint64_t v_rax, v_rbx, v_rcx, v_rdx, v_rsi, v_rdi, v_rsp, v_rbp;
233 
234 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
235 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
236 
237 		DPRINTF("Before running assembly from child\n");
238 
239 		__asm__ __volatile__(
240 			/* save rsp & rbp */
241 			"movq    %%rsp, %4\n\t"
242 			"movq    %%rbp, %5\n\t"
243 			"\n\t"
244 			/* fill registers with clobber pattern */
245 			"movq    %8, %%rax\n\t"
246 			"movq    %8, %%rbx\n\t"
247 			"movq    %8, %%rcx\n\t"
248 			"movq    %8, %%rdx\n\t"
249 			"movq    %8, %%rsp\n\t"
250 			"movq    %8, %%rbp\n\t"
251 			"movq    %8, %%rsi\n\t"
252 			"movq    %8, %%rdi\n\t"
253 			"\n\t"
254 			"int3\n\t"
255 			"\n\t"
256 			/* swap saved & current rsp & rbp */
257 			"xchgq    %%rsp, %4\n\t"
258 			"xchgq    %%rbp, %5\n\t"
259 			: "=a"(v_rax), "=b"(v_rbx), "=c"(v_rcx), "=d"(v_rdx), "=r"(v_rsp),
260 			"=r"(v_rbp), "=S"(v_rsi), "=D"(v_rdi)
261 			: "g"(fill)
262 			:
263 		);
264 
265 		FORKEE_ASSERT_EQ(v_rax, rax);
266 		FORKEE_ASSERT_EQ(v_rbx, rbx);
267 		FORKEE_ASSERT_EQ(v_rcx, rcx);
268 		FORKEE_ASSERT_EQ(v_rdx, rdx);
269 		FORKEE_ASSERT_EQ(v_rsi, rsi);
270 		FORKEE_ASSERT_EQ(v_rdi, rdi);
271 		FORKEE_ASSERT_EQ(v_rsp, rsp);
272 		FORKEE_ASSERT_EQ(v_rbp, rbp);
273 
274 		DPRINTF("Before exiting of the child process\n");
275 		_exit(exitval);
276 	}
277 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
278 
279 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
280 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
281 
282 	validate_status_stopped(status, sigval);
283 
284 	DPRINTF("Call GETREGS for the child process\n");
285 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
286 
287 	gpr.regs[_REG_RAX] = rax;
288 	gpr.regs[_REG_RBX] = rbx;
289 	gpr.regs[_REG_RCX] = rcx;
290 	gpr.regs[_REG_RDX] = rdx;
291 	gpr.regs[_REG_RSI] = rsi;
292 	gpr.regs[_REG_RDI] = rdi;
293 	gpr.regs[_REG_RSP] = rsp;
294 	gpr.regs[_REG_RBP] = rbp;
295 
296 	DPRINTF("Call SETREGS for the child process\n");
297 	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
298 
299 	DPRINTF("Before resuming the child process where it left off and "
300 	    "without signal to be sent\n");
301 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
302 
303 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
304 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
305 
306 	validate_status_exited(status, exitval);
307 
308 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
309 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
310 }
311 
312 ATF_TC(x86_64_regs_r8_read);
313 ATF_TC_HEAD(x86_64_regs_r8_read, tc)
314 {
315 	atf_tc_set_md_var(tc, "descr",
316 		"Set r8..r15 reg values from debugged program and read "
317 		"them via PT_GETREGS, comparing values against expected.");
318 }
319 
320 ATF_TC_BODY(x86_64_regs_r8_read, tc)
321 {
322 	const int exitval = 5;
323 	pid_t child, wpid;
324 #if defined(TWAIT_HAVE_STATUS)
325 	const int sigval = SIGTRAP;
326 	int status;
327 #endif
328 	struct reg gpr;
329 
330 	const uint64_t r8[] = {
331 		0x0001020304050607,
332 		0x1011121314151617,
333 		0x2021222324252627,
334 		0x3031323334353637,
335 		0x4041424344454647,
336 		0x5051525354555657,
337 		0x6061626364656667,
338 		0x7071727374757677,
339 	};
340 
341 	DPRINTF("Before forking process PID=%d\n", getpid());
342 	SYSCALL_REQUIRE((child = fork()) != -1);
343 	if (child == 0) {
344 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
345 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
346 
347 		DPRINTF("Before running assembly from child\n");
348 
349 		__asm__ __volatile__(
350 			"movq    0x00(%%rbx), %%r8\n\t"
351 			"movq    0x08(%%rbx), %%r9\n\t"
352 			"movq    0x10(%%rbx), %%r10\n\t"
353 			"movq    0x18(%%rbx), %%r11\n\t"
354 			"movq    0x20(%%rbx), %%r12\n\t"
355 			"movq    0x28(%%rbx), %%r13\n\t"
356 			"movq    0x30(%%rbx), %%r14\n\t"
357 			"movq    0x38(%%rbx), %%r15\n\t"
358 			"int3\n\t"
359 			:
360 			: "b"(r8)
361 			: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
362 		);
363 
364 		DPRINTF("Before exiting of the child process\n");
365 		_exit(exitval);
366 	}
367 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
368 
369 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
370 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
371 
372 	validate_status_stopped(status, sigval);
373 
374 	DPRINTF("Call GETREGS for the child process\n");
375 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
376 
377 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R8], r8[0]);
378 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R9], r8[1]);
379 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R10], r8[2]);
380 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R11], r8[3]);
381 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R12], r8[4]);
382 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R13], r8[5]);
383 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R14], r8[6]);
384 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R15], r8[7]);
385 
386 	DPRINTF("Before resuming the child process where it left off and "
387 	    "without signal to be sent\n");
388 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
389 
390 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
391 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
392 
393 	validate_status_exited(status, exitval);
394 
395 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
396 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
397 }
398 
399 ATF_TC(x86_64_regs_r8_write);
400 ATF_TC_HEAD(x86_64_regs_r8_write, tc)
401 {
402 	atf_tc_set_md_var(tc, "descr",
403 		"Set r8..r15 reg values into a debugged program via "
404 		"PT_SETREGS and compare the result against expected.");
405 }
406 
407 ATF_TC_BODY(x86_64_regs_r8_write, tc)
408 {
409 	const int exitval = 5;
410 	pid_t child, wpid;
411 #if defined(TWAIT_HAVE_STATUS)
412 	const int sigval = SIGTRAP;
413 	int status;
414 #endif
415 	struct reg gpr;
416 
417 	const uint64_t r8[] = {
418 		0x0001020304050607,
419 		0x1011121314151617,
420 		0x2021222324252627,
421 		0x3031323334353637,
422 		0x4041424344454647,
423 		0x5051525354555657,
424 		0x6061626364656667,
425 		0x7071727374757677,
426 	};
427 
428 	DPRINTF("Before forking process PID=%d\n", getpid());
429 	SYSCALL_REQUIRE((child = fork()) != -1);
430 	if (child == 0) {
431 		const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
432 		uint64_t v_r8[8];
433 
434 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
435 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
436 
437 		DPRINTF("Before running assembly from child\n");
438 
439 		__asm__ __volatile__(
440 			/* fill registers with clobber pattern */
441 			"movq    %1, %%r8\n\t"
442 			"movq    %1, %%r9\n\t"
443 			"movq    %1, %%r10\n\t"
444 			"movq    %1, %%r11\n\t"
445 			"movq    %1, %%r12\n\t"
446 			"movq    %1, %%r13\n\t"
447 			"movq    %1, %%r14\n\t"
448 			"movq    %1, %%r15\n\t"
449 			"\n\t"
450 			"int3\n\t"
451 			"\n\t"
452 			"movq    %%r8, 0x00(%0)\n\t"
453 			"movq    %%r9, 0x08(%0)\n\t"
454 			"movq    %%r10, 0x10(%0)\n\t"
455 			"movq    %%r11, 0x18(%0)\n\t"
456 			"movq    %%r12, 0x20(%0)\n\t"
457 			"movq    %%r13, 0x28(%0)\n\t"
458 			"movq    %%r14, 0x30(%0)\n\t"
459 			"movq    %%r15, 0x38(%0)\n\t"
460 			:
461 			: "a"(v_r8), "m"(fill)
462 			: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
463 		);
464 
465 		FORKEE_ASSERT_EQ(v_r8[0], r8[0]);
466 		FORKEE_ASSERT_EQ(v_r8[1], r8[1]);
467 		FORKEE_ASSERT_EQ(v_r8[2], r8[2]);
468 		FORKEE_ASSERT_EQ(v_r8[3], r8[3]);
469 		FORKEE_ASSERT_EQ(v_r8[4], r8[4]);
470 		FORKEE_ASSERT_EQ(v_r8[5], r8[5]);
471 		FORKEE_ASSERT_EQ(v_r8[6], r8[6]);
472 		FORKEE_ASSERT_EQ(v_r8[7], r8[7]);
473 
474 		DPRINTF("Before exiting of the child process\n");
475 		_exit(exitval);
476 	}
477 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
478 
479 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
480 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
481 
482 	validate_status_stopped(status, sigval);
483 
484 	DPRINTF("Call GETREGS for the child process\n");
485 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
486 
487 	gpr.regs[_REG_R8] = r8[0];
488 	gpr.regs[_REG_R9] = r8[1];
489 	gpr.regs[_REG_R10] = r8[2];
490 	gpr.regs[_REG_R11] = r8[3];
491 	gpr.regs[_REG_R12] = r8[4];
492 	gpr.regs[_REG_R13] = r8[5];
493 	gpr.regs[_REG_R14] = r8[6];
494 	gpr.regs[_REG_R15] = r8[7];
495 
496 	DPRINTF("Call SETREGS for the child process\n");
497 	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
498 
499 	DPRINTF("Before resuming the child process where it left off and "
500 	    "without signal to be sent\n");
501 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
502 
503 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
504 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
505 
506 	validate_status_exited(status, exitval);
507 
508 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
509 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
510 }
511 
512 /// ----------------------------------------------------------------------------
513 
514 
515 #define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64() \
516 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs1); \
517 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_read); \
518 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_write); \
519 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_read); \
520 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_write);
521 #else
522 #define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64()
523 #endif
524