1e1976efdSKonstantin Belousov /*-
2e1976efdSKonstantin Belousov * Copyright (c) 2011, 2012 Konstantin Belousov <kib@FreeBSD.org>
3e1976efdSKonstantin Belousov *
4e1976efdSKonstantin Belousov * Redistribution and use in source and binary forms, with or without
5e1976efdSKonstantin Belousov * modification, are permitted provided that the following conditions
6e1976efdSKonstantin Belousov * are met:
7e1976efdSKonstantin Belousov * 1. Redistributions of source code must retain the above copyright
8e1976efdSKonstantin Belousov * notice, this list of conditions and the following disclaimer.
9e1976efdSKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright
10e1976efdSKonstantin Belousov * notice, this list of conditions and the following disclaimer in the
11e1976efdSKonstantin Belousov * documentation and/or other materials provided with the distribution.
12e1976efdSKonstantin Belousov *
13e1976efdSKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14e1976efdSKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15e1976efdSKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16e1976efdSKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17e1976efdSKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18e1976efdSKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19e1976efdSKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20e1976efdSKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21e1976efdSKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22e1976efdSKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23e1976efdSKonstantin Belousov * SUCH DAMAGE.
24e1976efdSKonstantin Belousov */
25e1976efdSKonstantin Belousov
26e1976efdSKonstantin Belousov #include <sys/types.h>
27e1976efdSKonstantin Belousov #include <sys/ptrace.h>
28*6403a140SKonstantin Belousov #include <sys/syscall.h>
29e1976efdSKonstantin Belousov #include <sys/sysctl.h>
30e1976efdSKonstantin Belousov #include <sys/wait.h>
31e1976efdSKonstantin Belousov #include <assert.h>
32e1976efdSKonstantin Belousov #include <errno.h>
33e1976efdSKonstantin Belousov #include <signal.h>
34e1976efdSKonstantin Belousov #include <stdio.h>
35e1976efdSKonstantin Belousov #include <stdlib.h>
36e1976efdSKonstantin Belousov #include <string.h>
37e1976efdSKonstantin Belousov #include <unistd.h>
38e1976efdSKonstantin Belousov
39e1976efdSKonstantin Belousov #define TRACE ">>>> "
40e1976efdSKonstantin Belousov
41e1976efdSKonstantin Belousov static const char *
decode_wait_status(int status)42e1976efdSKonstantin Belousov decode_wait_status(int status)
43e1976efdSKonstantin Belousov {
44e1976efdSKonstantin Belousov static char c[128];
45e1976efdSKonstantin Belousov char b[32];
46e1976efdSKonstantin Belousov int first;
47e1976efdSKonstantin Belousov
48e1976efdSKonstantin Belousov c[0] = '\0';
49e1976efdSKonstantin Belousov first = 1;
50e1976efdSKonstantin Belousov if (WIFCONTINUED(status)) {
51e1976efdSKonstantin Belousov first = 0;
52e1976efdSKonstantin Belousov strlcat(c, "CONT", sizeof(c));
53e1976efdSKonstantin Belousov }
54e1976efdSKonstantin Belousov if (WIFEXITED(status)) {
55e1976efdSKonstantin Belousov if (first)
56e1976efdSKonstantin Belousov first = 0;
57e1976efdSKonstantin Belousov else
58e1976efdSKonstantin Belousov strlcat(c, ",", sizeof(c));
59e1976efdSKonstantin Belousov snprintf(b, sizeof(b), "EXIT(%d)", WEXITSTATUS(status));
60e1976efdSKonstantin Belousov strlcat(c, b, sizeof(c));
61e1976efdSKonstantin Belousov }
62e1976efdSKonstantin Belousov if (WIFSIGNALED(status)) {
63e1976efdSKonstantin Belousov if (first)
64e1976efdSKonstantin Belousov first = 0;
65e1976efdSKonstantin Belousov else
66e1976efdSKonstantin Belousov strlcat(c, ",", sizeof(c));
67e1976efdSKonstantin Belousov snprintf(b, sizeof(b), "SIG(%s)", strsignal(WTERMSIG(status)));
68e1976efdSKonstantin Belousov strlcat(c, b, sizeof(c));
69e1976efdSKonstantin Belousov if (WCOREDUMP(status))
70e1976efdSKonstantin Belousov strlcat(c, ",CORE", sizeof(c));
71e1976efdSKonstantin Belousov }
72e1976efdSKonstantin Belousov if (WIFSTOPPED(status)) {
73e1976efdSKonstantin Belousov if (first)
74e1976efdSKonstantin Belousov first = 0;
75e1976efdSKonstantin Belousov else
76e1976efdSKonstantin Belousov strlcat(c, ",", sizeof(c));
77e1976efdSKonstantin Belousov snprintf(b, sizeof(b), "SIG(%s)", strsignal(WSTOPSIG(status)));
78e1976efdSKonstantin Belousov strlcat(c, b, sizeof(c));
79e1976efdSKonstantin Belousov }
80e1976efdSKonstantin Belousov return (c);
81e1976efdSKonstantin Belousov }
82e1976efdSKonstantin Belousov
83e1976efdSKonstantin Belousov static const char *
decode_pl_flags(struct ptrace_lwpinfo * lwpinfo)84e1976efdSKonstantin Belousov decode_pl_flags(struct ptrace_lwpinfo *lwpinfo)
85e1976efdSKonstantin Belousov {
86e1976efdSKonstantin Belousov static char c[128];
87e1976efdSKonstantin Belousov static struct decode_tag {
88e1976efdSKonstantin Belousov int flag;
89e1976efdSKonstantin Belousov const char *desc;
90e1976efdSKonstantin Belousov } decode[] = {
91e1976efdSKonstantin Belousov { PL_FLAG_SA, "SA" },
92e1976efdSKonstantin Belousov { PL_FLAG_BOUND, "BOUND" },
93e1976efdSKonstantin Belousov { PL_FLAG_SCE, "SCE" },
94e1976efdSKonstantin Belousov { PL_FLAG_SCX, "SCX" },
95e1976efdSKonstantin Belousov { PL_FLAG_EXEC, "EXEC" },
96e1976efdSKonstantin Belousov { PL_FLAG_SI, "SI" },
97e1976efdSKonstantin Belousov { PL_FLAG_FORKED, "FORKED" },
98b275edf7SKonstantin Belousov { PL_FLAG_CHILD, "CHILD" },
99b275edf7SKonstantin Belousov { PL_FLAG_BORN, "LWPBORN" },
100b275edf7SKonstantin Belousov { PL_FLAG_EXITED, "LWPEXITED" },
101b275edf7SKonstantin Belousov { PL_FLAG_VFORKED, "VFORKED" },
102b275edf7SKonstantin Belousov { PL_FLAG_VFORK_DONE, "VFORKDONE" },
103e1976efdSKonstantin Belousov };
104e1976efdSKonstantin Belousov char de[32];
105e1976efdSKonstantin Belousov unsigned first, flags, i;
106e1976efdSKonstantin Belousov
107e1976efdSKonstantin Belousov c[0] = '\0';
108e1976efdSKonstantin Belousov first = 1;
109e1976efdSKonstantin Belousov flags = lwpinfo->pl_flags;
110e1976efdSKonstantin Belousov for (i = 0; i < sizeof(decode) / sizeof(decode[0]); i++) {
111e1976efdSKonstantin Belousov if ((flags & decode[i].flag) != 0) {
112e1976efdSKonstantin Belousov if (first)
113e1976efdSKonstantin Belousov first = 0;
114e1976efdSKonstantin Belousov else
115e1976efdSKonstantin Belousov strlcat(c, ",", sizeof(c));
116e1976efdSKonstantin Belousov strlcat(c, decode[i].desc, sizeof(c));
117e1976efdSKonstantin Belousov flags &= ~decode[i].flag;
118e1976efdSKonstantin Belousov }
119e1976efdSKonstantin Belousov }
120e1976efdSKonstantin Belousov for (i = 0; i < sizeof(flags) * NBBY; i++) {
121e1976efdSKonstantin Belousov if ((flags & (1 << i)) != 0) {
122e1976efdSKonstantin Belousov if (first)
123e1976efdSKonstantin Belousov first = 0;
124e1976efdSKonstantin Belousov else
125e1976efdSKonstantin Belousov strlcat(c, ",", sizeof(c));
126e1976efdSKonstantin Belousov snprintf(de, sizeof(de), "<%d>", i);
127e1976efdSKonstantin Belousov strlcat(c, de, sizeof(c));
128e1976efdSKonstantin Belousov }
129e1976efdSKonstantin Belousov }
130e1976efdSKonstantin Belousov return (c);
131e1976efdSKonstantin Belousov }
132e1976efdSKonstantin Belousov
133e1976efdSKonstantin Belousov static const char *
decode_pl_event(struct ptrace_lwpinfo * lwpinfo)134e1976efdSKonstantin Belousov decode_pl_event(struct ptrace_lwpinfo *lwpinfo)
135e1976efdSKonstantin Belousov {
136e1976efdSKonstantin Belousov
137e1976efdSKonstantin Belousov switch (lwpinfo->pl_event) {
138e1976efdSKonstantin Belousov case PL_EVENT_NONE:
139e1976efdSKonstantin Belousov return ("NONE");
140e1976efdSKonstantin Belousov
141e1976efdSKonstantin Belousov case PL_EVENT_SIGNAL:
142e1976efdSKonstantin Belousov return ("SIG");
143e1976efdSKonstantin Belousov
144e1976efdSKonstantin Belousov default:
145e1976efdSKonstantin Belousov return ("UNKNOWN");
146e1976efdSKonstantin Belousov }
147e1976efdSKonstantin Belousov }
148e1976efdSKonstantin Belousov
149e1976efdSKonstantin Belousov static void
get_pathname(pid_t pid)150e1976efdSKonstantin Belousov get_pathname(pid_t pid)
151e1976efdSKonstantin Belousov {
152e1976efdSKonstantin Belousov char pathname[PATH_MAX];
153e1976efdSKonstantin Belousov int error, name[4];
154e1976efdSKonstantin Belousov size_t len;
155e1976efdSKonstantin Belousov
156e1976efdSKonstantin Belousov name[0] = CTL_KERN;
157e1976efdSKonstantin Belousov name[1] = KERN_PROC;
158e1976efdSKonstantin Belousov name[2] = KERN_PROC_PATHNAME;
159e1976efdSKonstantin Belousov name[3] = pid;
160e1976efdSKonstantin Belousov
161e1976efdSKonstantin Belousov len = sizeof(pathname);
162e1976efdSKonstantin Belousov error = sysctl(name, 4, pathname, &len, NULL, 0);
163e1976efdSKonstantin Belousov if (error < 0) {
164e1976efdSKonstantin Belousov if (errno != ESRCH) {
165e1976efdSKonstantin Belousov fprintf(stderr, "sysctl kern.proc.pathname.%d: %s\n",
166e1976efdSKonstantin Belousov pid, strerror(errno));
167e1976efdSKonstantin Belousov return;
168e1976efdSKonstantin Belousov }
169e1976efdSKonstantin Belousov fprintf(stderr, "pid %d exited\n", pid);
170e1976efdSKonstantin Belousov return;
171e1976efdSKonstantin Belousov }
172e1976efdSKonstantin Belousov if (len == 0 || strlen(pathname) == 0) {
173e1976efdSKonstantin Belousov fprintf(stderr, "No cached pathname for process %d\n", pid);
174e1976efdSKonstantin Belousov return;
175e1976efdSKonstantin Belousov }
176e1976efdSKonstantin Belousov printf(TRACE "pid %d path %s\n", pid, pathname);
177e1976efdSKonstantin Belousov }
178e1976efdSKonstantin Belousov
179e1976efdSKonstantin Belousov static void
wait_info(int pid,int status,struct ptrace_lwpinfo * lwpinfo)180e1976efdSKonstantin Belousov wait_info(int pid, int status, struct ptrace_lwpinfo *lwpinfo)
181e1976efdSKonstantin Belousov {
182965ee749SKonstantin Belousov long *args;
183965ee749SKonstantin Belousov int error, i;
184e1976efdSKonstantin Belousov
185e1976efdSKonstantin Belousov printf(TRACE "pid %d wait %s", pid,
186e1976efdSKonstantin Belousov decode_wait_status(status));
187e1976efdSKonstantin Belousov if (lwpinfo != NULL) {
188e1976efdSKonstantin Belousov printf(" event %s flags %s",
189e1976efdSKonstantin Belousov decode_pl_event(lwpinfo), decode_pl_flags(lwpinfo));
190965ee749SKonstantin Belousov if ((lwpinfo->pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)) != 0) {
191965ee749SKonstantin Belousov printf(" sc%d", lwpinfo->pl_syscall_code);
192965ee749SKonstantin Belousov args = calloc(lwpinfo->pl_syscall_narg, sizeof(long));
193965ee749SKonstantin Belousov error = ptrace(PT_GET_SC_ARGS, lwpinfo->pl_lwpid,
194965ee749SKonstantin Belousov (caddr_t)args, lwpinfo->pl_syscall_narg *
195965ee749SKonstantin Belousov sizeof(long));
196965ee749SKonstantin Belousov if (error == 0) {
1979a8eb5dbSKonstantin Belousov printf("(");
198965ee749SKonstantin Belousov for (i = 0; i < (int)lwpinfo->pl_syscall_narg;
199965ee749SKonstantin Belousov i++) {
2009a8eb5dbSKonstantin Belousov printf("%s%#lx", i == 0 ? "" : ",",
201965ee749SKonstantin Belousov args[i]);
202965ee749SKonstantin Belousov }
2039a8eb5dbSKonstantin Belousov printf(")");
204965ee749SKonstantin Belousov } else {
205965ee749SKonstantin Belousov fprintf(stderr, "PT_GET_SC_ARGS failed: %s",
206965ee749SKonstantin Belousov strerror(errno));
207965ee749SKonstantin Belousov }
208965ee749SKonstantin Belousov free(args);
209965ee749SKonstantin Belousov }
210e1976efdSKonstantin Belousov }
211e1976efdSKonstantin Belousov printf("\n");
212e1976efdSKonstantin Belousov }
213e1976efdSKonstantin Belousov
214*6403a140SKonstantin Belousov static int trace_syscalls = 1;
215*6403a140SKonstantin Belousov static int remote_getpid = 0;
216*6403a140SKonstantin Belousov
217e1976efdSKonstantin Belousov static int
trace_sc(int pid)218e1976efdSKonstantin Belousov trace_sc(int pid)
219e1976efdSKonstantin Belousov {
220*6403a140SKonstantin Belousov struct ptrace_sc_remote pscr;
221e1976efdSKonstantin Belousov struct ptrace_lwpinfo lwpinfo;
222e1976efdSKonstantin Belousov int status;
223e1976efdSKonstantin Belousov
224e1976efdSKonstantin Belousov if (ptrace(PT_TO_SCE, pid, (caddr_t)1, 0) < 0) {
225e1976efdSKonstantin Belousov perror("PT_TO_SCE");
226e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
227e1976efdSKonstantin Belousov return (-1);
228e1976efdSKonstantin Belousov }
229e1976efdSKonstantin Belousov
230e1976efdSKonstantin Belousov if (waitpid(pid, &status, 0) == -1) {
231e1976efdSKonstantin Belousov perror("waitpid");
232e1976efdSKonstantin Belousov return (-1);
233e1976efdSKonstantin Belousov }
234e1976efdSKonstantin Belousov if (WIFEXITED(status) || WIFSIGNALED(status)) {
235e1976efdSKonstantin Belousov wait_info(pid, status, NULL);
236e1976efdSKonstantin Belousov return (-1);
237e1976efdSKonstantin Belousov }
238e1976efdSKonstantin Belousov assert(WIFSTOPPED(status));
239e1976efdSKonstantin Belousov assert(WSTOPSIG(status) == SIGTRAP);
240e1976efdSKonstantin Belousov
241e1976efdSKonstantin Belousov if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) {
242e1976efdSKonstantin Belousov perror("PT_LWPINFO");
243e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
244e1976efdSKonstantin Belousov return (-1);
245e1976efdSKonstantin Belousov }
246e1976efdSKonstantin Belousov wait_info(pid, status, &lwpinfo);
247e1976efdSKonstantin Belousov assert(lwpinfo.pl_flags & PL_FLAG_SCE);
248e1976efdSKonstantin Belousov
249e1976efdSKonstantin Belousov if (ptrace(PT_TO_SCX, pid, (caddr_t)1, 0) < 0) {
250e1976efdSKonstantin Belousov perror("PT_TO_SCX");
251e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
252e1976efdSKonstantin Belousov return (-1);
253e1976efdSKonstantin Belousov }
254e1976efdSKonstantin Belousov
255e1976efdSKonstantin Belousov if (waitpid(pid, &status, 0) == -1) {
256e1976efdSKonstantin Belousov perror("waitpid");
257e1976efdSKonstantin Belousov return (-1);
258e1976efdSKonstantin Belousov }
259e1976efdSKonstantin Belousov if (WIFEXITED(status) || WIFSIGNALED(status)) {
260e1976efdSKonstantin Belousov wait_info(pid, status, NULL);
261e1976efdSKonstantin Belousov return (-1);
262e1976efdSKonstantin Belousov }
263e1976efdSKonstantin Belousov assert(WIFSTOPPED(status));
264e1976efdSKonstantin Belousov assert(WSTOPSIG(status) == SIGTRAP);
265e1976efdSKonstantin Belousov
266e1976efdSKonstantin Belousov if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) {
267e1976efdSKonstantin Belousov perror("PT_LWPINFO");
268e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
269e1976efdSKonstantin Belousov return (-1);
270e1976efdSKonstantin Belousov }
271e1976efdSKonstantin Belousov wait_info(pid, status, &lwpinfo);
272e1976efdSKonstantin Belousov assert(lwpinfo.pl_flags & PL_FLAG_SCX);
273e1976efdSKonstantin Belousov
274*6403a140SKonstantin Belousov if (remote_getpid) {
275*6403a140SKonstantin Belousov memset(&pscr, 0, sizeof(pscr));
276*6403a140SKonstantin Belousov pscr.pscr_syscall = SYS_getpid;
277*6403a140SKonstantin Belousov pscr.pscr_nargs = 0;
278*6403a140SKonstantin Belousov if (ptrace(PT_SC_REMOTE, pid, (caddr_t)&pscr,
279*6403a140SKonstantin Belousov sizeof(pscr)) < 0) {
280*6403a140SKonstantin Belousov perror("PT_SC_REMOTE");
281*6403a140SKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
282*6403a140SKonstantin Belousov return (-1);
283*6403a140SKonstantin Belousov } else {
284*6403a140SKonstantin Belousov printf(TRACE "remote getpid %ld errno %d\n",
285*6403a140SKonstantin Belousov pscr.pscr_ret.sr_retval[0], pscr.pscr_ret.sr_error);
286*6403a140SKonstantin Belousov if (waitpid(pid, &status, 0) == -1) {
287*6403a140SKonstantin Belousov perror("waitpid");
288*6403a140SKonstantin Belousov return (-1);
289*6403a140SKonstantin Belousov }
290*6403a140SKonstantin Belousov }
291*6403a140SKonstantin Belousov }
292e1976efdSKonstantin Belousov if (lwpinfo.pl_flags & PL_FLAG_EXEC)
293e1976efdSKonstantin Belousov get_pathname(pid);
294e1976efdSKonstantin Belousov
295e1976efdSKonstantin Belousov if (lwpinfo.pl_flags & PL_FLAG_FORKED) {
296e1976efdSKonstantin Belousov printf(TRACE "forked child %d\n", lwpinfo.pl_child_pid);
297e1976efdSKonstantin Belousov return (lwpinfo.pl_child_pid);
298e1976efdSKonstantin Belousov }
299e1976efdSKonstantin Belousov return (0);
300e1976efdSKonstantin Belousov }
301e1976efdSKonstantin Belousov
302e1976efdSKonstantin Belousov static int
trace_cont(int pid)303e1976efdSKonstantin Belousov trace_cont(int pid)
304e1976efdSKonstantin Belousov {
305e1976efdSKonstantin Belousov struct ptrace_lwpinfo lwpinfo;
306e1976efdSKonstantin Belousov int status;
307e1976efdSKonstantin Belousov
308e1976efdSKonstantin Belousov if (ptrace(PT_CONTINUE, pid, (caddr_t)1, 0) < 0) {
309e1976efdSKonstantin Belousov perror("PT_CONTINUE");
310e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
311e1976efdSKonstantin Belousov return (-1);
312e1976efdSKonstantin Belousov }
313e1976efdSKonstantin Belousov
314e1976efdSKonstantin Belousov if (waitpid(pid, &status, 0) == -1) {
315e1976efdSKonstantin Belousov perror("waitpid");
316e1976efdSKonstantin Belousov return (-1);
317e1976efdSKonstantin Belousov }
318e1976efdSKonstantin Belousov if (WIFEXITED(status) || WIFSIGNALED(status)) {
319e1976efdSKonstantin Belousov wait_info(pid, status, NULL);
320e1976efdSKonstantin Belousov return (-1);
321e1976efdSKonstantin Belousov }
322e1976efdSKonstantin Belousov assert(WIFSTOPPED(status));
323e1976efdSKonstantin Belousov assert(WSTOPSIG(status) == SIGTRAP);
324e1976efdSKonstantin Belousov
325e1976efdSKonstantin Belousov if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) {
326e1976efdSKonstantin Belousov perror("PT_LWPINFO");
327e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
328e1976efdSKonstantin Belousov return (-1);
329e1976efdSKonstantin Belousov }
330e1976efdSKonstantin Belousov wait_info(pid, status, &lwpinfo);
331e1976efdSKonstantin Belousov
332e1976efdSKonstantin Belousov if ((lwpinfo.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
333e1976efdSKonstantin Belousov (PL_FLAG_EXEC | PL_FLAG_SCX))
334e1976efdSKonstantin Belousov get_pathname(pid);
335e1976efdSKonstantin Belousov
336e1976efdSKonstantin Belousov if ((lwpinfo.pl_flags & (PL_FLAG_FORKED | PL_FLAG_SCX)) ==
337e1976efdSKonstantin Belousov (PL_FLAG_FORKED | PL_FLAG_SCX)) {
338e1976efdSKonstantin Belousov printf(TRACE "forked child %d\n", lwpinfo.pl_child_pid);
339e1976efdSKonstantin Belousov return (lwpinfo.pl_child_pid);
340e1976efdSKonstantin Belousov }
341e1976efdSKonstantin Belousov
342e1976efdSKonstantin Belousov return (0);
343e1976efdSKonstantin Belousov }
344e1976efdSKonstantin Belousov
345e1976efdSKonstantin Belousov static int
trace(pid_t pid)346e1976efdSKonstantin Belousov trace(pid_t pid)
347e1976efdSKonstantin Belousov {
348e1976efdSKonstantin Belousov
349e1976efdSKonstantin Belousov return (trace_syscalls ? trace_sc(pid) : trace_cont(pid));
350e1976efdSKonstantin Belousov }
351e1976efdSKonstantin Belousov
352e1976efdSKonstantin Belousov
353e1976efdSKonstantin Belousov int
main(int argc,char * argv[])354e1976efdSKonstantin Belousov main(int argc, char *argv[])
355e1976efdSKonstantin Belousov {
356e1976efdSKonstantin Belousov struct ptrace_lwpinfo lwpinfo;
357e1976efdSKonstantin Belousov int c, status, use_vfork;
358e1976efdSKonstantin Belousov pid_t pid, pid1;
359e1976efdSKonstantin Belousov
360e1976efdSKonstantin Belousov trace_syscalls = 1;
361*6403a140SKonstantin Belousov remote_getpid = 0;
362e1976efdSKonstantin Belousov use_vfork = 0;
363*6403a140SKonstantin Belousov while ((c = getopt(argc, argv, "crsv")) != -1) {
364e1976efdSKonstantin Belousov switch (c) {
365e1976efdSKonstantin Belousov case 'c':
366e1976efdSKonstantin Belousov trace_syscalls = 0;
367e1976efdSKonstantin Belousov break;
368*6403a140SKonstantin Belousov case 'r':
369*6403a140SKonstantin Belousov remote_getpid = 1;
370*6403a140SKonstantin Belousov break;
371e1976efdSKonstantin Belousov case 's':
372e1976efdSKonstantin Belousov trace_syscalls = 1;
373e1976efdSKonstantin Belousov break;
374e1976efdSKonstantin Belousov case 'v':
375e1976efdSKonstantin Belousov use_vfork = 1;
376e1976efdSKonstantin Belousov break;
377e1976efdSKonstantin Belousov default:
378e1976efdSKonstantin Belousov case '?':
379*6403a140SKonstantin Belousov fprintf(stderr, "Usage: %s [-c] [-r] [-s] [-v]\n",
380*6403a140SKonstantin Belousov argv[0]);
381e1976efdSKonstantin Belousov return (2);
382e1976efdSKonstantin Belousov }
383e1976efdSKonstantin Belousov }
384e1976efdSKonstantin Belousov
385e1976efdSKonstantin Belousov if ((pid = fork()) < 0) {
386e1976efdSKonstantin Belousov perror("fork");
387e1976efdSKonstantin Belousov return 1;
388e1976efdSKonstantin Belousov }
389e1976efdSKonstantin Belousov else if (pid == 0) {
390e1976efdSKonstantin Belousov if (ptrace(PT_TRACE_ME, 0, NULL, 0) < 0) {
391e1976efdSKonstantin Belousov perror("PT_TRACE_ME");
392e1976efdSKonstantin Belousov _exit(1);
393e1976efdSKonstantin Belousov }
394e1976efdSKonstantin Belousov kill(getpid(), SIGSTOP);
395e1976efdSKonstantin Belousov getpid();
396e1976efdSKonstantin Belousov if ((pid1 = use_vfork ? vfork() : fork()) < 0) {
397e1976efdSKonstantin Belousov perror("fork1");
398e1976efdSKonstantin Belousov return (1);
399e1976efdSKonstantin Belousov } else if (pid1 == 0) {
400e1976efdSKonstantin Belousov printf("Hi from child %d\n", getpid());
401e1976efdSKonstantin Belousov execl("/bin/ls", "ls", "/", (char *)NULL);
402e1976efdSKonstantin Belousov }
403e1976efdSKonstantin Belousov }
404e1976efdSKonstantin Belousov else { /* parent */
405e1976efdSKonstantin Belousov if (waitpid(pid, &status, 0) == -1) {
406e1976efdSKonstantin Belousov perror("waitpid");
407e1976efdSKonstantin Belousov return (-1);
408e1976efdSKonstantin Belousov }
409e1976efdSKonstantin Belousov assert(WIFSTOPPED(status));
410e1976efdSKonstantin Belousov assert(WSTOPSIG(status) == SIGSTOP);
411e1976efdSKonstantin Belousov
412e1976efdSKonstantin Belousov if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo,
413e1976efdSKonstantin Belousov sizeof(lwpinfo)) < 0) {
414e1976efdSKonstantin Belousov perror("PT_LWPINFO");
415e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
416e1976efdSKonstantin Belousov return (-1);
417e1976efdSKonstantin Belousov }
418e1976efdSKonstantin Belousov wait_info(pid, status, &lwpinfo);
419e1976efdSKonstantin Belousov
420e1976efdSKonstantin Belousov if (ptrace(PT_FOLLOW_FORK, pid, 0, 1) < 0) {
421e1976efdSKonstantin Belousov perror("PT_FOLLOW_FORK");
422e1976efdSKonstantin Belousov ptrace(PT_KILL, pid, NULL, 0);
423e1976efdSKonstantin Belousov return (2);
424e1976efdSKonstantin Belousov }
425e1976efdSKonstantin Belousov
426e1976efdSKonstantin Belousov while ((pid1 = trace(pid)) >= 0) {
427e1976efdSKonstantin Belousov if (pid1 != 0) {
428e1976efdSKonstantin Belousov printf(TRACE "attached to pid %d\n", pid1);
429e1976efdSKonstantin Belousov #if 0
430e1976efdSKonstantin Belousov kill(pid1, SIGCONT);
431e1976efdSKonstantin Belousov #endif
432e1976efdSKonstantin Belousov if (waitpid(pid1, &status, 0) == -1) {
433e1976efdSKonstantin Belousov perror("waitpid");
434e1976efdSKonstantin Belousov return (-1);
435e1976efdSKonstantin Belousov }
436e1976efdSKonstantin Belousov printf(TRACE "nested loop, pid %d status %s\n",
437e1976efdSKonstantin Belousov pid1, decode_wait_status(status));
438e1976efdSKonstantin Belousov assert(WIFSTOPPED(status));
439e1976efdSKonstantin Belousov assert(WSTOPSIG(status) == SIGSTOP);
440e1976efdSKonstantin Belousov if (ptrace(PT_LWPINFO, pid1, (caddr_t)&lwpinfo,
441e1976efdSKonstantin Belousov sizeof(lwpinfo)) < 0) {
442e1976efdSKonstantin Belousov perror("PT_LWPINFO");
443e1976efdSKonstantin Belousov ptrace(PT_KILL, pid1, NULL, 0);
444e1976efdSKonstantin Belousov return (-1);
445e1976efdSKonstantin Belousov }
446e1976efdSKonstantin Belousov wait_info(pid1, status, &lwpinfo);
447e1976efdSKonstantin Belousov
448e1976efdSKonstantin Belousov while (trace(pid1) >= 0)
449e1976efdSKonstantin Belousov ;
450e1976efdSKonstantin Belousov }
451e1976efdSKonstantin Belousov }
452e1976efdSKonstantin Belousov
453e1976efdSKonstantin Belousov ptrace(PT_CONTINUE, pid, (caddr_t)1, 0);
454e1976efdSKonstantin Belousov }
455e1976efdSKonstantin Belousov return (0);
456e1976efdSKonstantin Belousov }
457