blob: 497b8d15ca5fb09f5b4b1eb08e854f6a2ef1266e [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;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000120const char *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);
Wang Chao21b8db42010-08-27 17:43:16 +0800446 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000447 tcbtab[tcbi]->nchildren++;
448 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000449 tcp->parent = tcbtab[tcbi];
450 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000451 if (interactive) {
452 sigprocmask(SIG_SETMASK, &empty_set, NULL);
453 if (interrupted)
454 return;
455 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
456 }
Roland McGrath02203312007-06-11 22:06:31 +0000457 }
458 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000459 ntid -= nerr;
460 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000461 perror("attach: ptrace(PTRACE_ATTACH, ...)");
462 droptcb(tcp);
463 continue;
464 }
465 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000466 fprintf(stderr, ntid > 1
467? "Process %u attached with %u threads - interrupt to quit\n"
468: "Process %u attached - interrupt to quit\n",
469 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000470 }
471 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000472 } /* if (opendir worked) */
473 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000474# endif
475 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
476 perror("attach: ptrace(PTRACE_ATTACH, ...)");
477 droptcb(tcp);
478 continue;
479 }
480 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000481
482 if (daemonized_tracer) {
483 /*
484 * It is our grandparent we trace, not a -p PID.
485 * Don't want to just detach on exit, so...
486 */
487 tcp->flags &= ~TCB_ATTACHED;
488 /*
489 * Make parent go away.
490 * Also makes grandparent's wait() unblock.
491 */
492 kill(getppid(), SIGKILL);
493 }
494
Roland McGrath02203312007-06-11 22:06:31 +0000495#endif /* !USE_PROCFS */
496 if (!qflag)
497 fprintf(stderr,
498 "Process %u attached - interrupt to quit\n",
499 tcp->pid);
500 }
501
502 if (interactive)
503 sigprocmask(SIG_SETMASK, &empty_set, NULL);
504}
505
506static void
507startup_child (char **argv)
508{
509 struct stat statbuf;
510 const char *filename;
511 char pathname[MAXPATHLEN];
512 int pid = 0;
513 struct tcb *tcp;
514
515 filename = argv[0];
516 if (strchr(filename, '/')) {
517 if (strlen(filename) > sizeof pathname - 1) {
518 errno = ENAMETOOLONG;
519 perror("strace: exec");
520 exit(1);
521 }
522 strcpy(pathname, filename);
523 }
524#ifdef USE_DEBUGGING_EXEC
525 /*
526 * Debuggers customarily check the current directory
527 * first regardless of the path but doing that gives
528 * security geeks a panic attack.
529 */
530 else if (stat(filename, &statbuf) == 0)
531 strcpy(pathname, filename);
532#endif /* USE_DEBUGGING_EXEC */
533 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000534 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000535 int m, n, len;
536
537 for (path = getenv("PATH"); path && *path; path += m) {
538 if (strchr(path, ':')) {
539 n = strchr(path, ':') - path;
540 m = n + 1;
541 }
542 else
543 m = n = strlen(path);
544 if (n == 0) {
545 if (!getcwd(pathname, MAXPATHLEN))
546 continue;
547 len = strlen(pathname);
548 }
549 else if (n > sizeof pathname - 1)
550 continue;
551 else {
552 strncpy(pathname, path, n);
553 len = n;
554 }
555 if (len && pathname[len - 1] != '/')
556 pathname[len++] = '/';
557 strcpy(pathname + len, filename);
558 if (stat(pathname, &statbuf) == 0 &&
559 /* Accept only regular files
560 with some execute bits set.
561 XXX not perfect, might still fail */
562 S_ISREG(statbuf.st_mode) &&
563 (statbuf.st_mode & 0111))
564 break;
565 }
566 }
567 if (stat(pathname, &statbuf) < 0) {
568 fprintf(stderr, "%s: %s: command not found\n",
569 progname, filename);
570 exit(1);
571 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000572 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000573 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000574 perror("strace: fork");
575 cleanup();
576 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000577 }
578 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
579 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
580 ) {
581 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000582#ifdef USE_PROCFS
583 if (outf != stderr) close (fileno (outf));
584#ifdef MIPS
585 /* Kludge for SGI, see proc_open for details. */
586 sa.sa_handler = foobar;
587 sa.sa_flags = 0;
588 sigemptyset(&sa.sa_mask);
589 sigaction(SIGINT, &sa, NULL);
590#endif /* MIPS */
591#ifndef FREEBSD
592 pause();
593#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000594 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000595#endif /* FREEBSD */
596#else /* !USE_PROCFS */
597 if (outf!=stderr)
598 close(fileno (outf));
599
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000600 if (!daemonized_tracer) {
601 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
602 perror("strace: ptrace(PTRACE_TRACEME, ...)");
603 exit(1);
604 }
605 if (debug)
606 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000607 }
Roland McGrath02203312007-06-11 22:06:31 +0000608
609 if (username != NULL || geteuid() == 0) {
610 uid_t run_euid = run_uid;
611 gid_t run_egid = run_gid;
612
613 if (statbuf.st_mode & S_ISUID)
614 run_euid = statbuf.st_uid;
615 if (statbuf.st_mode & S_ISGID)
616 run_egid = statbuf.st_gid;
617
618 /*
619 * It is important to set groups before we
620 * lose privileges on setuid.
621 */
622 if (username != NULL) {
623 if (initgroups(username, run_gid) < 0) {
624 perror("initgroups");
625 exit(1);
626 }
627 if (setregid(run_gid, run_egid) < 0) {
628 perror("setregid");
629 exit(1);
630 }
631 if (setreuid(run_uid, run_euid) < 0) {
632 perror("setreuid");
633 exit(1);
634 }
635 }
636 }
637 else
638 setreuid(run_uid, run_uid);
639
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000640 if (!daemonized_tracer) {
641 /*
642 * Induce an immediate stop so that the parent
643 * will resume us with PTRACE_SYSCALL and display
644 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400645 * Unless of course we're on a no-MMU system where
646 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000647 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400648 if (!strace_vforked)
649 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000650 } else {
651 struct sigaction sv_sigchld;
652 sigaction(SIGCHLD, NULL, &sv_sigchld);
653 /*
654 * Make sure it is not SIG_IGN, otherwise wait
655 * will not block.
656 */
657 signal(SIGCHLD, SIG_DFL);
658 /*
659 * Wait for grandchild to attach to us.
660 * It kills child after that, and wait() unblocks.
661 */
662 alarm(3);
663 wait(NULL);
664 alarm(0);
665 sigaction(SIGCHLD, &sv_sigchld, NULL);
666 }
Roland McGrath02203312007-06-11 22:06:31 +0000667#endif /* !USE_PROCFS */
668
669 execv(pathname, argv);
670 perror("strace: exec");
671 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000672 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000673
674 /* We are the tracer. */
675 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 if (daemonized_tracer) {
677 /* We want subsequent startup_attach() to attach to it. */
678 tcp->flags |= TCB_ATTACHED;
679 }
Roland McGrath02203312007-06-11 22:06:31 +0000680#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000681 if (proc_open(tcp, 0) < 0) {
682 fprintf(stderr, "trouble opening proc file\n");
683 cleanup();
684 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000685 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000686#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000687}
688
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000690main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000691{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692 struct tcb *tcp;
693 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000694 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 struct sigaction sa;
696
697 static char buf[BUFSIZ];
698
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000699 progname = argv[0] ? argv[0] : "strace";
700
Roland McGrathee9d4352002-12-18 04:16:10 +0000701 /* Allocate the initial tcbtab. */
702 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000703 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000704 fprintf(stderr, "%s: out of memory\n", progname);
705 exit(1);
706 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000707 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000708 fprintf(stderr, "%s: out of memory\n", progname);
709 exit(1);
710 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000711 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
712 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
713
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 outf = stderr;
715 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000716 set_sortby(DEFAULT_SORTBY);
717 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718 qualify("trace=all");
719 qualify("abbrev=all");
720 qualify("verbose=all");
721 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 while ((c = getopt(argc, argv,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000723 "+cCdfFhiqrtTvVxz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000724#ifndef USE_PROCFS
725 "D"
726#endif
727 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000728 switch (c) {
729 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000730 if (cflag == CFLAG_BOTH) {
731 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
732 progname);
733 exit(1);
734 }
735 cflag = CFLAG_ONLY_STATS;
736 break;
737 case 'C':
738 if (cflag == CFLAG_ONLY_STATS) {
739 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
740 progname);
741 exit(1);
742 }
743 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000744 break;
745 case 'd':
746 debug++;
747 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000748#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000749 case 'D':
750 daemonized_tracer = 1;
751 break;
752#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000753 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000754 optF = 1;
755 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 case 'f':
757 followfork++;
758 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000759 case 'h':
760 usage(stdout, 0);
761 break;
762 case 'i':
763 iflag++;
764 break;
765 case 'q':
766 qflag++;
767 break;
768 case 'r':
769 rflag++;
770 tflag++;
771 break;
772 case 't':
773 tflag++;
774 break;
775 case 'T':
776 dtime++;
777 break;
778 case 'x':
779 xflag++;
780 break;
781 case 'v':
782 qualify("abbrev=none");
783 break;
784 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000785 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000786 exit(0);
787 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000788 case 'z':
789 not_failing_only = 1;
790 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791 case 'a':
792 acolumn = atoi(optarg);
793 break;
794 case 'e':
795 qualify(optarg);
796 break;
797 case 'o':
798 outfname = strdup(optarg);
799 break;
800 case 'O':
801 set_overhead(atoi(optarg));
802 break;
803 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000804 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805 fprintf(stderr, "%s: Invalid process id: %s\n",
806 progname, optarg);
807 break;
808 }
809 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000810 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 break;
812 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000813 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814 tcp->flags |= TCB_ATTACHED;
815 pflag_seen++;
816 break;
817 case 's':
818 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000819 if (max_strlen < 0) {
820 fprintf(stderr,
821 "%s: invalid -s argument: %s\n",
822 progname, optarg);
823 exit(1);
824 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000825 break;
826 case 'S':
827 set_sortby(optarg);
828 break;
829 case 'u':
830 username = strdup(optarg);
831 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000832 case 'E':
833 if (putenv(optarg) < 0) {
834 fprintf(stderr, "%s: out of memory\n",
835 progname);
836 exit(1);
837 }
838 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000839 default:
840 usage(stderr, 1);
841 break;
842 }
843 }
844
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000845 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000846 usage(stderr, 1);
847
Wang Chaod322a4b2010-08-05 14:30:11 +0800848 if (pflag_seen && daemonized_tracer) {
849 fprintf(stderr,
850 "%s: -D and -p are mutually exclusive options\n",
851 progname);
852 exit(1);
853 }
854
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000855 if (!followfork)
856 followfork = optF;
857
Roland McGrathcb9def62006-04-25 07:48:03 +0000858 if (followfork > 1 && cflag) {
859 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000860 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +0000861 progname);
862 exit(1);
863 }
864
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000865 /* See if they want to run as another user. */
866 if (username != NULL) {
867 struct passwd *pent;
868
869 if (getuid() != 0 || geteuid() != 0) {
870 fprintf(stderr,
871 "%s: you must be root to use the -u option\n",
872 progname);
873 exit(1);
874 }
875 if ((pent = getpwnam(username)) == NULL) {
876 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000877 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878 exit(1);
879 }
880 run_uid = pent->pw_uid;
881 run_gid = pent->pw_gid;
882 }
883 else {
884 run_uid = getuid();
885 run_gid = getgid();
886 }
887
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888 /* Check if they want to redirect the output. */
889 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000890 /* See if they want to pipe the output. */
891 if (outfname[0] == '|' || outfname[0] == '!') {
892 /*
893 * We can't do the <outfname>.PID funny business
894 * when using popen, so prohibit it.
895 */
896 if (followfork > 1) {
897 fprintf(stderr, "\
898%s: piping the output and -ff are mutually exclusive options\n",
899 progname);
900 exit(1);
901 }
902
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000903 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000904 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000905 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000906 else if (followfork <= 1 &&
907 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000908 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 }
910
Roland McGrath37b9a662003-11-07 02:26:54 +0000911 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000913 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000916 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000917 /* Valid states here:
918 optind < argc pflag_seen outfname interactive
919 1 0 0 1
920 0 1 0 1
921 1 0 1 0
922 0 1 1 1
923 */
924
925 /* STARTUP_CHILD must be called before the signal handlers get
926 installed below as they are inherited into the spawned process.
927 Also we do not need to be protected by them as during interruption
928 in the STARTUP_CHILD mode we kill the spawned process anyway. */
929 if (!pflag_seen)
930 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000932 sigemptyset(&empty_set);
933 sigemptyset(&blocked_set);
934 sa.sa_handler = SIG_IGN;
935 sigemptyset(&sa.sa_mask);
936 sa.sa_flags = 0;
937 sigaction(SIGTTOU, &sa, NULL);
938 sigaction(SIGTTIN, &sa, NULL);
939 if (interactive) {
940 sigaddset(&blocked_set, SIGHUP);
941 sigaddset(&blocked_set, SIGINT);
942 sigaddset(&blocked_set, SIGQUIT);
943 sigaddset(&blocked_set, SIGPIPE);
944 sigaddset(&blocked_set, SIGTERM);
945 sa.sa_handler = interrupt;
946#ifdef SUNOS4
947 /* POSIX signals on sunos4.1 are a little broken. */
948 sa.sa_flags = SA_INTERRUPT;
949#endif /* SUNOS4 */
950 }
951 sigaction(SIGHUP, &sa, NULL);
952 sigaction(SIGINT, &sa, NULL);
953 sigaction(SIGQUIT, &sa, NULL);
954 sigaction(SIGPIPE, &sa, NULL);
955 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000956#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 sa.sa_handler = reaper;
958 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000959#else
960 /* Make sure SIGCHLD has the default action so that waitpid
961 definitely works without losing track of children. The user
962 should not have given us a bogus state to inherit, but he might
963 have. Arguably we should detect SIG_IGN here and pass it on
964 to children, but probably noone really needs that. */
965 sa.sa_handler = SIG_DFL;
966 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000967#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000969 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000970 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000971
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 if (trace() < 0)
973 exit(1);
974 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000975 fflush(NULL);
976 if (exit_code > 0xff) {
977 /* Child was killed by a signal, mimic that. */
978 exit_code &= 0xff;
979 signal(exit_code, SIG_DFL);
980 raise(exit_code);
981 /* Paranoia - what if this signal is not fatal?
982 Exit with 128 + signo then. */
983 exit_code += 128;
984 }
985 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986}
987
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000988void
989expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000990{
991 /* Allocate some more TCBs and expand the table.
992 We don't want to relocate the TCBs because our
993 callers have pointers and it would be a pain.
994 So tcbtab is a table of pointers. Since we never
995 free the TCBs, we allocate a single chunk of many. */
996 struct tcb **newtab = (struct tcb **)
997 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
998 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
999 sizeof *newtcbs);
1000 int i;
1001 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +00001002 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
1003 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001004 cleanup();
1005 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001006 }
1007 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1008 newtab[i] = &newtcbs[i - tcbtabsize];
1009 tcbtabsize *= 2;
1010 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001011}
1012
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001014alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015{
1016 int i;
1017 struct tcb *tcp;
1018
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001019 if (nprocs == tcbtabsize)
1020 expand_tcbtab();
1021
Roland McGrathee9d4352002-12-18 04:16:10 +00001022 for (i = 0; i < tcbtabsize; i++) {
1023 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024 if ((tcp->flags & TCB_INUSE) == 0) {
1025 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001026 tcp->parent = NULL;
1027 tcp->nchildren = 0;
1028 tcp->nzombies = 0;
1029#ifdef TCB_CLONE_THREAD
Wang Chao21b8db42010-08-27 17:43:16 +08001030 tcp->nclone_threads = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001031 tcp->nclone_waiting = 0;
1032#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033 tcp->flags = TCB_INUSE | TCB_STARTUP;
1034 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001035 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001036 tcp->stime.tv_sec = 0;
1037 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 tcp->pfd = -1;
1039 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001040 if (command_options_parsed)
1041 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 return tcp;
1043 }
1044 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001045 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1046 cleanup();
1047 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048}
1049
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001050#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001052proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053{
1054 char proc[32];
1055 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001056#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001057 int i;
1058 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 sigset_t signals;
1060 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001061#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062#ifndef HAVE_POLLABLE_PROCFS
1063 static int last_pfd;
1064#endif
1065
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001066#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001067 /* Open the process pseudo-files in /proc. */
1068 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1069 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 perror("strace: open(\"/proc/...\", ...)");
1071 return -1;
1072 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001073 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 return -1;
1075 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001076 sprintf(proc, "/proc/%d/status", tcp->pid);
1077 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1078 perror("strace: open(\"/proc/...\", ...)");
1079 return -1;
1080 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001081 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001082 return -1;
1083 }
1084 sprintf(proc, "/proc/%d/as", tcp->pid);
1085 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1086 perror("strace: open(\"/proc/...\", ...)");
1087 return -1;
1088 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001089 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001090 return -1;
1091 }
1092#else
1093 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001094#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001095 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001096 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001097#else /* FREEBSD */
1098 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001099 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001100#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001101 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001102 perror("strace: open(\"/proc/...\", ...)");
1103 return -1;
1104 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001105 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001106 return -1;
1107 }
1108#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001109#ifdef FREEBSD
1110 sprintf(proc, "/proc/%d/regs", tcp->pid);
1111 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1112 perror("strace: open(\"/proc/.../regs\", ...)");
1113 return -1;
1114 }
1115 if (cflag) {
1116 sprintf(proc, "/proc/%d/status", tcp->pid);
1117 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1118 perror("strace: open(\"/proc/.../status\", ...)");
1119 return -1;
1120 }
1121 } else
1122 tcp->pfd_status = -1;
1123#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001124 rebuild_pollv();
1125 if (!attaching) {
1126 /*
1127 * Wait for the child to pause. Because of a race
1128 * condition we have to poll for the event.
1129 */
1130 for (;;) {
1131 if (IOCTL_STATUS (tcp) < 0) {
1132 perror("strace: PIOCSTATUS");
1133 return -1;
1134 }
1135 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001136 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001137 }
1138 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001139#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001140 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001141 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001142 perror("strace: PIOCSTOP");
1143 return -1;
1144 }
Roland McGrath553a6092002-12-16 20:40:39 +00001145#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146#ifdef PIOCSET
1147 /* Set Run-on-Last-Close. */
1148 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001149 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 perror("PIOCSET PR_RLC");
1151 return -1;
1152 }
1153 /* Set or Reset Inherit-on-Fork. */
1154 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001155 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 perror("PIOC{SET,RESET} PR_FORK");
1157 return -1;
1158 }
1159#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001160#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1162 perror("PIOCSRLC");
1163 return -1;
1164 }
1165 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1166 perror("PIOC{S,R}FORK");
1167 return -1;
1168 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001169#else /* FREEBSD */
1170 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1171 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1172 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001173 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001174 }
1175 arg &= ~PF_LINGER;
1176 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001177 perror("PIOCSFL");
1178 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001179 }
1180#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001182#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001183 /* Enable all syscall entries we care about. */
1184 premptyset(&syscalls);
1185 for (i = 1; i < MAX_QUALS; ++i) {
1186 if (i > (sizeof syscalls) * CHAR_BIT) break;
1187 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1188 }
1189 praddset (&syscalls, SYS_execve);
1190 if (followfork) {
1191 praddset (&syscalls, SYS_fork);
1192#ifdef SYS_forkall
1193 praddset (&syscalls, SYS_forkall);
1194#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001195#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001196 praddset (&syscalls, SYS_fork1);
1197#endif
1198#ifdef SYS_rfork1
1199 praddset (&syscalls, SYS_rfork1);
1200#endif
1201#ifdef SYS_rforkall
1202 praddset (&syscalls, SYS_rforkall);
1203#endif
1204 }
1205 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206 perror("PIOCSENTRY");
1207 return -1;
1208 }
John Hughes19e49982001-10-19 08:59:12 +00001209 /* Enable the syscall exits. */
1210 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 perror("PIOSEXIT");
1212 return -1;
1213 }
John Hughes19e49982001-10-19 08:59:12 +00001214 /* Enable signals we care about. */
1215 premptyset(&signals);
1216 for (i = 1; i < MAX_QUALS; ++i) {
1217 if (i > (sizeof signals) * CHAR_BIT) break;
1218 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1219 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001220 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221 perror("PIOCSTRACE");
1222 return -1;
1223 }
John Hughes19e49982001-10-19 08:59:12 +00001224 /* Enable faults we care about */
1225 premptyset(&faults);
1226 for (i = 1; i < MAX_QUALS; ++i) {
1227 if (i > (sizeof faults) * CHAR_BIT) break;
1228 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1229 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001230 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 perror("PIOCSFAULT");
1232 return -1;
1233 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001234#else /* FREEBSD */
1235 /* set events flags. */
1236 arg = S_SIG | S_SCE | S_SCX ;
1237 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1238 perror("PIOCBIS");
1239 return -1;
1240 }
1241#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 if (!attaching) {
1243#ifdef MIPS
1244 /*
1245 * The SGI PRSABORT doesn't work for pause() so
1246 * we send it a caught signal to wake it up.
1247 */
1248 kill(tcp->pid, SIGINT);
1249#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001250#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001252 arg = PRSABORT;
1253 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254 perror("PIOCRUN");
1255 return -1;
1256 }
Roland McGrath553a6092002-12-16 20:40:39 +00001257#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001258#endif /* !MIPS*/
1259#ifdef FREEBSD
1260 /* wake up the child if it received the SIGSTOP */
1261 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001262#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263 for (;;) {
1264 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001265 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 perror("PIOCWSTOP");
1267 return -1;
1268 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001269 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001270 tcp->flags &= ~TCB_INSYSCALL;
1271 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001272 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001273 break;
1274 }
1275 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001276#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001277 arg = 0;
1278 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001279#else /* FREEBSD */
1280 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001281#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001282 perror("PIOCRUN");
1283 return -1;
1284 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001285#ifdef FREEBSD
1286 /* handle the case where we "opened" the child before
1287 it did the kill -STOP */
1288 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1289 tcp->status.PR_WHAT == SIGSTOP)
1290 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001291#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001293#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001295#else /* FREEBSD */
1296 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001297 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001298 /* We are attaching to an already running process.
1299 * Try to figure out the state of the process in syscalls,
1300 * to handle the first event well.
1301 * This is done by having a look at the "wchan" property of the
1302 * process, which tells where it is stopped (if it is). */
1303 FILE * status;
1304 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001305
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001306 sprintf(proc, "/proc/%d/status", tcp->pid);
1307 status = fopen(proc, "r");
1308 if (status &&
1309 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1310 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1311 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1312 strcmp(wchan, "stopevent")) {
1313 /* The process is asleep in the middle of a syscall.
1314 Fake the syscall entry event */
1315 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1316 tcp->status.PR_WHY = PR_SYSENTRY;
1317 trace_syscall(tcp);
1318 }
1319 if (status)
1320 fclose(status);
1321 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001322 }
1323#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001324#ifndef HAVE_POLLABLE_PROCFS
1325 if (proc_poll_pipe[0] != -1)
1326 proc_poller(tcp->pfd);
1327 else if (nprocs > 1) {
1328 proc_poll_open();
1329 proc_poller(last_pfd);
1330 proc_poller(tcp->pfd);
1331 }
1332 last_pfd = tcp->pfd;
1333#endif /* !HAVE_POLLABLE_PROCFS */
1334 return 0;
1335}
1336
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001337#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001338
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001339struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001340pid2tcb(int pid)
1341{
1342 int i;
1343
1344 if (pid <= 0)
1345 return NULL;
1346
1347 for (i = 0; i < tcbtabsize; i++) {
1348 struct tcb *tcp = tcbtab[i];
1349 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1350 return tcp;
1351 }
1352
1353 return NULL;
1354}
1355
1356#ifdef USE_PROCFS
1357
1358static struct tcb *
1359first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360{
1361 int i;
1362 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001363 for (i = 0; i < tcbtabsize; i++) {
1364 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001365 if (tcp->flags & TCB_INUSE)
1366 return tcp;
1367 }
1368 return NULL;
1369}
1370
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001371static struct tcb *
1372pfd2tcb(pfd)
1373int pfd;
1374{
1375 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376
Roland McGrathca16be82003-01-10 19:55:28 +00001377 for (i = 0; i < tcbtabsize; i++) {
1378 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001379 if (tcp->pfd != pfd)
1380 continue;
1381 if (tcp->flags & TCB_INUSE)
1382 return tcp;
1383 }
1384 return NULL;
1385}
1386
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001387#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001388
1389void
1390droptcb(tcp)
1391struct tcb *tcp;
1392{
1393 if (tcp->pid == 0)
1394 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001395#ifdef TCB_CLONE_THREAD
1396 if (tcp->nclone_threads > 0) {
1397 /* There are other threads left in this process, but this
1398 is the one whose PID represents the whole process.
1399 We need to keep this record around as a zombie until
1400 all the threads die. */
1401 tcp->flags |= TCB_EXITING;
1402 return;
1403 }
1404#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405 nprocs--;
1406 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001407
Roland McGrathe29341c2003-01-10 20:14:20 +00001408 if (tcp->parent != NULL) {
1409 tcp->parent->nchildren--;
1410#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001411 if (tcp->flags & TCB_CLONE_THREAD)
1412 tcp->parent->nclone_threads--;
1413#endif
Wang Chao21b8db42010-08-27 17:43:16 +08001414 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001415#ifdef LINUX
1416 /* Update `tcp->parent->parent->nchildren' and the other fields
1417 like NCLONE_DETACHED, only for zombie group leader that has
1418 already reported and been short-circuited at the top of this
1419 function. The same condition as at the top of DETACH. */
1420 if ((tcp->flags & TCB_CLONE_THREAD) &&
1421 tcp->parent->nclone_threads == 0 &&
1422 (tcp->parent->flags & TCB_EXITING))
1423 droptcb(tcp->parent);
1424#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001425 tcp->parent = NULL;
1426 }
1427
1428 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001429 if (tcp->pfd != -1) {
1430 close(tcp->pfd);
1431 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001432#ifdef FREEBSD
1433 if (tcp->pfd_reg != -1) {
1434 close(tcp->pfd_reg);
1435 tcp->pfd_reg = -1;
1436 }
1437 if (tcp->pfd_status != -1) {
1438 close(tcp->pfd_status);
1439 tcp->pfd_status = -1;
1440 }
Roland McGrath553a6092002-12-16 20:40:39 +00001441#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001442#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001443 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444#endif
1445 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001446
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001447 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001449
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450 tcp->outf = 0;
1451}
1452
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001453#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454
1455static int
1456resume(tcp)
1457struct tcb *tcp;
1458{
1459 if (tcp == NULL)
1460 return -1;
1461
1462 if (!(tcp->flags & TCB_SUSPENDED)) {
1463 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1464 return -1;
1465 }
1466 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001467#ifdef TCB_CLONE_THREAD
1468 if (tcp->flags & TCB_CLONE_THREAD)
1469 tcp->parent->nclone_waiting--;
1470#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001472 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001474
1475 if (!qflag)
1476 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1477 return 0;
1478}
1479
Roland McGrath1bfd3102007-08-03 10:02:00 +00001480static int
1481resume_from_tcp (struct tcb *tcp)
1482{
1483 int error = 0;
1484 int resumed = 0;
1485
1486 /* XXX This won't always be quite right (but it never was).
1487 A waiter with argument 0 or < -1 is waiting for any pid in
1488 a particular pgrp, which this child might or might not be
1489 in. The waiter will only wake up if it's argument is -1
1490 or if it's waiting for tcp->pid's pgrp. It makes a
1491 difference to wake up a waiter when there might be more
1492 traced children, because it could get a false ECHILD
1493 error. OTOH, if this was the last child in the pgrp, then
1494 it ought to wake up and get ECHILD. We would have to
1495 search the system for all pid's in the pgrp to be sure.
1496
1497 && (t->waitpid == -1 ||
1498 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1499 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1500 */
1501
1502 if (tcp->parent &&
1503 (tcp->parent->flags & TCB_SUSPENDED) &&
1504 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001505 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001506 ++resumed;
1507 }
1508#ifdef TCB_CLONE_THREAD
1509 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1510 /* Some other threads of our parent are waiting too. */
1511 unsigned int i;
1512
1513 /* Resume all the threads that were waiting for this PID. */
1514 for (i = 0; i < tcbtabsize; i++) {
1515 struct tcb *t = tcbtab[i];
1516 if (t->parent == tcp->parent && t != tcp
1517 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1518 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1519 && t->waitpid == tcp->pid) {
1520 error |= resume (t);
1521 ++resumed;
1522 }
1523 }
1524 if (resumed == 0)
1525 /* Noone was waiting for this PID in particular,
1526 so now we might need to resume some wildcarders. */
1527 for (i = 0; i < tcbtabsize; i++) {
1528 struct tcb *t = tcbtab[i];
1529 if (t->parent == tcp->parent && t != tcp
1530 && ((t->flags
1531 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1532 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1533 && t->waitpid <= 0
1534 ) {
1535 error |= resume (t);
1536 break;
1537 }
1538 }
1539 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001540#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001541
1542 return error;
1543}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001544
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001545#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546
Roland McGrath0a463882007-07-05 18:43:16 +00001547/* detach traced process; continue with sig
1548 Never call DETACH twice on the same process as both unattached and
1549 attached-unstopped processes give the same ESRCH. For unattached process we
1550 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551
1552static int
1553detach(tcp, sig)
1554struct tcb *tcp;
1555int sig;
1556{
1557 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001558#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001559 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001560 struct tcb *zombie = NULL;
1561
1562 /* If the group leader is lingering only because of this other
1563 thread now dying, then detach the leader as well. */
1564 if ((tcp->flags & TCB_CLONE_THREAD) &&
1565 tcp->parent->nclone_threads == 1 &&
1566 (tcp->parent->flags & TCB_EXITING))
1567 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001568#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569
1570 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001571 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572
1573#ifdef LINUX
1574 /*
1575 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001576 * before detaching. Arghh. We go through hoops
1577 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001579#if defined(SPARC)
1580#undef PTRACE_DETACH
1581#define PTRACE_DETACH PTRACE_SUNDETACH
1582#endif
Roland McGrath02203312007-06-11 22:06:31 +00001583 /*
1584 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1585 * expected SIGSTOP. We must catch exactly one as otherwise the
1586 * detached process would be left stopped (process state T).
1587 */
1588 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1590 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001591 }
1592 else if (errno != ESRCH) {
1593 /* Shouldn't happen. */
1594 perror("detach: ptrace(PTRACE_DETACH, ...)");
1595 }
Roland McGrath134813a2007-06-02 00:07:33 +00001596 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1597 : tcp->pid),
1598 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001599 if (errno != ESRCH)
1600 perror("detach: checking sanity");
1601 }
Roland McGrath02203312007-06-11 22:06:31 +00001602 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1603 ? tcp->parent->pid : tcp->pid),
1604 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001605 if (errno != ESRCH)
1606 perror("detach: stopping child");
1607 }
Roland McGrath02203312007-06-11 22:06:31 +00001608 else
1609 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001610 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001611 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001612#ifdef __WALL
1613 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1614 if (errno == ECHILD) /* Already gone. */
1615 break;
1616 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001617 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001618 break;
1619 }
1620#endif /* __WALL */
1621 /* No __WALL here. */
1622 if (waitpid(tcp->pid, &status, 0) < 0) {
1623 if (errno != ECHILD) {
1624 perror("detach: waiting");
1625 break;
1626 }
1627#ifdef __WCLONE
1628 /* If no processes, try clones. */
1629 if (wait4(tcp->pid, &status, __WCLONE,
1630 NULL) < 0) {
1631 if (errno != ECHILD)
1632 perror("detach: waiting");
1633 break;
1634 }
1635#endif /* __WCLONE */
1636 }
1637#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001638 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001639#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640 if (!WIFSTOPPED(status)) {
1641 /* Au revoir, mon ami. */
1642 break;
1643 }
1644 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001645 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646 break;
1647 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001648 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001649 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001650 : WSTOPSIG(status));
1651 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001654 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001655#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656
1657#if defined(SUNOS4)
1658 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1659 if (sig && kill(tcp->pid, sig) < 0)
1660 perror("detach: kill");
1661 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001662 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663#endif /* SUNOS4 */
1664
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001665#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001666 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001667#endif
1668
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669 if (!qflag)
1670 fprintf(stderr, "Process %u detached\n", tcp->pid);
1671
1672 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001673
1674#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001675 if (zombie != NULL) {
1676 /* TCP no longer exists therefore you must not detach () it. */
1677 droptcb(zombie);
1678 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001679#endif
1680
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 return error;
1682}
1683
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001684#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001686static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687{
1688 int pid;
1689 int status;
1690
1691 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692 }
1693}
1694
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001695#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696
1697static void
1698cleanup()
1699{
1700 int i;
1701 struct tcb *tcp;
1702
Roland McGrathee9d4352002-12-18 04:16:10 +00001703 for (i = 0; i < tcbtabsize; i++) {
1704 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705 if (!(tcp->flags & TCB_INUSE))
1706 continue;
1707 if (debug)
1708 fprintf(stderr,
1709 "cleanup: looking at pid %u\n", tcp->pid);
1710 if (tcp_last &&
1711 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001712 tprintf(" <unfinished ...>");
1713 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 }
1715 if (tcp->flags & TCB_ATTACHED)
1716 detach(tcp, 0);
1717 else {
1718 kill(tcp->pid, SIGCONT);
1719 kill(tcp->pid, SIGTERM);
1720 }
1721 }
1722 if (cflag)
1723 call_summary(outf);
1724}
1725
1726static void
1727interrupt(sig)
1728int sig;
1729{
1730 interrupted = 1;
1731}
1732
1733#ifndef HAVE_STRERROR
1734
Roland McGrath6d2b3492002-12-30 00:51:30 +00001735#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736extern int sys_nerr;
1737extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001738#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739
1740const char *
1741strerror(errno)
1742int errno;
1743{
1744 static char buf[64];
1745
1746 if (errno < 1 || errno >= sys_nerr) {
1747 sprintf(buf, "Unknown error %d", errno);
1748 return buf;
1749 }
1750 return sys_errlist[errno];
1751}
1752
1753#endif /* HAVE_STERRROR */
1754
1755#ifndef HAVE_STRSIGNAL
1756
Roland McGrath8f474e02003-01-14 07:53:33 +00001757#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001758extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001760#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1761extern char *_sys_siglist[];
1762#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763
1764const char *
1765strsignal(sig)
1766int sig;
1767{
1768 static char buf[64];
1769
1770 if (sig < 1 || sig >= NSIG) {
1771 sprintf(buf, "Unknown signal %d", sig);
1772 return buf;
1773 }
1774#ifdef HAVE__SYS_SIGLIST
1775 return _sys_siglist[sig];
1776#else
1777 return sys_siglist[sig];
1778#endif
1779}
1780
1781#endif /* HAVE_STRSIGNAL */
1782
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001783#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784
1785static void
1786rebuild_pollv()
1787{
1788 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789
Roland McGrathee9d4352002-12-18 04:16:10 +00001790 if (pollv != NULL)
1791 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001792 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001793 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001794 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001795 exit(1);
1796 }
1797
Roland McGrathca16be82003-01-10 19:55:28 +00001798 for (i = j = 0; i < tcbtabsize; i++) {
1799 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800 if (!(tcp->flags & TCB_INUSE))
1801 continue;
1802 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001803 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 j++;
1805 }
1806 if (j != nprocs) {
1807 fprintf(stderr, "strace: proc miscount\n");
1808 exit(1);
1809 }
1810}
1811
1812#ifndef HAVE_POLLABLE_PROCFS
1813
1814static void
1815proc_poll_open()
1816{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817 int i;
1818
1819 if (pipe(proc_poll_pipe) < 0) {
1820 perror("pipe");
1821 exit(1);
1822 }
1823 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001824 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825 exit(1);
1826 }
1827 }
1828}
1829
1830static int
1831proc_poll(pollv, nfds, timeout)
1832struct pollfd *pollv;
1833int nfds;
1834int timeout;
1835{
1836 int i;
1837 int n;
1838 struct proc_pollfd pollinfo;
1839
1840 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1841 return n;
1842 if (n != sizeof(struct proc_pollfd)) {
1843 fprintf(stderr, "panic: short read: %d\n", n);
1844 exit(1);
1845 }
1846 for (i = 0; i < nprocs; i++) {
1847 if (pollv[i].fd == pollinfo.fd)
1848 pollv[i].revents = pollinfo.revents;
1849 else
1850 pollv[i].revents = 0;
1851 }
1852 poller_pid = pollinfo.pid;
1853 return 1;
1854}
1855
1856static void
1857wakeup_handler(sig)
1858int sig;
1859{
1860}
1861
1862static void
1863proc_poller(pfd)
1864int pfd;
1865{
1866 struct proc_pollfd pollinfo;
1867 struct sigaction sa;
1868 sigset_t blocked_set, empty_set;
1869 int i;
1870 int n;
1871 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001872#ifdef FREEBSD
1873 struct procfs_status pfs;
1874#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875
1876 switch (fork()) {
1877 case -1:
1878 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001879 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 case 0:
1881 break;
1882 default:
1883 return;
1884 }
1885
1886 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1887 sa.sa_flags = 0;
1888 sigemptyset(&sa.sa_mask);
1889 sigaction(SIGHUP, &sa, NULL);
1890 sigaction(SIGINT, &sa, NULL);
1891 sigaction(SIGQUIT, &sa, NULL);
1892 sigaction(SIGPIPE, &sa, NULL);
1893 sigaction(SIGTERM, &sa, NULL);
1894 sa.sa_handler = wakeup_handler;
1895 sigaction(SIGUSR1, &sa, NULL);
1896 sigemptyset(&blocked_set);
1897 sigaddset(&blocked_set, SIGUSR1);
1898 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1899 sigemptyset(&empty_set);
1900
1901 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1902 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001903 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904 }
1905 n = rl.rlim_cur;
1906 for (i = 0; i < n; i++) {
1907 if (i != pfd && i != proc_poll_pipe[1])
1908 close(i);
1909 }
1910
1911 pollinfo.fd = pfd;
1912 pollinfo.pid = getpid();
1913 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001914#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001915 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1916#else
1917 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1918#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001919 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001920 switch (errno) {
1921 case EINTR:
1922 continue;
1923 case EBADF:
1924 pollinfo.revents = POLLERR;
1925 break;
1926 case ENOENT:
1927 pollinfo.revents = POLLHUP;
1928 break;
1929 default:
1930 perror("proc_poller: PIOCWSTOP");
1931 }
1932 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1933 _exit(0);
1934 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001935 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1937 sigsuspend(&empty_set);
1938 }
1939}
1940
1941#endif /* !HAVE_POLLABLE_PROCFS */
1942
1943static int
1944choose_pfd()
1945{
1946 int i, j;
1947 struct tcb *tcp;
1948
1949 static int last;
1950
1951 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001952 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953 /*
1954 * The previous process is ready to run again. We'll
1955 * let it do so if it is currently in a syscall. This
1956 * heuristic improves the readability of the trace.
1957 */
1958 tcp = pfd2tcb(pollv[last].fd);
1959 if (tcp && (tcp->flags & TCB_INSYSCALL))
1960 return pollv[last].fd;
1961 }
1962
1963 for (i = 0; i < nprocs; i++) {
1964 /* Let competing children run round robin. */
1965 j = (i + last + 1) % nprocs;
1966 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1967 tcp = pfd2tcb(pollv[j].fd);
1968 if (!tcp) {
1969 fprintf(stderr, "strace: lost proc\n");
1970 exit(1);
1971 }
1972 droptcb(tcp);
1973 return -1;
1974 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001975 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976 last = j;
1977 return pollv[j].fd;
1978 }
1979 }
1980 fprintf(stderr, "strace: nothing ready\n");
1981 exit(1);
1982}
1983
1984static int
1985trace()
1986{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001987#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001988 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001989#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001990 struct tcb *tcp;
1991 int pfd;
1992 int what;
1993 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001994 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995
1996 for (;;) {
1997 if (interactive)
1998 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1999
2000 if (nprocs == 0)
2001 break;
2002
2003 switch (nprocs) {
2004 case 1:
2005#ifndef HAVE_POLLABLE_PROCFS
2006 if (proc_poll_pipe[0] == -1) {
2007#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002008 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 if (!tcp)
2010 continue;
2011 pfd = tcp->pfd;
2012 if (pfd == -1)
2013 continue;
2014 break;
2015#ifndef HAVE_POLLABLE_PROCFS
2016 }
2017 /* fall through ... */
2018#endif /* !HAVE_POLLABLE_PROCFS */
2019 default:
2020#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002021#ifdef POLL_HACK
2022 /* On some systems (e.g. UnixWare) we get too much ugly
2023 "unfinished..." stuff when multiple proceses are in
2024 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002025
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002026 if (in_syscall) {
2027 struct pollfd pv;
2028 tcp = in_syscall;
2029 in_syscall = NULL;
2030 pv.fd = tcp->pfd;
2031 pv.events = POLLWANT;
2032 if ((what = poll (&pv, 1, 1)) < 0) {
2033 if (interrupted)
2034 return 0;
2035 continue;
2036 }
2037 else if (what == 1 && pv.revents & POLLWANT) {
2038 goto FOUND;
2039 }
2040 }
2041#endif
2042
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002043 if (poll(pollv, nprocs, INFTIM) < 0) {
2044 if (interrupted)
2045 return 0;
2046 continue;
2047 }
2048#else /* !HAVE_POLLABLE_PROCFS */
2049 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2050 if (interrupted)
2051 return 0;
2052 continue;
2053 }
2054#endif /* !HAVE_POLLABLE_PROCFS */
2055 pfd = choose_pfd();
2056 if (pfd == -1)
2057 continue;
2058 break;
2059 }
2060
2061 /* Look up `pfd' in our table. */
2062 if ((tcp = pfd2tcb(pfd)) == NULL) {
2063 fprintf(stderr, "unknown pfd: %u\n", pfd);
2064 exit(1);
2065 }
John Hughesb6643082002-05-23 11:02:22 +00002066#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002067 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002068#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002069 /* Get the status of the process. */
2070 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002071#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002072 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002073#else /* FREEBSD */
2074 /* Thanks to some scheduling mystery, the first poller
2075 sometimes waits for the already processed end of fork
2076 event. Doing a non blocking poll here solves the problem. */
2077 if (proc_poll_pipe[0] != -1)
2078 ioctl_result = IOCTL_STATUS (tcp);
2079 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002080 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002081#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002082 ioctl_errno = errno;
2083#ifndef HAVE_POLLABLE_PROCFS
2084 if (proc_poll_pipe[0] != -1) {
2085 if (ioctl_result < 0)
2086 kill(poller_pid, SIGKILL);
2087 else
2088 kill(poller_pid, SIGUSR1);
2089 }
2090#endif /* !HAVE_POLLABLE_PROCFS */
2091 }
2092 if (interrupted)
2093 return 0;
2094
2095 if (interactive)
2096 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2097
2098 if (ioctl_result < 0) {
2099 /* Find out what happened if it failed. */
2100 switch (ioctl_errno) {
2101 case EINTR:
2102 case EBADF:
2103 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002104#ifdef FREEBSD
2105 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002106#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 case ENOENT:
2108 droptcb(tcp);
2109 continue;
2110 default:
2111 perror("PIOCWSTOP");
2112 exit(1);
2113 }
2114 }
2115
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002116#ifdef FREEBSD
2117 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2118 /* discard first event for a syscall we never entered */
2119 IOCTL (tcp->pfd, PIOCRUN, 0);
2120 continue;
2121 }
Roland McGrath553a6092002-12-16 20:40:39 +00002122#endif
2123
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002124 /* clear the just started flag */
2125 tcp->flags &= ~TCB_STARTUP;
2126
2127 /* set current output file */
2128 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002129 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130
2131 if (cflag) {
2132 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002133#ifdef FREEBSD
2134 char buf[1024];
2135 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002136
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002137 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2138 buf[len] = '\0';
2139 sscanf(buf,
2140 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2141 &stime.tv_sec, &stime.tv_usec);
2142 } else
2143 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002144#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002145 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2146 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002147#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2149 tcp->stime = stime;
2150 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002151 what = tcp->status.PR_WHAT;
2152 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002153#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002154 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002155 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2156 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002157 if (trace_syscall(tcp) < 0) {
2158 fprintf(stderr, "syscall trouble\n");
2159 exit(1);
2160 }
2161 }
2162 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002163#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002164 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002165#ifdef POLL_HACK
2166 in_syscall = tcp;
2167#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002168 case PR_SYSEXIT:
2169 if (trace_syscall(tcp) < 0) {
2170 fprintf(stderr, "syscall trouble\n");
2171 exit(1);
2172 }
2173 break;
2174 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002175 if (cflag != CFLAG_ONLY_STATS
2176 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177 printleader(tcp);
2178 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002179 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002180 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002181#ifdef PR_INFO
2182 if (tcp->status.PR_INFO.si_signo == what) {
2183 printleader(tcp);
2184 tprintf(" siginfo=");
2185 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002186 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002187 }
2188#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 }
2190 break;
2191 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002192 if (cflag != CFLAGS_ONLY_STATS
2193 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002194 printleader(tcp);
2195 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002196 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 }
2198 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002199#ifdef FREEBSD
2200 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002201 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002202#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002204 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002205 exit(1);
2206 break;
2207 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002208 /* Remember current print column before continuing. */
2209 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002210 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002211#ifndef FREEBSD
Andreas Schwab372cc842010-07-09 11:49:27 +02002212 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002213#else
Andreas Schwab372cc842010-07-09 11:49:27 +02002214 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002215#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002216 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002217 perror("PIOCRUN");
2218 exit(1);
2219 }
2220 }
2221 return 0;
2222}
2223
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002224#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002225
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002226#ifdef TCB_GROUP_EXITING
2227/* Handle an exit detach or death signal that is taking all the
2228 related clone threads with it. This is called in three circumstances:
2229 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2230 SIG == 0 Continuing TCP will perform an exit_group syscall.
2231 SIG == other Continuing TCP with SIG will kill the process.
2232*/
2233static int
2234handle_group_exit(struct tcb *tcp, int sig)
2235{
2236 /* We need to locate our records of all the clone threads
2237 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002238 struct tcb *leader = NULL;
2239
2240 if (tcp->flags & TCB_CLONE_THREAD)
2241 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002242
2243 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002244 if (leader != NULL && leader != tcp
2245 && !(leader->flags & TCB_GROUP_EXITING)
2246 && !(tcp->flags & TCB_STARTUP)
2247 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002248 fprintf(stderr,
2249 "PANIC: handle_group_exit: %d leader %d\n",
2250 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002251 }
2252 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002253#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002254 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002255#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002256 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002257 }
2258 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002259 /* Mark that we are taking the process down. */
2260 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002261 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002262 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002263 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002264 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002265 } else {
2266 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2267 cleanup();
2268 return -1;
2269 }
2270 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002271 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002272 if (leader != tcp)
2273 droptcb(tcp);
2274 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002275 /* The leader will report to us as parent now,
2276 and then we'll get to the SIG==-1 case. */
2277 return 0;
2278 }
2279 }
2280
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002281 return 0;
2282}
2283#endif
2284
Roland McGratheb9e2e82009-06-02 16:49:22 -07002285static int
2286trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287{
2288 int pid;
2289 int wait_errno;
2290 int status;
2291 struct tcb *tcp;
2292#ifdef LINUX
2293 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002294#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002295 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002296#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002297#endif /* LINUX */
2298
Roland McGratheb9e2e82009-06-02 16:49:22 -07002299 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002300 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002301 return 0;
2302 if (interactive)
2303 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002304#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002305#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002306 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002307 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002308 /* this kernel does not support __WALL */
2309 wait4_options &= ~__WALL;
2310 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002311 pid = wait4(-1, &status, wait4_options,
2312 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002313 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002314 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002315 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002316 pid = wait4(-1, &status, __WCLONE,
2317 cflag ? &ru : NULL);
2318 if (pid == -1) {
2319 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002320 "failed: %s\n", strerror(errno));
2321 }
2322 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002323#else
2324 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2325#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002326#endif /* LINUX */
2327#ifdef SUNOS4
2328 pid = wait(&status);
2329#endif /* SUNOS4 */
2330 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002331 if (interactive)
2332 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002333
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002335 switch (wait_errno) {
2336 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002338 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002339 /*
2340 * We would like to verify this case
2341 * but sometimes a race in Solbourne's
2342 * version of SunOS sometimes reports
2343 * ECHILD before sending us SIGCHILD.
2344 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002345 return 0;
2346 default:
2347 errno = wait_errno;
2348 perror("strace: wait");
2349 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002350 }
2351 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002352 if (pid == popen_pid) {
2353 if (WIFEXITED(status) || WIFSIGNALED(status))
2354 popen_pid = -1;
2355 continue;
2356 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002357 if (debug)
2358 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2359
2360 /* Look up `pid' in our table. */
2361 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002362#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002363 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002364 /* This is needed to go with the CLONE_PTRACE
2365 changes in process.c/util.c: we might see
2366 the child's initial trap before we see the
2367 parent return from the clone syscall.
2368 Leave the child suspended until the parent
2369 returns from its system call. Only then
2370 will we have the association of parent and
2371 child so that we know how to do clearbpt
2372 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002373 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002374 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002375 if (!qflag)
2376 fprintf(stderr, "\
2377Process %d attached (waiting for parent)\n",
2378 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002379 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002380 else
2381 /* This can happen if a clone call used
2382 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002383#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002384 {
2385 fprintf(stderr, "unknown pid: %u\n", pid);
2386 if (WIFSTOPPED(status))
2387 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2388 exit(1);
2389 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002390 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002391 /* set current output file */
2392 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002393 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002394 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002395#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2397 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002398#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002399 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002400
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002401 if (tcp->flags & TCB_SUSPENDED) {
2402 /*
2403 * Apparently, doing any ptrace() call on a stopped
2404 * process, provokes the kernel to report the process
2405 * status again on a subsequent wait(), even if the
2406 * process has not been actually restarted.
2407 * Since we have inspected the arguments of suspended
2408 * processes we end up here testing for this case.
2409 */
2410 continue;
2411 }
2412 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002413 if (pid == strace_child)
2414 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002415 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002416 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2417 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002418 tprintf("+++ killed by %s %s+++",
2419 signame(WTERMSIG(status)),
2420#ifdef WCOREDUMP
2421 WCOREDUMP(status) ? "(core dumped) " :
2422#endif
2423 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002424 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002425 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002426#ifdef TCB_GROUP_EXITING
2427 handle_group_exit(tcp, -1);
2428#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002429 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002430#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002431 continue;
2432 }
2433 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002434 if (pid == strace_child)
2435 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002436 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002437 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2438 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002439#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002440 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002441 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002442#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002443 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002445 "PANIC: attached pid %u exited with %d\n",
2446 pid, WEXITSTATUS(status));
2447 }
Roland McGrath0a396902003-06-10 03:05:53 +00002448 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002449 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002450 tprintf(" <unfinished ... exit status %d>\n",
2451 WEXITSTATUS(status));
2452 tcp_last = NULL;
2453 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002454#ifdef TCB_GROUP_EXITING
2455 handle_group_exit(tcp, -1);
2456#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002457 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002458#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002459 continue;
2460 }
2461 if (!WIFSTOPPED(status)) {
2462 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2463 droptcb(tcp);
2464 continue;
2465 }
2466 if (debug)
2467 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002468 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002469
Roland McGrath02203312007-06-11 22:06:31 +00002470 /*
2471 * Interestingly, the process may stop
2472 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002473 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002474 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002475 * A no-MMU vforked child won't send up a signal,
2476 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002477 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002478 if ((tcp->flags & TCB_STARTUP) &&
2479 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002480 /*
2481 * This flag is there to keep us in sync.
2482 * Next time this process stops it should
2483 * really be entering a system call.
2484 */
2485 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002486 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002487 /*
2488 * One example is a breakpoint inherited from
2489 * parent through fork ().
2490 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002491 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2492 droptcb(tcp);
2493 cleanup();
2494 return -1;
2495 }
2496 }
2497 goto tracing;
2498 }
2499
Roland McGratheb9e2e82009-06-02 16:49:22 -07002500 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002501 if (WSTOPSIG(status) == SIGSTOP &&
2502 (tcp->flags & TCB_SIGTRAPPED)) {
2503 /*
2504 * Trapped attempt to block SIGTRAP
2505 * Hope we are back in control now.
2506 */
2507 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002508 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002509 cleanup();
2510 return -1;
2511 }
2512 continue;
2513 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002514 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002515 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002516 unsigned long addr = 0;
2517 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002518#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002519# define PSR_RI 41
2520 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002521 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002522
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002523 upeek(tcp, PT_CR_IPSR, &psr);
2524 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002525
2526 pc += (psr >> PSR_RI) & 0x3;
2527 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2528 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002529#elif defined PTRACE_GETSIGINFO
2530 if (WSTOPSIG(status) == SIGSEGV ||
2531 WSTOPSIG(status) == SIGBUS) {
2532 siginfo_t si;
2533 if (ptrace(PTRACE_GETSIGINFO, pid,
2534 0, &si) == 0)
2535 addr = (unsigned long)
2536 si.si_addr;
2537 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002538#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002540 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002541 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002542 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002543 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 }
Roland McGrath05690952004-10-20 01:00:27 +00002545 if (((tcp->flags & TCB_ATTACHED) ||
2546 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002547 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002548#ifdef TCB_GROUP_EXITING
2549 handle_group_exit(tcp, WSTOPSIG(status));
2550#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002552#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002553 continue;
2554 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002555 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002556 cleanup();
2557 return -1;
2558 }
2559 tcp->flags &= ~TCB_SUSPENDED;
2560 continue;
2561 }
Roland McGrath02203312007-06-11 22:06:31 +00002562 /* we handled the STATUS, we are permitted to interrupt now. */
2563 if (interrupted)
2564 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002565 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2566 /* ptrace() failed in trace_syscall() with ESRCH.
2567 * Likely a result of process disappearing mid-flight.
2568 * Observed case: exit_group() terminating
2569 * all processes in thread group. In this case, threads
2570 * "disappear" in an unpredictable moment without any
2571 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002572 */
2573 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002574 if (tcp_last) {
2575 /* Do we have dangling line "syscall(param, param"?
2576 * Finish the line then. We cannot
2577 */
2578 tcp_last->flags |= TCB_REPRINT;
2579 tprintf(" <unfinished ...>");
2580 printtrailer();
2581 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002582 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002583 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002584 ptrace(PTRACE_KILL,
2585 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002586 droptcb(tcp);
2587 }
2588 continue;
2589 }
2590 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002591#ifdef TCB_GROUP_EXITING
2592 if (tcp->flags & TCB_GROUP_EXITING) {
2593 if (handle_group_exit(tcp, 0) < 0)
2594 return -1;
2595 continue;
2596 }
2597#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002598 if (tcp->flags & TCB_ATTACHED)
2599 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002600 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002601 cleanup();
2602 return -1;
2603 }
2604 continue;
2605 }
2606 if (tcp->flags & TCB_SUSPENDED) {
2607 if (!qflag)
2608 fprintf(stderr, "Process %u suspended\n", pid);
2609 continue;
2610 }
2611 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002612 /* Remember current print column before continuing. */
2613 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002614 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002615 cleanup();
2616 return -1;
2617 }
2618 }
2619 return 0;
2620}
2621
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002622#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002623
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002624#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002625
2626void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002627tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002628{
2629 va_list args;
2630
Andreas Schwabe5355de2009-10-27 16:56:43 +01002631 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002632 if (outf) {
2633 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002634 if (n < 0) {
2635 if (outf != stderr)
2636 perror(outfname == NULL
2637 ? "<writing to pipe>" : outfname);
2638 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002639 curcol += n;
2640 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002641 va_end(args);
2642 return;
2643}
2644
2645void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002646printleader(tcp)
2647struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002648{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002649 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002650 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002651 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002652 tprintf(" <unavailable>)");
2653 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002654 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002655 tprintf("= ? <unavailable>\n");
2656 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002657 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002658 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002659 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002660 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 }
2662 curcol = 0;
2663 if ((followfork == 1 || pflag_seen > 1) && outfname)
2664 tprintf("%-5d ", tcp->pid);
2665 else if (nprocs > 1 && !outfname)
2666 tprintf("[pid %5u] ", tcp->pid);
2667 if (tflag) {
2668 char str[sizeof("HH:MM:SS")];
2669 struct timeval tv, dtv;
2670 static struct timeval otv;
2671
2672 gettimeofday(&tv, NULL);
2673 if (rflag) {
2674 if (otv.tv_sec == 0)
2675 otv = tv;
2676 tv_sub(&dtv, &tv, &otv);
2677 tprintf("%6ld.%06ld ",
2678 (long) dtv.tv_sec, (long) dtv.tv_usec);
2679 otv = tv;
2680 }
2681 else if (tflag > 2) {
2682 tprintf("%ld.%06ld ",
2683 (long) tv.tv_sec, (long) tv.tv_usec);
2684 }
2685 else {
2686 time_t local = tv.tv_sec;
2687 strftime(str, sizeof(str), "%T", localtime(&local));
2688 if (tflag > 1)
2689 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2690 else
2691 tprintf("%s ", str);
2692 }
2693 }
2694 if (iflag)
2695 printcall(tcp);
2696}
2697
2698void
2699tabto(col)
2700int col;
2701{
2702 if (curcol < col)
2703 tprintf("%*s", col - curcol, "");
2704}
2705
2706void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002707printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002708{
2709 tprintf("\n");
2710 tcp_last = NULL;
2711}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002712
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002713#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002714
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002715int
2716mp_ioctl(int fd, int cmd, void *arg, int size)
2717{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002718 struct iovec iov[2];
2719 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002720
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002721 iov[0].iov_base = &cmd;
2722 iov[0].iov_len = sizeof cmd;
2723 if (arg) {
2724 ++n;
2725 iov[1].iov_base = arg;
2726 iov[1].iov_len = size;
2727 }
Roland McGrath553a6092002-12-16 20:40:39 +00002728
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002729 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002730}
2731
2732#endif