Home | History | Annotate | Line # | Download | only in sys
t_ptrace_amd64_wait.h revision 1.5.2.1
      1 /*	$NetBSD: t_ptrace_amd64_wait.h,v 1.5.2.1 2019/06/10 22:10:05 christos 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 		DPRINTF("Before comparing results\n");
    266 		FORKEE_ASSERT_EQ(v_rax, rax);
    267 		FORKEE_ASSERT_EQ(v_rbx, rbx);
    268 		FORKEE_ASSERT_EQ(v_rcx, rcx);
    269 		FORKEE_ASSERT_EQ(v_rdx, rdx);
    270 		FORKEE_ASSERT_EQ(v_rsi, rsi);
    271 		FORKEE_ASSERT_EQ(v_rdi, rdi);
    272 		FORKEE_ASSERT_EQ(v_rsp, rsp);
    273 		FORKEE_ASSERT_EQ(v_rbp, rbp);
    274 
    275 		DPRINTF("Before exiting of the child process\n");
    276 		_exit(exitval);
    277 	}
    278 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    279 
    280 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    281 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    282 
    283 	validate_status_stopped(status, sigval);
    284 
    285 	DPRINTF("Call GETREGS for the child process\n");
    286 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
    287 
    288 	gpr.regs[_REG_RAX] = rax;
    289 	gpr.regs[_REG_RBX] = rbx;
    290 	gpr.regs[_REG_RCX] = rcx;
    291 	gpr.regs[_REG_RDX] = rdx;
    292 	gpr.regs[_REG_RSI] = rsi;
    293 	gpr.regs[_REG_RDI] = rdi;
    294 	gpr.regs[_REG_RSP] = rsp;
    295 	gpr.regs[_REG_RBP] = rbp;
    296 
    297 	DPRINTF("Call SETREGS for the child process\n");
    298 	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
    299 
    300 	DPRINTF("Before resuming the child process where it left off and "
    301 	    "without signal to be sent\n");
    302 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    303 
    304 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    305 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    306 
    307 	validate_status_exited(status, exitval);
    308 
    309 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    310 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    311 }
    312 
    313 ATF_TC(x86_64_regs_r8_read);
    314 ATF_TC_HEAD(x86_64_regs_r8_read, tc)
    315 {
    316 	atf_tc_set_md_var(tc, "descr",
    317 		"Set r8..r15 reg values from debugged program and read "
    318 		"them via PT_GETREGS, comparing values against expected.");
    319 }
    320 
    321 ATF_TC_BODY(x86_64_regs_r8_read, tc)
    322 {
    323 	const int exitval = 5;
    324 	pid_t child, wpid;
    325 #if defined(TWAIT_HAVE_STATUS)
    326 	const int sigval = SIGTRAP;
    327 	int status;
    328 #endif
    329 	struct reg gpr;
    330 
    331 	const uint64_t r8[] = {
    332 		0x0001020304050607,
    333 		0x1011121314151617,
    334 		0x2021222324252627,
    335 		0x3031323334353637,
    336 		0x4041424344454647,
    337 		0x5051525354555657,
    338 		0x6061626364656667,
    339 		0x7071727374757677,
    340 	};
    341 
    342 	DPRINTF("Before forking process PID=%d\n", getpid());
    343 	SYSCALL_REQUIRE((child = fork()) != -1);
    344 	if (child == 0) {
    345 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
    346 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
    347 
    348 		DPRINTF("Before running assembly from child\n");
    349 
    350 		__asm__ __volatile__(
    351 			"movq    0x00(%%rbx), %%r8\n\t"
    352 			"movq    0x08(%%rbx), %%r9\n\t"
    353 			"movq    0x10(%%rbx), %%r10\n\t"
    354 			"movq    0x18(%%rbx), %%r11\n\t"
    355 			"movq    0x20(%%rbx), %%r12\n\t"
    356 			"movq    0x28(%%rbx), %%r13\n\t"
    357 			"movq    0x30(%%rbx), %%r14\n\t"
    358 			"movq    0x38(%%rbx), %%r15\n\t"
    359 			"int3\n\t"
    360 			:
    361 			: "b"(r8)
    362 			: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
    363 		);
    364 
    365 		DPRINTF("Before exiting of the child process\n");
    366 		_exit(exitval);
    367 	}
    368 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    369 
    370 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    371 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    372 
    373 	validate_status_stopped(status, sigval);
    374 
    375 	DPRINTF("Call GETREGS for the child process\n");
    376 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
    377 
    378 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R8], r8[0]);
    379 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R9], r8[1]);
    380 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R10], r8[2]);
    381 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R11], r8[3]);
    382 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R12], r8[4]);
    383 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R13], r8[5]);
    384 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R14], r8[6]);
    385 	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R15], r8[7]);
    386 
    387 	DPRINTF("Before resuming the child process where it left off and "
    388 	    "without signal to be sent\n");
    389 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    390 
    391 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    392 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    393 
    394 	validate_status_exited(status, exitval);
    395 
    396 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    397 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    398 }
    399 
    400 ATF_TC(x86_64_regs_r8_write);
    401 ATF_TC_HEAD(x86_64_regs_r8_write, tc)
    402 {
    403 	atf_tc_set_md_var(tc, "descr",
    404 		"Set r8..r15 reg values into a debugged program via "
    405 		"PT_SETREGS and compare the result against expected.");
    406 }
    407 
    408 ATF_TC_BODY(x86_64_regs_r8_write, tc)
    409 {
    410 	const int exitval = 5;
    411 	pid_t child, wpid;
    412 #if defined(TWAIT_HAVE_STATUS)
    413 	const int sigval = SIGTRAP;
    414 	int status;
    415 #endif
    416 	struct reg gpr;
    417 
    418 	const uint64_t r8[] = {
    419 		0x0001020304050607,
    420 		0x1011121314151617,
    421 		0x2021222324252627,
    422 		0x3031323334353637,
    423 		0x4041424344454647,
    424 		0x5051525354555657,
    425 		0x6061626364656667,
    426 		0x7071727374757677,
    427 	};
    428 
    429 	DPRINTF("Before forking process PID=%d\n", getpid());
    430 	SYSCALL_REQUIRE((child = fork()) != -1);
    431 	if (child == 0) {
    432 		const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
    433 		uint64_t v_r8[8];
    434 
    435 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
    436 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
    437 
    438 		DPRINTF("Before running assembly from child\n");
    439 
    440 		__asm__ __volatile__(
    441 			/* fill registers with clobber pattern */
    442 			"movq    %1, %%r8\n\t"
    443 			"movq    %1, %%r9\n\t"
    444 			"movq    %1, %%r10\n\t"
    445 			"movq    %1, %%r11\n\t"
    446 			"movq    %1, %%r12\n\t"
    447 			"movq    %1, %%r13\n\t"
    448 			"movq    %1, %%r14\n\t"
    449 			"movq    %1, %%r15\n\t"
    450 			"\n\t"
    451 			"int3\n\t"
    452 			"\n\t"
    453 			"movq    %%r8, 0x00(%0)\n\t"
    454 			"movq    %%r9, 0x08(%0)\n\t"
    455 			"movq    %%r10, 0x10(%0)\n\t"
    456 			"movq    %%r11, 0x18(%0)\n\t"
    457 			"movq    %%r12, 0x20(%0)\n\t"
    458 			"movq    %%r13, 0x28(%0)\n\t"
    459 			"movq    %%r14, 0x30(%0)\n\t"
    460 			"movq    %%r15, 0x38(%0)\n\t"
    461 			:
    462 			: "a"(v_r8), "m"(fill)
    463 			: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
    464 		);
    465 
    466 		DPRINTF("Before comparing results\n");
    467 		FORKEE_ASSERT_EQ(v_r8[0], r8[0]);
    468 		FORKEE_ASSERT_EQ(v_r8[1], r8[1]);
    469 		FORKEE_ASSERT_EQ(v_r8[2], r8[2]);
    470 		FORKEE_ASSERT_EQ(v_r8[3], r8[3]);
    471 		FORKEE_ASSERT_EQ(v_r8[4], r8[4]);
    472 		FORKEE_ASSERT_EQ(v_r8[5], r8[5]);
    473 		FORKEE_ASSERT_EQ(v_r8[6], r8[6]);
    474 		FORKEE_ASSERT_EQ(v_r8[7], r8[7]);
    475 
    476 		DPRINTF("Before exiting of the child process\n");
    477 		_exit(exitval);
    478 	}
    479 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    480 
    481 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    482 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    483 
    484 	validate_status_stopped(status, sigval);
    485 
    486 	DPRINTF("Call GETREGS for the child process\n");
    487 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
    488 
    489 	gpr.regs[_REG_R8] = r8[0];
    490 	gpr.regs[_REG_R9] = r8[1];
    491 	gpr.regs[_REG_R10] = r8[2];
    492 	gpr.regs[_REG_R11] = r8[3];
    493 	gpr.regs[_REG_R12] = r8[4];
    494 	gpr.regs[_REG_R13] = r8[5];
    495 	gpr.regs[_REG_R14] = r8[6];
    496 	gpr.regs[_REG_R15] = r8[7];
    497 
    498 	DPRINTF("Call SETREGS for the child process\n");
    499 	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
    500 
    501 	DPRINTF("Before resuming the child process where it left off and "
    502 	    "without signal to be sent\n");
    503 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    504 
    505 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    506 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    507 
    508 	validate_status_exited(status, exitval);
    509 
    510 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    511 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    512 }
    513 
    514 /// ----------------------------------------------------------------------------
    515 
    516 
    517 #define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64() \
    518 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs1); \
    519 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_read); \
    520 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_write); \
    521 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_read); \
    522 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_write);
    523 #else
    524 #define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64()
    525 #endif
    526