blob: 35059483e0f71aa31930cc1b0fe6bb83f8e06556 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <signal.h>
37#include <errno.h>
38#include <sys/param.h>
39#include <fcntl.h>
40#include <sys/resource.h>
41#include <sys/wait.h>
42#include <sys/stat.h>
43#include <pwd.h>
44#include <grp.h>
45#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000046#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# include <asm/unistd.h>
51# if defined __NR_tgkill
52# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53# elif defined __NR_tkill
54# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55# else
56 /* kill() may choose arbitrarily the target task of the process group
57 while we later wait on a that specific TID. PID process waits become
58 TID task specific waits for a process under ptrace(2). */
59# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61# endif
62#endif
63
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000064#if defined(IA64) && defined(LINUX)
65# include <asm/ptrace_offsets.h>
66#endif
67
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000068#ifdef USE_PROCFS
69#include <poll.h>
70#endif
71
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000072#ifdef SVR4
73#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000074#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000075#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000076#include <sys/uio.h>
77#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000079#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000080extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000081extern int optind;
82extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000083
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
Roland McGrath41c48222008-07-18 00:25:10 +000085int debug = 0, followfork = 0;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000086int dtime = 0, xflag = 0, qflag = 0;
87cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000088static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000089/*
90 * daemonized_tracer supports -D option.
91 * With this option, strace forks twice.
92 * Unlike normal case, with -D *grandparent* process exec's,
93 * becoming a traced process. Child exits (this prevents traced process
94 * from having children it doesn't expect to have), and grandchild
95 * attaches to grandparent similarly to strace -p PID.
96 * This allows for more transparent interaction in cases
97 * when process and its parent are communicating via signals,
98 * wait() etc. Without -D, strace process gets lodged in between,
99 * disrupting parent<->child link.
100 */
101static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000103/* Sometimes we want to print only succeeding syscalls. */
104int not_failing_only = 0;
105
Dmitry V. Levina6809652008-11-10 17:14:58 +0000106static int exit_code = 0;
107static int strace_child = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700108
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000109static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110uid_t run_uid;
111gid_t run_gid;
112
113int acolumn = DEFAULT_ACOLUMN;
114int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000115static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100117static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000118struct tcb **tcbtab;
119unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700121extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122
Andreas Schwabe5355de2009-10-27 16:56:43 +0100123static int detach(struct tcb *tcp, int sig);
124static int trace(void);
125static void cleanup(void);
126static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127static sigset_t empty_set, blocked_set;
128
129#ifdef HAVE_SIG_ATOMIC_T
130static volatile sig_atomic_t interrupted;
131#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133#endif /* !HAVE_SIG_ATOMIC_T */
134
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000135#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136
Andreas Schwabe5355de2009-10-27 16:56:43 +0100137static struct tcb *pfd2tcb(int pfd);
138static void reaper(int sig);
139static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000140static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141
142#ifndef HAVE_POLLABLE_PROCFS
143
Andreas Schwabe5355de2009-10-27 16:56:43 +0100144static void proc_poll_open(void);
145static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146
147struct proc_pollfd {
148 int fd;
149 int revents;
150 int pid;
151};
152
153static int poller_pid;
154static int proc_poll_pipe[2] = { -1, -1 };
155
156#endif /* !HAVE_POLLABLE_PROCFS */
157
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000158#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000159#define POLLWANT POLLWRNORM
160#else
161#define POLLWANT POLLPRI
162#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000163#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164
165static void
166usage(ofp, exitval)
167FILE *ofp;
168int exitval;
169{
170 fprintf(ofp, "\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200171usage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000172 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
173 [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200174 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000175 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200177-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178-f -- follow forks, -ff -- with output into separate files\n\
179-F -- attempt to follow vforks, -h -- print help message\n\
180-i -- print instruction pointer at time of syscall\n\
181-q -- suppress messages about attaching, detaching, etc.\n\
182-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
183-T -- print time spent in each syscall, -V -- print version\n\
184-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
185-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
186-a column -- alignment COLUMN for printing syscall results (default %d)\n\
187-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
188 options: trace, abbrev, verbose, raw, signal, read, or write\n\
189-o file -- send trace output to FILE instead of stderr\n\
190-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
191-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000192-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
194-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
195-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000196-E var=val -- put var=val in the environment for command\n\
197-E var -- remove var from the environment for command\n\
198" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000199-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000200 */
201, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202 exit(exitval);
203}
204
205#ifdef SVR4
206#ifdef MIPS
207void
208foobar()
209{
210}
211#endif /* MIPS */
212#endif /* SVR4 */
213
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400214/* Glue for systems without a MMU that cannot provide fork() */
215#ifdef HAVE_FORK
216# define strace_vforked 0
217#else
218# define strace_vforked 1
219# define fork() vfork()
220#endif
221
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000222static int
223set_cloexec_flag(int fd)
224{
225 int flags, newflags;
226
227 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
228 {
229 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
230 progname, strerror(errno));
231 return -1;
232 }
233
234 newflags = flags | FD_CLOEXEC;
235 if (flags == newflags)
236 return 0;
237
238 if (fcntl(fd, F_SETFD, newflags) < 0)
239 {
240 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
241 progname, strerror(errno));
242 return -1;
243 }
244
245 return 0;
246}
247
248/*
249 * When strace is setuid executable, we have to swap uids
250 * before and after filesystem and process management operations.
251 */
252static void
253swap_uid(void)
254{
255#ifndef SVR4
256 int euid = geteuid(), uid = getuid();
257
258 if (euid != uid && setreuid(euid, uid) < 0)
259 {
260 fprintf(stderr, "%s: setreuid: %s\n",
261 progname, strerror(errno));
262 exit(1);
263 }
264#endif
265}
266
Roland McGrath4bfa6262007-07-05 20:03:16 +0000267#if _LFS64_LARGEFILE
268# define fopen_for_output fopen64
269#else
270# define fopen_for_output fopen
271#endif
272
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000273static FILE *
274strace_fopen(const char *path, const char *mode)
275{
276 FILE *fp;
277
278 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000279 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000280 fprintf(stderr, "%s: can't fopen '%s': %s\n",
281 progname, path, strerror(errno));
282 swap_uid();
283 if (fp && set_cloexec_flag(fileno(fp)) < 0)
284 {
285 fclose(fp);
286 fp = NULL;
287 }
288 return fp;
289}
290
291static int popen_pid = -1;
292
293#ifndef _PATH_BSHELL
294# define _PATH_BSHELL "/bin/sh"
295#endif
296
297/*
298 * We cannot use standard popen(3) here because we have to distinguish
299 * popen child process from other processes we trace, and standard popen(3)
300 * does not export its child's pid.
301 */
302static FILE *
303strace_popen(const char *command)
304{
305 int fds[2];
306
307 swap_uid();
308 if (pipe(fds) < 0)
309 {
310 fprintf(stderr, "%s: pipe: %s\n",
311 progname, strerror(errno));
312 swap_uid();
313 return NULL;
314 }
315
316 if (set_cloexec_flag(fds[1]) < 0)
317 {
318 close(fds[0]);
319 close(fds[1]);
320 swap_uid();
321 return NULL;
322 }
323
324 if ((popen_pid = fork()) == -1)
325 {
326 fprintf(stderr, "%s: fork: %s\n",
327 progname, strerror(errno));
328 close(fds[0]);
329 close(fds[1]);
330 swap_uid();
331 return NULL;
332 }
333
334 if (popen_pid)
335 {
336 /* parent */
337 close(fds[0]);
338 swap_uid();
339 return fdopen(fds[1], "w");
340 } else
341 {
342 /* child */
343 close(fds[1]);
344 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
345 {
346 fprintf(stderr, "%s: dup2: %s\n",
347 progname, strerror(errno));
348 _exit(1);
349 }
350 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
351 fprintf(stderr, "%s: execl: %s: %s\n",
352 progname, _PATH_BSHELL, strerror(errno));
353 _exit(1);
354 }
355}
356
357static int
358newoutf(struct tcb *tcp)
359{
360 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000361 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362 FILE *fp;
363
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000364 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000365 if ((fp = strace_fopen(name, "w")) == NULL)
366 return -1;
367 tcp->outf = fp;
368 }
369 return 0;
370}
371
Roland McGrath02203312007-06-11 22:06:31 +0000372static void
373startup_attach(void)
374{
375 int tcbi;
376 struct tcb *tcp;
377
378 /*
379 * Block user interruptions as we would leave the traced
380 * process stopped (process state T) if we would terminate in
381 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
382 * We rely on cleanup () from this point on.
383 */
384 if (interactive)
385 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
386
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000387 if (daemonized_tracer) {
388 pid_t pid = fork();
389 if (pid < 0) {
390 _exit(1);
391 }
392 if (pid) { /* parent */
393 /*
394 * Wait for child to attach to straced process
395 * (our parent). Child SIGKILLs us after it attached.
396 * Parent's wait() is unblocked by our death,
397 * it proceeds to exec the straced program.
398 */
399 pause();
400 _exit(0); /* paranoia */
401 }
402 }
403
Roland McGrath02203312007-06-11 22:06:31 +0000404 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
405 tcp = tcbtab[tcbi];
406 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
407 continue;
408#ifdef LINUX
409 if (tcp->flags & TCB_CLONE_THREAD)
410 continue;
411#endif
412 /* Reinitialize the output since it may have changed. */
413 tcp->outf = outf;
414 if (newoutf(tcp) < 0)
415 exit(1);
416
417#ifdef USE_PROCFS
418 if (proc_open(tcp, 1) < 0) {
419 fprintf(stderr, "trouble opening proc file\n");
420 droptcb(tcp);
421 continue;
422 }
423#else /* !USE_PROCFS */
424# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000425 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000426 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000427 DIR *dir;
428
429 sprintf(procdir, "/proc/%d/task", tcp->pid);
430 dir = opendir(procdir);
431 if (dir != NULL) {
432 unsigned int ntid = 0, nerr = 0;
433 struct dirent *de;
434 int tid;
435 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000436 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000437 continue;
438 tid = atoi(de->d_name);
439 if (tid <= 0)
440 continue;
441 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000442 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000443 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000444 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000445 tcp = alloctcb(tid);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700446 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000447 tcbtab[tcbi]->nchildren++;
448 tcbtab[tcbi]->nclone_threads++;
449 tcbtab[tcbi]->nclone_detached++;
450 tcp->parent = tcbtab[tcbi];
451 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000452 if (interactive) {
453 sigprocmask(SIG_SETMASK, &empty_set, NULL);
454 if (interrupted)
455 return;
456 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
457 }
Roland McGrath02203312007-06-11 22:06:31 +0000458 }
459 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000460 ntid -= nerr;
461 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000462 perror("attach: ptrace(PTRACE_ATTACH, ...)");
463 droptcb(tcp);
464 continue;
465 }
466 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000467 fprintf(stderr, ntid > 1
468? "Process %u attached with %u threads - interrupt to quit\n"
469: "Process %u attached - interrupt to quit\n",
470 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000471 }
472 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000473 } /* if (opendir worked) */
474 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000475# endif
476 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
477 perror("attach: ptrace(PTRACE_ATTACH, ...)");
478 droptcb(tcp);
479 continue;
480 }
481 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000482
483 if (daemonized_tracer) {
484 /*
485 * It is our grandparent we trace, not a -p PID.
486 * Don't want to just detach on exit, so...
487 */
488 tcp->flags &= ~TCB_ATTACHED;
489 /*
490 * Make parent go away.
491 * Also makes grandparent's wait() unblock.
492 */
493 kill(getppid(), SIGKILL);
494 }
495
Roland McGrath02203312007-06-11 22:06:31 +0000496#endif /* !USE_PROCFS */
497 if (!qflag)
498 fprintf(stderr,
499 "Process %u attached - interrupt to quit\n",
500 tcp->pid);
501 }
502
503 if (interactive)
504 sigprocmask(SIG_SETMASK, &empty_set, NULL);
505}
506
507static void
508startup_child (char **argv)
509{
510 struct stat statbuf;
511 const char *filename;
512 char pathname[MAXPATHLEN];
513 int pid = 0;
514 struct tcb *tcp;
515
516 filename = argv[0];
517 if (strchr(filename, '/')) {
518 if (strlen(filename) > sizeof pathname - 1) {
519 errno = ENAMETOOLONG;
520 perror("strace: exec");
521 exit(1);
522 }
523 strcpy(pathname, filename);
524 }
525#ifdef USE_DEBUGGING_EXEC
526 /*
527 * Debuggers customarily check the current directory
528 * first regardless of the path but doing that gives
529 * security geeks a panic attack.
530 */
531 else if (stat(filename, &statbuf) == 0)
532 strcpy(pathname, filename);
533#endif /* USE_DEBUGGING_EXEC */
534 else {
535 char *path;
536 int m, n, len;
537
538 for (path = getenv("PATH"); path && *path; path += m) {
539 if (strchr(path, ':')) {
540 n = strchr(path, ':') - path;
541 m = n + 1;
542 }
543 else
544 m = n = strlen(path);
545 if (n == 0) {
546 if (!getcwd(pathname, MAXPATHLEN))
547 continue;
548 len = strlen(pathname);
549 }
550 else if (n > sizeof pathname - 1)
551 continue;
552 else {
553 strncpy(pathname, path, n);
554 len = n;
555 }
556 if (len && pathname[len - 1] != '/')
557 pathname[len++] = '/';
558 strcpy(pathname + len, filename);
559 if (stat(pathname, &statbuf) == 0 &&
560 /* Accept only regular files
561 with some execute bits set.
562 XXX not perfect, might still fail */
563 S_ISREG(statbuf.st_mode) &&
564 (statbuf.st_mode & 0111))
565 break;
566 }
567 }
568 if (stat(pathname, &statbuf) < 0) {
569 fprintf(stderr, "%s: %s: command not found\n",
570 progname, filename);
571 exit(1);
572 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000573 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000574 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000575 perror("strace: fork");
576 cleanup();
577 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000578 }
579 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
580 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
581 ) {
582 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000583#ifdef USE_PROCFS
584 if (outf != stderr) close (fileno (outf));
585#ifdef MIPS
586 /* Kludge for SGI, see proc_open for details. */
587 sa.sa_handler = foobar;
588 sa.sa_flags = 0;
589 sigemptyset(&sa.sa_mask);
590 sigaction(SIGINT, &sa, NULL);
591#endif /* MIPS */
592#ifndef FREEBSD
593 pause();
594#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000595 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000596#endif /* FREEBSD */
597#else /* !USE_PROCFS */
598 if (outf!=stderr)
599 close(fileno (outf));
600
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000601 if (!daemonized_tracer) {
602 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
603 perror("strace: ptrace(PTRACE_TRACEME, ...)");
604 exit(1);
605 }
606 if (debug)
607 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000608 }
Roland McGrath02203312007-06-11 22:06:31 +0000609
610 if (username != NULL || geteuid() == 0) {
611 uid_t run_euid = run_uid;
612 gid_t run_egid = run_gid;
613
614 if (statbuf.st_mode & S_ISUID)
615 run_euid = statbuf.st_uid;
616 if (statbuf.st_mode & S_ISGID)
617 run_egid = statbuf.st_gid;
618
619 /*
620 * It is important to set groups before we
621 * lose privileges on setuid.
622 */
623 if (username != NULL) {
624 if (initgroups(username, run_gid) < 0) {
625 perror("initgroups");
626 exit(1);
627 }
628 if (setregid(run_gid, run_egid) < 0) {
629 perror("setregid");
630 exit(1);
631 }
632 if (setreuid(run_uid, run_euid) < 0) {
633 perror("setreuid");
634 exit(1);
635 }
636 }
637 }
638 else
639 setreuid(run_uid, run_uid);
640
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000641 if (!daemonized_tracer) {
642 /*
643 * Induce an immediate stop so that the parent
644 * will resume us with PTRACE_SYSCALL and display
645 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400646 * Unless of course we're on a no-MMU system where
647 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000648 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400649 if (!strace_vforked)
650 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000651 } else {
652 struct sigaction sv_sigchld;
653 sigaction(SIGCHLD, NULL, &sv_sigchld);
654 /*
655 * Make sure it is not SIG_IGN, otherwise wait
656 * will not block.
657 */
658 signal(SIGCHLD, SIG_DFL);
659 /*
660 * Wait for grandchild to attach to us.
661 * It kills child after that, and wait() unblocks.
662 */
663 alarm(3);
664 wait(NULL);
665 alarm(0);
666 sigaction(SIGCHLD, &sv_sigchld, NULL);
667 }
Roland McGrath02203312007-06-11 22:06:31 +0000668#endif /* !USE_PROCFS */
669
670 execv(pathname, argv);
671 perror("strace: exec");
672 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000673 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000674
675 /* We are the tracer. */
676 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677 if (daemonized_tracer) {
678 /* We want subsequent startup_attach() to attach to it. */
679 tcp->flags |= TCB_ATTACHED;
680 }
Roland McGrath02203312007-06-11 22:06:31 +0000681#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000682 if (proc_open(tcp, 0) < 0) {
683 fprintf(stderr, "trouble opening proc file\n");
684 cleanup();
685 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000686 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000687#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000688}
689
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000691main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693 struct tcb *tcp;
694 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000695 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000696 struct sigaction sa;
697
698 static char buf[BUFSIZ];
699
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000700 progname = argv[0] ? argv[0] : "strace";
701
Roland McGrathee9d4352002-12-18 04:16:10 +0000702 /* Allocate the initial tcbtab. */
703 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000704 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000705 fprintf(stderr, "%s: out of memory\n", progname);
706 exit(1);
707 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000708 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000709 fprintf(stderr, "%s: out of memory\n", progname);
710 exit(1);
711 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000712 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
713 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
714
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 outf = stderr;
716 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000717 set_sortby(DEFAULT_SORTBY);
718 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 qualify("trace=all");
720 qualify("abbrev=all");
721 qualify("verbose=all");
722 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 while ((c = getopt(argc, argv,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000724 "+cCdfFhiqrtTvVxz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000725#ifndef USE_PROCFS
726 "D"
727#endif
728 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000729 switch (c) {
730 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000731 if (cflag == CFLAG_BOTH) {
732 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
733 progname);
734 exit(1);
735 }
736 cflag = CFLAG_ONLY_STATS;
737 break;
738 case 'C':
739 if (cflag == CFLAG_ONLY_STATS) {
740 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
741 progname);
742 exit(1);
743 }
744 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000745 break;
746 case 'd':
747 debug++;
748 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000749#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000750 case 'D':
751 daemonized_tracer = 1;
752 break;
753#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000754 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000755 optF = 1;
756 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757 case 'f':
758 followfork++;
759 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 case 'h':
761 usage(stdout, 0);
762 break;
763 case 'i':
764 iflag++;
765 break;
766 case 'q':
767 qflag++;
768 break;
769 case 'r':
770 rflag++;
771 tflag++;
772 break;
773 case 't':
774 tflag++;
775 break;
776 case 'T':
777 dtime++;
778 break;
779 case 'x':
780 xflag++;
781 break;
782 case 'v':
783 qualify("abbrev=none");
784 break;
785 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000786 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787 exit(0);
788 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000789 case 'z':
790 not_failing_only = 1;
791 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 case 'a':
793 acolumn = atoi(optarg);
794 break;
795 case 'e':
796 qualify(optarg);
797 break;
798 case 'o':
799 outfname = strdup(optarg);
800 break;
801 case 'O':
802 set_overhead(atoi(optarg));
803 break;
804 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000805 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 fprintf(stderr, "%s: Invalid process id: %s\n",
807 progname, optarg);
808 break;
809 }
810 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000811 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 break;
813 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000814 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815 tcp->flags |= TCB_ATTACHED;
816 pflag_seen++;
817 break;
818 case 's':
819 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000820 if (max_strlen < 0) {
821 fprintf(stderr,
822 "%s: invalid -s argument: %s\n",
823 progname, optarg);
824 exit(1);
825 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 break;
827 case 'S':
828 set_sortby(optarg);
829 break;
830 case 'u':
831 username = strdup(optarg);
832 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000833 case 'E':
834 if (putenv(optarg) < 0) {
835 fprintf(stderr, "%s: out of memory\n",
836 progname);
837 exit(1);
838 }
839 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 default:
841 usage(stderr, 1);
842 break;
843 }
844 }
845
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000846 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000847 usage(stderr, 1);
848
Wang Chaod322a4b2010-08-05 14:30:11 +0800849 if (pflag_seen && daemonized_tracer) {
850 fprintf(stderr,
851 "%s: -D and -p are mutually exclusive options\n",
852 progname);
853 exit(1);
854 }
855
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000856 if (!followfork)
857 followfork = optF;
858
Roland McGrathcb9def62006-04-25 07:48:03 +0000859 if (followfork > 1 && cflag) {
860 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000861 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +0000862 progname);
863 exit(1);
864 }
865
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000866 /* See if they want to run as another user. */
867 if (username != NULL) {
868 struct passwd *pent;
869
870 if (getuid() != 0 || geteuid() != 0) {
871 fprintf(stderr,
872 "%s: you must be root to use the -u option\n",
873 progname);
874 exit(1);
875 }
876 if ((pent = getpwnam(username)) == NULL) {
877 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000878 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879 exit(1);
880 }
881 run_uid = pent->pw_uid;
882 run_gid = pent->pw_gid;
883 }
884 else {
885 run_uid = getuid();
886 run_gid = getgid();
887 }
888
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889 /* Check if they want to redirect the output. */
890 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000891 /* See if they want to pipe the output. */
892 if (outfname[0] == '|' || outfname[0] == '!') {
893 /*
894 * We can't do the <outfname>.PID funny business
895 * when using popen, so prohibit it.
896 */
897 if (followfork > 1) {
898 fprintf(stderr, "\
899%s: piping the output and -ff are mutually exclusive options\n",
900 progname);
901 exit(1);
902 }
903
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000904 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000905 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000906 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000907 else if (followfork <= 1 &&
908 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910 }
911
Roland McGrath37b9a662003-11-07 02:26:54 +0000912 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000913 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000914 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000917 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000918 /* Valid states here:
919 optind < argc pflag_seen outfname interactive
920 1 0 0 1
921 0 1 0 1
922 1 0 1 0
923 0 1 1 1
924 */
925
926 /* STARTUP_CHILD must be called before the signal handlers get
927 installed below as they are inherited into the spawned process.
928 Also we do not need to be protected by them as during interruption
929 in the STARTUP_CHILD mode we kill the spawned process anyway. */
930 if (!pflag_seen)
931 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000932
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933 sigemptyset(&empty_set);
934 sigemptyset(&blocked_set);
935 sa.sa_handler = SIG_IGN;
936 sigemptyset(&sa.sa_mask);
937 sa.sa_flags = 0;
938 sigaction(SIGTTOU, &sa, NULL);
939 sigaction(SIGTTIN, &sa, NULL);
940 if (interactive) {
941 sigaddset(&blocked_set, SIGHUP);
942 sigaddset(&blocked_set, SIGINT);
943 sigaddset(&blocked_set, SIGQUIT);
944 sigaddset(&blocked_set, SIGPIPE);
945 sigaddset(&blocked_set, SIGTERM);
946 sa.sa_handler = interrupt;
947#ifdef SUNOS4
948 /* POSIX signals on sunos4.1 are a little broken. */
949 sa.sa_flags = SA_INTERRUPT;
950#endif /* SUNOS4 */
951 }
952 sigaction(SIGHUP, &sa, NULL);
953 sigaction(SIGINT, &sa, NULL);
954 sigaction(SIGQUIT, &sa, NULL);
955 sigaction(SIGPIPE, &sa, NULL);
956 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000957#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 sa.sa_handler = reaper;
959 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000960#else
961 /* Make sure SIGCHLD has the default action so that waitpid
962 definitely works without losing track of children. The user
963 should not have given us a bogus state to inherit, but he might
964 have. Arguably we should detect SIG_IGN here and pass it on
965 to children, but probably noone really needs that. */
966 sa.sa_handler = SIG_DFL;
967 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000968#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000970 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000971 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000972
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 if (trace() < 0)
974 exit(1);
975 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000976 fflush(NULL);
977 if (exit_code > 0xff) {
978 /* Child was killed by a signal, mimic that. */
979 exit_code &= 0xff;
980 signal(exit_code, SIG_DFL);
981 raise(exit_code);
982 /* Paranoia - what if this signal is not fatal?
983 Exit with 128 + signo then. */
984 exit_code += 128;
985 }
986 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987}
988
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000989void
990expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000991{
992 /* Allocate some more TCBs and expand the table.
993 We don't want to relocate the TCBs because our
994 callers have pointers and it would be a pain.
995 So tcbtab is a table of pointers. Since we never
996 free the TCBs, we allocate a single chunk of many. */
997 struct tcb **newtab = (struct tcb **)
998 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
999 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
1000 sizeof *newtcbs);
1001 int i;
1002 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +00001003 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
1004 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001005 cleanup();
1006 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001007 }
1008 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1009 newtab[i] = &newtcbs[i - tcbtabsize];
1010 tcbtabsize *= 2;
1011 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001012}
1013
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001015alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001016{
1017 int i;
1018 struct tcb *tcp;
1019
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001020 if (nprocs == tcbtabsize)
1021 expand_tcbtab();
1022
Roland McGrathee9d4352002-12-18 04:16:10 +00001023 for (i = 0; i < tcbtabsize; i++) {
1024 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 if ((tcp->flags & TCB_INUSE) == 0) {
1026 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001027 tcp->parent = NULL;
1028 tcp->nchildren = 0;
1029 tcp->nzombies = 0;
1030#ifdef TCB_CLONE_THREAD
1031 tcp->nclone_threads = tcp->nclone_detached = 0;
1032 tcp->nclone_waiting = 0;
1033#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 tcp->flags = TCB_INUSE | TCB_STARTUP;
1035 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001036 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001037 tcp->stime.tv_sec = 0;
1038 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 tcp->pfd = -1;
1040 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001041 if (command_options_parsed)
1042 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 return tcp;
1044 }
1045 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001046 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1047 cleanup();
1048 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049}
1050
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001051#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001053proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054{
1055 char proc[32];
1056 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001057#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001058 int i;
1059 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 sigset_t signals;
1061 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001062#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001063#ifndef HAVE_POLLABLE_PROCFS
1064 static int last_pfd;
1065#endif
1066
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001067#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001068 /* Open the process pseudo-files in /proc. */
1069 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1070 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 perror("strace: open(\"/proc/...\", ...)");
1072 return -1;
1073 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001074 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 return -1;
1076 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001077 sprintf(proc, "/proc/%d/status", tcp->pid);
1078 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1079 perror("strace: open(\"/proc/...\", ...)");
1080 return -1;
1081 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001082 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001083 return -1;
1084 }
1085 sprintf(proc, "/proc/%d/as", tcp->pid);
1086 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1087 perror("strace: open(\"/proc/...\", ...)");
1088 return -1;
1089 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001090 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001091 return -1;
1092 }
1093#else
1094 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001095#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001096 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001097 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001098#else /* FREEBSD */
1099 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001100 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001101#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001102 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001103 perror("strace: open(\"/proc/...\", ...)");
1104 return -1;
1105 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001106 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001107 return -1;
1108 }
1109#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001110#ifdef FREEBSD
1111 sprintf(proc, "/proc/%d/regs", tcp->pid);
1112 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1113 perror("strace: open(\"/proc/.../regs\", ...)");
1114 return -1;
1115 }
1116 if (cflag) {
1117 sprintf(proc, "/proc/%d/status", tcp->pid);
1118 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1119 perror("strace: open(\"/proc/.../status\", ...)");
1120 return -1;
1121 }
1122 } else
1123 tcp->pfd_status = -1;
1124#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001125 rebuild_pollv();
1126 if (!attaching) {
1127 /*
1128 * Wait for the child to pause. Because of a race
1129 * condition we have to poll for the event.
1130 */
1131 for (;;) {
1132 if (IOCTL_STATUS (tcp) < 0) {
1133 perror("strace: PIOCSTATUS");
1134 return -1;
1135 }
1136 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001137 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001138 }
1139 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001140#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001141 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001142 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001143 perror("strace: PIOCSTOP");
1144 return -1;
1145 }
Roland McGrath553a6092002-12-16 20:40:39 +00001146#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147#ifdef PIOCSET
1148 /* Set Run-on-Last-Close. */
1149 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001150 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 perror("PIOCSET PR_RLC");
1152 return -1;
1153 }
1154 /* Set or Reset Inherit-on-Fork. */
1155 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001156 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 perror("PIOC{SET,RESET} PR_FORK");
1158 return -1;
1159 }
1160#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001161#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1163 perror("PIOCSRLC");
1164 return -1;
1165 }
1166 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1167 perror("PIOC{S,R}FORK");
1168 return -1;
1169 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001170#else /* FREEBSD */
1171 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1172 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1173 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001174 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001175 }
1176 arg &= ~PF_LINGER;
1177 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001178 perror("PIOCSFL");
1179 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001180 }
1181#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001183#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001184 /* Enable all syscall entries we care about. */
1185 premptyset(&syscalls);
1186 for (i = 1; i < MAX_QUALS; ++i) {
1187 if (i > (sizeof syscalls) * CHAR_BIT) break;
1188 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1189 }
1190 praddset (&syscalls, SYS_execve);
1191 if (followfork) {
1192 praddset (&syscalls, SYS_fork);
1193#ifdef SYS_forkall
1194 praddset (&syscalls, SYS_forkall);
1195#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001196#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001197 praddset (&syscalls, SYS_fork1);
1198#endif
1199#ifdef SYS_rfork1
1200 praddset (&syscalls, SYS_rfork1);
1201#endif
1202#ifdef SYS_rforkall
1203 praddset (&syscalls, SYS_rforkall);
1204#endif
1205 }
1206 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 perror("PIOCSENTRY");
1208 return -1;
1209 }
John Hughes19e49982001-10-19 08:59:12 +00001210 /* Enable the syscall exits. */
1211 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 perror("PIOSEXIT");
1213 return -1;
1214 }
John Hughes19e49982001-10-19 08:59:12 +00001215 /* Enable signals we care about. */
1216 premptyset(&signals);
1217 for (i = 1; i < MAX_QUALS; ++i) {
1218 if (i > (sizeof signals) * CHAR_BIT) break;
1219 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1220 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001221 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 perror("PIOCSTRACE");
1223 return -1;
1224 }
John Hughes19e49982001-10-19 08:59:12 +00001225 /* Enable faults we care about */
1226 premptyset(&faults);
1227 for (i = 1; i < MAX_QUALS; ++i) {
1228 if (i > (sizeof faults) * CHAR_BIT) break;
1229 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1230 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001231 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232 perror("PIOCSFAULT");
1233 return -1;
1234 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001235#else /* FREEBSD */
1236 /* set events flags. */
1237 arg = S_SIG | S_SCE | S_SCX ;
1238 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1239 perror("PIOCBIS");
1240 return -1;
1241 }
1242#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001243 if (!attaching) {
1244#ifdef MIPS
1245 /*
1246 * The SGI PRSABORT doesn't work for pause() so
1247 * we send it a caught signal to wake it up.
1248 */
1249 kill(tcp->pid, SIGINT);
1250#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001251#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001253 arg = PRSABORT;
1254 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255 perror("PIOCRUN");
1256 return -1;
1257 }
Roland McGrath553a6092002-12-16 20:40:39 +00001258#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001259#endif /* !MIPS*/
1260#ifdef FREEBSD
1261 /* wake up the child if it received the SIGSTOP */
1262 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001263#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 for (;;) {
1265 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001266 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267 perror("PIOCWSTOP");
1268 return -1;
1269 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001270 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001271 tcp->flags &= ~TCB_INSYSCALL;
1272 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001273 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 break;
1275 }
1276 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001277#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001278 arg = 0;
1279 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001280#else /* FREEBSD */
1281 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001282#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283 perror("PIOCRUN");
1284 return -1;
1285 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001286#ifdef FREEBSD
1287 /* handle the case where we "opened" the child before
1288 it did the kill -STOP */
1289 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1290 tcp->status.PR_WHAT == SIGSTOP)
1291 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001292#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001294#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001296#else /* FREEBSD */
1297 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001298 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001299 /* We are attaching to an already running process.
1300 * Try to figure out the state of the process in syscalls,
1301 * to handle the first event well.
1302 * This is done by having a look at the "wchan" property of the
1303 * process, which tells where it is stopped (if it is). */
1304 FILE * status;
1305 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001306
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001307 sprintf(proc, "/proc/%d/status", tcp->pid);
1308 status = fopen(proc, "r");
1309 if (status &&
1310 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1311 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1312 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1313 strcmp(wchan, "stopevent")) {
1314 /* The process is asleep in the middle of a syscall.
1315 Fake the syscall entry event */
1316 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1317 tcp->status.PR_WHY = PR_SYSENTRY;
1318 trace_syscall(tcp);
1319 }
1320 if (status)
1321 fclose(status);
1322 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001323 }
1324#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325#ifndef HAVE_POLLABLE_PROCFS
1326 if (proc_poll_pipe[0] != -1)
1327 proc_poller(tcp->pfd);
1328 else if (nprocs > 1) {
1329 proc_poll_open();
1330 proc_poller(last_pfd);
1331 proc_poller(tcp->pfd);
1332 }
1333 last_pfd = tcp->pfd;
1334#endif /* !HAVE_POLLABLE_PROCFS */
1335 return 0;
1336}
1337
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001340struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341pid2tcb(pid)
1342int pid;
1343{
1344 int i;
1345 struct tcb *tcp;
1346
Roland McGrathee9d4352002-12-18 04:16:10 +00001347 for (i = 0; i < tcbtabsize; i++) {
1348 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001349 if (pid && tcp->pid != pid)
1350 continue;
1351 if (tcp->flags & TCB_INUSE)
1352 return tcp;
1353 }
1354 return NULL;
1355}
1356
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001357#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358
1359static struct tcb *
1360pfd2tcb(pfd)
1361int pfd;
1362{
1363 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001364
Roland McGrathca16be82003-01-10 19:55:28 +00001365 for (i = 0; i < tcbtabsize; i++) {
1366 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001367 if (tcp->pfd != pfd)
1368 continue;
1369 if (tcp->flags & TCB_INUSE)
1370 return tcp;
1371 }
1372 return NULL;
1373}
1374
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001375#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376
1377void
1378droptcb(tcp)
1379struct tcb *tcp;
1380{
1381 if (tcp->pid == 0)
1382 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001383#ifdef TCB_CLONE_THREAD
1384 if (tcp->nclone_threads > 0) {
1385 /* There are other threads left in this process, but this
1386 is the one whose PID represents the whole process.
1387 We need to keep this record around as a zombie until
1388 all the threads die. */
1389 tcp->flags |= TCB_EXITING;
1390 return;
1391 }
1392#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001393 nprocs--;
1394 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001395
Roland McGrathe29341c2003-01-10 20:14:20 +00001396 if (tcp->parent != NULL) {
1397 tcp->parent->nchildren--;
1398#ifdef TCB_CLONE_THREAD
1399 if (tcp->flags & TCB_CLONE_DETACHED)
1400 tcp->parent->nclone_detached--;
1401 if (tcp->flags & TCB_CLONE_THREAD)
1402 tcp->parent->nclone_threads--;
1403#endif
Roland McGrath09623452003-05-23 02:27:13 +00001404#ifdef TCB_CLONE_DETACHED
1405 if (!(tcp->flags & TCB_CLONE_DETACHED))
1406#endif
1407 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001408#ifdef LINUX
1409 /* Update `tcp->parent->parent->nchildren' and the other fields
1410 like NCLONE_DETACHED, only for zombie group leader that has
1411 already reported and been short-circuited at the top of this
1412 function. The same condition as at the top of DETACH. */
1413 if ((tcp->flags & TCB_CLONE_THREAD) &&
1414 tcp->parent->nclone_threads == 0 &&
1415 (tcp->parent->flags & TCB_EXITING))
1416 droptcb(tcp->parent);
1417#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001418 tcp->parent = NULL;
1419 }
1420
1421 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 if (tcp->pfd != -1) {
1423 close(tcp->pfd);
1424 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001425#ifdef FREEBSD
1426 if (tcp->pfd_reg != -1) {
1427 close(tcp->pfd_reg);
1428 tcp->pfd_reg = -1;
1429 }
1430 if (tcp->pfd_status != -1) {
1431 close(tcp->pfd_status);
1432 tcp->pfd_status = -1;
1433 }
Roland McGrath553a6092002-12-16 20:40:39 +00001434#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001435#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001436 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437#endif
1438 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001439
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001440 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001441 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001442
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443 tcp->outf = 0;
1444}
1445
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001446#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447
1448static int
1449resume(tcp)
1450struct tcb *tcp;
1451{
1452 if (tcp == NULL)
1453 return -1;
1454
1455 if (!(tcp->flags & TCB_SUSPENDED)) {
1456 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1457 return -1;
1458 }
1459 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001460#ifdef TCB_CLONE_THREAD
1461 if (tcp->flags & TCB_CLONE_THREAD)
1462 tcp->parent->nclone_waiting--;
1463#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001464
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001465 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001466 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001467
1468 if (!qflag)
1469 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1470 return 0;
1471}
1472
Roland McGrath1bfd3102007-08-03 10:02:00 +00001473static int
1474resume_from_tcp (struct tcb *tcp)
1475{
1476 int error = 0;
1477 int resumed = 0;
1478
1479 /* XXX This won't always be quite right (but it never was).
1480 A waiter with argument 0 or < -1 is waiting for any pid in
1481 a particular pgrp, which this child might or might not be
1482 in. The waiter will only wake up if it's argument is -1
1483 or if it's waiting for tcp->pid's pgrp. It makes a
1484 difference to wake up a waiter when there might be more
1485 traced children, because it could get a false ECHILD
1486 error. OTOH, if this was the last child in the pgrp, then
1487 it ought to wake up and get ECHILD. We would have to
1488 search the system for all pid's in the pgrp to be sure.
1489
1490 && (t->waitpid == -1 ||
1491 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1492 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1493 */
1494
1495 if (tcp->parent &&
1496 (tcp->parent->flags & TCB_SUSPENDED) &&
1497 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001498 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001499 ++resumed;
1500 }
1501#ifdef TCB_CLONE_THREAD
1502 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1503 /* Some other threads of our parent are waiting too. */
1504 unsigned int i;
1505
1506 /* Resume all the threads that were waiting for this PID. */
1507 for (i = 0; i < tcbtabsize; i++) {
1508 struct tcb *t = tcbtab[i];
1509 if (t->parent == tcp->parent && t != tcp
1510 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1511 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1512 && t->waitpid == tcp->pid) {
1513 error |= resume (t);
1514 ++resumed;
1515 }
1516 }
1517 if (resumed == 0)
1518 /* Noone was waiting for this PID in particular,
1519 so now we might need to resume some wildcarders. */
1520 for (i = 0; i < tcbtabsize; i++) {
1521 struct tcb *t = tcbtab[i];
1522 if (t->parent == tcp->parent && t != tcp
1523 && ((t->flags
1524 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1525 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1526 && t->waitpid <= 0
1527 ) {
1528 error |= resume (t);
1529 break;
1530 }
1531 }
1532 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001533#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001534
1535 return error;
1536}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001537
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001538#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539
Roland McGrath0a463882007-07-05 18:43:16 +00001540/* detach traced process; continue with sig
1541 Never call DETACH twice on the same process as both unattached and
1542 attached-unstopped processes give the same ESRCH. For unattached process we
1543 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544
1545static int
1546detach(tcp, sig)
1547struct tcb *tcp;
1548int sig;
1549{
1550 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001551#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001552 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001553 struct tcb *zombie = NULL;
1554
1555 /* If the group leader is lingering only because of this other
1556 thread now dying, then detach the leader as well. */
1557 if ((tcp->flags & TCB_CLONE_THREAD) &&
1558 tcp->parent->nclone_threads == 1 &&
1559 (tcp->parent->flags & TCB_EXITING))
1560 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001561#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562
1563 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001564 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565
1566#ifdef LINUX
1567 /*
1568 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001569 * before detaching. Arghh. We go through hoops
1570 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001571 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001572#if defined(SPARC)
1573#undef PTRACE_DETACH
1574#define PTRACE_DETACH PTRACE_SUNDETACH
1575#endif
Roland McGrath02203312007-06-11 22:06:31 +00001576 /*
1577 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1578 * expected SIGSTOP. We must catch exactly one as otherwise the
1579 * detached process would be left stopped (process state T).
1580 */
1581 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1583 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001584 }
1585 else if (errno != ESRCH) {
1586 /* Shouldn't happen. */
1587 perror("detach: ptrace(PTRACE_DETACH, ...)");
1588 }
Roland McGrath134813a2007-06-02 00:07:33 +00001589 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1590 : tcp->pid),
1591 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001592 if (errno != ESRCH)
1593 perror("detach: checking sanity");
1594 }
Roland McGrath02203312007-06-11 22:06:31 +00001595 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1596 ? tcp->parent->pid : tcp->pid),
1597 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001598 if (errno != ESRCH)
1599 perror("detach: stopping child");
1600 }
Roland McGrath02203312007-06-11 22:06:31 +00001601 else
1602 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001603 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001605#ifdef __WALL
1606 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1607 if (errno == ECHILD) /* Already gone. */
1608 break;
1609 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001610 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001611 break;
1612 }
1613#endif /* __WALL */
1614 /* No __WALL here. */
1615 if (waitpid(tcp->pid, &status, 0) < 0) {
1616 if (errno != ECHILD) {
1617 perror("detach: waiting");
1618 break;
1619 }
1620#ifdef __WCLONE
1621 /* If no processes, try clones. */
1622 if (wait4(tcp->pid, &status, __WCLONE,
1623 NULL) < 0) {
1624 if (errno != ECHILD)
1625 perror("detach: waiting");
1626 break;
1627 }
1628#endif /* __WCLONE */
1629 }
1630#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001631 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001632#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633 if (!WIFSTOPPED(status)) {
1634 /* Au revoir, mon ami. */
1635 break;
1636 }
1637 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001638 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 break;
1640 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001641 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001642 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001643 : WSTOPSIG(status));
1644 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001647 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001648#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649
1650#if defined(SUNOS4)
1651 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1652 if (sig && kill(tcp->pid, sig) < 0)
1653 perror("detach: kill");
1654 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001655 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656#endif /* SUNOS4 */
1657
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001658#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001659 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001660#endif
1661
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662 if (!qflag)
1663 fprintf(stderr, "Process %u detached\n", tcp->pid);
1664
1665 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001666
1667#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001668 if (zombie != NULL) {
1669 /* TCP no longer exists therefore you must not detach () it. */
1670 droptcb(zombie);
1671 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001672#endif
1673
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 return error;
1675}
1676
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001677#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001679static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680{
1681 int pid;
1682 int status;
1683
1684 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 }
1686}
1687
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001688#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689
1690static void
1691cleanup()
1692{
1693 int i;
1694 struct tcb *tcp;
1695
Roland McGrathee9d4352002-12-18 04:16:10 +00001696 for (i = 0; i < tcbtabsize; i++) {
1697 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698 if (!(tcp->flags & TCB_INUSE))
1699 continue;
1700 if (debug)
1701 fprintf(stderr,
1702 "cleanup: looking at pid %u\n", tcp->pid);
1703 if (tcp_last &&
1704 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001705 tprintf(" <unfinished ...>");
1706 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707 }
1708 if (tcp->flags & TCB_ATTACHED)
1709 detach(tcp, 0);
1710 else {
1711 kill(tcp->pid, SIGCONT);
1712 kill(tcp->pid, SIGTERM);
1713 }
1714 }
1715 if (cflag)
1716 call_summary(outf);
1717}
1718
1719static void
1720interrupt(sig)
1721int sig;
1722{
1723 interrupted = 1;
1724}
1725
1726#ifndef HAVE_STRERROR
1727
Roland McGrath6d2b3492002-12-30 00:51:30 +00001728#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729extern int sys_nerr;
1730extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001731#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732
1733const char *
1734strerror(errno)
1735int errno;
1736{
1737 static char buf[64];
1738
1739 if (errno < 1 || errno >= sys_nerr) {
1740 sprintf(buf, "Unknown error %d", errno);
1741 return buf;
1742 }
1743 return sys_errlist[errno];
1744}
1745
1746#endif /* HAVE_STERRROR */
1747
1748#ifndef HAVE_STRSIGNAL
1749
Roland McGrath8f474e02003-01-14 07:53:33 +00001750#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001751extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001753#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1754extern char *_sys_siglist[];
1755#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756
1757const char *
1758strsignal(sig)
1759int sig;
1760{
1761 static char buf[64];
1762
1763 if (sig < 1 || sig >= NSIG) {
1764 sprintf(buf, "Unknown signal %d", sig);
1765 return buf;
1766 }
1767#ifdef HAVE__SYS_SIGLIST
1768 return _sys_siglist[sig];
1769#else
1770 return sys_siglist[sig];
1771#endif
1772}
1773
1774#endif /* HAVE_STRSIGNAL */
1775
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001776#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777
1778static void
1779rebuild_pollv()
1780{
1781 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782
Roland McGrathee9d4352002-12-18 04:16:10 +00001783 if (pollv != NULL)
1784 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001785 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001786 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001787 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001788 exit(1);
1789 }
1790
Roland McGrathca16be82003-01-10 19:55:28 +00001791 for (i = j = 0; i < tcbtabsize; i++) {
1792 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793 if (!(tcp->flags & TCB_INUSE))
1794 continue;
1795 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001796 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 j++;
1798 }
1799 if (j != nprocs) {
1800 fprintf(stderr, "strace: proc miscount\n");
1801 exit(1);
1802 }
1803}
1804
1805#ifndef HAVE_POLLABLE_PROCFS
1806
1807static void
1808proc_poll_open()
1809{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810 int i;
1811
1812 if (pipe(proc_poll_pipe) < 0) {
1813 perror("pipe");
1814 exit(1);
1815 }
1816 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001817 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818 exit(1);
1819 }
1820 }
1821}
1822
1823static int
1824proc_poll(pollv, nfds, timeout)
1825struct pollfd *pollv;
1826int nfds;
1827int timeout;
1828{
1829 int i;
1830 int n;
1831 struct proc_pollfd pollinfo;
1832
1833 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1834 return n;
1835 if (n != sizeof(struct proc_pollfd)) {
1836 fprintf(stderr, "panic: short read: %d\n", n);
1837 exit(1);
1838 }
1839 for (i = 0; i < nprocs; i++) {
1840 if (pollv[i].fd == pollinfo.fd)
1841 pollv[i].revents = pollinfo.revents;
1842 else
1843 pollv[i].revents = 0;
1844 }
1845 poller_pid = pollinfo.pid;
1846 return 1;
1847}
1848
1849static void
1850wakeup_handler(sig)
1851int sig;
1852{
1853}
1854
1855static void
1856proc_poller(pfd)
1857int pfd;
1858{
1859 struct proc_pollfd pollinfo;
1860 struct sigaction sa;
1861 sigset_t blocked_set, empty_set;
1862 int i;
1863 int n;
1864 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001865#ifdef FREEBSD
1866 struct procfs_status pfs;
1867#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868
1869 switch (fork()) {
1870 case -1:
1871 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001872 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873 case 0:
1874 break;
1875 default:
1876 return;
1877 }
1878
1879 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1880 sa.sa_flags = 0;
1881 sigemptyset(&sa.sa_mask);
1882 sigaction(SIGHUP, &sa, NULL);
1883 sigaction(SIGINT, &sa, NULL);
1884 sigaction(SIGQUIT, &sa, NULL);
1885 sigaction(SIGPIPE, &sa, NULL);
1886 sigaction(SIGTERM, &sa, NULL);
1887 sa.sa_handler = wakeup_handler;
1888 sigaction(SIGUSR1, &sa, NULL);
1889 sigemptyset(&blocked_set);
1890 sigaddset(&blocked_set, SIGUSR1);
1891 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1892 sigemptyset(&empty_set);
1893
1894 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1895 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001896 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897 }
1898 n = rl.rlim_cur;
1899 for (i = 0; i < n; i++) {
1900 if (i != pfd && i != proc_poll_pipe[1])
1901 close(i);
1902 }
1903
1904 pollinfo.fd = pfd;
1905 pollinfo.pid = getpid();
1906 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001907#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001908 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1909#else
1910 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1911#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001912 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001913 switch (errno) {
1914 case EINTR:
1915 continue;
1916 case EBADF:
1917 pollinfo.revents = POLLERR;
1918 break;
1919 case ENOENT:
1920 pollinfo.revents = POLLHUP;
1921 break;
1922 default:
1923 perror("proc_poller: PIOCWSTOP");
1924 }
1925 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1926 _exit(0);
1927 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001928 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001929 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1930 sigsuspend(&empty_set);
1931 }
1932}
1933
1934#endif /* !HAVE_POLLABLE_PROCFS */
1935
1936static int
1937choose_pfd()
1938{
1939 int i, j;
1940 struct tcb *tcp;
1941
1942 static int last;
1943
1944 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001945 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946 /*
1947 * The previous process is ready to run again. We'll
1948 * let it do so if it is currently in a syscall. This
1949 * heuristic improves the readability of the trace.
1950 */
1951 tcp = pfd2tcb(pollv[last].fd);
1952 if (tcp && (tcp->flags & TCB_INSYSCALL))
1953 return pollv[last].fd;
1954 }
1955
1956 for (i = 0; i < nprocs; i++) {
1957 /* Let competing children run round robin. */
1958 j = (i + last + 1) % nprocs;
1959 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1960 tcp = pfd2tcb(pollv[j].fd);
1961 if (!tcp) {
1962 fprintf(stderr, "strace: lost proc\n");
1963 exit(1);
1964 }
1965 droptcb(tcp);
1966 return -1;
1967 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001968 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 last = j;
1970 return pollv[j].fd;
1971 }
1972 }
1973 fprintf(stderr, "strace: nothing ready\n");
1974 exit(1);
1975}
1976
1977static int
1978trace()
1979{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001980#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001981 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001982#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001983 struct tcb *tcp;
1984 int pfd;
1985 int what;
1986 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001987 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001988
1989 for (;;) {
1990 if (interactive)
1991 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1992
1993 if (nprocs == 0)
1994 break;
1995
1996 switch (nprocs) {
1997 case 1:
1998#ifndef HAVE_POLLABLE_PROCFS
1999 if (proc_poll_pipe[0] == -1) {
2000#endif
2001 tcp = pid2tcb(0);
2002 if (!tcp)
2003 continue;
2004 pfd = tcp->pfd;
2005 if (pfd == -1)
2006 continue;
2007 break;
2008#ifndef HAVE_POLLABLE_PROCFS
2009 }
2010 /* fall through ... */
2011#endif /* !HAVE_POLLABLE_PROCFS */
2012 default:
2013#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002014#ifdef POLL_HACK
2015 /* On some systems (e.g. UnixWare) we get too much ugly
2016 "unfinished..." stuff when multiple proceses are in
2017 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002018
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002019 if (in_syscall) {
2020 struct pollfd pv;
2021 tcp = in_syscall;
2022 in_syscall = NULL;
2023 pv.fd = tcp->pfd;
2024 pv.events = POLLWANT;
2025 if ((what = poll (&pv, 1, 1)) < 0) {
2026 if (interrupted)
2027 return 0;
2028 continue;
2029 }
2030 else if (what == 1 && pv.revents & POLLWANT) {
2031 goto FOUND;
2032 }
2033 }
2034#endif
2035
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002036 if (poll(pollv, nprocs, INFTIM) < 0) {
2037 if (interrupted)
2038 return 0;
2039 continue;
2040 }
2041#else /* !HAVE_POLLABLE_PROCFS */
2042 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2043 if (interrupted)
2044 return 0;
2045 continue;
2046 }
2047#endif /* !HAVE_POLLABLE_PROCFS */
2048 pfd = choose_pfd();
2049 if (pfd == -1)
2050 continue;
2051 break;
2052 }
2053
2054 /* Look up `pfd' in our table. */
2055 if ((tcp = pfd2tcb(pfd)) == NULL) {
2056 fprintf(stderr, "unknown pfd: %u\n", pfd);
2057 exit(1);
2058 }
John Hughesb6643082002-05-23 11:02:22 +00002059#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002060 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002061#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062 /* Get the status of the process. */
2063 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002064#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002065 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002066#else /* FREEBSD */
2067 /* Thanks to some scheduling mystery, the first poller
2068 sometimes waits for the already processed end of fork
2069 event. Doing a non blocking poll here solves the problem. */
2070 if (proc_poll_pipe[0] != -1)
2071 ioctl_result = IOCTL_STATUS (tcp);
2072 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002073 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002074#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002075 ioctl_errno = errno;
2076#ifndef HAVE_POLLABLE_PROCFS
2077 if (proc_poll_pipe[0] != -1) {
2078 if (ioctl_result < 0)
2079 kill(poller_pid, SIGKILL);
2080 else
2081 kill(poller_pid, SIGUSR1);
2082 }
2083#endif /* !HAVE_POLLABLE_PROCFS */
2084 }
2085 if (interrupted)
2086 return 0;
2087
2088 if (interactive)
2089 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2090
2091 if (ioctl_result < 0) {
2092 /* Find out what happened if it failed. */
2093 switch (ioctl_errno) {
2094 case EINTR:
2095 case EBADF:
2096 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002097#ifdef FREEBSD
2098 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002099#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100 case ENOENT:
2101 droptcb(tcp);
2102 continue;
2103 default:
2104 perror("PIOCWSTOP");
2105 exit(1);
2106 }
2107 }
2108
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002109#ifdef FREEBSD
2110 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2111 /* discard first event for a syscall we never entered */
2112 IOCTL (tcp->pfd, PIOCRUN, 0);
2113 continue;
2114 }
Roland McGrath553a6092002-12-16 20:40:39 +00002115#endif
2116
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002117 /* clear the just started flag */
2118 tcp->flags &= ~TCB_STARTUP;
2119
2120 /* set current output file */
2121 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002122 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002123
2124 if (cflag) {
2125 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002126#ifdef FREEBSD
2127 char buf[1024];
2128 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002130 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2131 buf[len] = '\0';
2132 sscanf(buf,
2133 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2134 &stime.tv_sec, &stime.tv_usec);
2135 } else
2136 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002137#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2139 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002140#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2142 tcp->stime = stime;
2143 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002144 what = tcp->status.PR_WHAT;
2145 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002146#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002147 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002148 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2149 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002150 if (trace_syscall(tcp) < 0) {
2151 fprintf(stderr, "syscall trouble\n");
2152 exit(1);
2153 }
2154 }
2155 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002156#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002157 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002158#ifdef POLL_HACK
2159 in_syscall = tcp;
2160#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002161 case PR_SYSEXIT:
2162 if (trace_syscall(tcp) < 0) {
2163 fprintf(stderr, "syscall trouble\n");
2164 exit(1);
2165 }
2166 break;
2167 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002168 if (cflag != CFLAG_ONLY_STATS
2169 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 printleader(tcp);
2171 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002172 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002173 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002174#ifdef PR_INFO
2175 if (tcp->status.PR_INFO.si_signo == what) {
2176 printleader(tcp);
2177 tprintf(" siginfo=");
2178 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002179 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002180 }
2181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182 }
2183 break;
2184 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002185 if (cflag != CFLAGS_ONLY_STATS
2186 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 printleader(tcp);
2188 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002189 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190 }
2191 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002192#ifdef FREEBSD
2193 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002194 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002195#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002197 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002198 exit(1);
2199 break;
2200 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002201 /* Remember current print column before continuing. */
2202 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002203 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002204#ifndef FREEBSD
Andreas Schwab372cc842010-07-09 11:49:27 +02002205 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002206#else
Andreas Schwab372cc842010-07-09 11:49:27 +02002207 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002208#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002209 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002210 perror("PIOCRUN");
2211 exit(1);
2212 }
2213 }
2214 return 0;
2215}
2216
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002217#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002219#ifdef TCB_GROUP_EXITING
2220/* Handle an exit detach or death signal that is taking all the
2221 related clone threads with it. This is called in three circumstances:
2222 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2223 SIG == 0 Continuing TCP will perform an exit_group syscall.
2224 SIG == other Continuing TCP with SIG will kill the process.
2225*/
2226static int
2227handle_group_exit(struct tcb *tcp, int sig)
2228{
2229 /* We need to locate our records of all the clone threads
2230 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002231 struct tcb *leader = NULL;
2232
2233 if (tcp->flags & TCB_CLONE_THREAD)
2234 leader = tcp->parent;
2235 else if (tcp->nclone_detached > 0)
2236 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002237
2238 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002239 if (leader != NULL && leader != tcp
2240 && !(leader->flags & TCB_GROUP_EXITING)
2241 && !(tcp->flags & TCB_STARTUP)
2242 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002243 fprintf(stderr,
2244 "PANIC: handle_group_exit: %d leader %d\n",
2245 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002246 }
2247 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002248#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002249 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002250#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002251 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002252 }
2253 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002254 /* Mark that we are taking the process down. */
2255 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002256 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002257 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002258 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002259 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002260 } else {
2261 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2262 cleanup();
2263 return -1;
2264 }
2265 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002266 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002267 if (leader != tcp)
2268 droptcb(tcp);
2269 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002270 /* The leader will report to us as parent now,
2271 and then we'll get to the SIG==-1 case. */
2272 return 0;
2273 }
2274 }
2275
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002276 return 0;
2277}
2278#endif
2279
Roland McGratheb9e2e82009-06-02 16:49:22 -07002280static int
2281trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002282{
2283 int pid;
2284 int wait_errno;
2285 int status;
2286 struct tcb *tcp;
2287#ifdef LINUX
2288 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002289#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002290 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002291#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002292#endif /* LINUX */
2293
Roland McGratheb9e2e82009-06-02 16:49:22 -07002294 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002295 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002296 return 0;
2297 if (interactive)
2298 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002299#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002300#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002301 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002302 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002303 /* this kernel does not support __WALL */
2304 wait4_options &= ~__WALL;
2305 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002306 pid = wait4(-1, &status, wait4_options,
2307 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002308 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002309 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002310 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002311 pid = wait4(-1, &status, __WCLONE,
2312 cflag ? &ru : NULL);
2313 if (pid == -1) {
2314 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002315 "failed: %s\n", strerror(errno));
2316 }
2317 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002318#else
2319 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2320#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002321#endif /* LINUX */
2322#ifdef SUNOS4
2323 pid = wait(&status);
2324#endif /* SUNOS4 */
2325 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002326 if (interactive)
2327 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002328
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002330 switch (wait_errno) {
2331 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002332 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002333 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 /*
2335 * We would like to verify this case
2336 * but sometimes a race in Solbourne's
2337 * version of SunOS sometimes reports
2338 * ECHILD before sending us SIGCHILD.
2339 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002340 return 0;
2341 default:
2342 errno = wait_errno;
2343 perror("strace: wait");
2344 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 }
2346 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002347 if (pid == popen_pid) {
2348 if (WIFEXITED(status) || WIFSIGNALED(status))
2349 popen_pid = -1;
2350 continue;
2351 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352 if (debug)
2353 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2354
2355 /* Look up `pid' in our table. */
2356 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002357#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002358 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002359 /* This is needed to go with the CLONE_PTRACE
2360 changes in process.c/util.c: we might see
2361 the child's initial trap before we see the
2362 parent return from the clone syscall.
2363 Leave the child suspended until the parent
2364 returns from its system call. Only then
2365 will we have the association of parent and
2366 child so that we know how to do clearbpt
2367 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002368 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002369 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002370 if (!qflag)
2371 fprintf(stderr, "\
2372Process %d attached (waiting for parent)\n",
2373 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002374 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002375 else
2376 /* This can happen if a clone call used
2377 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002378#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002379 {
2380 fprintf(stderr, "unknown pid: %u\n", pid);
2381 if (WIFSTOPPED(status))
2382 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2383 exit(1);
2384 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002386 /* set current output file */
2387 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002388 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002389 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002390#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002391 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2392 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002393#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002395
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 if (tcp->flags & TCB_SUSPENDED) {
2397 /*
2398 * Apparently, doing any ptrace() call on a stopped
2399 * process, provokes the kernel to report the process
2400 * status again on a subsequent wait(), even if the
2401 * process has not been actually restarted.
2402 * Since we have inspected the arguments of suspended
2403 * processes we end up here testing for this case.
2404 */
2405 continue;
2406 }
2407 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002408 if (pid == strace_child)
2409 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002410 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2412 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002413 tprintf("+++ killed by %s %s+++",
2414 signame(WTERMSIG(status)),
2415#ifdef WCOREDUMP
2416 WCOREDUMP(status) ? "(core dumped) " :
2417#endif
2418 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002419 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002421#ifdef TCB_GROUP_EXITING
2422 handle_group_exit(tcp, -1);
2423#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002424 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002425#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002426 continue;
2427 }
2428 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002429 if (pid == strace_child)
2430 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002431 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002432 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2433 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002434#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002435 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002436 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002437#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002438 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002439 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002440 "PANIC: attached pid %u exited with %d\n",
2441 pid, WEXITSTATUS(status));
2442 }
Roland McGrath0a396902003-06-10 03:05:53 +00002443 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002444 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002445 tprintf(" <unfinished ... exit status %d>\n",
2446 WEXITSTATUS(status));
2447 tcp_last = NULL;
2448 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002449#ifdef TCB_GROUP_EXITING
2450 handle_group_exit(tcp, -1);
2451#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002452 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002453#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454 continue;
2455 }
2456 if (!WIFSTOPPED(status)) {
2457 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2458 droptcb(tcp);
2459 continue;
2460 }
2461 if (debug)
2462 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002463 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002464
Roland McGrath02203312007-06-11 22:06:31 +00002465 /*
2466 * Interestingly, the process may stop
2467 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002468 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002469 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002470 * A no-MMU vforked child won't send up a signal,
2471 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002472 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002473 if ((tcp->flags & TCB_STARTUP) &&
2474 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002475 /*
2476 * This flag is there to keep us in sync.
2477 * Next time this process stops it should
2478 * really be entering a system call.
2479 */
2480 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002481 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002482 /*
2483 * One example is a breakpoint inherited from
2484 * parent through fork ().
2485 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002486 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2487 droptcb(tcp);
2488 cleanup();
2489 return -1;
2490 }
2491 }
2492 goto tracing;
2493 }
2494
Roland McGratheb9e2e82009-06-02 16:49:22 -07002495 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002496 if (WSTOPSIG(status) == SIGSTOP &&
2497 (tcp->flags & TCB_SIGTRAPPED)) {
2498 /*
2499 * Trapped attempt to block SIGTRAP
2500 * Hope we are back in control now.
2501 */
2502 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002503 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002504 cleanup();
2505 return -1;
2506 }
2507 continue;
2508 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002509 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002510 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002511 unsigned long addr = 0;
2512 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002513#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002514# define PSR_RI 41
2515 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002516 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002517
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002518 upeek(tcp, PT_CR_IPSR, &psr);
2519 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002520
2521 pc += (psr >> PSR_RI) & 0x3;
2522 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2523 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002524#elif defined PTRACE_GETSIGINFO
2525 if (WSTOPSIG(status) == SIGSEGV ||
2526 WSTOPSIG(status) == SIGBUS) {
2527 siginfo_t si;
2528 if (ptrace(PTRACE_GETSIGINFO, pid,
2529 0, &si) == 0)
2530 addr = (unsigned long)
2531 si.si_addr;
2532 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002533#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002535 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002536 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002537 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002538 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 }
Roland McGrath05690952004-10-20 01:00:27 +00002540 if (((tcp->flags & TCB_ATTACHED) ||
2541 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002542 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002543#ifdef TCB_GROUP_EXITING
2544 handle_group_exit(tcp, WSTOPSIG(status));
2545#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002546 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002547#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002548 continue;
2549 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002550 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551 cleanup();
2552 return -1;
2553 }
2554 tcp->flags &= ~TCB_SUSPENDED;
2555 continue;
2556 }
Roland McGrath02203312007-06-11 22:06:31 +00002557 /* we handled the STATUS, we are permitted to interrupt now. */
2558 if (interrupted)
2559 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002560 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2561 /* ptrace() failed in trace_syscall() with ESRCH.
2562 * Likely a result of process disappearing mid-flight.
2563 * Observed case: exit_group() terminating
2564 * all processes in thread group. In this case, threads
2565 * "disappear" in an unpredictable moment without any
2566 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002567 */
2568 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002569 if (tcp_last) {
2570 /* Do we have dangling line "syscall(param, param"?
2571 * Finish the line then. We cannot
2572 */
2573 tcp_last->flags |= TCB_REPRINT;
2574 tprintf(" <unfinished ...>");
2575 printtrailer();
2576 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002578 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002579 ptrace(PTRACE_KILL,
2580 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002581 droptcb(tcp);
2582 }
2583 continue;
2584 }
2585 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002586#ifdef TCB_GROUP_EXITING
2587 if (tcp->flags & TCB_GROUP_EXITING) {
2588 if (handle_group_exit(tcp, 0) < 0)
2589 return -1;
2590 continue;
2591 }
2592#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002593 if (tcp->flags & TCB_ATTACHED)
2594 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002595 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002596 cleanup();
2597 return -1;
2598 }
2599 continue;
2600 }
2601 if (tcp->flags & TCB_SUSPENDED) {
2602 if (!qflag)
2603 fprintf(stderr, "Process %u suspended\n", pid);
2604 continue;
2605 }
2606 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002607 /* Remember current print column before continuing. */
2608 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002609 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002610 cleanup();
2611 return -1;
2612 }
2613 }
2614 return 0;
2615}
2616
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002617#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002618
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002619#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002620
2621void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002622tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002623{
2624 va_list args;
2625
Andreas Schwabe5355de2009-10-27 16:56:43 +01002626 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002627 if (outf) {
2628 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002629 if (n < 0) {
2630 if (outf != stderr)
2631 perror(outfname == NULL
2632 ? "<writing to pipe>" : outfname);
2633 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002634 curcol += n;
2635 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636 va_end(args);
2637 return;
2638}
2639
2640void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002641printleader(tcp)
2642struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002643{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002644 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002645 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002646 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002647 tprintf(" <unavailable>)");
2648 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002649 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002650 tprintf("= ? <unavailable>\n");
2651 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002652 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002653 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002654 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002655 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002656 }
2657 curcol = 0;
2658 if ((followfork == 1 || pflag_seen > 1) && outfname)
2659 tprintf("%-5d ", tcp->pid);
2660 else if (nprocs > 1 && !outfname)
2661 tprintf("[pid %5u] ", tcp->pid);
2662 if (tflag) {
2663 char str[sizeof("HH:MM:SS")];
2664 struct timeval tv, dtv;
2665 static struct timeval otv;
2666
2667 gettimeofday(&tv, NULL);
2668 if (rflag) {
2669 if (otv.tv_sec == 0)
2670 otv = tv;
2671 tv_sub(&dtv, &tv, &otv);
2672 tprintf("%6ld.%06ld ",
2673 (long) dtv.tv_sec, (long) dtv.tv_usec);
2674 otv = tv;
2675 }
2676 else if (tflag > 2) {
2677 tprintf("%ld.%06ld ",
2678 (long) tv.tv_sec, (long) tv.tv_usec);
2679 }
2680 else {
2681 time_t local = tv.tv_sec;
2682 strftime(str, sizeof(str), "%T", localtime(&local));
2683 if (tflag > 1)
2684 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2685 else
2686 tprintf("%s ", str);
2687 }
2688 }
2689 if (iflag)
2690 printcall(tcp);
2691}
2692
2693void
2694tabto(col)
2695int col;
2696{
2697 if (curcol < col)
2698 tprintf("%*s", col - curcol, "");
2699}
2700
2701void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002702printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002703{
2704 tprintf("\n");
2705 tcp_last = NULL;
2706}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002707
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002708#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002709
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002710int
2711mp_ioctl(int fd, int cmd, void *arg, int size)
2712{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002713 struct iovec iov[2];
2714 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002715
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002716 iov[0].iov_base = &cmd;
2717 iov[0].iov_len = sizeof cmd;
2718 if (arg) {
2719 ++n;
2720 iov[1].iov_base = arg;
2721 iov[1].iov_len = size;
2722 }
Roland McGrath553a6092002-12-16 20:40:39 +00002723
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002724 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002725}
2726
2727#endif