blob: 6765ba3cce390cc334386dcd6fa7c8fd11c4e871 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <signal.h>
37#include <errno.h>
38#include <sys/param.h>
39#include <fcntl.h>
40#include <sys/resource.h>
41#include <sys/wait.h>
42#include <sys/stat.h>
43#include <pwd.h>
44#include <grp.h>
45#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000046#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# include <asm/unistd.h>
51# if defined __NR_tgkill
52# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53# elif defined __NR_tkill
54# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55# else
56 /* kill() may choose arbitrarily the target task of the process group
57 while we later wait on a that specific TID. PID process waits become
58 TID task specific waits for a process under ptrace(2). */
59# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61# endif
62#endif
63
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000064#if defined(IA64) && defined(LINUX)
65# include <asm/ptrace_offsets.h>
66#endif
67
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000068#ifdef USE_PROCFS
69#include <poll.h>
70#endif
71
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000072#ifdef SVR4
73#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000074#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000075#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000076#include <sys/uio.h>
77#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000079#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000080extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000081extern int optind;
82extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000083
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
Roland McGrath41c48222008-07-18 00:25:10 +000085int debug = 0, followfork = 0;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000086int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
87static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000088/*
89 * daemonized_tracer supports -D option.
90 * With this option, strace forks twice.
91 * Unlike normal case, with -D *grandparent* process exec's,
92 * becoming a traced process. Child exits (this prevents traced process
93 * from having children it doesn't expect to have), and grandchild
94 * attaches to grandparent similarly to strace -p PID.
95 * This allows for more transparent interaction in cases
96 * when process and its parent are communicating via signals,
97 * wait() etc. Without -D, strace process gets lodged in between,
98 * disrupting parent<->child link.
99 */
100static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000102/* Sometimes we want to print only succeeding syscalls. */
103int not_failing_only = 0;
104
Dmitry V. Levina6809652008-11-10 17:14:58 +0000105static int exit_code = 0;
106static int strace_child = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700107
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000108static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109uid_t run_uid;
110gid_t run_gid;
111
112int acolumn = DEFAULT_ACOLUMN;
113int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000114static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +0000116struct tcb **tcbtab;
117unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700119extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120
Roland McGrath0a463882007-07-05 18:43:16 +0000121static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122static int trace P((void));
123static void cleanup P((void));
124static void interrupt P((int sig));
125static sigset_t empty_set, blocked_set;
126
127#ifdef HAVE_SIG_ATOMIC_T
128static volatile sig_atomic_t interrupted;
129#else /* !HAVE_SIG_ATOMIC_T */
130#ifdef __STDC__
131static volatile int interrupted;
132#else /* !__STDC__ */
133static int interrupted;
134#endif /* !__STDC__ */
135#endif /* !HAVE_SIG_ATOMIC_T */
136
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000137#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138
139static struct tcb *pfd2tcb P((int pfd));
140static void reaper P((int sig));
141static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000142static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
144#ifndef HAVE_POLLABLE_PROCFS
145
146static void proc_poll_open P((void));
147static void proc_poller P((int pfd));
148
149struct proc_pollfd {
150 int fd;
151 int revents;
152 int pid;
153};
154
155static int poller_pid;
156static int proc_poll_pipe[2] = { -1, -1 };
157
158#endif /* !HAVE_POLLABLE_PROCFS */
159
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000160#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000161#define POLLWANT POLLWRNORM
162#else
163#define POLLWANT POLLPRI
164#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000165#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166
167static void
168usage(ofp, exitval)
169FILE *ofp;
170int exitval;
171{
172 fprintf(ofp, "\
173usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000174 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
175 [command [arg ...]]\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000176 or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000177 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178-c -- count time, calls, and errors for each syscall and report summary\n\
179-f -- follow forks, -ff -- with output into separate files\n\
180-F -- attempt to follow vforks, -h -- print help message\n\
181-i -- print instruction pointer at time of syscall\n\
182-q -- suppress messages about attaching, detaching, etc.\n\
183-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
184-T -- print time spent in each syscall, -V -- print version\n\
185-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
186-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
187-a column -- alignment COLUMN for printing syscall results (default %d)\n\
188-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
189 options: trace, abbrev, verbose, raw, signal, read, or write\n\
190-o file -- send trace output to FILE instead of stderr\n\
191-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
192-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000193-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
195-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
196-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000197-E var=val -- put var=val in the environment for command\n\
198-E var -- remove var from the environment for command\n\
199" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000200-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000201 */
202, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000203 exit(exitval);
204}
205
206#ifdef SVR4
207#ifdef MIPS
208void
209foobar()
210{
211}
212#endif /* MIPS */
213#endif /* SVR4 */
214
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400215/* Glue for systems without a MMU that cannot provide fork() */
216#ifdef HAVE_FORK
217# define strace_vforked 0
218#else
219# define strace_vforked 1
220# define fork() vfork()
221#endif
222
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000223static int
224set_cloexec_flag(int fd)
225{
226 int flags, newflags;
227
228 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
229 {
230 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
231 progname, strerror(errno));
232 return -1;
233 }
234
235 newflags = flags | FD_CLOEXEC;
236 if (flags == newflags)
237 return 0;
238
239 if (fcntl(fd, F_SETFD, newflags) < 0)
240 {
241 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
242 progname, strerror(errno));
243 return -1;
244 }
245
246 return 0;
247}
248
249/*
250 * When strace is setuid executable, we have to swap uids
251 * before and after filesystem and process management operations.
252 */
253static void
254swap_uid(void)
255{
256#ifndef SVR4
257 int euid = geteuid(), uid = getuid();
258
259 if (euid != uid && setreuid(euid, uid) < 0)
260 {
261 fprintf(stderr, "%s: setreuid: %s\n",
262 progname, strerror(errno));
263 exit(1);
264 }
265#endif
266}
267
Roland McGrath4bfa6262007-07-05 20:03:16 +0000268#if _LFS64_LARGEFILE
269# define fopen_for_output fopen64
270#else
271# define fopen_for_output fopen
272#endif
273
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000274static FILE *
275strace_fopen(const char *path, const char *mode)
276{
277 FILE *fp;
278
279 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000280 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000281 fprintf(stderr, "%s: can't fopen '%s': %s\n",
282 progname, path, strerror(errno));
283 swap_uid();
284 if (fp && set_cloexec_flag(fileno(fp)) < 0)
285 {
286 fclose(fp);
287 fp = NULL;
288 }
289 return fp;
290}
291
292static int popen_pid = -1;
293
294#ifndef _PATH_BSHELL
295# define _PATH_BSHELL "/bin/sh"
296#endif
297
298/*
299 * We cannot use standard popen(3) here because we have to distinguish
300 * popen child process from other processes we trace, and standard popen(3)
301 * does not export its child's pid.
302 */
303static FILE *
304strace_popen(const char *command)
305{
306 int fds[2];
307
308 swap_uid();
309 if (pipe(fds) < 0)
310 {
311 fprintf(stderr, "%s: pipe: %s\n",
312 progname, strerror(errno));
313 swap_uid();
314 return NULL;
315 }
316
317 if (set_cloexec_flag(fds[1]) < 0)
318 {
319 close(fds[0]);
320 close(fds[1]);
321 swap_uid();
322 return NULL;
323 }
324
325 if ((popen_pid = fork()) == -1)
326 {
327 fprintf(stderr, "%s: fork: %s\n",
328 progname, strerror(errno));
329 close(fds[0]);
330 close(fds[1]);
331 swap_uid();
332 return NULL;
333 }
334
335 if (popen_pid)
336 {
337 /* parent */
338 close(fds[0]);
339 swap_uid();
340 return fdopen(fds[1], "w");
341 } else
342 {
343 /* child */
344 close(fds[1]);
345 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
346 {
347 fprintf(stderr, "%s: dup2: %s\n",
348 progname, strerror(errno));
349 _exit(1);
350 }
351 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
352 fprintf(stderr, "%s: execl: %s: %s\n",
353 progname, _PATH_BSHELL, strerror(errno));
354 _exit(1);
355 }
356}
357
358static int
359newoutf(struct tcb *tcp)
360{
361 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000362 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000363 FILE *fp;
364
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000365 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000366 if ((fp = strace_fopen(name, "w")) == NULL)
367 return -1;
368 tcp->outf = fp;
369 }
370 return 0;
371}
372
Roland McGrath02203312007-06-11 22:06:31 +0000373static void
374startup_attach(void)
375{
376 int tcbi;
377 struct tcb *tcp;
378
379 /*
380 * Block user interruptions as we would leave the traced
381 * process stopped (process state T) if we would terminate in
382 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
383 * We rely on cleanup () from this point on.
384 */
385 if (interactive)
386 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
387
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000388 if (daemonized_tracer) {
389 pid_t pid = fork();
390 if (pid < 0) {
391 _exit(1);
392 }
393 if (pid) { /* parent */
394 /*
395 * Wait for child to attach to straced process
396 * (our parent). Child SIGKILLs us after it attached.
397 * Parent's wait() is unblocked by our death,
398 * it proceeds to exec the straced program.
399 */
400 pause();
401 _exit(0); /* paranoia */
402 }
403 }
404
Roland McGrath02203312007-06-11 22:06:31 +0000405 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
406 tcp = tcbtab[tcbi];
407 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
408 continue;
409#ifdef LINUX
410 if (tcp->flags & TCB_CLONE_THREAD)
411 continue;
412#endif
413 /* Reinitialize the output since it may have changed. */
414 tcp->outf = outf;
415 if (newoutf(tcp) < 0)
416 exit(1);
417
418#ifdef USE_PROCFS
419 if (proc_open(tcp, 1) < 0) {
420 fprintf(stderr, "trouble opening proc file\n");
421 droptcb(tcp);
422 continue;
423 }
424#else /* !USE_PROCFS */
425# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000426 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000427 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000428 DIR *dir;
429
430 sprintf(procdir, "/proc/%d/task", tcp->pid);
431 dir = opendir(procdir);
432 if (dir != NULL) {
433 unsigned int ntid = 0, nerr = 0;
434 struct dirent *de;
435 int tid;
436 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000437 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000438 continue;
439 tid = atoi(de->d_name);
440 if (tid <= 0)
441 continue;
442 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000443 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000444 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000445 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000446 tcp = alloctcb(tid);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700447 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000448 tcbtab[tcbi]->nchildren++;
449 tcbtab[tcbi]->nclone_threads++;
450 tcbtab[tcbi]->nclone_detached++;
451 tcp->parent = tcbtab[tcbi];
452 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000453 if (interactive) {
454 sigprocmask(SIG_SETMASK, &empty_set, NULL);
455 if (interrupted)
456 return;
457 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
458 }
Roland McGrath02203312007-06-11 22:06:31 +0000459 }
460 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000461 ntid -= nerr;
462 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000463 perror("attach: ptrace(PTRACE_ATTACH, ...)");
464 droptcb(tcp);
465 continue;
466 }
467 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000468 fprintf(stderr, ntid > 1
469? "Process %u attached with %u threads - interrupt to quit\n"
470: "Process %u attached - interrupt to quit\n",
471 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000472 }
473 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000474 } /* if (opendir worked) */
475 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000476# endif
477 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
478 perror("attach: ptrace(PTRACE_ATTACH, ...)");
479 droptcb(tcp);
480 continue;
481 }
482 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000483
484 if (daemonized_tracer) {
485 /*
486 * It is our grandparent we trace, not a -p PID.
487 * Don't want to just detach on exit, so...
488 */
489 tcp->flags &= ~TCB_ATTACHED;
490 /*
491 * Make parent go away.
492 * Also makes grandparent's wait() unblock.
493 */
494 kill(getppid(), SIGKILL);
495 }
496
Roland McGrath02203312007-06-11 22:06:31 +0000497#endif /* !USE_PROCFS */
498 if (!qflag)
499 fprintf(stderr,
500 "Process %u attached - interrupt to quit\n",
501 tcp->pid);
502 }
503
504 if (interactive)
505 sigprocmask(SIG_SETMASK, &empty_set, NULL);
506}
507
508static void
509startup_child (char **argv)
510{
511 struct stat statbuf;
512 const char *filename;
513 char pathname[MAXPATHLEN];
514 int pid = 0;
515 struct tcb *tcp;
516
517 filename = argv[0];
518 if (strchr(filename, '/')) {
519 if (strlen(filename) > sizeof pathname - 1) {
520 errno = ENAMETOOLONG;
521 perror("strace: exec");
522 exit(1);
523 }
524 strcpy(pathname, filename);
525 }
526#ifdef USE_DEBUGGING_EXEC
527 /*
528 * Debuggers customarily check the current directory
529 * first regardless of the path but doing that gives
530 * security geeks a panic attack.
531 */
532 else if (stat(filename, &statbuf) == 0)
533 strcpy(pathname, filename);
534#endif /* USE_DEBUGGING_EXEC */
535 else {
536 char *path;
537 int m, n, len;
538
539 for (path = getenv("PATH"); path && *path; path += m) {
540 if (strchr(path, ':')) {
541 n = strchr(path, ':') - path;
542 m = n + 1;
543 }
544 else
545 m = n = strlen(path);
546 if (n == 0) {
547 if (!getcwd(pathname, MAXPATHLEN))
548 continue;
549 len = strlen(pathname);
550 }
551 else if (n > sizeof pathname - 1)
552 continue;
553 else {
554 strncpy(pathname, path, n);
555 len = n;
556 }
557 if (len && pathname[len - 1] != '/')
558 pathname[len++] = '/';
559 strcpy(pathname + len, filename);
560 if (stat(pathname, &statbuf) == 0 &&
561 /* Accept only regular files
562 with some execute bits set.
563 XXX not perfect, might still fail */
564 S_ISREG(statbuf.st_mode) &&
565 (statbuf.st_mode & 0111))
566 break;
567 }
568 }
569 if (stat(pathname, &statbuf) < 0) {
570 fprintf(stderr, "%s: %s: command not found\n",
571 progname, filename);
572 exit(1);
573 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000574 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000575 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000576 perror("strace: fork");
577 cleanup();
578 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000579 }
580 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
581 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
582 ) {
583 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000584#ifdef USE_PROCFS
585 if (outf != stderr) close (fileno (outf));
586#ifdef MIPS
587 /* Kludge for SGI, see proc_open for details. */
588 sa.sa_handler = foobar;
589 sa.sa_flags = 0;
590 sigemptyset(&sa.sa_mask);
591 sigaction(SIGINT, &sa, NULL);
592#endif /* MIPS */
593#ifndef FREEBSD
594 pause();
595#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000596 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000597#endif /* FREEBSD */
598#else /* !USE_PROCFS */
599 if (outf!=stderr)
600 close(fileno (outf));
601
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000602 if (!daemonized_tracer) {
603 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
604 perror("strace: ptrace(PTRACE_TRACEME, ...)");
605 exit(1);
606 }
607 if (debug)
608 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000609 }
Roland McGrath02203312007-06-11 22:06:31 +0000610
611 if (username != NULL || geteuid() == 0) {
612 uid_t run_euid = run_uid;
613 gid_t run_egid = run_gid;
614
615 if (statbuf.st_mode & S_ISUID)
616 run_euid = statbuf.st_uid;
617 if (statbuf.st_mode & S_ISGID)
618 run_egid = statbuf.st_gid;
619
620 /*
621 * It is important to set groups before we
622 * lose privileges on setuid.
623 */
624 if (username != NULL) {
625 if (initgroups(username, run_gid) < 0) {
626 perror("initgroups");
627 exit(1);
628 }
629 if (setregid(run_gid, run_egid) < 0) {
630 perror("setregid");
631 exit(1);
632 }
633 if (setreuid(run_uid, run_euid) < 0) {
634 perror("setreuid");
635 exit(1);
636 }
637 }
638 }
639 else
640 setreuid(run_uid, run_uid);
641
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000642 if (!daemonized_tracer) {
643 /*
644 * Induce an immediate stop so that the parent
645 * will resume us with PTRACE_SYSCALL and display
646 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400647 * Unless of course we're on a no-MMU system where
648 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000649 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400650 if (!strace_vforked)
651 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000652 } else {
653 struct sigaction sv_sigchld;
654 sigaction(SIGCHLD, NULL, &sv_sigchld);
655 /*
656 * Make sure it is not SIG_IGN, otherwise wait
657 * will not block.
658 */
659 signal(SIGCHLD, SIG_DFL);
660 /*
661 * Wait for grandchild to attach to us.
662 * It kills child after that, and wait() unblocks.
663 */
664 alarm(3);
665 wait(NULL);
666 alarm(0);
667 sigaction(SIGCHLD, &sv_sigchld, NULL);
668 }
Roland McGrath02203312007-06-11 22:06:31 +0000669#endif /* !USE_PROCFS */
670
671 execv(pathname, argv);
672 perror("strace: exec");
673 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000674 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000675
676 /* We are the tracer. */
677 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000678 if (daemonized_tracer) {
679 /* We want subsequent startup_attach() to attach to it. */
680 tcp->flags |= TCB_ATTACHED;
681 }
Roland McGrath02203312007-06-11 22:06:31 +0000682#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 if (proc_open(tcp, 0) < 0) {
684 fprintf(stderr, "trouble opening proc file\n");
685 cleanup();
686 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000687 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000688#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000689}
690
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000691int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000692main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694 struct tcb *tcp;
695 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000696 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697 struct sigaction sa;
698
699 static char buf[BUFSIZ];
700
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000701 progname = argv[0] ? argv[0] : "strace";
702
Roland McGrathee9d4352002-12-18 04:16:10 +0000703 /* Allocate the initial tcbtab. */
704 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000705 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000706 fprintf(stderr, "%s: out of memory\n", progname);
707 exit(1);
708 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000709 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000710 fprintf(stderr, "%s: out of memory\n", progname);
711 exit(1);
712 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000713 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
714 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
715
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000716 outf = stderr;
717 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000718 set_sortby(DEFAULT_SORTBY);
719 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720 qualify("trace=all");
721 qualify("abbrev=all");
722 qualify("verbose=all");
723 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000724 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000725 "+cdfFhiqrtTvVxz"
726#ifndef USE_PROCFS
727 "D"
728#endif
729 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000730 switch (c) {
731 case 'c':
732 cflag++;
733 dtime++;
734 break;
735 case 'd':
736 debug++;
737 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000738#ifndef USE_PROCFS
739 /* Experimental, not documented in manpage yet. */
740 case 'D':
741 daemonized_tracer = 1;
742 break;
743#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000744 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000745 optF = 1;
746 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000747 case 'f':
748 followfork++;
749 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000750 case 'h':
751 usage(stdout, 0);
752 break;
753 case 'i':
754 iflag++;
755 break;
756 case 'q':
757 qflag++;
758 break;
759 case 'r':
760 rflag++;
761 tflag++;
762 break;
763 case 't':
764 tflag++;
765 break;
766 case 'T':
767 dtime++;
768 break;
769 case 'x':
770 xflag++;
771 break;
772 case 'v':
773 qualify("abbrev=none");
774 break;
775 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000776 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777 exit(0);
778 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000779 case 'z':
780 not_failing_only = 1;
781 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000782 case 'a':
783 acolumn = atoi(optarg);
784 break;
785 case 'e':
786 qualify(optarg);
787 break;
788 case 'o':
789 outfname = strdup(optarg);
790 break;
791 case 'O':
792 set_overhead(atoi(optarg));
793 break;
794 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000795 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 fprintf(stderr, "%s: Invalid process id: %s\n",
797 progname, optarg);
798 break;
799 }
800 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000801 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802 break;
803 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000804 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805 tcp->flags |= TCB_ATTACHED;
806 pflag_seen++;
807 break;
808 case 's':
809 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000810 if (max_strlen < 0) {
811 fprintf(stderr,
812 "%s: invalid -s argument: %s\n",
813 progname, optarg);
814 exit(1);
815 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816 break;
817 case 'S':
818 set_sortby(optarg);
819 break;
820 case 'u':
821 username = strdup(optarg);
822 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000823 case 'E':
824 if (putenv(optarg) < 0) {
825 fprintf(stderr, "%s: out of memory\n",
826 progname);
827 exit(1);
828 }
829 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830 default:
831 usage(stderr, 1);
832 break;
833 }
834 }
835
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000836 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000837 usage(stderr, 1);
838
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000839 if (!followfork)
840 followfork = optF;
841
Roland McGrathcb9def62006-04-25 07:48:03 +0000842 if (followfork > 1 && cflag) {
843 fprintf(stderr,
844 "%s: -c and -ff are mutually exclusive options\n",
845 progname);
846 exit(1);
847 }
848
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000849 /* See if they want to run as another user. */
850 if (username != NULL) {
851 struct passwd *pent;
852
853 if (getuid() != 0 || geteuid() != 0) {
854 fprintf(stderr,
855 "%s: you must be root to use the -u option\n",
856 progname);
857 exit(1);
858 }
859 if ((pent = getpwnam(username)) == NULL) {
860 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000861 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000862 exit(1);
863 }
864 run_uid = pent->pw_uid;
865 run_gid = pent->pw_gid;
866 }
867 else {
868 run_uid = getuid();
869 run_gid = getgid();
870 }
871
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000872 /* Check if they want to redirect the output. */
873 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000874 /* See if they want to pipe the output. */
875 if (outfname[0] == '|' || outfname[0] == '!') {
876 /*
877 * We can't do the <outfname>.PID funny business
878 * when using popen, so prohibit it.
879 */
880 if (followfork > 1) {
881 fprintf(stderr, "\
882%s: piping the output and -ff are mutually exclusive options\n",
883 progname);
884 exit(1);
885 }
886
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000887 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000888 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000889 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000890 else if (followfork <= 1 &&
891 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000892 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 }
894
Roland McGrath37b9a662003-11-07 02:26:54 +0000895 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000896 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000897 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000898 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000899 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000900 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000901 /* Valid states here:
902 optind < argc pflag_seen outfname interactive
903 1 0 0 1
904 0 1 0 1
905 1 0 1 0
906 0 1 1 1
907 */
908
909 /* STARTUP_CHILD must be called before the signal handlers get
910 installed below as they are inherited into the spawned process.
911 Also we do not need to be protected by them as during interruption
912 in the STARTUP_CHILD mode we kill the spawned process anyway. */
913 if (!pflag_seen)
914 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916 sigemptyset(&empty_set);
917 sigemptyset(&blocked_set);
918 sa.sa_handler = SIG_IGN;
919 sigemptyset(&sa.sa_mask);
920 sa.sa_flags = 0;
921 sigaction(SIGTTOU, &sa, NULL);
922 sigaction(SIGTTIN, &sa, NULL);
923 if (interactive) {
924 sigaddset(&blocked_set, SIGHUP);
925 sigaddset(&blocked_set, SIGINT);
926 sigaddset(&blocked_set, SIGQUIT);
927 sigaddset(&blocked_set, SIGPIPE);
928 sigaddset(&blocked_set, SIGTERM);
929 sa.sa_handler = interrupt;
930#ifdef SUNOS4
931 /* POSIX signals on sunos4.1 are a little broken. */
932 sa.sa_flags = SA_INTERRUPT;
933#endif /* SUNOS4 */
934 }
935 sigaction(SIGHUP, &sa, NULL);
936 sigaction(SIGINT, &sa, NULL);
937 sigaction(SIGQUIT, &sa, NULL);
938 sigaction(SIGPIPE, &sa, NULL);
939 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000940#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 sa.sa_handler = reaper;
942 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000943#else
944 /* Make sure SIGCHLD has the default action so that waitpid
945 definitely works without losing track of children. The user
946 should not have given us a bogus state to inherit, but he might
947 have. Arguably we should detect SIG_IGN here and pass it on
948 to children, but probably noone really needs that. */
949 sa.sa_handler = SIG_DFL;
950 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000951#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000953 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000954 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000955
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956 if (trace() < 0)
957 exit(1);
958 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000959 fflush(NULL);
960 if (exit_code > 0xff) {
961 /* Child was killed by a signal, mimic that. */
962 exit_code &= 0xff;
963 signal(exit_code, SIG_DFL);
964 raise(exit_code);
965 /* Paranoia - what if this signal is not fatal?
966 Exit with 128 + signo then. */
967 exit_code += 128;
968 }
969 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970}
971
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000972void
973expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000974{
975 /* Allocate some more TCBs and expand the table.
976 We don't want to relocate the TCBs because our
977 callers have pointers and it would be a pain.
978 So tcbtab is a table of pointers. Since we never
979 free the TCBs, we allocate a single chunk of many. */
980 struct tcb **newtab = (struct tcb **)
981 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
982 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
983 sizeof *newtcbs);
984 int i;
985 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000986 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
987 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000988 cleanup();
989 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000990 }
991 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
992 newtab[i] = &newtcbs[i - tcbtabsize];
993 tcbtabsize *= 2;
994 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000995}
996
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000998alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999{
1000 int i;
1001 struct tcb *tcp;
1002
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001003 if (nprocs == tcbtabsize)
1004 expand_tcbtab();
1005
Roland McGrathee9d4352002-12-18 04:16:10 +00001006 for (i = 0; i < tcbtabsize; i++) {
1007 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 if ((tcp->flags & TCB_INUSE) == 0) {
1009 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001010 tcp->parent = NULL;
1011 tcp->nchildren = 0;
1012 tcp->nzombies = 0;
1013#ifdef TCB_CLONE_THREAD
1014 tcp->nclone_threads = tcp->nclone_detached = 0;
1015 tcp->nclone_waiting = 0;
1016#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 tcp->flags = TCB_INUSE | TCB_STARTUP;
1018 tcp->outf = outf; /* Initialise to current out file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001019 tcp->stime.tv_sec = 0;
1020 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 tcp->pfd = -1;
1022 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001023 if (command_options_parsed)
1024 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 return tcp;
1026 }
1027 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001028 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1029 cleanup();
1030 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031}
1032
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001033#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001035proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036{
1037 char proc[32];
1038 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001039#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001040 int i;
1041 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 sigset_t signals;
1043 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001044#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045#ifndef HAVE_POLLABLE_PROCFS
1046 static int last_pfd;
1047#endif
1048
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001049#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001050 /* Open the process pseudo-files in /proc. */
1051 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1052 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 perror("strace: open(\"/proc/...\", ...)");
1054 return -1;
1055 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001056 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 return -1;
1058 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001059 sprintf(proc, "/proc/%d/status", tcp->pid);
1060 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1061 perror("strace: open(\"/proc/...\", ...)");
1062 return -1;
1063 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001064 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001065 return -1;
1066 }
1067 sprintf(proc, "/proc/%d/as", tcp->pid);
1068 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1069 perror("strace: open(\"/proc/...\", ...)");
1070 return -1;
1071 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001072 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001073 return -1;
1074 }
1075#else
1076 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001077#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001078 sprintf(proc, "/proc/%d", tcp->pid);
1079 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001080#else /* FREEBSD */
1081 sprintf(proc, "/proc/%d/mem", tcp->pid);
1082 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1083#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001084 perror("strace: open(\"/proc/...\", ...)");
1085 return -1;
1086 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001087 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001088 return -1;
1089 }
1090#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001091#ifdef FREEBSD
1092 sprintf(proc, "/proc/%d/regs", tcp->pid);
1093 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1094 perror("strace: open(\"/proc/.../regs\", ...)");
1095 return -1;
1096 }
1097 if (cflag) {
1098 sprintf(proc, "/proc/%d/status", tcp->pid);
1099 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1100 perror("strace: open(\"/proc/.../status\", ...)");
1101 return -1;
1102 }
1103 } else
1104 tcp->pfd_status = -1;
1105#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001106 rebuild_pollv();
1107 if (!attaching) {
1108 /*
1109 * Wait for the child to pause. Because of a race
1110 * condition we have to poll for the event.
1111 */
1112 for (;;) {
1113 if (IOCTL_STATUS (tcp) < 0) {
1114 perror("strace: PIOCSTATUS");
1115 return -1;
1116 }
1117 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001118 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001119 }
1120 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001121#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001122 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001123 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001124 perror("strace: PIOCSTOP");
1125 return -1;
1126 }
Roland McGrath553a6092002-12-16 20:40:39 +00001127#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128#ifdef PIOCSET
1129 /* Set Run-on-Last-Close. */
1130 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001131 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 perror("PIOCSET PR_RLC");
1133 return -1;
1134 }
1135 /* Set or Reset Inherit-on-Fork. */
1136 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001137 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138 perror("PIOC{SET,RESET} PR_FORK");
1139 return -1;
1140 }
1141#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001142#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1144 perror("PIOCSRLC");
1145 return -1;
1146 }
1147 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1148 perror("PIOC{S,R}FORK");
1149 return -1;
1150 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001151#else /* FREEBSD */
1152 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1153 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1154 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001155 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001156 }
1157 arg &= ~PF_LINGER;
1158 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001159 perror("PIOCSFL");
1160 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001161 }
1162#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001164#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001165 /* Enable all syscall entries we care about. */
1166 premptyset(&syscalls);
1167 for (i = 1; i < MAX_QUALS; ++i) {
1168 if (i > (sizeof syscalls) * CHAR_BIT) break;
1169 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1170 }
1171 praddset (&syscalls, SYS_execve);
1172 if (followfork) {
1173 praddset (&syscalls, SYS_fork);
1174#ifdef SYS_forkall
1175 praddset (&syscalls, SYS_forkall);
1176#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001177#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001178 praddset (&syscalls, SYS_fork1);
1179#endif
1180#ifdef SYS_rfork1
1181 praddset (&syscalls, SYS_rfork1);
1182#endif
1183#ifdef SYS_rforkall
1184 praddset (&syscalls, SYS_rforkall);
1185#endif
1186 }
1187 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 perror("PIOCSENTRY");
1189 return -1;
1190 }
John Hughes19e49982001-10-19 08:59:12 +00001191 /* Enable the syscall exits. */
1192 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193 perror("PIOSEXIT");
1194 return -1;
1195 }
John Hughes19e49982001-10-19 08:59:12 +00001196 /* Enable signals we care about. */
1197 premptyset(&signals);
1198 for (i = 1; i < MAX_QUALS; ++i) {
1199 if (i > (sizeof signals) * CHAR_BIT) break;
1200 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1201 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001202 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203 perror("PIOCSTRACE");
1204 return -1;
1205 }
John Hughes19e49982001-10-19 08:59:12 +00001206 /* Enable faults we care about */
1207 premptyset(&faults);
1208 for (i = 1; i < MAX_QUALS; ++i) {
1209 if (i > (sizeof faults) * CHAR_BIT) break;
1210 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1211 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001212 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213 perror("PIOCSFAULT");
1214 return -1;
1215 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001216#else /* FREEBSD */
1217 /* set events flags. */
1218 arg = S_SIG | S_SCE | S_SCX ;
1219 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1220 perror("PIOCBIS");
1221 return -1;
1222 }
1223#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 if (!attaching) {
1225#ifdef MIPS
1226 /*
1227 * The SGI PRSABORT doesn't work for pause() so
1228 * we send it a caught signal to wake it up.
1229 */
1230 kill(tcp->pid, SIGINT);
1231#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001232#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001234 arg = PRSABORT;
1235 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 perror("PIOCRUN");
1237 return -1;
1238 }
Roland McGrath553a6092002-12-16 20:40:39 +00001239#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001240#endif /* !MIPS*/
1241#ifdef FREEBSD
1242 /* wake up the child if it received the SIGSTOP */
1243 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001244#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 for (;;) {
1246 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001247 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 perror("PIOCWSTOP");
1249 return -1;
1250 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001251 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001252 tcp->flags &= ~TCB_INSYSCALL;
1253 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001254 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255 break;
1256 }
1257 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001258#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001259 arg = 0;
1260 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001261#else /* FREEBSD */
1262 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001263#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 perror("PIOCRUN");
1265 return -1;
1266 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001267#ifdef FREEBSD
1268 /* handle the case where we "opened" the child before
1269 it did the kill -STOP */
1270 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1271 tcp->status.PR_WHAT == SIGSTOP)
1272 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001273#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001275#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001277#else /* FREEBSD */
1278 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001279 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001280 /* We are attaching to an already running process.
1281 * Try to figure out the state of the process in syscalls,
1282 * to handle the first event well.
1283 * This is done by having a look at the "wchan" property of the
1284 * process, which tells where it is stopped (if it is). */
1285 FILE * status;
1286 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001287
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001288 sprintf(proc, "/proc/%d/status", tcp->pid);
1289 status = fopen(proc, "r");
1290 if (status &&
1291 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1292 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1293 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1294 strcmp(wchan, "stopevent")) {
1295 /* The process is asleep in the middle of a syscall.
1296 Fake the syscall entry event */
1297 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1298 tcp->status.PR_WHY = PR_SYSENTRY;
1299 trace_syscall(tcp);
1300 }
1301 if (status)
1302 fclose(status);
1303 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001304 }
1305#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306#ifndef HAVE_POLLABLE_PROCFS
1307 if (proc_poll_pipe[0] != -1)
1308 proc_poller(tcp->pfd);
1309 else if (nprocs > 1) {
1310 proc_poll_open();
1311 proc_poller(last_pfd);
1312 proc_poller(tcp->pfd);
1313 }
1314 last_pfd = tcp->pfd;
1315#endif /* !HAVE_POLLABLE_PROCFS */
1316 return 0;
1317}
1318
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001319#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001321struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001322pid2tcb(pid)
1323int pid;
1324{
1325 int i;
1326 struct tcb *tcp;
1327
Roland McGrathee9d4352002-12-18 04:16:10 +00001328 for (i = 0; i < tcbtabsize; i++) {
1329 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 if (pid && tcp->pid != pid)
1331 continue;
1332 if (tcp->flags & TCB_INUSE)
1333 return tcp;
1334 }
1335 return NULL;
1336}
1337
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339
1340static struct tcb *
1341pfd2tcb(pfd)
1342int pfd;
1343{
1344 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345
Roland McGrathca16be82003-01-10 19:55:28 +00001346 for (i = 0; i < tcbtabsize; i++) {
1347 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001348 if (tcp->pfd != pfd)
1349 continue;
1350 if (tcp->flags & TCB_INUSE)
1351 return tcp;
1352 }
1353 return NULL;
1354}
1355
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001356#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001357
1358void
1359droptcb(tcp)
1360struct tcb *tcp;
1361{
1362 if (tcp->pid == 0)
1363 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001364#ifdef TCB_CLONE_THREAD
1365 if (tcp->nclone_threads > 0) {
1366 /* There are other threads left in this process, but this
1367 is the one whose PID represents the whole process.
1368 We need to keep this record around as a zombie until
1369 all the threads die. */
1370 tcp->flags |= TCB_EXITING;
1371 return;
1372 }
1373#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374 nprocs--;
1375 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001376
Roland McGrathe29341c2003-01-10 20:14:20 +00001377 if (tcp->parent != NULL) {
1378 tcp->parent->nchildren--;
1379#ifdef TCB_CLONE_THREAD
1380 if (tcp->flags & TCB_CLONE_DETACHED)
1381 tcp->parent->nclone_detached--;
1382 if (tcp->flags & TCB_CLONE_THREAD)
1383 tcp->parent->nclone_threads--;
1384#endif
Roland McGrath09623452003-05-23 02:27:13 +00001385#ifdef TCB_CLONE_DETACHED
1386 if (!(tcp->flags & TCB_CLONE_DETACHED))
1387#endif
1388 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001389#ifdef LINUX
1390 /* Update `tcp->parent->parent->nchildren' and the other fields
1391 like NCLONE_DETACHED, only for zombie group leader that has
1392 already reported and been short-circuited at the top of this
1393 function. The same condition as at the top of DETACH. */
1394 if ((tcp->flags & TCB_CLONE_THREAD) &&
1395 tcp->parent->nclone_threads == 0 &&
1396 (tcp->parent->flags & TCB_EXITING))
1397 droptcb(tcp->parent);
1398#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001399 tcp->parent = NULL;
1400 }
1401
1402 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001403 if (tcp->pfd != -1) {
1404 close(tcp->pfd);
1405 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001406#ifdef FREEBSD
1407 if (tcp->pfd_reg != -1) {
1408 close(tcp->pfd_reg);
1409 tcp->pfd_reg = -1;
1410 }
1411 if (tcp->pfd_status != -1) {
1412 close(tcp->pfd_status);
1413 tcp->pfd_status = -1;
1414 }
Roland McGrath553a6092002-12-16 20:40:39 +00001415#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001416#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001417 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418#endif
1419 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001420
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001421 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001423
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424 tcp->outf = 0;
1425}
1426
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001427#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428
1429static int
1430resume(tcp)
1431struct tcb *tcp;
1432{
1433 if (tcp == NULL)
1434 return -1;
1435
1436 if (!(tcp->flags & TCB_SUSPENDED)) {
1437 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1438 return -1;
1439 }
1440 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001441#ifdef TCB_CLONE_THREAD
1442 if (tcp->flags & TCB_CLONE_THREAD)
1443 tcp->parent->nclone_waiting--;
1444#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001446 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448
1449 if (!qflag)
1450 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1451 return 0;
1452}
1453
Roland McGrath1bfd3102007-08-03 10:02:00 +00001454static int
1455resume_from_tcp (struct tcb *tcp)
1456{
1457 int error = 0;
1458 int resumed = 0;
1459
1460 /* XXX This won't always be quite right (but it never was).
1461 A waiter with argument 0 or < -1 is waiting for any pid in
1462 a particular pgrp, which this child might or might not be
1463 in. The waiter will only wake up if it's argument is -1
1464 or if it's waiting for tcp->pid's pgrp. It makes a
1465 difference to wake up a waiter when there might be more
1466 traced children, because it could get a false ECHILD
1467 error. OTOH, if this was the last child in the pgrp, then
1468 it ought to wake up and get ECHILD. We would have to
1469 search the system for all pid's in the pgrp to be sure.
1470
1471 && (t->waitpid == -1 ||
1472 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1473 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1474 */
1475
1476 if (tcp->parent &&
1477 (tcp->parent->flags & TCB_SUSPENDED) &&
1478 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001479 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001480 ++resumed;
1481 }
1482#ifdef TCB_CLONE_THREAD
1483 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1484 /* Some other threads of our parent are waiting too. */
1485 unsigned int i;
1486
1487 /* Resume all the threads that were waiting for this PID. */
1488 for (i = 0; i < tcbtabsize; i++) {
1489 struct tcb *t = tcbtab[i];
1490 if (t->parent == tcp->parent && t != tcp
1491 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1492 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1493 && t->waitpid == tcp->pid) {
1494 error |= resume (t);
1495 ++resumed;
1496 }
1497 }
1498 if (resumed == 0)
1499 /* Noone was waiting for this PID in particular,
1500 so now we might need to resume some wildcarders. */
1501 for (i = 0; i < tcbtabsize; i++) {
1502 struct tcb *t = tcbtab[i];
1503 if (t->parent == tcp->parent && t != tcp
1504 && ((t->flags
1505 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1506 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1507 && t->waitpid <= 0
1508 ) {
1509 error |= resume (t);
1510 break;
1511 }
1512 }
1513 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001514#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001515
1516 return error;
1517}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001518
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001519#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001520
Roland McGrath0a463882007-07-05 18:43:16 +00001521/* detach traced process; continue with sig
1522 Never call DETACH twice on the same process as both unattached and
1523 attached-unstopped processes give the same ESRCH. For unattached process we
1524 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525
1526static int
1527detach(tcp, sig)
1528struct tcb *tcp;
1529int sig;
1530{
1531 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001532#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001533 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001534 struct tcb *zombie = NULL;
1535
1536 /* If the group leader is lingering only because of this other
1537 thread now dying, then detach the leader as well. */
1538 if ((tcp->flags & TCB_CLONE_THREAD) &&
1539 tcp->parent->nclone_threads == 1 &&
1540 (tcp->parent->flags & TCB_EXITING))
1541 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001542#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543
1544 if (tcp->flags & TCB_BPTSET)
1545 sig = SIGKILL;
1546
1547#ifdef LINUX
1548 /*
1549 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001550 * before detaching. Arghh. We go through hoops
1551 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001553#if defined(SPARC)
1554#undef PTRACE_DETACH
1555#define PTRACE_DETACH PTRACE_SUNDETACH
1556#endif
Roland McGrath02203312007-06-11 22:06:31 +00001557 /*
1558 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1559 * expected SIGSTOP. We must catch exactly one as otherwise the
1560 * detached process would be left stopped (process state T).
1561 */
1562 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1564 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001565 }
1566 else if (errno != ESRCH) {
1567 /* Shouldn't happen. */
1568 perror("detach: ptrace(PTRACE_DETACH, ...)");
1569 }
Roland McGrath134813a2007-06-02 00:07:33 +00001570 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1571 : tcp->pid),
1572 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001573 if (errno != ESRCH)
1574 perror("detach: checking sanity");
1575 }
Roland McGrath02203312007-06-11 22:06:31 +00001576 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1577 ? tcp->parent->pid : tcp->pid),
1578 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001579 if (errno != ESRCH)
1580 perror("detach: stopping child");
1581 }
Roland McGrath02203312007-06-11 22:06:31 +00001582 else
1583 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001584 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001586#ifdef __WALL
1587 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1588 if (errno == ECHILD) /* Already gone. */
1589 break;
1590 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001591 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001592 break;
1593 }
1594#endif /* __WALL */
1595 /* No __WALL here. */
1596 if (waitpid(tcp->pid, &status, 0) < 0) {
1597 if (errno != ECHILD) {
1598 perror("detach: waiting");
1599 break;
1600 }
1601#ifdef __WCLONE
1602 /* If no processes, try clones. */
1603 if (wait4(tcp->pid, &status, __WCLONE,
1604 NULL) < 0) {
1605 if (errno != ECHILD)
1606 perror("detach: waiting");
1607 break;
1608 }
1609#endif /* __WCLONE */
1610 }
1611#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001612 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001613#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 if (!WIFSTOPPED(status)) {
1615 /* Au revoir, mon ami. */
1616 break;
1617 }
1618 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001619 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620 break;
1621 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001622 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001623 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001624 : WSTOPSIG(status));
1625 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001628 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001629#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630
1631#if defined(SUNOS4)
1632 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1633 if (sig && kill(tcp->pid, sig) < 0)
1634 perror("detach: kill");
1635 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001636 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637#endif /* SUNOS4 */
1638
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001639#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001640 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001641#endif
1642
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643 if (!qflag)
1644 fprintf(stderr, "Process %u detached\n", tcp->pid);
1645
1646 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001647
1648#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001649 if (zombie != NULL) {
1650 /* TCP no longer exists therefore you must not detach () it. */
1651 droptcb(zombie);
1652 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001653#endif
1654
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655 return error;
1656}
1657
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001658#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001659
1660static void
1661reaper(sig)
1662int sig;
1663{
1664 int pid;
1665 int status;
1666
1667 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1668#if 0
1669 struct tcb *tcp;
1670
1671 tcp = pid2tcb(pid);
1672 if (tcp)
1673 droptcb(tcp);
1674#endif
1675 }
1676}
1677
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001678#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001679
1680static void
1681cleanup()
1682{
1683 int i;
1684 struct tcb *tcp;
1685
Roland McGrathee9d4352002-12-18 04:16:10 +00001686 for (i = 0; i < tcbtabsize; i++) {
1687 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688 if (!(tcp->flags & TCB_INUSE))
1689 continue;
1690 if (debug)
1691 fprintf(stderr,
1692 "cleanup: looking at pid %u\n", tcp->pid);
1693 if (tcp_last &&
1694 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001695 tprintf(" <unfinished ...>");
1696 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 }
1698 if (tcp->flags & TCB_ATTACHED)
1699 detach(tcp, 0);
1700 else {
1701 kill(tcp->pid, SIGCONT);
1702 kill(tcp->pid, SIGTERM);
1703 }
1704 }
1705 if (cflag)
1706 call_summary(outf);
1707}
1708
1709static void
1710interrupt(sig)
1711int sig;
1712{
1713 interrupted = 1;
1714}
1715
1716#ifndef HAVE_STRERROR
1717
Roland McGrath6d2b3492002-12-30 00:51:30 +00001718#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719extern int sys_nerr;
1720extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001721#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722
1723const char *
1724strerror(errno)
1725int errno;
1726{
1727 static char buf[64];
1728
1729 if (errno < 1 || errno >= sys_nerr) {
1730 sprintf(buf, "Unknown error %d", errno);
1731 return buf;
1732 }
1733 return sys_errlist[errno];
1734}
1735
1736#endif /* HAVE_STERRROR */
1737
1738#ifndef HAVE_STRSIGNAL
1739
Roland McGrath8f474e02003-01-14 07:53:33 +00001740#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001741extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001743#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1744extern char *_sys_siglist[];
1745#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746
1747const char *
1748strsignal(sig)
1749int sig;
1750{
1751 static char buf[64];
1752
1753 if (sig < 1 || sig >= NSIG) {
1754 sprintf(buf, "Unknown signal %d", sig);
1755 return buf;
1756 }
1757#ifdef HAVE__SYS_SIGLIST
1758 return _sys_siglist[sig];
1759#else
1760 return sys_siglist[sig];
1761#endif
1762}
1763
1764#endif /* HAVE_STRSIGNAL */
1765
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001766#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767
1768static void
1769rebuild_pollv()
1770{
1771 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772
Roland McGrathee9d4352002-12-18 04:16:10 +00001773 if (pollv != NULL)
1774 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001775 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001776 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001777 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001778 exit(1);
1779 }
1780
Roland McGrathca16be82003-01-10 19:55:28 +00001781 for (i = j = 0; i < tcbtabsize; i++) {
1782 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783 if (!(tcp->flags & TCB_INUSE))
1784 continue;
1785 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001786 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 j++;
1788 }
1789 if (j != nprocs) {
1790 fprintf(stderr, "strace: proc miscount\n");
1791 exit(1);
1792 }
1793}
1794
1795#ifndef HAVE_POLLABLE_PROCFS
1796
1797static void
1798proc_poll_open()
1799{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800 int i;
1801
1802 if (pipe(proc_poll_pipe) < 0) {
1803 perror("pipe");
1804 exit(1);
1805 }
1806 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001807 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 exit(1);
1809 }
1810 }
1811}
1812
1813static int
1814proc_poll(pollv, nfds, timeout)
1815struct pollfd *pollv;
1816int nfds;
1817int timeout;
1818{
1819 int i;
1820 int n;
1821 struct proc_pollfd pollinfo;
1822
1823 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1824 return n;
1825 if (n != sizeof(struct proc_pollfd)) {
1826 fprintf(stderr, "panic: short read: %d\n", n);
1827 exit(1);
1828 }
1829 for (i = 0; i < nprocs; i++) {
1830 if (pollv[i].fd == pollinfo.fd)
1831 pollv[i].revents = pollinfo.revents;
1832 else
1833 pollv[i].revents = 0;
1834 }
1835 poller_pid = pollinfo.pid;
1836 return 1;
1837}
1838
1839static void
1840wakeup_handler(sig)
1841int sig;
1842{
1843}
1844
1845static void
1846proc_poller(pfd)
1847int pfd;
1848{
1849 struct proc_pollfd pollinfo;
1850 struct sigaction sa;
1851 sigset_t blocked_set, empty_set;
1852 int i;
1853 int n;
1854 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001855#ifdef FREEBSD
1856 struct procfs_status pfs;
1857#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001858
1859 switch (fork()) {
1860 case -1:
1861 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001862 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001863 case 0:
1864 break;
1865 default:
1866 return;
1867 }
1868
1869 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1870 sa.sa_flags = 0;
1871 sigemptyset(&sa.sa_mask);
1872 sigaction(SIGHUP, &sa, NULL);
1873 sigaction(SIGINT, &sa, NULL);
1874 sigaction(SIGQUIT, &sa, NULL);
1875 sigaction(SIGPIPE, &sa, NULL);
1876 sigaction(SIGTERM, &sa, NULL);
1877 sa.sa_handler = wakeup_handler;
1878 sigaction(SIGUSR1, &sa, NULL);
1879 sigemptyset(&blocked_set);
1880 sigaddset(&blocked_set, SIGUSR1);
1881 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1882 sigemptyset(&empty_set);
1883
1884 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1885 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001886 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001887 }
1888 n = rl.rlim_cur;
1889 for (i = 0; i < n; i++) {
1890 if (i != pfd && i != proc_poll_pipe[1])
1891 close(i);
1892 }
1893
1894 pollinfo.fd = pfd;
1895 pollinfo.pid = getpid();
1896 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001897#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001898 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1899#else
1900 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1901#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001902 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903 switch (errno) {
1904 case EINTR:
1905 continue;
1906 case EBADF:
1907 pollinfo.revents = POLLERR;
1908 break;
1909 case ENOENT:
1910 pollinfo.revents = POLLHUP;
1911 break;
1912 default:
1913 perror("proc_poller: PIOCWSTOP");
1914 }
1915 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1916 _exit(0);
1917 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001918 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001919 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1920 sigsuspend(&empty_set);
1921 }
1922}
1923
1924#endif /* !HAVE_POLLABLE_PROCFS */
1925
1926static int
1927choose_pfd()
1928{
1929 int i, j;
1930 struct tcb *tcp;
1931
1932 static int last;
1933
1934 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001935 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936 /*
1937 * The previous process is ready to run again. We'll
1938 * let it do so if it is currently in a syscall. This
1939 * heuristic improves the readability of the trace.
1940 */
1941 tcp = pfd2tcb(pollv[last].fd);
1942 if (tcp && (tcp->flags & TCB_INSYSCALL))
1943 return pollv[last].fd;
1944 }
1945
1946 for (i = 0; i < nprocs; i++) {
1947 /* Let competing children run round robin. */
1948 j = (i + last + 1) % nprocs;
1949 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1950 tcp = pfd2tcb(pollv[j].fd);
1951 if (!tcp) {
1952 fprintf(stderr, "strace: lost proc\n");
1953 exit(1);
1954 }
1955 droptcb(tcp);
1956 return -1;
1957 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001958 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959 last = j;
1960 return pollv[j].fd;
1961 }
1962 }
1963 fprintf(stderr, "strace: nothing ready\n");
1964 exit(1);
1965}
1966
1967static int
1968trace()
1969{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001970#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001971 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001972#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001973 struct tcb *tcp;
1974 int pfd;
1975 int what;
1976 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001977 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001978
1979 for (;;) {
1980 if (interactive)
1981 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1982
1983 if (nprocs == 0)
1984 break;
1985
1986 switch (nprocs) {
1987 case 1:
1988#ifndef HAVE_POLLABLE_PROCFS
1989 if (proc_poll_pipe[0] == -1) {
1990#endif
1991 tcp = pid2tcb(0);
1992 if (!tcp)
1993 continue;
1994 pfd = tcp->pfd;
1995 if (pfd == -1)
1996 continue;
1997 break;
1998#ifndef HAVE_POLLABLE_PROCFS
1999 }
2000 /* fall through ... */
2001#endif /* !HAVE_POLLABLE_PROCFS */
2002 default:
2003#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002004#ifdef POLL_HACK
2005 /* On some systems (e.g. UnixWare) we get too much ugly
2006 "unfinished..." stuff when multiple proceses are in
2007 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002008
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002009 if (in_syscall) {
2010 struct pollfd pv;
2011 tcp = in_syscall;
2012 in_syscall = NULL;
2013 pv.fd = tcp->pfd;
2014 pv.events = POLLWANT;
2015 if ((what = poll (&pv, 1, 1)) < 0) {
2016 if (interrupted)
2017 return 0;
2018 continue;
2019 }
2020 else if (what == 1 && pv.revents & POLLWANT) {
2021 goto FOUND;
2022 }
2023 }
2024#endif
2025
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002026 if (poll(pollv, nprocs, INFTIM) < 0) {
2027 if (interrupted)
2028 return 0;
2029 continue;
2030 }
2031#else /* !HAVE_POLLABLE_PROCFS */
2032 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2033 if (interrupted)
2034 return 0;
2035 continue;
2036 }
2037#endif /* !HAVE_POLLABLE_PROCFS */
2038 pfd = choose_pfd();
2039 if (pfd == -1)
2040 continue;
2041 break;
2042 }
2043
2044 /* Look up `pfd' in our table. */
2045 if ((tcp = pfd2tcb(pfd)) == NULL) {
2046 fprintf(stderr, "unknown pfd: %u\n", pfd);
2047 exit(1);
2048 }
John Hughesb6643082002-05-23 11:02:22 +00002049#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002050 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002051#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052 /* Get the status of the process. */
2053 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002054#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002055 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002056#else /* FREEBSD */
2057 /* Thanks to some scheduling mystery, the first poller
2058 sometimes waits for the already processed end of fork
2059 event. Doing a non blocking poll here solves the problem. */
2060 if (proc_poll_pipe[0] != -1)
2061 ioctl_result = IOCTL_STATUS (tcp);
2062 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002063 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002064#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065 ioctl_errno = errno;
2066#ifndef HAVE_POLLABLE_PROCFS
2067 if (proc_poll_pipe[0] != -1) {
2068 if (ioctl_result < 0)
2069 kill(poller_pid, SIGKILL);
2070 else
2071 kill(poller_pid, SIGUSR1);
2072 }
2073#endif /* !HAVE_POLLABLE_PROCFS */
2074 }
2075 if (interrupted)
2076 return 0;
2077
2078 if (interactive)
2079 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2080
2081 if (ioctl_result < 0) {
2082 /* Find out what happened if it failed. */
2083 switch (ioctl_errno) {
2084 case EINTR:
2085 case EBADF:
2086 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002087#ifdef FREEBSD
2088 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002089#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090 case ENOENT:
2091 droptcb(tcp);
2092 continue;
2093 default:
2094 perror("PIOCWSTOP");
2095 exit(1);
2096 }
2097 }
2098
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002099#ifdef FREEBSD
2100 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2101 /* discard first event for a syscall we never entered */
2102 IOCTL (tcp->pfd, PIOCRUN, 0);
2103 continue;
2104 }
Roland McGrath553a6092002-12-16 20:40:39 +00002105#endif
2106
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 /* clear the just started flag */
2108 tcp->flags &= ~TCB_STARTUP;
2109
2110 /* set current output file */
2111 outf = tcp->outf;
2112
2113 if (cflag) {
2114 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002115#ifdef FREEBSD
2116 char buf[1024];
2117 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002118
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002119 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2120 buf[len] = '\0';
2121 sscanf(buf,
2122 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2123 &stime.tv_sec, &stime.tv_usec);
2124 } else
2125 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002126#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2128 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002129#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2131 tcp->stime = stime;
2132 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002133 what = tcp->status.PR_WHAT;
2134 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002135#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002136 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002137 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2138 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 if (trace_syscall(tcp) < 0) {
2140 fprintf(stderr, "syscall trouble\n");
2141 exit(1);
2142 }
2143 }
2144 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002145#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002147#ifdef POLL_HACK
2148 in_syscall = tcp;
2149#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002150 case PR_SYSEXIT:
2151 if (trace_syscall(tcp) < 0) {
2152 fprintf(stderr, "syscall trouble\n");
2153 exit(1);
2154 }
2155 break;
2156 case PR_SIGNALLED:
2157 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2158 printleader(tcp);
2159 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002160 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002161 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002162#ifdef PR_INFO
2163 if (tcp->status.PR_INFO.si_signo == what) {
2164 printleader(tcp);
2165 tprintf(" siginfo=");
2166 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002167 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002168 }
2169#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 }
2171 break;
2172 case PR_FAULTED:
2173 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2174 printleader(tcp);
2175 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002176 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177 }
2178 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002179#ifdef FREEBSD
2180 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002181 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002182#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002183 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002184 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002185 exit(1);
2186 break;
2187 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002188 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002189#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002190 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002191#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002192 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002193#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002194 perror("PIOCRUN");
2195 exit(1);
2196 }
2197 }
2198 return 0;
2199}
2200
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002201#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002202
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002203#ifdef TCB_GROUP_EXITING
2204/* Handle an exit detach or death signal that is taking all the
2205 related clone threads with it. This is called in three circumstances:
2206 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2207 SIG == 0 Continuing TCP will perform an exit_group syscall.
2208 SIG == other Continuing TCP with SIG will kill the process.
2209*/
2210static int
2211handle_group_exit(struct tcb *tcp, int sig)
2212{
2213 /* We need to locate our records of all the clone threads
2214 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002215 struct tcb *leader = NULL;
2216
2217 if (tcp->flags & TCB_CLONE_THREAD)
2218 leader = tcp->parent;
2219 else if (tcp->nclone_detached > 0)
2220 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002221
2222 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002223 if (leader != NULL && leader != tcp
2224 && !(leader->flags & TCB_GROUP_EXITING)
2225 && !(tcp->flags & TCB_STARTUP)
2226 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002227 fprintf(stderr,
2228 "PANIC: handle_group_exit: %d leader %d\n",
2229 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002230 }
2231 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002232#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002233 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002234#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002235 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002236 }
2237 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002238 /* Mark that we are taking the process down. */
2239 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002240 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002241 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002242 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002243 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002244 } else {
2245 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2246 cleanup();
2247 return -1;
2248 }
2249 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002250 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002251 if (leader != tcp)
2252 droptcb(tcp);
2253 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002254 /* The leader will report to us as parent now,
2255 and then we'll get to the SIG==-1 case. */
2256 return 0;
2257 }
2258 }
2259
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002260 return 0;
2261}
2262#endif
2263
Roland McGratheb9e2e82009-06-02 16:49:22 -07002264static int
2265trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266{
2267 int pid;
2268 int wait_errno;
2269 int status;
2270 struct tcb *tcp;
2271#ifdef LINUX
2272 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002273#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002274 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002275#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002276#endif /* LINUX */
2277
Roland McGratheb9e2e82009-06-02 16:49:22 -07002278 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002279 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002280 return 0;
2281 if (interactive)
2282 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002283#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002284#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002285 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002286 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002287 /* this kernel does not support __WALL */
2288 wait4_options &= ~__WALL;
2289 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002290 pid = wait4(-1, &status, wait4_options,
2291 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002292 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002293 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002294 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002295 pid = wait4(-1, &status, __WCLONE,
2296 cflag ? &ru : NULL);
2297 if (pid == -1) {
2298 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002299 "failed: %s\n", strerror(errno));
2300 }
2301 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002302#else
2303 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2304#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305#endif /* LINUX */
2306#ifdef SUNOS4
2307 pid = wait(&status);
2308#endif /* SUNOS4 */
2309 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002310 if (interactive)
2311 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002313 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002314 switch (wait_errno) {
2315 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002316 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002317 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002318 /*
2319 * We would like to verify this case
2320 * but sometimes a race in Solbourne's
2321 * version of SunOS sometimes reports
2322 * ECHILD before sending us SIGCHILD.
2323 */
2324#if 0
Roland McGratheb9e2e82009-06-02 16:49:22 -07002325 if (nprocs == 0)
2326 return 0;
2327 fprintf(stderr, "strace: proc miscount\n");
2328 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002330 return 0;
2331 default:
2332 errno = wait_errno;
2333 perror("strace: wait");
2334 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002335 }
2336 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002337 if (pid == popen_pid) {
2338 if (WIFEXITED(status) || WIFSIGNALED(status))
2339 popen_pid = -1;
2340 continue;
2341 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002342 if (debug)
2343 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2344
2345 /* Look up `pid' in our table. */
2346 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002347#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002348 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002349 /* This is needed to go with the CLONE_PTRACE
2350 changes in process.c/util.c: we might see
2351 the child's initial trap before we see the
2352 parent return from the clone syscall.
2353 Leave the child suspended until the parent
2354 returns from its system call. Only then
2355 will we have the association of parent and
2356 child so that we know how to do clearbpt
2357 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002358 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002359 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002360 if (!qflag)
2361 fprintf(stderr, "\
2362Process %d attached (waiting for parent)\n",
2363 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002364 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002365 else
2366 /* This can happen if a clone call used
2367 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002368#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002369 {
2370 fprintf(stderr, "unknown pid: %u\n", pid);
2371 if (WIFSTOPPED(status))
2372 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2373 exit(1);
2374 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002375 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002376 /* set current output file */
2377 outf = tcp->outf;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002378 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002379#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002380 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2381 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002382#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002383 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002384
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 if (tcp->flags & TCB_SUSPENDED) {
2386 /*
2387 * Apparently, doing any ptrace() call on a stopped
2388 * process, provokes the kernel to report the process
2389 * status again on a subsequent wait(), even if the
2390 * process has not been actually restarted.
2391 * Since we have inspected the arguments of suspended
2392 * processes we end up here testing for this case.
2393 */
2394 continue;
2395 }
2396 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002397 if (pid == strace_child)
2398 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002399 if (!cflag
2400 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2401 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002402 tprintf("+++ killed by %s %s+++",
2403 signame(WTERMSIG(status)),
2404#ifdef WCOREDUMP
2405 WCOREDUMP(status) ? "(core dumped) " :
2406#endif
2407 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002408 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002409 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002410#ifdef TCB_GROUP_EXITING
2411 handle_group_exit(tcp, -1);
2412#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002413 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002414#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415 continue;
2416 }
2417 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002418 if (pid == strace_child)
2419 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002421 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2422 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002423#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002424 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002425 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002426#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002427 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002428 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002429 "PANIC: attached pid %u exited with %d\n",
2430 pid, WEXITSTATUS(status));
2431 }
Roland McGrath0a396902003-06-10 03:05:53 +00002432 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002433 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002434 tprintf(" <unfinished ... exit status %d>\n",
2435 WEXITSTATUS(status));
2436 tcp_last = NULL;
2437 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002438#ifdef TCB_GROUP_EXITING
2439 handle_group_exit(tcp, -1);
2440#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002441 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002442#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 continue;
2444 }
2445 if (!WIFSTOPPED(status)) {
2446 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2447 droptcb(tcp);
2448 continue;
2449 }
2450 if (debug)
2451 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002452 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002453
Roland McGrath02203312007-06-11 22:06:31 +00002454 /*
2455 * Interestingly, the process may stop
2456 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002457 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002458 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002459 * A no-MMU vforked child won't send up a signal,
2460 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002461 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002462 if ((tcp->flags & TCB_STARTUP) &&
2463 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002464 /*
2465 * This flag is there to keep us in sync.
2466 * Next time this process stops it should
2467 * really be entering a system call.
2468 */
2469 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002470 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002471 /*
2472 * One example is a breakpoint inherited from
2473 * parent through fork ().
2474 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002475 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2476 droptcb(tcp);
2477 cleanup();
2478 return -1;
2479 }
2480 }
2481 goto tracing;
2482 }
2483
Roland McGratheb9e2e82009-06-02 16:49:22 -07002484 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002485 if (WSTOPSIG(status) == SIGSTOP &&
2486 (tcp->flags & TCB_SIGTRAPPED)) {
2487 /*
2488 * Trapped attempt to block SIGTRAP
2489 * Hope we are back in control now.
2490 */
2491 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002492 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002493 cleanup();
2494 return -1;
2495 }
2496 continue;
2497 }
2498 if (!cflag
2499 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002500 unsigned long addr = 0;
2501 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002502#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002503# define PSR_RI 41
2504 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002505 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002506
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002507 upeek(tcp, PT_CR_IPSR, &psr);
2508 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002509
2510 pc += (psr >> PSR_RI) & 0x3;
2511 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2512 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002513#elif defined PTRACE_GETSIGINFO
2514 if (WSTOPSIG(status) == SIGSEGV ||
2515 WSTOPSIG(status) == SIGBUS) {
2516 siginfo_t si;
2517 if (ptrace(PTRACE_GETSIGINFO, pid,
2518 0, &si) == 0)
2519 addr = (unsigned long)
2520 si.si_addr;
2521 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002522#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002523 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002524 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002525 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002526 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002527 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002528 }
Roland McGrath05690952004-10-20 01:00:27 +00002529 if (((tcp->flags & TCB_ATTACHED) ||
2530 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002531 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002532#ifdef TCB_GROUP_EXITING
2533 handle_group_exit(tcp, WSTOPSIG(status));
2534#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002535 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002536#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537 continue;
2538 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002539 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540 cleanup();
2541 return -1;
2542 }
2543 tcp->flags &= ~TCB_SUSPENDED;
2544 continue;
2545 }
Roland McGrath02203312007-06-11 22:06:31 +00002546 /* we handled the STATUS, we are permitted to interrupt now. */
2547 if (interrupted)
2548 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002549 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2550 /* ptrace() failed in trace_syscall() with ESRCH.
2551 * Likely a result of process disappearing mid-flight.
2552 * Observed case: exit_group() terminating
2553 * all processes in thread group. In this case, threads
2554 * "disappear" in an unpredictable moment without any
2555 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002556 */
2557 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002558 if (tcp_last) {
2559 /* Do we have dangling line "syscall(param, param"?
2560 * Finish the line then. We cannot
2561 */
2562 tcp_last->flags |= TCB_REPRINT;
2563 tprintf(" <unfinished ...>");
2564 printtrailer();
2565 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002566 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002567 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002568 ptrace(PTRACE_KILL,
2569 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002570 droptcb(tcp);
2571 }
2572 continue;
2573 }
2574 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002575#ifdef TCB_GROUP_EXITING
2576 if (tcp->flags & TCB_GROUP_EXITING) {
2577 if (handle_group_exit(tcp, 0) < 0)
2578 return -1;
2579 continue;
2580 }
2581#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002582 if (tcp->flags & TCB_ATTACHED)
2583 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002584 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002585 cleanup();
2586 return -1;
2587 }
2588 continue;
2589 }
2590 if (tcp->flags & TCB_SUSPENDED) {
2591 if (!qflag)
2592 fprintf(stderr, "Process %u suspended\n", pid);
2593 continue;
2594 }
2595 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002596 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002597 cleanup();
2598 return -1;
2599 }
2600 }
2601 return 0;
2602}
2603
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002604#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605
2606static int curcol;
2607
2608#ifdef __STDC__
2609#include <stdarg.h>
2610#define VA_START(a, b) va_start(a, b)
2611#else
2612#include <varargs.h>
2613#define VA_START(a, b) va_start(a)
2614#endif
2615
2616void
2617#ifdef __STDC__
2618tprintf(const char *fmt, ...)
2619#else
2620tprintf(fmt, va_alist)
2621char *fmt;
2622va_dcl
2623#endif
2624{
2625 va_list args;
2626
2627 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002628 if (outf) {
2629 int n = vfprintf(outf, fmt, args);
2630 if (n < 0 && outf != stderr)
2631 perror(outfname == NULL
2632 ? "<writing to pipe>" : outfname);
2633 else
2634 curcol += n;
2635 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636 va_end(args);
2637 return;
2638}
2639
2640void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002641printleader(tcp)
2642struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002643{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002644 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002645 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002646 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002647 tprintf(" <unavailable>)");
2648 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002649 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002650 tprintf("= ? <unavailable>\n");
2651 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002652 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002653 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002654 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002655 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002656 }
2657 curcol = 0;
2658 if ((followfork == 1 || pflag_seen > 1) && outfname)
2659 tprintf("%-5d ", tcp->pid);
2660 else if (nprocs > 1 && !outfname)
2661 tprintf("[pid %5u] ", tcp->pid);
2662 if (tflag) {
2663 char str[sizeof("HH:MM:SS")];
2664 struct timeval tv, dtv;
2665 static struct timeval otv;
2666
2667 gettimeofday(&tv, NULL);
2668 if (rflag) {
2669 if (otv.tv_sec == 0)
2670 otv = tv;
2671 tv_sub(&dtv, &tv, &otv);
2672 tprintf("%6ld.%06ld ",
2673 (long) dtv.tv_sec, (long) dtv.tv_usec);
2674 otv = tv;
2675 }
2676 else if (tflag > 2) {
2677 tprintf("%ld.%06ld ",
2678 (long) tv.tv_sec, (long) tv.tv_usec);
2679 }
2680 else {
2681 time_t local = tv.tv_sec;
2682 strftime(str, sizeof(str), "%T", localtime(&local));
2683 if (tflag > 1)
2684 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2685 else
2686 tprintf("%s ", str);
2687 }
2688 }
2689 if (iflag)
2690 printcall(tcp);
2691}
2692
2693void
2694tabto(col)
2695int col;
2696{
2697 if (curcol < col)
2698 tprintf("%*s", col - curcol, "");
2699}
2700
2701void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002702printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002703{
2704 tprintf("\n");
2705 tcp_last = NULL;
2706}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002707
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002708#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002709
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002710int
2711mp_ioctl(int fd, int cmd, void *arg, int size)
2712{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002713 struct iovec iov[2];
2714 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002715
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002716 iov[0].iov_base = &cmd;
2717 iov[0].iov_len = sizeof cmd;
2718 if (arg) {
2719 ++n;
2720 iov[1].iov_base = arg;
2721 iov[1].iov_len = size;
2722 }
Roland McGrath553a6092002-12-16 20:40:39 +00002723
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002724 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002725}
2726
2727#endif