t_ptrace_i386_wait.h revision 1.2.4.1 1 1.2.4.1 christos /* $NetBSD: t_ptrace_i386_wait.h,v 1.2.4.1 2019/06/10 22:10:05 christos Exp $ */
2 1.1 kamil
3 1.1 kamil /*-
4 1.2.4.1 christos * 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 #if defined(__i386__)
30 1.1 kamil ATF_TC(i386_regs1);
31 1.1 kamil ATF_TC_HEAD(i386_regs1, tc)
32 1.1 kamil {
33 1.1 kamil atf_tc_set_md_var(tc, "descr",
34 1.1 kamil "Call PT_GETREGS and iterate over General Purpose registers");
35 1.1 kamil }
36 1.1 kamil
37 1.1 kamil ATF_TC_BODY(i386_regs1, tc)
38 1.1 kamil {
39 1.1 kamil const int exitval = 5;
40 1.1 kamil const int sigval = SIGSTOP;
41 1.1 kamil pid_t child, wpid;
42 1.1 kamil #if defined(TWAIT_HAVE_STATUS)
43 1.1 kamil int status;
44 1.1 kamil #endif
45 1.1 kamil struct reg r;
46 1.1 kamil
47 1.2 christos DPRINTF("Before forking process PID=%d\n", getpid());
48 1.2 christos SYSCALL_REQUIRE((child = fork()) != -1);
49 1.1 kamil if (child == 0) {
50 1.2 christos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51 1.1 kamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52 1.1 kamil
53 1.2 christos DPRINTF("Before raising %s from child\n", strsignal(sigval));
54 1.1 kamil FORKEE_ASSERT(raise(sigval) == 0);
55 1.1 kamil
56 1.2 christos DPRINTF("Before exiting of the child process\n");
57 1.1 kamil _exit(exitval);
58 1.1 kamil }
59 1.2 christos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60 1.1 kamil
61 1.2 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62 1.1 kamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63 1.1 kamil
64 1.1 kamil validate_status_stopped(status, sigval);
65 1.1 kamil
66 1.2 christos DPRINTF("Call GETREGS for the child process\n");
67 1.2 christos SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
68 1.1 kamil
69 1.2 christos DPRINTF("EAX=%#" PRIxREGISTER "\n", r.r_eax);
70 1.2 christos DPRINTF("EBX=%#" PRIxREGISTER "\n", r.r_ebx);
71 1.2 christos DPRINTF("ECX=%#" PRIxREGISTER "\n", r.r_ecx);
72 1.2 christos DPRINTF("EDX=%#" PRIxREGISTER "\n", r.r_edx);
73 1.1 kamil
74 1.2 christos DPRINTF("ESP=%#" PRIxREGISTER "\n", r.r_esp);
75 1.2 christos DPRINTF("EBP=%#" PRIxREGISTER "\n", r.r_ebp);
76 1.1 kamil
77 1.2 christos DPRINTF("ESI=%#" PRIxREGISTER "\n", r.r_esi);
78 1.2 christos DPRINTF("EDI=%#" PRIxREGISTER "\n", r.r_edi);
79 1.1 kamil
80 1.2 christos DPRINTF("EIP=%#" PRIxREGISTER "\n", r.r_eip);
81 1.1 kamil
82 1.2 christos DPRINTF("EFLAGS=%#" PRIxREGISTER "\n", r.r_eflags);
83 1.1 kamil
84 1.2 christos DPRINTF("CS=%#" PRIxREGISTER "\n", r.r_cs);
85 1.2 christos DPRINTF("SS=%#" PRIxREGISTER "\n", r.r_ss);
86 1.2 christos DPRINTF("DS=%#" PRIxREGISTER "\n", r.r_ds);
87 1.2 christos DPRINTF("ES=%#" PRIxREGISTER "\n", r.r_es);
88 1.2 christos DPRINTF("FS=%#" PRIxREGISTER "\n", r.r_fs);
89 1.2 christos DPRINTF("GS=%#" PRIxREGISTER "\n", r.r_gs);
90 1.1 kamil
91 1.2 christos DPRINTF("Before resuming the child process where it left off and "
92 1.1 kamil "without signal to be sent\n");
93 1.2 christos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
94 1.1 kamil
95 1.2 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
96 1.1 kamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
97 1.1 kamil
98 1.1 kamil validate_status_exited(status, exitval);
99 1.1 kamil
100 1.2 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
101 1.1 kamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
102 1.1 kamil }
103 1.2.4.1 christos
104 1.2.4.1 christos ATF_TC(i386_regs_gp_read);
105 1.2.4.1 christos ATF_TC_HEAD(i386_regs_gp_read, tc)
106 1.2.4.1 christos {
107 1.2.4.1 christos atf_tc_set_md_var(tc, "descr",
108 1.2.4.1 christos "Set general-purpose reg values from debugged program and read "
109 1.2.4.1 christos "them via PT_GETREGS, comparing values against expected.");
110 1.2.4.1 christos }
111 1.2.4.1 christos
112 1.2.4.1 christos ATF_TC_BODY(i386_regs_gp_read, tc)
113 1.2.4.1 christos {
114 1.2.4.1 christos const int exitval = 5;
115 1.2.4.1 christos pid_t child, wpid;
116 1.2.4.1 christos #if defined(TWAIT_HAVE_STATUS)
117 1.2.4.1 christos const int sigval = SIGTRAP;
118 1.2.4.1 christos int status;
119 1.2.4.1 christos #endif
120 1.2.4.1 christos struct reg gpr;
121 1.2.4.1 christos
122 1.2.4.1 christos const uint32_t eax = 0x00010203;
123 1.2.4.1 christos const uint32_t ebx = 0x10111213;
124 1.2.4.1 christos const uint32_t ecx = 0x20212223;
125 1.2.4.1 christos const uint32_t edx = 0x30313233;
126 1.2.4.1 christos const uint32_t esi = 0x40414243;
127 1.2.4.1 christos const uint32_t edi = 0x50515253;
128 1.2.4.1 christos
129 1.2.4.1 christos DPRINTF("Before forking process PID=%d\n", getpid());
130 1.2.4.1 christos SYSCALL_REQUIRE((child = fork()) != -1);
131 1.2.4.1 christos if (child == 0) {
132 1.2.4.1 christos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
133 1.2.4.1 christos FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
134 1.2.4.1 christos
135 1.2.4.1 christos DPRINTF("Before running assembly from child\n");
136 1.2.4.1 christos
137 1.2.4.1 christos __asm__ __volatile__(
138 1.2.4.1 christos "int3\n\t"
139 1.2.4.1 christos :
140 1.2.4.1 christos : "a"(eax), "b"(ebx), "c"(ecx), "d"(edx), "S"(esi), "D"(edi)
141 1.2.4.1 christos :
142 1.2.4.1 christos );
143 1.2.4.1 christos
144 1.2.4.1 christos DPRINTF("Before exiting of the child process\n");
145 1.2.4.1 christos _exit(exitval);
146 1.2.4.1 christos }
147 1.2.4.1 christos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
148 1.2.4.1 christos
149 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
150 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
151 1.2.4.1 christos
152 1.2.4.1 christos validate_status_stopped(status, sigval);
153 1.2.4.1 christos
154 1.2.4.1 christos DPRINTF("Call GETREGS for the child process\n");
155 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
156 1.2.4.1 christos
157 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_eax, eax);
158 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_ebx, ebx);
159 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_ecx, ecx);
160 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_edx, edx);
161 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_esi, esi);
162 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_edi, edi);
163 1.2.4.1 christos
164 1.2.4.1 christos DPRINTF("Before resuming the child process where it left off and "
165 1.2.4.1 christos "without signal to be sent\n");
166 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
167 1.2.4.1 christos
168 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
169 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
170 1.2.4.1 christos
171 1.2.4.1 christos validate_status_exited(status, exitval);
172 1.2.4.1 christos
173 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
174 1.2.4.1 christos TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
175 1.2.4.1 christos }
176 1.2.4.1 christos
177 1.2.4.1 christos ATF_TC(i386_regs_gp_write);
178 1.2.4.1 christos ATF_TC_HEAD(i386_regs_gp_write, tc)
179 1.2.4.1 christos {
180 1.2.4.1 christos atf_tc_set_md_var(tc, "descr",
181 1.2.4.1 christos "Set general-purpose reg values into a debugged program via "
182 1.2.4.1 christos "PT_SETREGS and compare the result against expected.");
183 1.2.4.1 christos }
184 1.2.4.1 christos
185 1.2.4.1 christos ATF_TC_BODY(i386_regs_gp_write, tc)
186 1.2.4.1 christos {
187 1.2.4.1 christos const int exitval = 5;
188 1.2.4.1 christos pid_t child, wpid;
189 1.2.4.1 christos #if defined(TWAIT_HAVE_STATUS)
190 1.2.4.1 christos const int sigval = SIGTRAP;
191 1.2.4.1 christos int status;
192 1.2.4.1 christos #endif
193 1.2.4.1 christos struct reg gpr;
194 1.2.4.1 christos
195 1.2.4.1 christos const uint32_t eax = 0x00010203;
196 1.2.4.1 christos const uint32_t ebx = 0x10111213;
197 1.2.4.1 christos const uint32_t ecx = 0x20212223;
198 1.2.4.1 christos const uint32_t edx = 0x30313233;
199 1.2.4.1 christos const uint32_t esi = 0x40414243;
200 1.2.4.1 christos const uint32_t edi = 0x50515253;
201 1.2.4.1 christos
202 1.2.4.1 christos DPRINTF("Before forking process PID=%d\n", getpid());
203 1.2.4.1 christos SYSCALL_REQUIRE((child = fork()) != -1);
204 1.2.4.1 christos if (child == 0) {
205 1.2.4.1 christos const uint64_t fill = 0x0F0F0F0F;
206 1.2.4.1 christos uint32_t v_eax, v_ebx, v_ecx, v_edx, v_esi, v_edi;
207 1.2.4.1 christos
208 1.2.4.1 christos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
209 1.2.4.1 christos FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
210 1.2.4.1 christos
211 1.2.4.1 christos DPRINTF("Before running assembly from child\n");
212 1.2.4.1 christos
213 1.2.4.1 christos __asm__ __volatile__(
214 1.2.4.1 christos /* fill registers with clobber pattern */
215 1.2.4.1 christos "movl %6, %%eax\n\t"
216 1.2.4.1 christos "movl %6, %%ebx\n\t"
217 1.2.4.1 christos "movl %6, %%ecx\n\t"
218 1.2.4.1 christos "movl %6, %%edx\n\t"
219 1.2.4.1 christos "movl %6, %%esi\n\t"
220 1.2.4.1 christos "movl %6, %%edi\n\t"
221 1.2.4.1 christos "\n\t"
222 1.2.4.1 christos "int3\n\t"
223 1.2.4.1 christos : "=a"(v_eax), "=b"(v_ebx), "=c"(v_ecx), "=d"(v_edx), "=S"(v_esi),
224 1.2.4.1 christos "=D"(v_edi)
225 1.2.4.1 christos : "g"(fill)
226 1.2.4.1 christos :
227 1.2.4.1 christos );
228 1.2.4.1 christos
229 1.2.4.1 christos DPRINTF("Before comparing results\n");
230 1.2.4.1 christos FORKEE_ASSERT_EQ(v_eax, eax);
231 1.2.4.1 christos FORKEE_ASSERT_EQ(v_ebx, ebx);
232 1.2.4.1 christos FORKEE_ASSERT_EQ(v_ecx, ecx);
233 1.2.4.1 christos FORKEE_ASSERT_EQ(v_edx, edx);
234 1.2.4.1 christos FORKEE_ASSERT_EQ(v_esi, esi);
235 1.2.4.1 christos FORKEE_ASSERT_EQ(v_edi, edi);
236 1.2.4.1 christos
237 1.2.4.1 christos DPRINTF("Before exiting of the child process\n");
238 1.2.4.1 christos _exit(exitval);
239 1.2.4.1 christos }
240 1.2.4.1 christos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
241 1.2.4.1 christos
242 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
243 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
244 1.2.4.1 christos
245 1.2.4.1 christos validate_status_stopped(status, sigval);
246 1.2.4.1 christos
247 1.2.4.1 christos DPRINTF("Call GETREGS for the child process\n");
248 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
249 1.2.4.1 christos
250 1.2.4.1 christos gpr.r_eax = eax;
251 1.2.4.1 christos gpr.r_ebx = ebx;
252 1.2.4.1 christos gpr.r_ecx = ecx;
253 1.2.4.1 christos gpr.r_edx = edx;
254 1.2.4.1 christos gpr.r_esi = esi;
255 1.2.4.1 christos gpr.r_edi = edi;
256 1.2.4.1 christos
257 1.2.4.1 christos DPRINTF("Call SETREGS for the child process\n");
258 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
259 1.2.4.1 christos
260 1.2.4.1 christos DPRINTF("Before resuming the child process where it left off and "
261 1.2.4.1 christos "without signal to be sent\n");
262 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
263 1.2.4.1 christos
264 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
265 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
266 1.2.4.1 christos
267 1.2.4.1 christos validate_status_exited(status, exitval);
268 1.2.4.1 christos
269 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
270 1.2.4.1 christos TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
271 1.2.4.1 christos }
272 1.2.4.1 christos
273 1.2.4.1 christos ATF_TC(i386_regs_ebp_esp_read);
274 1.2.4.1 christos ATF_TC_HEAD(i386_regs_ebp_esp_read, tc)
275 1.2.4.1 christos {
276 1.2.4.1 christos atf_tc_set_md_var(tc, "descr",
277 1.2.4.1 christos "Set EBP & ESP reg values from debugged program and read "
278 1.2.4.1 christos "them via PT_GETREGS, comparing values against expected.");
279 1.2.4.1 christos }
280 1.2.4.1 christos
281 1.2.4.1 christos ATF_TC_BODY(i386_regs_ebp_esp_read, tc)
282 1.2.4.1 christos {
283 1.2.4.1 christos const int exitval = 5;
284 1.2.4.1 christos pid_t child, wpid;
285 1.2.4.1 christos #if defined(TWAIT_HAVE_STATUS)
286 1.2.4.1 christos const int sigval = SIGTRAP;
287 1.2.4.1 christos int status;
288 1.2.4.1 christos #endif
289 1.2.4.1 christos struct reg gpr;
290 1.2.4.1 christos
291 1.2.4.1 christos const uint32_t esp = 0x60616263;
292 1.2.4.1 christos const uint32_t ebp = 0x70717273;
293 1.2.4.1 christos
294 1.2.4.1 christos DPRINTF("Before forking process PID=%d\n", getpid());
295 1.2.4.1 christos SYSCALL_REQUIRE((child = fork()) != -1);
296 1.2.4.1 christos if (child == 0) {
297 1.2.4.1 christos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
298 1.2.4.1 christos FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
299 1.2.4.1 christos
300 1.2.4.1 christos DPRINTF("Before running assembly from child\n");
301 1.2.4.1 christos
302 1.2.4.1 christos __asm__ __volatile__(
303 1.2.4.1 christos /* ebp & ebp are a bit tricky, we must not clobber them */
304 1.2.4.1 christos "movl %%esp, %%eax\n\t"
305 1.2.4.1 christos "movl %%ebp, %%ebx\n\t"
306 1.2.4.1 christos "movl %0, %%esp\n\t"
307 1.2.4.1 christos "movl %1, %%ebp\n\t"
308 1.2.4.1 christos "\n\t"
309 1.2.4.1 christos "int3\n\t"
310 1.2.4.1 christos "\n\t"
311 1.2.4.1 christos "movl %%eax, %%esp\n\t"
312 1.2.4.1 christos "movl %%ebx, %%ebp\n\t"
313 1.2.4.1 christos :
314 1.2.4.1 christos : "ri"(esp), "ri"(ebp)
315 1.2.4.1 christos : "%eax", "%ebx"
316 1.2.4.1 christos );
317 1.2.4.1 christos
318 1.2.4.1 christos DPRINTF("Before exiting of the child process\n");
319 1.2.4.1 christos _exit(exitval);
320 1.2.4.1 christos }
321 1.2.4.1 christos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
322 1.2.4.1 christos
323 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
324 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
325 1.2.4.1 christos
326 1.2.4.1 christos validate_status_stopped(status, sigval);
327 1.2.4.1 christos
328 1.2.4.1 christos DPRINTF("Call GETREGS for the child process\n");
329 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
330 1.2.4.1 christos
331 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_esp, esp);
332 1.2.4.1 christos ATF_CHECK_EQ((uint32_t)gpr.r_ebp, ebp);
333 1.2.4.1 christos
334 1.2.4.1 christos DPRINTF("Before resuming the child process where it left off and "
335 1.2.4.1 christos "without signal to be sent\n");
336 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
337 1.2.4.1 christos
338 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
339 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
340 1.2.4.1 christos
341 1.2.4.1 christos validate_status_exited(status, exitval);
342 1.2.4.1 christos
343 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
344 1.2.4.1 christos TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
345 1.2.4.1 christos }
346 1.2.4.1 christos
347 1.2.4.1 christos ATF_TC(i386_regs_ebp_esp_write);
348 1.2.4.1 christos ATF_TC_HEAD(i386_regs_ebp_esp_write, tc)
349 1.2.4.1 christos {
350 1.2.4.1 christos atf_tc_set_md_var(tc, "descr",
351 1.2.4.1 christos "Set EBP & ESP reg values into a debugged program via "
352 1.2.4.1 christos "PT_SETREGS and compare the result against expected.");
353 1.2.4.1 christos }
354 1.2.4.1 christos
355 1.2.4.1 christos ATF_TC_BODY(i386_regs_ebp_esp_write, tc)
356 1.2.4.1 christos {
357 1.2.4.1 christos const int exitval = 5;
358 1.2.4.1 christos pid_t child, wpid;
359 1.2.4.1 christos #if defined(TWAIT_HAVE_STATUS)
360 1.2.4.1 christos const int sigval = SIGTRAP;
361 1.2.4.1 christos int status;
362 1.2.4.1 christos #endif
363 1.2.4.1 christos struct reg gpr;
364 1.2.4.1 christos
365 1.2.4.1 christos const uint32_t esp = 0x60616263;
366 1.2.4.1 christos const uint32_t ebp = 0x70717273;
367 1.2.4.1 christos
368 1.2.4.1 christos DPRINTF("Before forking process PID=%d\n", getpid());
369 1.2.4.1 christos SYSCALL_REQUIRE((child = fork()) != -1);
370 1.2.4.1 christos if (child == 0) {
371 1.2.4.1 christos const uint64_t fill = 0x0F0F0F0F;
372 1.2.4.1 christos uint32_t v_esp, v_ebp;
373 1.2.4.1 christos
374 1.2.4.1 christos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
375 1.2.4.1 christos FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
376 1.2.4.1 christos
377 1.2.4.1 christos DPRINTF("Before running assembly from child\n");
378 1.2.4.1 christos
379 1.2.4.1 christos __asm__ __volatile__(
380 1.2.4.1 christos /* save original ebp & esp using our output registers */
381 1.2.4.1 christos "movl %%esp, %0\n\t"
382 1.2.4.1 christos "movl %%ebp, %1\n\t"
383 1.2.4.1 christos /* fill them with clobber pattern */
384 1.2.4.1 christos "movl %2, %%esp\n\t"
385 1.2.4.1 christos "movl %2, %%ebp\n\t"
386 1.2.4.1 christos "\n\t"
387 1.2.4.1 christos "int3\n\t"
388 1.2.4.1 christos "\n\t"
389 1.2.4.1 christos /* restore ebp & esp, and save the result */
390 1.2.4.1 christos "xchgl %%esp, %0\n\t"
391 1.2.4.1 christos "xchgl %%ebp, %1\n\t"
392 1.2.4.1 christos : "=r"(v_esp), "=r"(v_ebp)
393 1.2.4.1 christos : "g"(fill)
394 1.2.4.1 christos :
395 1.2.4.1 christos );
396 1.2.4.1 christos
397 1.2.4.1 christos DPRINTF("Before comparing results\n");
398 1.2.4.1 christos FORKEE_ASSERT_EQ(v_esp, esp);
399 1.2.4.1 christos FORKEE_ASSERT_EQ(v_ebp, ebp);
400 1.2.4.1 christos
401 1.2.4.1 christos DPRINTF("Before exiting of the child process\n");
402 1.2.4.1 christos _exit(exitval);
403 1.2.4.1 christos }
404 1.2.4.1 christos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
405 1.2.4.1 christos
406 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
407 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
408 1.2.4.1 christos
409 1.2.4.1 christos validate_status_stopped(status, sigval);
410 1.2.4.1 christos
411 1.2.4.1 christos DPRINTF("Call GETREGS for the child process\n");
412 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
413 1.2.4.1 christos
414 1.2.4.1 christos gpr.r_esp = esp;
415 1.2.4.1 christos gpr.r_ebp = ebp;
416 1.2.4.1 christos
417 1.2.4.1 christos DPRINTF("Call SETREGS for the child process\n");
418 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
419 1.2.4.1 christos
420 1.2.4.1 christos DPRINTF("Before resuming the child process where it left off and "
421 1.2.4.1 christos "without signal to be sent\n");
422 1.2.4.1 christos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
423 1.2.4.1 christos
424 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
425 1.2.4.1 christos TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
426 1.2.4.1 christos
427 1.2.4.1 christos validate_status_exited(status, exitval);
428 1.2.4.1 christos
429 1.2.4.1 christos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
430 1.2.4.1 christos TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
431 1.2.4.1 christos }
432 1.2.4.1 christos
433 1.1 kamil #define ATF_TP_ADD_TCS_PTRACE_WAIT_I386() \
434 1.2.4.1 christos ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs1); \
435 1.2.4.1 christos ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_read); \
436 1.2.4.1 christos ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_write); \
437 1.2.4.1 christos ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_read); \
438 1.2.4.1 christos ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_write);
439 1.1 kamil #else
440 1.1 kamil #define ATF_TP_ADD_TCS_PTRACE_WAIT_I386()
441 1.1 kamil #endif
442