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