blob: 21febb3519a88ffb11c97dde8b634e1bd25eff3f [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. Levine3a7ef52010-03-28 19:24:54 +000086int dtime = 0, xflag = 0, qflag = 0;
87cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000088static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000089/*
90 * daemonized_tracer supports -D option.
91 * With this option, strace forks twice.
92 * Unlike normal case, with -D *grandparent* process exec's,
93 * becoming a traced process. Child exits (this prevents traced process
94 * from having children it doesn't expect to have), and grandchild
95 * attaches to grandparent similarly to strace -p PID.
96 * This allows for more transparent interaction in cases
97 * when process and its parent are communicating via signals,
98 * wait() etc. Without -D, strace process gets lodged in between,
99 * disrupting parent<->child link.
100 */
101static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000103/* Sometimes we want to print only succeeding syscalls. */
104int not_failing_only = 0;
105
Dmitry V. Levina6809652008-11-10 17:14:58 +0000106static int exit_code = 0;
107static int strace_child = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700108
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000109static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110uid_t run_uid;
111gid_t run_gid;
112
113int acolumn = DEFAULT_ACOLUMN;
114int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000115static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100117static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000118struct tcb **tcbtab;
119unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700121extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122
Andreas Schwabe5355de2009-10-27 16:56:43 +0100123static int detach(struct tcb *tcp, int sig);
124static int trace(void);
125static void cleanup(void);
126static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127static sigset_t empty_set, blocked_set;
128
129#ifdef HAVE_SIG_ATOMIC_T
130static volatile sig_atomic_t interrupted;
131#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133#endif /* !HAVE_SIG_ATOMIC_T */
134
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000135#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136
Andreas Schwabe5355de2009-10-27 16:56:43 +0100137static struct tcb *pfd2tcb(int pfd);
138static void reaper(int sig);
139static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000140static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141
142#ifndef HAVE_POLLABLE_PROCFS
143
Andreas Schwabe5355de2009-10-27 16:56:43 +0100144static void proc_poll_open(void);
145static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146
147struct proc_pollfd {
148 int fd;
149 int revents;
150 int pid;
151};
152
153static int poller_pid;
154static int proc_poll_pipe[2] = { -1, -1 };
155
156#endif /* !HAVE_POLLABLE_PROCFS */
157
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000158#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000159#define POLLWANT POLLWRNORM
160#else
161#define POLLWANT POLLPRI
162#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000163#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164
165static void
166usage(ofp, exitval)
167FILE *ofp;
168int exitval;
169{
170 fprintf(ofp, "\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200171usage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000172 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
173 [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200174 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000175 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200177-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178-f -- follow forks, -ff -- with output into separate files\n\
179-F -- attempt to follow vforks, -h -- print help message\n\
180-i -- print instruction pointer at time of syscall\n\
181-q -- suppress messages about attaching, detaching, etc.\n\
182-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
183-T -- print time spent in each syscall, -V -- print version\n\
184-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
185-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
186-a column -- alignment COLUMN for printing syscall results (default %d)\n\
187-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
188 options: trace, abbrev, verbose, raw, signal, read, or write\n\
189-o file -- send trace output to FILE instead of stderr\n\
190-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
191-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000192-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
194-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
195-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000196-E var=val -- put var=val in the environment for command\n\
197-E var -- remove var from the environment for command\n\
198" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000199-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000200 */
201, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202 exit(exitval);
203}
204
205#ifdef SVR4
206#ifdef MIPS
207void
208foobar()
209{
210}
211#endif /* MIPS */
212#endif /* SVR4 */
213
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400214/* Glue for systems without a MMU that cannot provide fork() */
215#ifdef HAVE_FORK
216# define strace_vforked 0
217#else
218# define strace_vforked 1
219# define fork() vfork()
220#endif
221
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000222static int
223set_cloexec_flag(int fd)
224{
225 int flags, newflags;
226
227 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
228 {
229 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
230 progname, strerror(errno));
231 return -1;
232 }
233
234 newflags = flags | FD_CLOEXEC;
235 if (flags == newflags)
236 return 0;
237
238 if (fcntl(fd, F_SETFD, newflags) < 0)
239 {
240 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
241 progname, strerror(errno));
242 return -1;
243 }
244
245 return 0;
246}
247
248/*
249 * When strace is setuid executable, we have to swap uids
250 * before and after filesystem and process management operations.
251 */
252static void
253swap_uid(void)
254{
255#ifndef SVR4
256 int euid = geteuid(), uid = getuid();
257
258 if (euid != uid && setreuid(euid, uid) < 0)
259 {
260 fprintf(stderr, "%s: setreuid: %s\n",
261 progname, strerror(errno));
262 exit(1);
263 }
264#endif
265}
266
Roland McGrath4bfa6262007-07-05 20:03:16 +0000267#if _LFS64_LARGEFILE
268# define fopen_for_output fopen64
269#else
270# define fopen_for_output fopen
271#endif
272
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000273static FILE *
274strace_fopen(const char *path, const char *mode)
275{
276 FILE *fp;
277
278 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000279 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000280 fprintf(stderr, "%s: can't fopen '%s': %s\n",
281 progname, path, strerror(errno));
282 swap_uid();
283 if (fp && set_cloexec_flag(fileno(fp)) < 0)
284 {
285 fclose(fp);
286 fp = NULL;
287 }
288 return fp;
289}
290
291static int popen_pid = -1;
292
293#ifndef _PATH_BSHELL
294# define _PATH_BSHELL "/bin/sh"
295#endif
296
297/*
298 * We cannot use standard popen(3) here because we have to distinguish
299 * popen child process from other processes we trace, and standard popen(3)
300 * does not export its child's pid.
301 */
302static FILE *
303strace_popen(const char *command)
304{
305 int fds[2];
306
307 swap_uid();
308 if (pipe(fds) < 0)
309 {
310 fprintf(stderr, "%s: pipe: %s\n",
311 progname, strerror(errno));
312 swap_uid();
313 return NULL;
314 }
315
316 if (set_cloexec_flag(fds[1]) < 0)
317 {
318 close(fds[0]);
319 close(fds[1]);
320 swap_uid();
321 return NULL;
322 }
323
324 if ((popen_pid = fork()) == -1)
325 {
326 fprintf(stderr, "%s: fork: %s\n",
327 progname, strerror(errno));
328 close(fds[0]);
329 close(fds[1]);
330 swap_uid();
331 return NULL;
332 }
333
334 if (popen_pid)
335 {
336 /* parent */
337 close(fds[0]);
338 swap_uid();
339 return fdopen(fds[1], "w");
340 } else
341 {
342 /* child */
343 close(fds[1]);
344 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
345 {
346 fprintf(stderr, "%s: dup2: %s\n",
347 progname, strerror(errno));
348 _exit(1);
349 }
350 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
351 fprintf(stderr, "%s: execl: %s: %s\n",
352 progname, _PATH_BSHELL, strerror(errno));
353 _exit(1);
354 }
355}
356
357static int
358newoutf(struct tcb *tcp)
359{
360 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000361 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362 FILE *fp;
363
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000364 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000365 if ((fp = strace_fopen(name, "w")) == NULL)
366 return -1;
367 tcp->outf = fp;
368 }
369 return 0;
370}
371
Roland McGrath02203312007-06-11 22:06:31 +0000372static void
373startup_attach(void)
374{
375 int tcbi;
376 struct tcb *tcp;
377
378 /*
379 * Block user interruptions as we would leave the traced
380 * process stopped (process state T) if we would terminate in
381 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
382 * We rely on cleanup () from this point on.
383 */
384 if (interactive)
385 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
386
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000387 if (daemonized_tracer) {
388 pid_t pid = fork();
389 if (pid < 0) {
390 _exit(1);
391 }
392 if (pid) { /* parent */
393 /*
394 * Wait for child to attach to straced process
395 * (our parent). Child SIGKILLs us after it attached.
396 * Parent's wait() is unblocked by our death,
397 * it proceeds to exec the straced program.
398 */
399 pause();
400 _exit(0); /* paranoia */
401 }
402 }
403
Roland McGrath02203312007-06-11 22:06:31 +0000404 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
405 tcp = tcbtab[tcbi];
406 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
407 continue;
408#ifdef LINUX
409 if (tcp->flags & TCB_CLONE_THREAD)
410 continue;
411#endif
412 /* Reinitialize the output since it may have changed. */
413 tcp->outf = outf;
414 if (newoutf(tcp) < 0)
415 exit(1);
416
417#ifdef USE_PROCFS
418 if (proc_open(tcp, 1) < 0) {
419 fprintf(stderr, "trouble opening proc file\n");
420 droptcb(tcp);
421 continue;
422 }
423#else /* !USE_PROCFS */
424# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000425 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000426 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000427 DIR *dir;
428
429 sprintf(procdir, "/proc/%d/task", tcp->pid);
430 dir = opendir(procdir);
431 if (dir != NULL) {
432 unsigned int ntid = 0, nerr = 0;
433 struct dirent *de;
434 int tid;
435 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000436 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000437 continue;
438 tid = atoi(de->d_name);
439 if (tid <= 0)
440 continue;
441 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000442 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000443 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000444 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000445 tcp = alloctcb(tid);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700446 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000447 tcbtab[tcbi]->nchildren++;
448 tcbtab[tcbi]->nclone_threads++;
449 tcbtab[tcbi]->nclone_detached++;
450 tcp->parent = tcbtab[tcbi];
451 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000452 if (interactive) {
453 sigprocmask(SIG_SETMASK, &empty_set, NULL);
454 if (interrupted)
455 return;
456 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
457 }
Roland McGrath02203312007-06-11 22:06:31 +0000458 }
459 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000460 ntid -= nerr;
461 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000462 perror("attach: ptrace(PTRACE_ATTACH, ...)");
463 droptcb(tcp);
464 continue;
465 }
466 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000467 fprintf(stderr, ntid > 1
468? "Process %u attached with %u threads - interrupt to quit\n"
469: "Process %u attached - interrupt to quit\n",
470 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000471 }
472 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000473 } /* if (opendir worked) */
474 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000475# endif
476 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
477 perror("attach: ptrace(PTRACE_ATTACH, ...)");
478 droptcb(tcp);
479 continue;
480 }
481 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000482
483 if (daemonized_tracer) {
484 /*
485 * It is our grandparent we trace, not a -p PID.
486 * Don't want to just detach on exit, so...
487 */
488 tcp->flags &= ~TCB_ATTACHED;
489 /*
490 * Make parent go away.
491 * Also makes grandparent's wait() unblock.
492 */
493 kill(getppid(), SIGKILL);
494 }
495
Roland McGrath02203312007-06-11 22:06:31 +0000496#endif /* !USE_PROCFS */
497 if (!qflag)
498 fprintf(stderr,
499 "Process %u attached - interrupt to quit\n",
500 tcp->pid);
501 }
502
503 if (interactive)
504 sigprocmask(SIG_SETMASK, &empty_set, NULL);
505}
506
507static void
508startup_child (char **argv)
509{
510 struct stat statbuf;
511 const char *filename;
512 char pathname[MAXPATHLEN];
513 int pid = 0;
514 struct tcb *tcp;
515
516 filename = argv[0];
517 if (strchr(filename, '/')) {
518 if (strlen(filename) > sizeof pathname - 1) {
519 errno = ENAMETOOLONG;
520 perror("strace: exec");
521 exit(1);
522 }
523 strcpy(pathname, filename);
524 }
525#ifdef USE_DEBUGGING_EXEC
526 /*
527 * Debuggers customarily check the current directory
528 * first regardless of the path but doing that gives
529 * security geeks a panic attack.
530 */
531 else if (stat(filename, &statbuf) == 0)
532 strcpy(pathname, filename);
533#endif /* USE_DEBUGGING_EXEC */
534 else {
535 char *path;
536 int m, n, len;
537
538 for (path = getenv("PATH"); path && *path; path += m) {
539 if (strchr(path, ':')) {
540 n = strchr(path, ':') - path;
541 m = n + 1;
542 }
543 else
544 m = n = strlen(path);
545 if (n == 0) {
546 if (!getcwd(pathname, MAXPATHLEN))
547 continue;
548 len = strlen(pathname);
549 }
550 else if (n > sizeof pathname - 1)
551 continue;
552 else {
553 strncpy(pathname, path, n);
554 len = n;
555 }
556 if (len && pathname[len - 1] != '/')
557 pathname[len++] = '/';
558 strcpy(pathname + len, filename);
559 if (stat(pathname, &statbuf) == 0 &&
560 /* Accept only regular files
561 with some execute bits set.
562 XXX not perfect, might still fail */
563 S_ISREG(statbuf.st_mode) &&
564 (statbuf.st_mode & 0111))
565 break;
566 }
567 }
568 if (stat(pathname, &statbuf) < 0) {
569 fprintf(stderr, "%s: %s: command not found\n",
570 progname, filename);
571 exit(1);
572 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000573 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000574 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000575 perror("strace: fork");
576 cleanup();
577 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000578 }
579 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
580 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
581 ) {
582 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000583#ifdef USE_PROCFS
584 if (outf != stderr) close (fileno (outf));
585#ifdef MIPS
586 /* Kludge for SGI, see proc_open for details. */
587 sa.sa_handler = foobar;
588 sa.sa_flags = 0;
589 sigemptyset(&sa.sa_mask);
590 sigaction(SIGINT, &sa, NULL);
591#endif /* MIPS */
592#ifndef FREEBSD
593 pause();
594#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000595 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000596#endif /* FREEBSD */
597#else /* !USE_PROCFS */
598 if (outf!=stderr)
599 close(fileno (outf));
600
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000601 if (!daemonized_tracer) {
602 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
603 perror("strace: ptrace(PTRACE_TRACEME, ...)");
604 exit(1);
605 }
606 if (debug)
607 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000608 }
Roland McGrath02203312007-06-11 22:06:31 +0000609
610 if (username != NULL || geteuid() == 0) {
611 uid_t run_euid = run_uid;
612 gid_t run_egid = run_gid;
613
614 if (statbuf.st_mode & S_ISUID)
615 run_euid = statbuf.st_uid;
616 if (statbuf.st_mode & S_ISGID)
617 run_egid = statbuf.st_gid;
618
619 /*
620 * It is important to set groups before we
621 * lose privileges on setuid.
622 */
623 if (username != NULL) {
624 if (initgroups(username, run_gid) < 0) {
625 perror("initgroups");
626 exit(1);
627 }
628 if (setregid(run_gid, run_egid) < 0) {
629 perror("setregid");
630 exit(1);
631 }
632 if (setreuid(run_uid, run_euid) < 0) {
633 perror("setreuid");
634 exit(1);
635 }
636 }
637 }
638 else
639 setreuid(run_uid, run_uid);
640
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000641 if (!daemonized_tracer) {
642 /*
643 * Induce an immediate stop so that the parent
644 * will resume us with PTRACE_SYSCALL and display
645 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400646 * Unless of course we're on a no-MMU system where
647 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000648 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400649 if (!strace_vforked)
650 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000651 } else {
652 struct sigaction sv_sigchld;
653 sigaction(SIGCHLD, NULL, &sv_sigchld);
654 /*
655 * Make sure it is not SIG_IGN, otherwise wait
656 * will not block.
657 */
658 signal(SIGCHLD, SIG_DFL);
659 /*
660 * Wait for grandchild to attach to us.
661 * It kills child after that, and wait() unblocks.
662 */
663 alarm(3);
664 wait(NULL);
665 alarm(0);
666 sigaction(SIGCHLD, &sv_sigchld, NULL);
667 }
Roland McGrath02203312007-06-11 22:06:31 +0000668#endif /* !USE_PROCFS */
669
670 execv(pathname, argv);
671 perror("strace: exec");
672 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000673 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000674
675 /* We are the tracer. */
676 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677 if (daemonized_tracer) {
678 /* We want subsequent startup_attach() to attach to it. */
679 tcp->flags |= TCB_ATTACHED;
680 }
Roland McGrath02203312007-06-11 22:06:31 +0000681#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000682 if (proc_open(tcp, 0) < 0) {
683 fprintf(stderr, "trouble opening proc file\n");
684 cleanup();
685 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000686 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000687#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000688}
689
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000691main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693 struct tcb *tcp;
694 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000695 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000696 struct sigaction sa;
697
698 static char buf[BUFSIZ];
699
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000700 progname = argv[0] ? argv[0] : "strace";
701
Roland McGrathee9d4352002-12-18 04:16:10 +0000702 /* Allocate the initial tcbtab. */
703 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000704 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000705 fprintf(stderr, "%s: out of memory\n", progname);
706 exit(1);
707 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000708 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000709 fprintf(stderr, "%s: out of memory\n", progname);
710 exit(1);
711 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000712 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
713 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
714
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 outf = stderr;
716 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000717 set_sortby(DEFAULT_SORTBY);
718 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 qualify("trace=all");
720 qualify("abbrev=all");
721 qualify("verbose=all");
722 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 while ((c = getopt(argc, argv,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000724 "+cCdfFhiqrtTvVxz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000725#ifndef USE_PROCFS
726 "D"
727#endif
728 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000729 switch (c) {
730 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000731 if (cflag == CFLAG_BOTH) {
732 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
733 progname);
734 exit(1);
735 }
736 cflag = CFLAG_ONLY_STATS;
737 break;
738 case 'C':
739 if (cflag == CFLAG_ONLY_STATS) {
740 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
741 progname);
742 exit(1);
743 }
744 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000745 break;
746 case 'd':
747 debug++;
748 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000749#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000750 case 'D':
751 daemonized_tracer = 1;
752 break;
753#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000754 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000755 optF = 1;
756 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757 case 'f':
758 followfork++;
759 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 case 'h':
761 usage(stdout, 0);
762 break;
763 case 'i':
764 iflag++;
765 break;
766 case 'q':
767 qflag++;
768 break;
769 case 'r':
770 rflag++;
771 tflag++;
772 break;
773 case 't':
774 tflag++;
775 break;
776 case 'T':
777 dtime++;
778 break;
779 case 'x':
780 xflag++;
781 break;
782 case 'v':
783 qualify("abbrev=none");
784 break;
785 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000786 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787 exit(0);
788 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000789 case 'z':
790 not_failing_only = 1;
791 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 case 'a':
793 acolumn = atoi(optarg);
794 break;
795 case 'e':
796 qualify(optarg);
797 break;
798 case 'o':
799 outfname = strdup(optarg);
800 break;
801 case 'O':
802 set_overhead(atoi(optarg));
803 break;
804 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000805 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 fprintf(stderr, "%s: Invalid process id: %s\n",
807 progname, optarg);
808 break;
809 }
810 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000811 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 break;
813 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000814 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815 tcp->flags |= TCB_ATTACHED;
816 pflag_seen++;
817 break;
818 case 's':
819 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000820 if (max_strlen < 0) {
821 fprintf(stderr,
822 "%s: invalid -s argument: %s\n",
823 progname, optarg);
824 exit(1);
825 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 break;
827 case 'S':
828 set_sortby(optarg);
829 break;
830 case 'u':
831 username = strdup(optarg);
832 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000833 case 'E':
834 if (putenv(optarg) < 0) {
835 fprintf(stderr, "%s: out of memory\n",
836 progname);
837 exit(1);
838 }
839 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 default:
841 usage(stderr, 1);
842 break;
843 }
844 }
845
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000846 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000847 usage(stderr, 1);
848
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000849 if (!followfork)
850 followfork = optF;
851
Roland McGrathcb9def62006-04-25 07:48:03 +0000852 if (followfork > 1 && cflag) {
853 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000854 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +0000855 progname);
856 exit(1);
857 }
858
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000859 /* See if they want to run as another user. */
860 if (username != NULL) {
861 struct passwd *pent;
862
863 if (getuid() != 0 || geteuid() != 0) {
864 fprintf(stderr,
865 "%s: you must be root to use the -u option\n",
866 progname);
867 exit(1);
868 }
869 if ((pent = getpwnam(username)) == NULL) {
870 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000871 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000872 exit(1);
873 }
874 run_uid = pent->pw_uid;
875 run_gid = pent->pw_gid;
876 }
877 else {
878 run_uid = getuid();
879 run_gid = getgid();
880 }
881
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 /* Check if they want to redirect the output. */
883 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000884 /* See if they want to pipe the output. */
885 if (outfname[0] == '|' || outfname[0] == '!') {
886 /*
887 * We can't do the <outfname>.PID funny business
888 * when using popen, so prohibit it.
889 */
890 if (followfork > 1) {
891 fprintf(stderr, "\
892%s: piping the output and -ff are mutually exclusive options\n",
893 progname);
894 exit(1);
895 }
896
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000897 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000898 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000899 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000900 else if (followfork <= 1 &&
901 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903 }
904
Roland McGrath37b9a662003-11-07 02:26:54 +0000905 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000907 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000908 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000910 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000911 /* Valid states here:
912 optind < argc pflag_seen outfname interactive
913 1 0 0 1
914 0 1 0 1
915 1 0 1 0
916 0 1 1 1
917 */
918
919 /* STARTUP_CHILD must be called before the signal handlers get
920 installed below as they are inherited into the spawned process.
921 Also we do not need to be protected by them as during interruption
922 in the STARTUP_CHILD mode we kill the spawned process anyway. */
923 if (!pflag_seen)
924 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926 sigemptyset(&empty_set);
927 sigemptyset(&blocked_set);
928 sa.sa_handler = SIG_IGN;
929 sigemptyset(&sa.sa_mask);
930 sa.sa_flags = 0;
931 sigaction(SIGTTOU, &sa, NULL);
932 sigaction(SIGTTIN, &sa, NULL);
933 if (interactive) {
934 sigaddset(&blocked_set, SIGHUP);
935 sigaddset(&blocked_set, SIGINT);
936 sigaddset(&blocked_set, SIGQUIT);
937 sigaddset(&blocked_set, SIGPIPE);
938 sigaddset(&blocked_set, SIGTERM);
939 sa.sa_handler = interrupt;
940#ifdef SUNOS4
941 /* POSIX signals on sunos4.1 are a little broken. */
942 sa.sa_flags = SA_INTERRUPT;
943#endif /* SUNOS4 */
944 }
945 sigaction(SIGHUP, &sa, NULL);
946 sigaction(SIGINT, &sa, NULL);
947 sigaction(SIGQUIT, &sa, NULL);
948 sigaction(SIGPIPE, &sa, NULL);
949 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000950#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 sa.sa_handler = reaper;
952 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000953#else
954 /* Make sure SIGCHLD has the default action so that waitpid
955 definitely works without losing track of children. The user
956 should not have given us a bogus state to inherit, but he might
957 have. Arguably we should detect SIG_IGN here and pass it on
958 to children, but probably noone really needs that. */
959 sa.sa_handler = SIG_DFL;
960 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000961#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000963 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000964 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000965
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 if (trace() < 0)
967 exit(1);
968 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000969 fflush(NULL);
970 if (exit_code > 0xff) {
971 /* Child was killed by a signal, mimic that. */
972 exit_code &= 0xff;
973 signal(exit_code, SIG_DFL);
974 raise(exit_code);
975 /* Paranoia - what if this signal is not fatal?
976 Exit with 128 + signo then. */
977 exit_code += 128;
978 }
979 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980}
981
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000982void
983expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000984{
985 /* Allocate some more TCBs and expand the table.
986 We don't want to relocate the TCBs because our
987 callers have pointers and it would be a pain.
988 So tcbtab is a table of pointers. Since we never
989 free the TCBs, we allocate a single chunk of many. */
990 struct tcb **newtab = (struct tcb **)
991 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
992 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
993 sizeof *newtcbs);
994 int i;
995 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000996 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
997 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000998 cleanup();
999 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001000 }
1001 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1002 newtab[i] = &newtcbs[i - tcbtabsize];
1003 tcbtabsize *= 2;
1004 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001005}
1006
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001008alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009{
1010 int i;
1011 struct tcb *tcp;
1012
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001013 if (nprocs == tcbtabsize)
1014 expand_tcbtab();
1015
Roland McGrathee9d4352002-12-18 04:16:10 +00001016 for (i = 0; i < tcbtabsize; i++) {
1017 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 if ((tcp->flags & TCB_INUSE) == 0) {
1019 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001020 tcp->parent = NULL;
1021 tcp->nchildren = 0;
1022 tcp->nzombies = 0;
1023#ifdef TCB_CLONE_THREAD
1024 tcp->nclone_threads = tcp->nclone_detached = 0;
1025 tcp->nclone_waiting = 0;
1026#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 tcp->flags = TCB_INUSE | TCB_STARTUP;
1028 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001029 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001030 tcp->stime.tv_sec = 0;
1031 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 tcp->pfd = -1;
1033 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001034 if (command_options_parsed)
1035 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036 return tcp;
1037 }
1038 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001039 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1040 cleanup();
1041 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042}
1043
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001044#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001046proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047{
1048 char proc[32];
1049 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001050#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001051 int i;
1052 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 sigset_t signals;
1054 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001055#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056#ifndef HAVE_POLLABLE_PROCFS
1057 static int last_pfd;
1058#endif
1059
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001060#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001061 /* Open the process pseudo-files in /proc. */
1062 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1063 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 perror("strace: open(\"/proc/...\", ...)");
1065 return -1;
1066 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001067 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 return -1;
1069 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001070 sprintf(proc, "/proc/%d/status", tcp->pid);
1071 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1072 perror("strace: open(\"/proc/...\", ...)");
1073 return -1;
1074 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001075 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001076 return -1;
1077 }
1078 sprintf(proc, "/proc/%d/as", tcp->pid);
1079 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1080 perror("strace: open(\"/proc/...\", ...)");
1081 return -1;
1082 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001083 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001084 return -1;
1085 }
1086#else
1087 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001088#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001089 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001090 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001091#else /* FREEBSD */
1092 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001093 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001094#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001095 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001096 perror("strace: open(\"/proc/...\", ...)");
1097 return -1;
1098 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001099 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001100 return -1;
1101 }
1102#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001103#ifdef FREEBSD
1104 sprintf(proc, "/proc/%d/regs", tcp->pid);
1105 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1106 perror("strace: open(\"/proc/.../regs\", ...)");
1107 return -1;
1108 }
1109 if (cflag) {
1110 sprintf(proc, "/proc/%d/status", tcp->pid);
1111 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1112 perror("strace: open(\"/proc/.../status\", ...)");
1113 return -1;
1114 }
1115 } else
1116 tcp->pfd_status = -1;
1117#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001118 rebuild_pollv();
1119 if (!attaching) {
1120 /*
1121 * Wait for the child to pause. Because of a race
1122 * condition we have to poll for the event.
1123 */
1124 for (;;) {
1125 if (IOCTL_STATUS (tcp) < 0) {
1126 perror("strace: PIOCSTATUS");
1127 return -1;
1128 }
1129 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001130 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001131 }
1132 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001133#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001134 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001135 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001136 perror("strace: PIOCSTOP");
1137 return -1;
1138 }
Roland McGrath553a6092002-12-16 20:40:39 +00001139#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140#ifdef PIOCSET
1141 /* Set Run-on-Last-Close. */
1142 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001143 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 perror("PIOCSET PR_RLC");
1145 return -1;
1146 }
1147 /* Set or Reset Inherit-on-Fork. */
1148 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001149 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 perror("PIOC{SET,RESET} PR_FORK");
1151 return -1;
1152 }
1153#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001154#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1156 perror("PIOCSRLC");
1157 return -1;
1158 }
1159 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1160 perror("PIOC{S,R}FORK");
1161 return -1;
1162 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001163#else /* FREEBSD */
1164 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1165 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1166 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001167 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001168 }
1169 arg &= ~PF_LINGER;
1170 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001171 perror("PIOCSFL");
1172 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001173 }
1174#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001176#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001177 /* Enable all syscall entries we care about. */
1178 premptyset(&syscalls);
1179 for (i = 1; i < MAX_QUALS; ++i) {
1180 if (i > (sizeof syscalls) * CHAR_BIT) break;
1181 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1182 }
1183 praddset (&syscalls, SYS_execve);
1184 if (followfork) {
1185 praddset (&syscalls, SYS_fork);
1186#ifdef SYS_forkall
1187 praddset (&syscalls, SYS_forkall);
1188#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001189#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001190 praddset (&syscalls, SYS_fork1);
1191#endif
1192#ifdef SYS_rfork1
1193 praddset (&syscalls, SYS_rfork1);
1194#endif
1195#ifdef SYS_rforkall
1196 praddset (&syscalls, SYS_rforkall);
1197#endif
1198 }
1199 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200 perror("PIOCSENTRY");
1201 return -1;
1202 }
John Hughes19e49982001-10-19 08:59:12 +00001203 /* Enable the syscall exits. */
1204 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 perror("PIOSEXIT");
1206 return -1;
1207 }
John Hughes19e49982001-10-19 08:59:12 +00001208 /* Enable signals we care about. */
1209 premptyset(&signals);
1210 for (i = 1; i < MAX_QUALS; ++i) {
1211 if (i > (sizeof signals) * CHAR_BIT) break;
1212 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1213 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001214 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 perror("PIOCSTRACE");
1216 return -1;
1217 }
John Hughes19e49982001-10-19 08:59:12 +00001218 /* Enable faults we care about */
1219 premptyset(&faults);
1220 for (i = 1; i < MAX_QUALS; ++i) {
1221 if (i > (sizeof faults) * CHAR_BIT) break;
1222 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1223 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001224 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225 perror("PIOCSFAULT");
1226 return -1;
1227 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001228#else /* FREEBSD */
1229 /* set events flags. */
1230 arg = S_SIG | S_SCE | S_SCX ;
1231 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1232 perror("PIOCBIS");
1233 return -1;
1234 }
1235#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 if (!attaching) {
1237#ifdef MIPS
1238 /*
1239 * The SGI PRSABORT doesn't work for pause() so
1240 * we send it a caught signal to wake it up.
1241 */
1242 kill(tcp->pid, SIGINT);
1243#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001244#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001246 arg = PRSABORT;
1247 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 perror("PIOCRUN");
1249 return -1;
1250 }
Roland McGrath553a6092002-12-16 20:40:39 +00001251#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001252#endif /* !MIPS*/
1253#ifdef FREEBSD
1254 /* wake up the child if it received the SIGSTOP */
1255 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001256#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257 for (;;) {
1258 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001259 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 perror("PIOCWSTOP");
1261 return -1;
1262 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001263 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001264 tcp->flags &= ~TCB_INSYSCALL;
1265 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001266 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267 break;
1268 }
1269 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001270#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001271 arg = 0;
1272 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001273#else /* FREEBSD */
1274 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001275#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 perror("PIOCRUN");
1277 return -1;
1278 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001279#ifdef FREEBSD
1280 /* handle the case where we "opened" the child before
1281 it did the kill -STOP */
1282 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1283 tcp->status.PR_WHAT == SIGSTOP)
1284 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001285#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001286 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001287#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001289#else /* FREEBSD */
1290 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001291 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001292 /* We are attaching to an already running process.
1293 * Try to figure out the state of the process in syscalls,
1294 * to handle the first event well.
1295 * This is done by having a look at the "wchan" property of the
1296 * process, which tells where it is stopped (if it is). */
1297 FILE * status;
1298 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001299
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001300 sprintf(proc, "/proc/%d/status", tcp->pid);
1301 status = fopen(proc, "r");
1302 if (status &&
1303 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1304 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1305 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1306 strcmp(wchan, "stopevent")) {
1307 /* The process is asleep in the middle of a syscall.
1308 Fake the syscall entry event */
1309 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1310 tcp->status.PR_WHY = PR_SYSENTRY;
1311 trace_syscall(tcp);
1312 }
1313 if (status)
1314 fclose(status);
1315 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001316 }
1317#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318#ifndef HAVE_POLLABLE_PROCFS
1319 if (proc_poll_pipe[0] != -1)
1320 proc_poller(tcp->pfd);
1321 else if (nprocs > 1) {
1322 proc_poll_open();
1323 proc_poller(last_pfd);
1324 proc_poller(tcp->pfd);
1325 }
1326 last_pfd = tcp->pfd;
1327#endif /* !HAVE_POLLABLE_PROCFS */
1328 return 0;
1329}
1330
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001331#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001333struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334pid2tcb(pid)
1335int pid;
1336{
1337 int i;
1338 struct tcb *tcp;
1339
Roland McGrathee9d4352002-12-18 04:16:10 +00001340 for (i = 0; i < tcbtabsize; i++) {
1341 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 if (pid && tcp->pid != pid)
1343 continue;
1344 if (tcp->flags & TCB_INUSE)
1345 return tcp;
1346 }
1347 return NULL;
1348}
1349
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001350#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001351
1352static struct tcb *
1353pfd2tcb(pfd)
1354int pfd;
1355{
1356 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001357
Roland McGrathca16be82003-01-10 19:55:28 +00001358 for (i = 0; i < tcbtabsize; i++) {
1359 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 if (tcp->pfd != pfd)
1361 continue;
1362 if (tcp->flags & TCB_INUSE)
1363 return tcp;
1364 }
1365 return NULL;
1366}
1367
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001368#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001369
1370void
1371droptcb(tcp)
1372struct tcb *tcp;
1373{
1374 if (tcp->pid == 0)
1375 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001376#ifdef TCB_CLONE_THREAD
1377 if (tcp->nclone_threads > 0) {
1378 /* There are other threads left in this process, but this
1379 is the one whose PID represents the whole process.
1380 We need to keep this record around as a zombie until
1381 all the threads die. */
1382 tcp->flags |= TCB_EXITING;
1383 return;
1384 }
1385#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386 nprocs--;
1387 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001388
Roland McGrathe29341c2003-01-10 20:14:20 +00001389 if (tcp->parent != NULL) {
1390 tcp->parent->nchildren--;
1391#ifdef TCB_CLONE_THREAD
1392 if (tcp->flags & TCB_CLONE_DETACHED)
1393 tcp->parent->nclone_detached--;
1394 if (tcp->flags & TCB_CLONE_THREAD)
1395 tcp->parent->nclone_threads--;
1396#endif
Roland McGrath09623452003-05-23 02:27:13 +00001397#ifdef TCB_CLONE_DETACHED
1398 if (!(tcp->flags & TCB_CLONE_DETACHED))
1399#endif
1400 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001401#ifdef LINUX
1402 /* Update `tcp->parent->parent->nchildren' and the other fields
1403 like NCLONE_DETACHED, only for zombie group leader that has
1404 already reported and been short-circuited at the top of this
1405 function. The same condition as at the top of DETACH. */
1406 if ((tcp->flags & TCB_CLONE_THREAD) &&
1407 tcp->parent->nclone_threads == 0 &&
1408 (tcp->parent->flags & TCB_EXITING))
1409 droptcb(tcp->parent);
1410#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001411 tcp->parent = NULL;
1412 }
1413
1414 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 if (tcp->pfd != -1) {
1416 close(tcp->pfd);
1417 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001418#ifdef FREEBSD
1419 if (tcp->pfd_reg != -1) {
1420 close(tcp->pfd_reg);
1421 tcp->pfd_reg = -1;
1422 }
1423 if (tcp->pfd_status != -1) {
1424 close(tcp->pfd_status);
1425 tcp->pfd_status = -1;
1426 }
Roland McGrath553a6092002-12-16 20:40:39 +00001427#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001428#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001429 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430#endif
1431 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001432
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001433 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001434 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001435
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 tcp->outf = 0;
1437}
1438
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001439#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001440
1441static int
1442resume(tcp)
1443struct tcb *tcp;
1444{
1445 if (tcp == NULL)
1446 return -1;
1447
1448 if (!(tcp->flags & TCB_SUSPENDED)) {
1449 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1450 return -1;
1451 }
1452 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001453#ifdef TCB_CLONE_THREAD
1454 if (tcp->flags & TCB_CLONE_THREAD)
1455 tcp->parent->nclone_waiting--;
1456#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001458 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460
1461 if (!qflag)
1462 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1463 return 0;
1464}
1465
Roland McGrath1bfd3102007-08-03 10:02:00 +00001466static int
1467resume_from_tcp (struct tcb *tcp)
1468{
1469 int error = 0;
1470 int resumed = 0;
1471
1472 /* XXX This won't always be quite right (but it never was).
1473 A waiter with argument 0 or < -1 is waiting for any pid in
1474 a particular pgrp, which this child might or might not be
1475 in. The waiter will only wake up if it's argument is -1
1476 or if it's waiting for tcp->pid's pgrp. It makes a
1477 difference to wake up a waiter when there might be more
1478 traced children, because it could get a false ECHILD
1479 error. OTOH, if this was the last child in the pgrp, then
1480 it ought to wake up and get ECHILD. We would have to
1481 search the system for all pid's in the pgrp to be sure.
1482
1483 && (t->waitpid == -1 ||
1484 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1485 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1486 */
1487
1488 if (tcp->parent &&
1489 (tcp->parent->flags & TCB_SUSPENDED) &&
1490 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001491 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001492 ++resumed;
1493 }
1494#ifdef TCB_CLONE_THREAD
1495 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1496 /* Some other threads of our parent are waiting too. */
1497 unsigned int i;
1498
1499 /* Resume all the threads that were waiting for this PID. */
1500 for (i = 0; i < tcbtabsize; i++) {
1501 struct tcb *t = tcbtab[i];
1502 if (t->parent == tcp->parent && t != tcp
1503 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1504 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1505 && t->waitpid == tcp->pid) {
1506 error |= resume (t);
1507 ++resumed;
1508 }
1509 }
1510 if (resumed == 0)
1511 /* Noone was waiting for this PID in particular,
1512 so now we might need to resume some wildcarders. */
1513 for (i = 0; i < tcbtabsize; i++) {
1514 struct tcb *t = tcbtab[i];
1515 if (t->parent == tcp->parent && t != tcp
1516 && ((t->flags
1517 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1518 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1519 && t->waitpid <= 0
1520 ) {
1521 error |= resume (t);
1522 break;
1523 }
1524 }
1525 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001526#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001527
1528 return error;
1529}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001530
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001531#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532
Roland McGrath0a463882007-07-05 18:43:16 +00001533/* detach traced process; continue with sig
1534 Never call DETACH twice on the same process as both unattached and
1535 attached-unstopped processes give the same ESRCH. For unattached process we
1536 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537
1538static int
1539detach(tcp, sig)
1540struct tcb *tcp;
1541int sig;
1542{
1543 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001544#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001545 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001546 struct tcb *zombie = NULL;
1547
1548 /* If the group leader is lingering only because of this other
1549 thread now dying, then detach the leader as well. */
1550 if ((tcp->flags & TCB_CLONE_THREAD) &&
1551 tcp->parent->nclone_threads == 1 &&
1552 (tcp->parent->flags & TCB_EXITING))
1553 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001554#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555
1556 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001557 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001558
1559#ifdef LINUX
1560 /*
1561 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001562 * before detaching. Arghh. We go through hoops
1563 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001565#if defined(SPARC)
1566#undef PTRACE_DETACH
1567#define PTRACE_DETACH PTRACE_SUNDETACH
1568#endif
Roland McGrath02203312007-06-11 22:06:31 +00001569 /*
1570 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1571 * expected SIGSTOP. We must catch exactly one as otherwise the
1572 * detached process would be left stopped (process state T).
1573 */
1574 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1576 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001577 }
1578 else if (errno != ESRCH) {
1579 /* Shouldn't happen. */
1580 perror("detach: ptrace(PTRACE_DETACH, ...)");
1581 }
Roland McGrath134813a2007-06-02 00:07:33 +00001582 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1583 : tcp->pid),
1584 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001585 if (errno != ESRCH)
1586 perror("detach: checking sanity");
1587 }
Roland McGrath02203312007-06-11 22:06:31 +00001588 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1589 ? tcp->parent->pid : tcp->pid),
1590 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001591 if (errno != ESRCH)
1592 perror("detach: stopping child");
1593 }
Roland McGrath02203312007-06-11 22:06:31 +00001594 else
1595 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001596 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001598#ifdef __WALL
1599 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1600 if (errno == ECHILD) /* Already gone. */
1601 break;
1602 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001603 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001604 break;
1605 }
1606#endif /* __WALL */
1607 /* No __WALL here. */
1608 if (waitpid(tcp->pid, &status, 0) < 0) {
1609 if (errno != ECHILD) {
1610 perror("detach: waiting");
1611 break;
1612 }
1613#ifdef __WCLONE
1614 /* If no processes, try clones. */
1615 if (wait4(tcp->pid, &status, __WCLONE,
1616 NULL) < 0) {
1617 if (errno != ECHILD)
1618 perror("detach: waiting");
1619 break;
1620 }
1621#endif /* __WCLONE */
1622 }
1623#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001624 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001625#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626 if (!WIFSTOPPED(status)) {
1627 /* Au revoir, mon ami. */
1628 break;
1629 }
1630 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001631 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632 break;
1633 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001634 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001635 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001636 : WSTOPSIG(status));
1637 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001640 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001641#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642
1643#if defined(SUNOS4)
1644 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1645 if (sig && kill(tcp->pid, sig) < 0)
1646 perror("detach: kill");
1647 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001648 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649#endif /* SUNOS4 */
1650
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001651#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001652 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001653#endif
1654
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655 if (!qflag)
1656 fprintf(stderr, "Process %u detached\n", tcp->pid);
1657
1658 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001659
1660#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001661 if (zombie != NULL) {
1662 /* TCP no longer exists therefore you must not detach () it. */
1663 droptcb(zombie);
1664 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001665#endif
1666
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667 return error;
1668}
1669
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001670#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001672static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673{
1674 int pid;
1675 int status;
1676
1677 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678 }
1679}
1680
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001681#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001682
1683static void
1684cleanup()
1685{
1686 int i;
1687 struct tcb *tcp;
1688
Roland McGrathee9d4352002-12-18 04:16:10 +00001689 for (i = 0; i < tcbtabsize; i++) {
1690 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 if (!(tcp->flags & TCB_INUSE))
1692 continue;
1693 if (debug)
1694 fprintf(stderr,
1695 "cleanup: looking at pid %u\n", tcp->pid);
1696 if (tcp_last &&
1697 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001698 tprintf(" <unfinished ...>");
1699 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700 }
1701 if (tcp->flags & TCB_ATTACHED)
1702 detach(tcp, 0);
1703 else {
1704 kill(tcp->pid, SIGCONT);
1705 kill(tcp->pid, SIGTERM);
1706 }
1707 }
1708 if (cflag)
1709 call_summary(outf);
1710}
1711
1712static void
1713interrupt(sig)
1714int sig;
1715{
1716 interrupted = 1;
1717}
1718
1719#ifndef HAVE_STRERROR
1720
Roland McGrath6d2b3492002-12-30 00:51:30 +00001721#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722extern int sys_nerr;
1723extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001724#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725
1726const char *
1727strerror(errno)
1728int errno;
1729{
1730 static char buf[64];
1731
1732 if (errno < 1 || errno >= sys_nerr) {
1733 sprintf(buf, "Unknown error %d", errno);
1734 return buf;
1735 }
1736 return sys_errlist[errno];
1737}
1738
1739#endif /* HAVE_STERRROR */
1740
1741#ifndef HAVE_STRSIGNAL
1742
Roland McGrath8f474e02003-01-14 07:53:33 +00001743#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001744extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001746#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1747extern char *_sys_siglist[];
1748#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749
1750const char *
1751strsignal(sig)
1752int sig;
1753{
1754 static char buf[64];
1755
1756 if (sig < 1 || sig >= NSIG) {
1757 sprintf(buf, "Unknown signal %d", sig);
1758 return buf;
1759 }
1760#ifdef HAVE__SYS_SIGLIST
1761 return _sys_siglist[sig];
1762#else
1763 return sys_siglist[sig];
1764#endif
1765}
1766
1767#endif /* HAVE_STRSIGNAL */
1768
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001769#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770
1771static void
1772rebuild_pollv()
1773{
1774 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775
Roland McGrathee9d4352002-12-18 04:16:10 +00001776 if (pollv != NULL)
1777 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001778 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001779 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001780 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001781 exit(1);
1782 }
1783
Roland McGrathca16be82003-01-10 19:55:28 +00001784 for (i = j = 0; i < tcbtabsize; i++) {
1785 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786 if (!(tcp->flags & TCB_INUSE))
1787 continue;
1788 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001789 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 j++;
1791 }
1792 if (j != nprocs) {
1793 fprintf(stderr, "strace: proc miscount\n");
1794 exit(1);
1795 }
1796}
1797
1798#ifndef HAVE_POLLABLE_PROCFS
1799
1800static void
1801proc_poll_open()
1802{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803 int i;
1804
1805 if (pipe(proc_poll_pipe) < 0) {
1806 perror("pipe");
1807 exit(1);
1808 }
1809 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001810 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001811 exit(1);
1812 }
1813 }
1814}
1815
1816static int
1817proc_poll(pollv, nfds, timeout)
1818struct pollfd *pollv;
1819int nfds;
1820int timeout;
1821{
1822 int i;
1823 int n;
1824 struct proc_pollfd pollinfo;
1825
1826 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1827 return n;
1828 if (n != sizeof(struct proc_pollfd)) {
1829 fprintf(stderr, "panic: short read: %d\n", n);
1830 exit(1);
1831 }
1832 for (i = 0; i < nprocs; i++) {
1833 if (pollv[i].fd == pollinfo.fd)
1834 pollv[i].revents = pollinfo.revents;
1835 else
1836 pollv[i].revents = 0;
1837 }
1838 poller_pid = pollinfo.pid;
1839 return 1;
1840}
1841
1842static void
1843wakeup_handler(sig)
1844int sig;
1845{
1846}
1847
1848static void
1849proc_poller(pfd)
1850int pfd;
1851{
1852 struct proc_pollfd pollinfo;
1853 struct sigaction sa;
1854 sigset_t blocked_set, empty_set;
1855 int i;
1856 int n;
1857 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001858#ifdef FREEBSD
1859 struct procfs_status pfs;
1860#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861
1862 switch (fork()) {
1863 case -1:
1864 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001865 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866 case 0:
1867 break;
1868 default:
1869 return;
1870 }
1871
1872 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1873 sa.sa_flags = 0;
1874 sigemptyset(&sa.sa_mask);
1875 sigaction(SIGHUP, &sa, NULL);
1876 sigaction(SIGINT, &sa, NULL);
1877 sigaction(SIGQUIT, &sa, NULL);
1878 sigaction(SIGPIPE, &sa, NULL);
1879 sigaction(SIGTERM, &sa, NULL);
1880 sa.sa_handler = wakeup_handler;
1881 sigaction(SIGUSR1, &sa, NULL);
1882 sigemptyset(&blocked_set);
1883 sigaddset(&blocked_set, SIGUSR1);
1884 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1885 sigemptyset(&empty_set);
1886
1887 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1888 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001889 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890 }
1891 n = rl.rlim_cur;
1892 for (i = 0; i < n; i++) {
1893 if (i != pfd && i != proc_poll_pipe[1])
1894 close(i);
1895 }
1896
1897 pollinfo.fd = pfd;
1898 pollinfo.pid = getpid();
1899 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001900#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001901 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1902#else
1903 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1904#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001905 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001906 switch (errno) {
1907 case EINTR:
1908 continue;
1909 case EBADF:
1910 pollinfo.revents = POLLERR;
1911 break;
1912 case ENOENT:
1913 pollinfo.revents = POLLHUP;
1914 break;
1915 default:
1916 perror("proc_poller: PIOCWSTOP");
1917 }
1918 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1919 _exit(0);
1920 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001921 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1923 sigsuspend(&empty_set);
1924 }
1925}
1926
1927#endif /* !HAVE_POLLABLE_PROCFS */
1928
1929static int
1930choose_pfd()
1931{
1932 int i, j;
1933 struct tcb *tcp;
1934
1935 static int last;
1936
1937 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001938 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001939 /*
1940 * The previous process is ready to run again. We'll
1941 * let it do so if it is currently in a syscall. This
1942 * heuristic improves the readability of the trace.
1943 */
1944 tcp = pfd2tcb(pollv[last].fd);
1945 if (tcp && (tcp->flags & TCB_INSYSCALL))
1946 return pollv[last].fd;
1947 }
1948
1949 for (i = 0; i < nprocs; i++) {
1950 /* Let competing children run round robin. */
1951 j = (i + last + 1) % nprocs;
1952 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1953 tcp = pfd2tcb(pollv[j].fd);
1954 if (!tcp) {
1955 fprintf(stderr, "strace: lost proc\n");
1956 exit(1);
1957 }
1958 droptcb(tcp);
1959 return -1;
1960 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001961 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962 last = j;
1963 return pollv[j].fd;
1964 }
1965 }
1966 fprintf(stderr, "strace: nothing ready\n");
1967 exit(1);
1968}
1969
1970static int
1971trace()
1972{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001973#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001974 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001975#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976 struct tcb *tcp;
1977 int pfd;
1978 int what;
1979 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001980 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981
1982 for (;;) {
1983 if (interactive)
1984 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1985
1986 if (nprocs == 0)
1987 break;
1988
1989 switch (nprocs) {
1990 case 1:
1991#ifndef HAVE_POLLABLE_PROCFS
1992 if (proc_poll_pipe[0] == -1) {
1993#endif
1994 tcp = pid2tcb(0);
1995 if (!tcp)
1996 continue;
1997 pfd = tcp->pfd;
1998 if (pfd == -1)
1999 continue;
2000 break;
2001#ifndef HAVE_POLLABLE_PROCFS
2002 }
2003 /* fall through ... */
2004#endif /* !HAVE_POLLABLE_PROCFS */
2005 default:
2006#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002007#ifdef POLL_HACK
2008 /* On some systems (e.g. UnixWare) we get too much ugly
2009 "unfinished..." stuff when multiple proceses are in
2010 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002011
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002012 if (in_syscall) {
2013 struct pollfd pv;
2014 tcp = in_syscall;
2015 in_syscall = NULL;
2016 pv.fd = tcp->pfd;
2017 pv.events = POLLWANT;
2018 if ((what = poll (&pv, 1, 1)) < 0) {
2019 if (interrupted)
2020 return 0;
2021 continue;
2022 }
2023 else if (what == 1 && pv.revents & POLLWANT) {
2024 goto FOUND;
2025 }
2026 }
2027#endif
2028
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029 if (poll(pollv, nprocs, INFTIM) < 0) {
2030 if (interrupted)
2031 return 0;
2032 continue;
2033 }
2034#else /* !HAVE_POLLABLE_PROCFS */
2035 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2036 if (interrupted)
2037 return 0;
2038 continue;
2039 }
2040#endif /* !HAVE_POLLABLE_PROCFS */
2041 pfd = choose_pfd();
2042 if (pfd == -1)
2043 continue;
2044 break;
2045 }
2046
2047 /* Look up `pfd' in our table. */
2048 if ((tcp = pfd2tcb(pfd)) == NULL) {
2049 fprintf(stderr, "unknown pfd: %u\n", pfd);
2050 exit(1);
2051 }
John Hughesb6643082002-05-23 11:02:22 +00002052#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002053 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002054#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 /* Get the status of the process. */
2056 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002057#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002058 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002059#else /* FREEBSD */
2060 /* Thanks to some scheduling mystery, the first poller
2061 sometimes waits for the already processed end of fork
2062 event. Doing a non blocking poll here solves the problem. */
2063 if (proc_poll_pipe[0] != -1)
2064 ioctl_result = IOCTL_STATUS (tcp);
2065 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002066 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002067#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068 ioctl_errno = errno;
2069#ifndef HAVE_POLLABLE_PROCFS
2070 if (proc_poll_pipe[0] != -1) {
2071 if (ioctl_result < 0)
2072 kill(poller_pid, SIGKILL);
2073 else
2074 kill(poller_pid, SIGUSR1);
2075 }
2076#endif /* !HAVE_POLLABLE_PROCFS */
2077 }
2078 if (interrupted)
2079 return 0;
2080
2081 if (interactive)
2082 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2083
2084 if (ioctl_result < 0) {
2085 /* Find out what happened if it failed. */
2086 switch (ioctl_errno) {
2087 case EINTR:
2088 case EBADF:
2089 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002090#ifdef FREEBSD
2091 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002092#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002093 case ENOENT:
2094 droptcb(tcp);
2095 continue;
2096 default:
2097 perror("PIOCWSTOP");
2098 exit(1);
2099 }
2100 }
2101
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002102#ifdef FREEBSD
2103 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2104 /* discard first event for a syscall we never entered */
2105 IOCTL (tcp->pfd, PIOCRUN, 0);
2106 continue;
2107 }
Roland McGrath553a6092002-12-16 20:40:39 +00002108#endif
2109
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 /* clear the just started flag */
2111 tcp->flags &= ~TCB_STARTUP;
2112
2113 /* set current output file */
2114 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002115 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116
2117 if (cflag) {
2118 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002119#ifdef FREEBSD
2120 char buf[1024];
2121 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002122
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002123 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2124 buf[len] = '\0';
2125 sscanf(buf,
2126 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2127 &stime.tv_sec, &stime.tv_usec);
2128 } else
2129 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002130#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002131 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2132 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002133#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2135 tcp->stime = stime;
2136 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002137 what = tcp->status.PR_WHAT;
2138 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002139#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002140 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002141 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2142 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002143 if (trace_syscall(tcp) < 0) {
2144 fprintf(stderr, "syscall trouble\n");
2145 exit(1);
2146 }
2147 }
2148 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002149#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002150 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002151#ifdef POLL_HACK
2152 in_syscall = tcp;
2153#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002154 case PR_SYSEXIT:
2155 if (trace_syscall(tcp) < 0) {
2156 fprintf(stderr, "syscall trouble\n");
2157 exit(1);
2158 }
2159 break;
2160 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002161 if (cflag != CFLAG_ONLY_STATS
2162 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002163 printleader(tcp);
2164 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002165 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002166 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002167#ifdef PR_INFO
2168 if (tcp->status.PR_INFO.si_signo == what) {
2169 printleader(tcp);
2170 tprintf(" siginfo=");
2171 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002172 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002173 }
2174#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002175 }
2176 break;
2177 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002178 if (cflag != CFLAGS_ONLY_STATS
2179 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002180 printleader(tcp);
2181 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002182 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002183 }
2184 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002185#ifdef FREEBSD
2186 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002187 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002188#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002190 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002191 exit(1);
2192 break;
2193 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002194 /* Remember current print column before continuing. */
2195 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002196 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002197#ifndef FREEBSD
Andreas Schwab372cc842010-07-09 11:49:27 +02002198 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002199#else
Andreas Schwab372cc842010-07-09 11:49:27 +02002200 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002201#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002202 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 perror("PIOCRUN");
2204 exit(1);
2205 }
2206 }
2207 return 0;
2208}
2209
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002210#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002212#ifdef TCB_GROUP_EXITING
2213/* Handle an exit detach or death signal that is taking all the
2214 related clone threads with it. This is called in three circumstances:
2215 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2216 SIG == 0 Continuing TCP will perform an exit_group syscall.
2217 SIG == other Continuing TCP with SIG will kill the process.
2218*/
2219static int
2220handle_group_exit(struct tcb *tcp, int sig)
2221{
2222 /* We need to locate our records of all the clone threads
2223 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002224 struct tcb *leader = NULL;
2225
2226 if (tcp->flags & TCB_CLONE_THREAD)
2227 leader = tcp->parent;
2228 else if (tcp->nclone_detached > 0)
2229 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002230
2231 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002232 if (leader != NULL && leader != tcp
2233 && !(leader->flags & TCB_GROUP_EXITING)
2234 && !(tcp->flags & TCB_STARTUP)
2235 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002236 fprintf(stderr,
2237 "PANIC: handle_group_exit: %d leader %d\n",
2238 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002239 }
2240 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002241#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002242 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002243#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002244 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002245 }
2246 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002247 /* Mark that we are taking the process down. */
2248 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002249 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002250 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002251 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002252 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002253 } else {
2254 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2255 cleanup();
2256 return -1;
2257 }
2258 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002259 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002260 if (leader != tcp)
2261 droptcb(tcp);
2262 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002263 /* The leader will report to us as parent now,
2264 and then we'll get to the SIG==-1 case. */
2265 return 0;
2266 }
2267 }
2268
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002269 return 0;
2270}
2271#endif
2272
Roland McGratheb9e2e82009-06-02 16:49:22 -07002273static int
2274trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002275{
2276 int pid;
2277 int wait_errno;
2278 int status;
2279 struct tcb *tcp;
2280#ifdef LINUX
2281 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002282#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002283 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002284#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285#endif /* LINUX */
2286
Roland McGratheb9e2e82009-06-02 16:49:22 -07002287 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002288 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002289 return 0;
2290 if (interactive)
2291 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002292#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002293#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002294 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002295 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002296 /* this kernel does not support __WALL */
2297 wait4_options &= ~__WALL;
2298 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002299 pid = wait4(-1, &status, wait4_options,
2300 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002301 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002302 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002303 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002304 pid = wait4(-1, &status, __WCLONE,
2305 cflag ? &ru : NULL);
2306 if (pid == -1) {
2307 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002308 "failed: %s\n", strerror(errno));
2309 }
2310 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002311#else
2312 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2313#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002314#endif /* LINUX */
2315#ifdef SUNOS4
2316 pid = wait(&status);
2317#endif /* SUNOS4 */
2318 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002319 if (interactive)
2320 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002321
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002322 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002323 switch (wait_errno) {
2324 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002325 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002326 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002327 /*
2328 * We would like to verify this case
2329 * but sometimes a race in Solbourne's
2330 * version of SunOS sometimes reports
2331 * ECHILD before sending us SIGCHILD.
2332 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002333 return 0;
2334 default:
2335 errno = wait_errno;
2336 perror("strace: wait");
2337 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002338 }
2339 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002340 if (pid == popen_pid) {
2341 if (WIFEXITED(status) || WIFSIGNALED(status))
2342 popen_pid = -1;
2343 continue;
2344 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 if (debug)
2346 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2347
2348 /* Look up `pid' in our table. */
2349 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002350#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002351 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002352 /* This is needed to go with the CLONE_PTRACE
2353 changes in process.c/util.c: we might see
2354 the child's initial trap before we see the
2355 parent return from the clone syscall.
2356 Leave the child suspended until the parent
2357 returns from its system call. Only then
2358 will we have the association of parent and
2359 child so that we know how to do clearbpt
2360 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002361 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002362 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002363 if (!qflag)
2364 fprintf(stderr, "\
2365Process %d attached (waiting for parent)\n",
2366 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002367 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002368 else
2369 /* This can happen if a clone call used
2370 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002371#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002372 {
2373 fprintf(stderr, "unknown pid: %u\n", pid);
2374 if (WIFSTOPPED(status))
2375 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2376 exit(1);
2377 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002378 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002379 /* set current output file */
2380 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002381 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002382 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002383#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002384 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2385 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002386#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002388
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002389 if (tcp->flags & TCB_SUSPENDED) {
2390 /*
2391 * Apparently, doing any ptrace() call on a stopped
2392 * process, provokes the kernel to report the process
2393 * status again on a subsequent wait(), even if the
2394 * process has not been actually restarted.
2395 * Since we have inspected the arguments of suspended
2396 * processes we end up here testing for this case.
2397 */
2398 continue;
2399 }
2400 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002401 if (pid == strace_child)
2402 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002403 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002404 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2405 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002406 tprintf("+++ killed by %s %s+++",
2407 signame(WTERMSIG(status)),
2408#ifdef WCOREDUMP
2409 WCOREDUMP(status) ? "(core dumped) " :
2410#endif
2411 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002412 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002413 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002414#ifdef TCB_GROUP_EXITING
2415 handle_group_exit(tcp, -1);
2416#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002417 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002418#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002419 continue;
2420 }
2421 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002422 if (pid == strace_child)
2423 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002424 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002425 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2426 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002427#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002428 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002429 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002430#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002431 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002432 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002433 "PANIC: attached pid %u exited with %d\n",
2434 pid, WEXITSTATUS(status));
2435 }
Roland McGrath0a396902003-06-10 03:05:53 +00002436 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002437 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002438 tprintf(" <unfinished ... exit status %d>\n",
2439 WEXITSTATUS(status));
2440 tcp_last = NULL;
2441 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002442#ifdef TCB_GROUP_EXITING
2443 handle_group_exit(tcp, -1);
2444#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002446#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002447 continue;
2448 }
2449 if (!WIFSTOPPED(status)) {
2450 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2451 droptcb(tcp);
2452 continue;
2453 }
2454 if (debug)
2455 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002456 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002457
Roland McGrath02203312007-06-11 22:06:31 +00002458 /*
2459 * Interestingly, the process may stop
2460 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002461 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002462 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002463 * A no-MMU vforked child won't send up a signal,
2464 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002465 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002466 if ((tcp->flags & TCB_STARTUP) &&
2467 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002468 /*
2469 * This flag is there to keep us in sync.
2470 * Next time this process stops it should
2471 * really be entering a system call.
2472 */
2473 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002474 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002475 /*
2476 * One example is a breakpoint inherited from
2477 * parent through fork ().
2478 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002479 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2480 droptcb(tcp);
2481 cleanup();
2482 return -1;
2483 }
2484 }
2485 goto tracing;
2486 }
2487
Roland McGratheb9e2e82009-06-02 16:49:22 -07002488 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002489 if (WSTOPSIG(status) == SIGSTOP &&
2490 (tcp->flags & TCB_SIGTRAPPED)) {
2491 /*
2492 * Trapped attempt to block SIGTRAP
2493 * Hope we are back in control now.
2494 */
2495 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002496 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002497 cleanup();
2498 return -1;
2499 }
2500 continue;
2501 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002502 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002503 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002504 unsigned long addr = 0;
2505 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002506#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002507# define PSR_RI 41
2508 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002509 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002510
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002511 upeek(tcp, PT_CR_IPSR, &psr);
2512 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002513
2514 pc += (psr >> PSR_RI) & 0x3;
2515 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2516 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002517#elif defined PTRACE_GETSIGINFO
2518 if (WSTOPSIG(status) == SIGSEGV ||
2519 WSTOPSIG(status) == SIGBUS) {
2520 siginfo_t si;
2521 if (ptrace(PTRACE_GETSIGINFO, pid,
2522 0, &si) == 0)
2523 addr = (unsigned long)
2524 si.si_addr;
2525 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002526#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002527 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002528 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002529 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002530 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002531 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002532 }
Roland McGrath05690952004-10-20 01:00:27 +00002533 if (((tcp->flags & TCB_ATTACHED) ||
2534 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002535 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002536#ifdef TCB_GROUP_EXITING
2537 handle_group_exit(tcp, WSTOPSIG(status));
2538#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002540#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002541 continue;
2542 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002543 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 cleanup();
2545 return -1;
2546 }
2547 tcp->flags &= ~TCB_SUSPENDED;
2548 continue;
2549 }
Roland McGrath02203312007-06-11 22:06:31 +00002550 /* we handled the STATUS, we are permitted to interrupt now. */
2551 if (interrupted)
2552 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002553 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2554 /* ptrace() failed in trace_syscall() with ESRCH.
2555 * Likely a result of process disappearing mid-flight.
2556 * Observed case: exit_group() terminating
2557 * all processes in thread group. In this case, threads
2558 * "disappear" in an unpredictable moment without any
2559 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002560 */
2561 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002562 if (tcp_last) {
2563 /* Do we have dangling line "syscall(param, param"?
2564 * Finish the line then. We cannot
2565 */
2566 tcp_last->flags |= TCB_REPRINT;
2567 tprintf(" <unfinished ...>");
2568 printtrailer();
2569 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002570 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002571 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002572 ptrace(PTRACE_KILL,
2573 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002574 droptcb(tcp);
2575 }
2576 continue;
2577 }
2578 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002579#ifdef TCB_GROUP_EXITING
2580 if (tcp->flags & TCB_GROUP_EXITING) {
2581 if (handle_group_exit(tcp, 0) < 0)
2582 return -1;
2583 continue;
2584 }
2585#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002586 if (tcp->flags & TCB_ATTACHED)
2587 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002588 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002589 cleanup();
2590 return -1;
2591 }
2592 continue;
2593 }
2594 if (tcp->flags & TCB_SUSPENDED) {
2595 if (!qflag)
2596 fprintf(stderr, "Process %u suspended\n", pid);
2597 continue;
2598 }
2599 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002600 /* Remember current print column before continuing. */
2601 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002602 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002603 cleanup();
2604 return -1;
2605 }
2606 }
2607 return 0;
2608}
2609
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002610#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002611
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002612#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613
2614void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002615tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002616{
2617 va_list args;
2618
Andreas Schwabe5355de2009-10-27 16:56:43 +01002619 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002620 if (outf) {
2621 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002622 if (n < 0) {
2623 if (outf != stderr)
2624 perror(outfname == NULL
2625 ? "<writing to pipe>" : outfname);
2626 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002627 curcol += n;
2628 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002629 va_end(args);
2630 return;
2631}
2632
2633void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002634printleader(tcp)
2635struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002637 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002638 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002639 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002640 tprintf(" <unavailable>)");
2641 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002642 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002643 tprintf("= ? <unavailable>\n");
2644 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002645 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002646 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002647 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002648 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002649 }
2650 curcol = 0;
2651 if ((followfork == 1 || pflag_seen > 1) && outfname)
2652 tprintf("%-5d ", tcp->pid);
2653 else if (nprocs > 1 && !outfname)
2654 tprintf("[pid %5u] ", tcp->pid);
2655 if (tflag) {
2656 char str[sizeof("HH:MM:SS")];
2657 struct timeval tv, dtv;
2658 static struct timeval otv;
2659
2660 gettimeofday(&tv, NULL);
2661 if (rflag) {
2662 if (otv.tv_sec == 0)
2663 otv = tv;
2664 tv_sub(&dtv, &tv, &otv);
2665 tprintf("%6ld.%06ld ",
2666 (long) dtv.tv_sec, (long) dtv.tv_usec);
2667 otv = tv;
2668 }
2669 else if (tflag > 2) {
2670 tprintf("%ld.%06ld ",
2671 (long) tv.tv_sec, (long) tv.tv_usec);
2672 }
2673 else {
2674 time_t local = tv.tv_sec;
2675 strftime(str, sizeof(str), "%T", localtime(&local));
2676 if (tflag > 1)
2677 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2678 else
2679 tprintf("%s ", str);
2680 }
2681 }
2682 if (iflag)
2683 printcall(tcp);
2684}
2685
2686void
2687tabto(col)
2688int col;
2689{
2690 if (curcol < col)
2691 tprintf("%*s", col - curcol, "");
2692}
2693
2694void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002695printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002696{
2697 tprintf("\n");
2698 tcp_last = NULL;
2699}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002700
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002701#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002702
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002703int
2704mp_ioctl(int fd, int cmd, void *arg, int size)
2705{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002706 struct iovec iov[2];
2707 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002708
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002709 iov[0].iov_base = &cmd;
2710 iov[0].iov_len = sizeof cmd;
2711 if (arg) {
2712 ++n;
2713 iov[1].iov_base = arg;
2714 iov[1].iov_len = size;
2715 }
Roland McGrath553a6092002-12-16 20:40:39 +00002716
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002717 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002718}
2719
2720#endif