blob: 40f89072517d75264d6b776e0401b671c020d14b [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, "\
171usage: strace [-dffhiqrtttTvVxx] [-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\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000174 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\
177-f -- follow forks, -ff -- with output into separate files\n\
178-F -- attempt to follow vforks, -h -- print help message\n\
179-i -- print instruction pointer at time of syscall\n\
180-q -- suppress messages about attaching, detaching, etc.\n\
181-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
182-T -- print time spent in each syscall, -V -- print version\n\
183-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
184-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
185-a column -- alignment COLUMN for printing syscall results (default %d)\n\
186-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
187 options: trace, abbrev, verbose, raw, signal, read, or write\n\
188-o file -- send trace output to FILE instead of stderr\n\
189-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
190-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000191-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000192-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
193-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
194-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000195-E var=val -- put var=val in the environment for command\n\
196-E var -- remove var from the environment for command\n\
197" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000198-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000199 */
200, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201 exit(exitval);
202}
203
204#ifdef SVR4
205#ifdef MIPS
206void
207foobar()
208{
209}
210#endif /* MIPS */
211#endif /* SVR4 */
212
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400213/* Glue for systems without a MMU that cannot provide fork() */
214#ifdef HAVE_FORK
215# define strace_vforked 0
216#else
217# define strace_vforked 1
218# define fork() vfork()
219#endif
220
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000221static int
222set_cloexec_flag(int fd)
223{
224 int flags, newflags;
225
226 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
227 {
228 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
229 progname, strerror(errno));
230 return -1;
231 }
232
233 newflags = flags | FD_CLOEXEC;
234 if (flags == newflags)
235 return 0;
236
237 if (fcntl(fd, F_SETFD, newflags) < 0)
238 {
239 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
240 progname, strerror(errno));
241 return -1;
242 }
243
244 return 0;
245}
246
247/*
248 * When strace is setuid executable, we have to swap uids
249 * before and after filesystem and process management operations.
250 */
251static void
252swap_uid(void)
253{
254#ifndef SVR4
255 int euid = geteuid(), uid = getuid();
256
257 if (euid != uid && setreuid(euid, uid) < 0)
258 {
259 fprintf(stderr, "%s: setreuid: %s\n",
260 progname, strerror(errno));
261 exit(1);
262 }
263#endif
264}
265
Roland McGrath4bfa6262007-07-05 20:03:16 +0000266#if _LFS64_LARGEFILE
267# define fopen_for_output fopen64
268#else
269# define fopen_for_output fopen
270#endif
271
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000272static FILE *
273strace_fopen(const char *path, const char *mode)
274{
275 FILE *fp;
276
277 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000278 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000279 fprintf(stderr, "%s: can't fopen '%s': %s\n",
280 progname, path, strerror(errno));
281 swap_uid();
282 if (fp && set_cloexec_flag(fileno(fp)) < 0)
283 {
284 fclose(fp);
285 fp = NULL;
286 }
287 return fp;
288}
289
290static int popen_pid = -1;
291
292#ifndef _PATH_BSHELL
293# define _PATH_BSHELL "/bin/sh"
294#endif
295
296/*
297 * We cannot use standard popen(3) here because we have to distinguish
298 * popen child process from other processes we trace, and standard popen(3)
299 * does not export its child's pid.
300 */
301static FILE *
302strace_popen(const char *command)
303{
304 int fds[2];
305
306 swap_uid();
307 if (pipe(fds) < 0)
308 {
309 fprintf(stderr, "%s: pipe: %s\n",
310 progname, strerror(errno));
311 swap_uid();
312 return NULL;
313 }
314
315 if (set_cloexec_flag(fds[1]) < 0)
316 {
317 close(fds[0]);
318 close(fds[1]);
319 swap_uid();
320 return NULL;
321 }
322
323 if ((popen_pid = fork()) == -1)
324 {
325 fprintf(stderr, "%s: fork: %s\n",
326 progname, strerror(errno));
327 close(fds[0]);
328 close(fds[1]);
329 swap_uid();
330 return NULL;
331 }
332
333 if (popen_pid)
334 {
335 /* parent */
336 close(fds[0]);
337 swap_uid();
338 return fdopen(fds[1], "w");
339 } else
340 {
341 /* child */
342 close(fds[1]);
343 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
344 {
345 fprintf(stderr, "%s: dup2: %s\n",
346 progname, strerror(errno));
347 _exit(1);
348 }
349 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
350 fprintf(stderr, "%s: execl: %s: %s\n",
351 progname, _PATH_BSHELL, strerror(errno));
352 _exit(1);
353 }
354}
355
356static int
357newoutf(struct tcb *tcp)
358{
359 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000360 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000361 FILE *fp;
362
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000363 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364 if ((fp = strace_fopen(name, "w")) == NULL)
365 return -1;
366 tcp->outf = fp;
367 }
368 return 0;
369}
370
Roland McGrath02203312007-06-11 22:06:31 +0000371static void
372startup_attach(void)
373{
374 int tcbi;
375 struct tcb *tcp;
376
377 /*
378 * Block user interruptions as we would leave the traced
379 * process stopped (process state T) if we would terminate in
380 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
381 * We rely on cleanup () from this point on.
382 */
383 if (interactive)
384 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
385
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000386 if (daemonized_tracer) {
387 pid_t pid = fork();
388 if (pid < 0) {
389 _exit(1);
390 }
391 if (pid) { /* parent */
392 /*
393 * Wait for child to attach to straced process
394 * (our parent). Child SIGKILLs us after it attached.
395 * Parent's wait() is unblocked by our death,
396 * it proceeds to exec the straced program.
397 */
398 pause();
399 _exit(0); /* paranoia */
400 }
401 }
402
Roland McGrath02203312007-06-11 22:06:31 +0000403 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
404 tcp = tcbtab[tcbi];
405 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
406 continue;
407#ifdef LINUX
408 if (tcp->flags & TCB_CLONE_THREAD)
409 continue;
410#endif
411 /* Reinitialize the output since it may have changed. */
412 tcp->outf = outf;
413 if (newoutf(tcp) < 0)
414 exit(1);
415
416#ifdef USE_PROCFS
417 if (proc_open(tcp, 1) < 0) {
418 fprintf(stderr, "trouble opening proc file\n");
419 droptcb(tcp);
420 continue;
421 }
422#else /* !USE_PROCFS */
423# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000424 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000425 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000426 DIR *dir;
427
428 sprintf(procdir, "/proc/%d/task", tcp->pid);
429 dir = opendir(procdir);
430 if (dir != NULL) {
431 unsigned int ntid = 0, nerr = 0;
432 struct dirent *de;
433 int tid;
434 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000435 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000436 continue;
437 tid = atoi(de->d_name);
438 if (tid <= 0)
439 continue;
440 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000441 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000442 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000443 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000444 tcp = alloctcb(tid);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700445 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000446 tcbtab[tcbi]->nchildren++;
447 tcbtab[tcbi]->nclone_threads++;
448 tcbtab[tcbi]->nclone_detached++;
449 tcp->parent = tcbtab[tcbi];
450 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000451 if (interactive) {
452 sigprocmask(SIG_SETMASK, &empty_set, NULL);
453 if (interrupted)
454 return;
455 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
456 }
Roland McGrath02203312007-06-11 22:06:31 +0000457 }
458 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000459 ntid -= nerr;
460 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000461 perror("attach: ptrace(PTRACE_ATTACH, ...)");
462 droptcb(tcp);
463 continue;
464 }
465 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000466 fprintf(stderr, ntid > 1
467? "Process %u attached with %u threads - interrupt to quit\n"
468: "Process %u attached - interrupt to quit\n",
469 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000470 }
471 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000472 } /* if (opendir worked) */
473 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000474# endif
475 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
476 perror("attach: ptrace(PTRACE_ATTACH, ...)");
477 droptcb(tcp);
478 continue;
479 }
480 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000481
482 if (daemonized_tracer) {
483 /*
484 * It is our grandparent we trace, not a -p PID.
485 * Don't want to just detach on exit, so...
486 */
487 tcp->flags &= ~TCB_ATTACHED;
488 /*
489 * Make parent go away.
490 * Also makes grandparent's wait() unblock.
491 */
492 kill(getppid(), SIGKILL);
493 }
494
Roland McGrath02203312007-06-11 22:06:31 +0000495#endif /* !USE_PROCFS */
496 if (!qflag)
497 fprintf(stderr,
498 "Process %u attached - interrupt to quit\n",
499 tcp->pid);
500 }
501
502 if (interactive)
503 sigprocmask(SIG_SETMASK, &empty_set, NULL);
504}
505
506static void
507startup_child (char **argv)
508{
509 struct stat statbuf;
510 const char *filename;
511 char pathname[MAXPATHLEN];
512 int pid = 0;
513 struct tcb *tcp;
514
515 filename = argv[0];
516 if (strchr(filename, '/')) {
517 if (strlen(filename) > sizeof pathname - 1) {
518 errno = ENAMETOOLONG;
519 perror("strace: exec");
520 exit(1);
521 }
522 strcpy(pathname, filename);
523 }
524#ifdef USE_DEBUGGING_EXEC
525 /*
526 * Debuggers customarily check the current directory
527 * first regardless of the path but doing that gives
528 * security geeks a panic attack.
529 */
530 else if (stat(filename, &statbuf) == 0)
531 strcpy(pathname, filename);
532#endif /* USE_DEBUGGING_EXEC */
533 else {
534 char *path;
535 int m, n, len;
536
537 for (path = getenv("PATH"); path && *path; path += m) {
538 if (strchr(path, ':')) {
539 n = strchr(path, ':') - path;
540 m = n + 1;
541 }
542 else
543 m = n = strlen(path);
544 if (n == 0) {
545 if (!getcwd(pathname, MAXPATHLEN))
546 continue;
547 len = strlen(pathname);
548 }
549 else if (n > sizeof pathname - 1)
550 continue;
551 else {
552 strncpy(pathname, path, n);
553 len = n;
554 }
555 if (len && pathname[len - 1] != '/')
556 pathname[len++] = '/';
557 strcpy(pathname + len, filename);
558 if (stat(pathname, &statbuf) == 0 &&
559 /* Accept only regular files
560 with some execute bits set.
561 XXX not perfect, might still fail */
562 S_ISREG(statbuf.st_mode) &&
563 (statbuf.st_mode & 0111))
564 break;
565 }
566 }
567 if (stat(pathname, &statbuf) < 0) {
568 fprintf(stderr, "%s: %s: command not found\n",
569 progname, filename);
570 exit(1);
571 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000572 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000573 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000574 perror("strace: fork");
575 cleanup();
576 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000577 }
578 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
579 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
580 ) {
581 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000582#ifdef USE_PROCFS
583 if (outf != stderr) close (fileno (outf));
584#ifdef MIPS
585 /* Kludge for SGI, see proc_open for details. */
586 sa.sa_handler = foobar;
587 sa.sa_flags = 0;
588 sigemptyset(&sa.sa_mask);
589 sigaction(SIGINT, &sa, NULL);
590#endif /* MIPS */
591#ifndef FREEBSD
592 pause();
593#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000594 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000595#endif /* FREEBSD */
596#else /* !USE_PROCFS */
597 if (outf!=stderr)
598 close(fileno (outf));
599
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000600 if (!daemonized_tracer) {
601 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
602 perror("strace: ptrace(PTRACE_TRACEME, ...)");
603 exit(1);
604 }
605 if (debug)
606 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000607 }
Roland McGrath02203312007-06-11 22:06:31 +0000608
609 if (username != NULL || geteuid() == 0) {
610 uid_t run_euid = run_uid;
611 gid_t run_egid = run_gid;
612
613 if (statbuf.st_mode & S_ISUID)
614 run_euid = statbuf.st_uid;
615 if (statbuf.st_mode & S_ISGID)
616 run_egid = statbuf.st_gid;
617
618 /*
619 * It is important to set groups before we
620 * lose privileges on setuid.
621 */
622 if (username != NULL) {
623 if (initgroups(username, run_gid) < 0) {
624 perror("initgroups");
625 exit(1);
626 }
627 if (setregid(run_gid, run_egid) < 0) {
628 perror("setregid");
629 exit(1);
630 }
631 if (setreuid(run_uid, run_euid) < 0) {
632 perror("setreuid");
633 exit(1);
634 }
635 }
636 }
637 else
638 setreuid(run_uid, run_uid);
639
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000640 if (!daemonized_tracer) {
641 /*
642 * Induce an immediate stop so that the parent
643 * will resume us with PTRACE_SYSCALL and display
644 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400645 * Unless of course we're on a no-MMU system where
646 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000647 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400648 if (!strace_vforked)
649 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000650 } else {
651 struct sigaction sv_sigchld;
652 sigaction(SIGCHLD, NULL, &sv_sigchld);
653 /*
654 * Make sure it is not SIG_IGN, otherwise wait
655 * will not block.
656 */
657 signal(SIGCHLD, SIG_DFL);
658 /*
659 * Wait for grandchild to attach to us.
660 * It kills child after that, and wait() unblocks.
661 */
662 alarm(3);
663 wait(NULL);
664 alarm(0);
665 sigaction(SIGCHLD, &sv_sigchld, NULL);
666 }
Roland McGrath02203312007-06-11 22:06:31 +0000667#endif /* !USE_PROCFS */
668
669 execv(pathname, argv);
670 perror("strace: exec");
671 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000672 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000673
674 /* We are the tracer. */
675 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 if (daemonized_tracer) {
677 /* We want subsequent startup_attach() to attach to it. */
678 tcp->flags |= TCB_ATTACHED;
679 }
Roland McGrath02203312007-06-11 22:06:31 +0000680#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000681 if (proc_open(tcp, 0) < 0) {
682 fprintf(stderr, "trouble opening proc file\n");
683 cleanup();
684 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000685 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000686#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000687}
688
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000690main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000691{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692 struct tcb *tcp;
693 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000694 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 struct sigaction sa;
696
697 static char buf[BUFSIZ];
698
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000699 progname = argv[0] ? argv[0] : "strace";
700
Roland McGrathee9d4352002-12-18 04:16:10 +0000701 /* Allocate the initial tcbtab. */
702 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000703 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000704 fprintf(stderr, "%s: out of memory\n", progname);
705 exit(1);
706 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000707 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000708 fprintf(stderr, "%s: out of memory\n", progname);
709 exit(1);
710 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000711 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
712 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
713
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 outf = stderr;
715 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000716 set_sortby(DEFAULT_SORTBY);
717 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718 qualify("trace=all");
719 qualify("abbrev=all");
720 qualify("verbose=all");
721 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 while ((c = getopt(argc, argv,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000723 "+cCdfFhiqrtTvVxz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000724#ifndef USE_PROCFS
725 "D"
726#endif
727 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000728 switch (c) {
729 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000730 if (cflag == CFLAG_BOTH) {
731 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
732 progname);
733 exit(1);
734 }
735 cflag = CFLAG_ONLY_STATS;
736 break;
737 case 'C':
738 if (cflag == CFLAG_ONLY_STATS) {
739 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
740 progname);
741 exit(1);
742 }
743 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000744 break;
745 case 'd':
746 debug++;
747 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000748#ifndef USE_PROCFS
749 /* Experimental, not documented in manpage yet. */
750 case 'D':
751 daemonized_tracer = 1;
752 break;
753#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000754 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000755 optF = 1;
756 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757 case 'f':
758 followfork++;
759 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 case 'h':
761 usage(stdout, 0);
762 break;
763 case 'i':
764 iflag++;
765 break;
766 case 'q':
767 qflag++;
768 break;
769 case 'r':
770 rflag++;
771 tflag++;
772 break;
773 case 't':
774 tflag++;
775 break;
776 case 'T':
777 dtime++;
778 break;
779 case 'x':
780 xflag++;
781 break;
782 case 'v':
783 qualify("abbrev=none");
784 break;
785 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000786 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787 exit(0);
788 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000789 case 'z':
790 not_failing_only = 1;
791 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 case 'a':
793 acolumn = atoi(optarg);
794 break;
795 case 'e':
796 qualify(optarg);
797 break;
798 case 'o':
799 outfname = strdup(optarg);
800 break;
801 case 'O':
802 set_overhead(atoi(optarg));
803 break;
804 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000805 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 fprintf(stderr, "%s: Invalid process id: %s\n",
807 progname, optarg);
808 break;
809 }
810 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000811 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 break;
813 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000814 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815 tcp->flags |= TCB_ATTACHED;
816 pflag_seen++;
817 break;
818 case 's':
819 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000820 if (max_strlen < 0) {
821 fprintf(stderr,
822 "%s: invalid -s argument: %s\n",
823 progname, optarg);
824 exit(1);
825 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 break;
827 case 'S':
828 set_sortby(optarg);
829 break;
830 case 'u':
831 username = strdup(optarg);
832 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000833 case 'E':
834 if (putenv(optarg) < 0) {
835 fprintf(stderr, "%s: out of memory\n",
836 progname);
837 exit(1);
838 }
839 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 default:
841 usage(stderr, 1);
842 break;
843 }
844 }
845
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000846 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000847 usage(stderr, 1);
848
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000849 if (!followfork)
850 followfork = optF;
851
Roland McGrathcb9def62006-04-25 07:48:03 +0000852 if (followfork > 1 && cflag) {
853 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000854 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +0000855 progname);
856 exit(1);
857 }
858
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000859 /* See if they want to run as another user. */
860 if (username != NULL) {
861 struct passwd *pent;
862
863 if (getuid() != 0 || geteuid() != 0) {
864 fprintf(stderr,
865 "%s: you must be root to use the -u option\n",
866 progname);
867 exit(1);
868 }
869 if ((pent = getpwnam(username)) == NULL) {
870 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000871 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000872 exit(1);
873 }
874 run_uid = pent->pw_uid;
875 run_gid = pent->pw_gid;
876 }
877 else {
878 run_uid = getuid();
879 run_gid = getgid();
880 }
881
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 /* Check if they want to redirect the output. */
883 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000884 /* See if they want to pipe the output. */
885 if (outfname[0] == '|' || outfname[0] == '!') {
886 /*
887 * We can't do the <outfname>.PID funny business
888 * when using popen, so prohibit it.
889 */
890 if (followfork > 1) {
891 fprintf(stderr, "\
892%s: piping the output and -ff are mutually exclusive options\n",
893 progname);
894 exit(1);
895 }
896
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000897 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000898 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000899 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000900 else if (followfork <= 1 &&
901 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903 }
904
Roland McGrath37b9a662003-11-07 02:26:54 +0000905 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000907 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000908 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000910 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000911 /* Valid states here:
912 optind < argc pflag_seen outfname interactive
913 1 0 0 1
914 0 1 0 1
915 1 0 1 0
916 0 1 1 1
917 */
918
919 /* STARTUP_CHILD must be called before the signal handlers get
920 installed below as they are inherited into the spawned process.
921 Also we do not need to be protected by them as during interruption
922 in the STARTUP_CHILD mode we kill the spawned process anyway. */
923 if (!pflag_seen)
924 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926 sigemptyset(&empty_set);
927 sigemptyset(&blocked_set);
928 sa.sa_handler = SIG_IGN;
929 sigemptyset(&sa.sa_mask);
930 sa.sa_flags = 0;
931 sigaction(SIGTTOU, &sa, NULL);
932 sigaction(SIGTTIN, &sa, NULL);
933 if (interactive) {
934 sigaddset(&blocked_set, SIGHUP);
935 sigaddset(&blocked_set, SIGINT);
936 sigaddset(&blocked_set, SIGQUIT);
937 sigaddset(&blocked_set, SIGPIPE);
938 sigaddset(&blocked_set, SIGTERM);
939 sa.sa_handler = interrupt;
940#ifdef SUNOS4
941 /* POSIX signals on sunos4.1 are a little broken. */
942 sa.sa_flags = SA_INTERRUPT;
943#endif /* SUNOS4 */
944 }
945 sigaction(SIGHUP, &sa, NULL);
946 sigaction(SIGINT, &sa, NULL);
947 sigaction(SIGQUIT, &sa, NULL);
948 sigaction(SIGPIPE, &sa, NULL);
949 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000950#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 sa.sa_handler = reaper;
952 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000953#else
954 /* Make sure SIGCHLD has the default action so that waitpid
955 definitely works without losing track of children. The user
956 should not have given us a bogus state to inherit, but he might
957 have. Arguably we should detect SIG_IGN here and pass it on
958 to children, but probably noone really needs that. */
959 sa.sa_handler = SIG_DFL;
960 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000961#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000963 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000964 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000965
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 if (trace() < 0)
967 exit(1);
968 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000969 fflush(NULL);
970 if (exit_code > 0xff) {
971 /* Child was killed by a signal, mimic that. */
972 exit_code &= 0xff;
973 signal(exit_code, SIG_DFL);
974 raise(exit_code);
975 /* Paranoia - what if this signal is not fatal?
976 Exit with 128 + signo then. */
977 exit_code += 128;
978 }
979 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980}
981
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000982void
983expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000984{
985 /* Allocate some more TCBs and expand the table.
986 We don't want to relocate the TCBs because our
987 callers have pointers and it would be a pain.
988 So tcbtab is a table of pointers. Since we never
989 free the TCBs, we allocate a single chunk of many. */
990 struct tcb **newtab = (struct tcb **)
991 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
992 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
993 sizeof *newtcbs);
994 int i;
995 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000996 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
997 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000998 cleanup();
999 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001000 }
1001 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1002 newtab[i] = &newtcbs[i - tcbtabsize];
1003 tcbtabsize *= 2;
1004 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001005}
1006
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001008alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009{
1010 int i;
1011 struct tcb *tcp;
1012
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001013 if (nprocs == tcbtabsize)
1014 expand_tcbtab();
1015
Roland McGrathee9d4352002-12-18 04:16:10 +00001016 for (i = 0; i < tcbtabsize; i++) {
1017 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 if ((tcp->flags & TCB_INUSE) == 0) {
1019 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001020 tcp->parent = NULL;
1021 tcp->nchildren = 0;
1022 tcp->nzombies = 0;
1023#ifdef TCB_CLONE_THREAD
1024 tcp->nclone_threads = tcp->nclone_detached = 0;
1025 tcp->nclone_waiting = 0;
1026#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 tcp->flags = TCB_INUSE | TCB_STARTUP;
1028 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001029 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001030 tcp->stime.tv_sec = 0;
1031 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 tcp->pfd = -1;
1033 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001034 if (command_options_parsed)
1035 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036 return tcp;
1037 }
1038 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001039 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1040 cleanup();
1041 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042}
1043
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001044#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001046proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047{
1048 char proc[32];
1049 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001050#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001051 int i;
1052 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 sigset_t signals;
1054 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001055#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056#ifndef HAVE_POLLABLE_PROCFS
1057 static int last_pfd;
1058#endif
1059
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001060#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001061 /* Open the process pseudo-files in /proc. */
1062 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1063 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 perror("strace: open(\"/proc/...\", ...)");
1065 return -1;
1066 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001067 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 return -1;
1069 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001070 sprintf(proc, "/proc/%d/status", tcp->pid);
1071 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1072 perror("strace: open(\"/proc/...\", ...)");
1073 return -1;
1074 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001075 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001076 return -1;
1077 }
1078 sprintf(proc, "/proc/%d/as", tcp->pid);
1079 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1080 perror("strace: open(\"/proc/...\", ...)");
1081 return -1;
1082 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001083 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001084 return -1;
1085 }
1086#else
1087 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001088#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001089 sprintf(proc, "/proc/%d", tcp->pid);
1090 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001091#else /* FREEBSD */
1092 sprintf(proc, "/proc/%d/mem", tcp->pid);
1093 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1094#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001095 perror("strace: open(\"/proc/...\", ...)");
1096 return -1;
1097 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001098 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001099 return -1;
1100 }
1101#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001102#ifdef FREEBSD
1103 sprintf(proc, "/proc/%d/regs", tcp->pid);
1104 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1105 perror("strace: open(\"/proc/.../regs\", ...)");
1106 return -1;
1107 }
1108 if (cflag) {
1109 sprintf(proc, "/proc/%d/status", tcp->pid);
1110 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1111 perror("strace: open(\"/proc/.../status\", ...)");
1112 return -1;
1113 }
1114 } else
1115 tcp->pfd_status = -1;
1116#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001117 rebuild_pollv();
1118 if (!attaching) {
1119 /*
1120 * Wait for the child to pause. Because of a race
1121 * condition we have to poll for the event.
1122 */
1123 for (;;) {
1124 if (IOCTL_STATUS (tcp) < 0) {
1125 perror("strace: PIOCSTATUS");
1126 return -1;
1127 }
1128 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001129 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001130 }
1131 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001132#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001133 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001134 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001135 perror("strace: PIOCSTOP");
1136 return -1;
1137 }
Roland McGrath553a6092002-12-16 20:40:39 +00001138#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139#ifdef PIOCSET
1140 /* Set Run-on-Last-Close. */
1141 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001142 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 perror("PIOCSET PR_RLC");
1144 return -1;
1145 }
1146 /* Set or Reset Inherit-on-Fork. */
1147 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001148 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149 perror("PIOC{SET,RESET} PR_FORK");
1150 return -1;
1151 }
1152#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001153#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1155 perror("PIOCSRLC");
1156 return -1;
1157 }
1158 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1159 perror("PIOC{S,R}FORK");
1160 return -1;
1161 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001162#else /* FREEBSD */
1163 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1164 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1165 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001166 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001167 }
1168 arg &= ~PF_LINGER;
1169 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001170 perror("PIOCSFL");
1171 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001172 }
1173#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001175#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001176 /* Enable all syscall entries we care about. */
1177 premptyset(&syscalls);
1178 for (i = 1; i < MAX_QUALS; ++i) {
1179 if (i > (sizeof syscalls) * CHAR_BIT) break;
1180 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1181 }
1182 praddset (&syscalls, SYS_execve);
1183 if (followfork) {
1184 praddset (&syscalls, SYS_fork);
1185#ifdef SYS_forkall
1186 praddset (&syscalls, SYS_forkall);
1187#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001188#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001189 praddset (&syscalls, SYS_fork1);
1190#endif
1191#ifdef SYS_rfork1
1192 praddset (&syscalls, SYS_rfork1);
1193#endif
1194#ifdef SYS_rforkall
1195 praddset (&syscalls, SYS_rforkall);
1196#endif
1197 }
1198 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 perror("PIOCSENTRY");
1200 return -1;
1201 }
John Hughes19e49982001-10-19 08:59:12 +00001202 /* Enable the syscall exits. */
1203 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 perror("PIOSEXIT");
1205 return -1;
1206 }
John Hughes19e49982001-10-19 08:59:12 +00001207 /* Enable signals we care about. */
1208 premptyset(&signals);
1209 for (i = 1; i < MAX_QUALS; ++i) {
1210 if (i > (sizeof signals) * CHAR_BIT) break;
1211 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1212 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001213 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214 perror("PIOCSTRACE");
1215 return -1;
1216 }
John Hughes19e49982001-10-19 08:59:12 +00001217 /* Enable faults we care about */
1218 premptyset(&faults);
1219 for (i = 1; i < MAX_QUALS; ++i) {
1220 if (i > (sizeof faults) * CHAR_BIT) break;
1221 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1222 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001223 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 perror("PIOCSFAULT");
1225 return -1;
1226 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001227#else /* FREEBSD */
1228 /* set events flags. */
1229 arg = S_SIG | S_SCE | S_SCX ;
1230 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1231 perror("PIOCBIS");
1232 return -1;
1233 }
1234#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001235 if (!attaching) {
1236#ifdef MIPS
1237 /*
1238 * The SGI PRSABORT doesn't work for pause() so
1239 * we send it a caught signal to wake it up.
1240 */
1241 kill(tcp->pid, SIGINT);
1242#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001243#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001245 arg = PRSABORT;
1246 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247 perror("PIOCRUN");
1248 return -1;
1249 }
Roland McGrath553a6092002-12-16 20:40:39 +00001250#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001251#endif /* !MIPS*/
1252#ifdef FREEBSD
1253 /* wake up the child if it received the SIGSTOP */
1254 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001255#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001256 for (;;) {
1257 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001258 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001259 perror("PIOCWSTOP");
1260 return -1;
1261 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001262 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001263 tcp->flags &= ~TCB_INSYSCALL;
1264 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001265 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 break;
1267 }
1268 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001269#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001270 arg = 0;
1271 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001272#else /* FREEBSD */
1273 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001274#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001275 perror("PIOCRUN");
1276 return -1;
1277 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001278#ifdef FREEBSD
1279 /* handle the case where we "opened" the child before
1280 it did the kill -STOP */
1281 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1282 tcp->status.PR_WHAT == SIGSTOP)
1283 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001284#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001286#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001288#else /* FREEBSD */
1289 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001290 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001291 /* We are attaching to an already running process.
1292 * Try to figure out the state of the process in syscalls,
1293 * to handle the first event well.
1294 * This is done by having a look at the "wchan" property of the
1295 * process, which tells where it is stopped (if it is). */
1296 FILE * status;
1297 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001298
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001299 sprintf(proc, "/proc/%d/status", tcp->pid);
1300 status = fopen(proc, "r");
1301 if (status &&
1302 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1303 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1304 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1305 strcmp(wchan, "stopevent")) {
1306 /* The process is asleep in the middle of a syscall.
1307 Fake the syscall entry event */
1308 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1309 tcp->status.PR_WHY = PR_SYSENTRY;
1310 trace_syscall(tcp);
1311 }
1312 if (status)
1313 fclose(status);
1314 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001315 }
1316#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001317#ifndef HAVE_POLLABLE_PROCFS
1318 if (proc_poll_pipe[0] != -1)
1319 proc_poller(tcp->pfd);
1320 else if (nprocs > 1) {
1321 proc_poll_open();
1322 proc_poller(last_pfd);
1323 proc_poller(tcp->pfd);
1324 }
1325 last_pfd = tcp->pfd;
1326#endif /* !HAVE_POLLABLE_PROCFS */
1327 return 0;
1328}
1329
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001330#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001332struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333pid2tcb(pid)
1334int pid;
1335{
1336 int i;
1337 struct tcb *tcp;
1338
Roland McGrathee9d4352002-12-18 04:16:10 +00001339 for (i = 0; i < tcbtabsize; i++) {
1340 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341 if (pid && tcp->pid != pid)
1342 continue;
1343 if (tcp->flags & TCB_INUSE)
1344 return tcp;
1345 }
1346 return NULL;
1347}
1348
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001349#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350
1351static struct tcb *
1352pfd2tcb(pfd)
1353int pfd;
1354{
1355 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356
Roland McGrathca16be82003-01-10 19:55:28 +00001357 for (i = 0; i < tcbtabsize; i++) {
1358 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001359 if (tcp->pfd != pfd)
1360 continue;
1361 if (tcp->flags & TCB_INUSE)
1362 return tcp;
1363 }
1364 return NULL;
1365}
1366
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001367#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001368
1369void
1370droptcb(tcp)
1371struct tcb *tcp;
1372{
1373 if (tcp->pid == 0)
1374 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001375#ifdef TCB_CLONE_THREAD
1376 if (tcp->nclone_threads > 0) {
1377 /* There are other threads left in this process, but this
1378 is the one whose PID represents the whole process.
1379 We need to keep this record around as a zombie until
1380 all the threads die. */
1381 tcp->flags |= TCB_EXITING;
1382 return;
1383 }
1384#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385 nprocs--;
1386 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001387
Roland McGrathe29341c2003-01-10 20:14:20 +00001388 if (tcp->parent != NULL) {
1389 tcp->parent->nchildren--;
1390#ifdef TCB_CLONE_THREAD
1391 if (tcp->flags & TCB_CLONE_DETACHED)
1392 tcp->parent->nclone_detached--;
1393 if (tcp->flags & TCB_CLONE_THREAD)
1394 tcp->parent->nclone_threads--;
1395#endif
Roland McGrath09623452003-05-23 02:27:13 +00001396#ifdef TCB_CLONE_DETACHED
1397 if (!(tcp->flags & TCB_CLONE_DETACHED))
1398#endif
1399 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001400#ifdef LINUX
1401 /* Update `tcp->parent->parent->nchildren' and the other fields
1402 like NCLONE_DETACHED, only for zombie group leader that has
1403 already reported and been short-circuited at the top of this
1404 function. The same condition as at the top of DETACH. */
1405 if ((tcp->flags & TCB_CLONE_THREAD) &&
1406 tcp->parent->nclone_threads == 0 &&
1407 (tcp->parent->flags & TCB_EXITING))
1408 droptcb(tcp->parent);
1409#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001410 tcp->parent = NULL;
1411 }
1412
1413 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001414 if (tcp->pfd != -1) {
1415 close(tcp->pfd);
1416 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001417#ifdef FREEBSD
1418 if (tcp->pfd_reg != -1) {
1419 close(tcp->pfd_reg);
1420 tcp->pfd_reg = -1;
1421 }
1422 if (tcp->pfd_status != -1) {
1423 close(tcp->pfd_status);
1424 tcp->pfd_status = -1;
1425 }
Roland McGrath553a6092002-12-16 20:40:39 +00001426#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001427#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001428 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001429#endif
1430 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001431
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001432 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001434
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 tcp->outf = 0;
1436}
1437
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001438#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439
1440static int
1441resume(tcp)
1442struct tcb *tcp;
1443{
1444 if (tcp == NULL)
1445 return -1;
1446
1447 if (!(tcp->flags & TCB_SUSPENDED)) {
1448 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1449 return -1;
1450 }
1451 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001452#ifdef TCB_CLONE_THREAD
1453 if (tcp->flags & TCB_CLONE_THREAD)
1454 tcp->parent->nclone_waiting--;
1455#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001457 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459
1460 if (!qflag)
1461 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1462 return 0;
1463}
1464
Roland McGrath1bfd3102007-08-03 10:02:00 +00001465static int
1466resume_from_tcp (struct tcb *tcp)
1467{
1468 int error = 0;
1469 int resumed = 0;
1470
1471 /* XXX This won't always be quite right (but it never was).
1472 A waiter with argument 0 or < -1 is waiting for any pid in
1473 a particular pgrp, which this child might or might not be
1474 in. The waiter will only wake up if it's argument is -1
1475 or if it's waiting for tcp->pid's pgrp. It makes a
1476 difference to wake up a waiter when there might be more
1477 traced children, because it could get a false ECHILD
1478 error. OTOH, if this was the last child in the pgrp, then
1479 it ought to wake up and get ECHILD. We would have to
1480 search the system for all pid's in the pgrp to be sure.
1481
1482 && (t->waitpid == -1 ||
1483 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1484 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1485 */
1486
1487 if (tcp->parent &&
1488 (tcp->parent->flags & TCB_SUSPENDED) &&
1489 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001490 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001491 ++resumed;
1492 }
1493#ifdef TCB_CLONE_THREAD
1494 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1495 /* Some other threads of our parent are waiting too. */
1496 unsigned int i;
1497
1498 /* Resume all the threads that were waiting for this PID. */
1499 for (i = 0; i < tcbtabsize; i++) {
1500 struct tcb *t = tcbtab[i];
1501 if (t->parent == tcp->parent && t != tcp
1502 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1503 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1504 && t->waitpid == tcp->pid) {
1505 error |= resume (t);
1506 ++resumed;
1507 }
1508 }
1509 if (resumed == 0)
1510 /* Noone was waiting for this PID in particular,
1511 so now we might need to resume some wildcarders. */
1512 for (i = 0; i < tcbtabsize; i++) {
1513 struct tcb *t = tcbtab[i];
1514 if (t->parent == tcp->parent && t != tcp
1515 && ((t->flags
1516 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1517 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1518 && t->waitpid <= 0
1519 ) {
1520 error |= resume (t);
1521 break;
1522 }
1523 }
1524 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001525#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001526
1527 return error;
1528}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001529
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001530#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531
Roland McGrath0a463882007-07-05 18:43:16 +00001532/* detach traced process; continue with sig
1533 Never call DETACH twice on the same process as both unattached and
1534 attached-unstopped processes give the same ESRCH. For unattached process we
1535 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536
1537static int
1538detach(tcp, sig)
1539struct tcb *tcp;
1540int sig;
1541{
1542 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001543#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001544 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001545 struct tcb *zombie = NULL;
1546
1547 /* If the group leader is lingering only because of this other
1548 thread now dying, then detach the leader as well. */
1549 if ((tcp->flags & TCB_CLONE_THREAD) &&
1550 tcp->parent->nclone_threads == 1 &&
1551 (tcp->parent->flags & TCB_EXITING))
1552 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001553#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554
1555 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001556 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557
1558#ifdef LINUX
1559 /*
1560 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001561 * before detaching. Arghh. We go through hoops
1562 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001564#if defined(SPARC)
1565#undef PTRACE_DETACH
1566#define PTRACE_DETACH PTRACE_SUNDETACH
1567#endif
Roland McGrath02203312007-06-11 22:06:31 +00001568 /*
1569 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1570 * expected SIGSTOP. We must catch exactly one as otherwise the
1571 * detached process would be left stopped (process state T).
1572 */
1573 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1575 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001576 }
1577 else if (errno != ESRCH) {
1578 /* Shouldn't happen. */
1579 perror("detach: ptrace(PTRACE_DETACH, ...)");
1580 }
Roland McGrath134813a2007-06-02 00:07:33 +00001581 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1582 : tcp->pid),
1583 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001584 if (errno != ESRCH)
1585 perror("detach: checking sanity");
1586 }
Roland McGrath02203312007-06-11 22:06:31 +00001587 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1588 ? tcp->parent->pid : tcp->pid),
1589 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001590 if (errno != ESRCH)
1591 perror("detach: stopping child");
1592 }
Roland McGrath02203312007-06-11 22:06:31 +00001593 else
1594 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001595 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001597#ifdef __WALL
1598 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1599 if (errno == ECHILD) /* Already gone. */
1600 break;
1601 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001602 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001603 break;
1604 }
1605#endif /* __WALL */
1606 /* No __WALL here. */
1607 if (waitpid(tcp->pid, &status, 0) < 0) {
1608 if (errno != ECHILD) {
1609 perror("detach: waiting");
1610 break;
1611 }
1612#ifdef __WCLONE
1613 /* If no processes, try clones. */
1614 if (wait4(tcp->pid, &status, __WCLONE,
1615 NULL) < 0) {
1616 if (errno != ECHILD)
1617 perror("detach: waiting");
1618 break;
1619 }
1620#endif /* __WCLONE */
1621 }
1622#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001623 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001624#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625 if (!WIFSTOPPED(status)) {
1626 /* Au revoir, mon ami. */
1627 break;
1628 }
1629 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001630 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 break;
1632 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001633 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001634 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001635 : WSTOPSIG(status));
1636 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001639 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001640#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001641
1642#if defined(SUNOS4)
1643 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1644 if (sig && kill(tcp->pid, sig) < 0)
1645 perror("detach: kill");
1646 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001647 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648#endif /* SUNOS4 */
1649
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001650#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001651 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001652#endif
1653
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 if (!qflag)
1655 fprintf(stderr, "Process %u detached\n", tcp->pid);
1656
1657 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001658
1659#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001660 if (zombie != NULL) {
1661 /* TCP no longer exists therefore you must not detach () it. */
1662 droptcb(zombie);
1663 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001664#endif
1665
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666 return error;
1667}
1668
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001669#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001671static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672{
1673 int pid;
1674 int status;
1675
1676 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 }
1678}
1679
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001680#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681
1682static void
1683cleanup()
1684{
1685 int i;
1686 struct tcb *tcp;
1687
Roland McGrathee9d4352002-12-18 04:16:10 +00001688 for (i = 0; i < tcbtabsize; i++) {
1689 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 if (!(tcp->flags & TCB_INUSE))
1691 continue;
1692 if (debug)
1693 fprintf(stderr,
1694 "cleanup: looking at pid %u\n", tcp->pid);
1695 if (tcp_last &&
1696 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001697 tprintf(" <unfinished ...>");
1698 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699 }
1700 if (tcp->flags & TCB_ATTACHED)
1701 detach(tcp, 0);
1702 else {
1703 kill(tcp->pid, SIGCONT);
1704 kill(tcp->pid, SIGTERM);
1705 }
1706 }
1707 if (cflag)
1708 call_summary(outf);
1709}
1710
1711static void
1712interrupt(sig)
1713int sig;
1714{
1715 interrupted = 1;
1716}
1717
1718#ifndef HAVE_STRERROR
1719
Roland McGrath6d2b3492002-12-30 00:51:30 +00001720#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001721extern int sys_nerr;
1722extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001723#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724
1725const char *
1726strerror(errno)
1727int errno;
1728{
1729 static char buf[64];
1730
1731 if (errno < 1 || errno >= sys_nerr) {
1732 sprintf(buf, "Unknown error %d", errno);
1733 return buf;
1734 }
1735 return sys_errlist[errno];
1736}
1737
1738#endif /* HAVE_STERRROR */
1739
1740#ifndef HAVE_STRSIGNAL
1741
Roland McGrath8f474e02003-01-14 07:53:33 +00001742#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001743extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001745#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1746extern char *_sys_siglist[];
1747#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748
1749const char *
1750strsignal(sig)
1751int sig;
1752{
1753 static char buf[64];
1754
1755 if (sig < 1 || sig >= NSIG) {
1756 sprintf(buf, "Unknown signal %d", sig);
1757 return buf;
1758 }
1759#ifdef HAVE__SYS_SIGLIST
1760 return _sys_siglist[sig];
1761#else
1762 return sys_siglist[sig];
1763#endif
1764}
1765
1766#endif /* HAVE_STRSIGNAL */
1767
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001768#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769
1770static void
1771rebuild_pollv()
1772{
1773 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774
Roland McGrathee9d4352002-12-18 04:16:10 +00001775 if (pollv != NULL)
1776 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001777 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001778 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001779 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001780 exit(1);
1781 }
1782
Roland McGrathca16be82003-01-10 19:55:28 +00001783 for (i = j = 0; i < tcbtabsize; i++) {
1784 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 if (!(tcp->flags & TCB_INUSE))
1786 continue;
1787 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001788 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789 j++;
1790 }
1791 if (j != nprocs) {
1792 fprintf(stderr, "strace: proc miscount\n");
1793 exit(1);
1794 }
1795}
1796
1797#ifndef HAVE_POLLABLE_PROCFS
1798
1799static void
1800proc_poll_open()
1801{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802 int i;
1803
1804 if (pipe(proc_poll_pipe) < 0) {
1805 perror("pipe");
1806 exit(1);
1807 }
1808 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001809 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810 exit(1);
1811 }
1812 }
1813}
1814
1815static int
1816proc_poll(pollv, nfds, timeout)
1817struct pollfd *pollv;
1818int nfds;
1819int timeout;
1820{
1821 int i;
1822 int n;
1823 struct proc_pollfd pollinfo;
1824
1825 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1826 return n;
1827 if (n != sizeof(struct proc_pollfd)) {
1828 fprintf(stderr, "panic: short read: %d\n", n);
1829 exit(1);
1830 }
1831 for (i = 0; i < nprocs; i++) {
1832 if (pollv[i].fd == pollinfo.fd)
1833 pollv[i].revents = pollinfo.revents;
1834 else
1835 pollv[i].revents = 0;
1836 }
1837 poller_pid = pollinfo.pid;
1838 return 1;
1839}
1840
1841static void
1842wakeup_handler(sig)
1843int sig;
1844{
1845}
1846
1847static void
1848proc_poller(pfd)
1849int pfd;
1850{
1851 struct proc_pollfd pollinfo;
1852 struct sigaction sa;
1853 sigset_t blocked_set, empty_set;
1854 int i;
1855 int n;
1856 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001857#ifdef FREEBSD
1858 struct procfs_status pfs;
1859#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001860
1861 switch (fork()) {
1862 case -1:
1863 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001864 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 case 0:
1866 break;
1867 default:
1868 return;
1869 }
1870
1871 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1872 sa.sa_flags = 0;
1873 sigemptyset(&sa.sa_mask);
1874 sigaction(SIGHUP, &sa, NULL);
1875 sigaction(SIGINT, &sa, NULL);
1876 sigaction(SIGQUIT, &sa, NULL);
1877 sigaction(SIGPIPE, &sa, NULL);
1878 sigaction(SIGTERM, &sa, NULL);
1879 sa.sa_handler = wakeup_handler;
1880 sigaction(SIGUSR1, &sa, NULL);
1881 sigemptyset(&blocked_set);
1882 sigaddset(&blocked_set, SIGUSR1);
1883 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1884 sigemptyset(&empty_set);
1885
1886 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1887 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001888 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001889 }
1890 n = rl.rlim_cur;
1891 for (i = 0; i < n; i++) {
1892 if (i != pfd && i != proc_poll_pipe[1])
1893 close(i);
1894 }
1895
1896 pollinfo.fd = pfd;
1897 pollinfo.pid = getpid();
1898 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001899#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001900 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1901#else
1902 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1903#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001904 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 switch (errno) {
1906 case EINTR:
1907 continue;
1908 case EBADF:
1909 pollinfo.revents = POLLERR;
1910 break;
1911 case ENOENT:
1912 pollinfo.revents = POLLHUP;
1913 break;
1914 default:
1915 perror("proc_poller: PIOCWSTOP");
1916 }
1917 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1918 _exit(0);
1919 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001920 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1922 sigsuspend(&empty_set);
1923 }
1924}
1925
1926#endif /* !HAVE_POLLABLE_PROCFS */
1927
1928static int
1929choose_pfd()
1930{
1931 int i, j;
1932 struct tcb *tcp;
1933
1934 static int last;
1935
1936 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001937 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 /*
1939 * The previous process is ready to run again. We'll
1940 * let it do so if it is currently in a syscall. This
1941 * heuristic improves the readability of the trace.
1942 */
1943 tcp = pfd2tcb(pollv[last].fd);
1944 if (tcp && (tcp->flags & TCB_INSYSCALL))
1945 return pollv[last].fd;
1946 }
1947
1948 for (i = 0; i < nprocs; i++) {
1949 /* Let competing children run round robin. */
1950 j = (i + last + 1) % nprocs;
1951 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1952 tcp = pfd2tcb(pollv[j].fd);
1953 if (!tcp) {
1954 fprintf(stderr, "strace: lost proc\n");
1955 exit(1);
1956 }
1957 droptcb(tcp);
1958 return -1;
1959 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001960 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 last = j;
1962 return pollv[j].fd;
1963 }
1964 }
1965 fprintf(stderr, "strace: nothing ready\n");
1966 exit(1);
1967}
1968
1969static int
1970trace()
1971{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001972#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001973 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001974#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 struct tcb *tcp;
1976 int pfd;
1977 int what;
1978 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001979 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001980
1981 for (;;) {
1982 if (interactive)
1983 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1984
1985 if (nprocs == 0)
1986 break;
1987
1988 switch (nprocs) {
1989 case 1:
1990#ifndef HAVE_POLLABLE_PROCFS
1991 if (proc_poll_pipe[0] == -1) {
1992#endif
1993 tcp = pid2tcb(0);
1994 if (!tcp)
1995 continue;
1996 pfd = tcp->pfd;
1997 if (pfd == -1)
1998 continue;
1999 break;
2000#ifndef HAVE_POLLABLE_PROCFS
2001 }
2002 /* fall through ... */
2003#endif /* !HAVE_POLLABLE_PROCFS */
2004 default:
2005#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002006#ifdef POLL_HACK
2007 /* On some systems (e.g. UnixWare) we get too much ugly
2008 "unfinished..." stuff when multiple proceses are in
2009 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002010
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002011 if (in_syscall) {
2012 struct pollfd pv;
2013 tcp = in_syscall;
2014 in_syscall = NULL;
2015 pv.fd = tcp->pfd;
2016 pv.events = POLLWANT;
2017 if ((what = poll (&pv, 1, 1)) < 0) {
2018 if (interrupted)
2019 return 0;
2020 continue;
2021 }
2022 else if (what == 1 && pv.revents & POLLWANT) {
2023 goto FOUND;
2024 }
2025 }
2026#endif
2027
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028 if (poll(pollv, nprocs, INFTIM) < 0) {
2029 if (interrupted)
2030 return 0;
2031 continue;
2032 }
2033#else /* !HAVE_POLLABLE_PROCFS */
2034 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2035 if (interrupted)
2036 return 0;
2037 continue;
2038 }
2039#endif /* !HAVE_POLLABLE_PROCFS */
2040 pfd = choose_pfd();
2041 if (pfd == -1)
2042 continue;
2043 break;
2044 }
2045
2046 /* Look up `pfd' in our table. */
2047 if ((tcp = pfd2tcb(pfd)) == NULL) {
2048 fprintf(stderr, "unknown pfd: %u\n", pfd);
2049 exit(1);
2050 }
John Hughesb6643082002-05-23 11:02:22 +00002051#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002052 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002053#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054 /* Get the status of the process. */
2055 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002056#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002057 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002058#else /* FREEBSD */
2059 /* Thanks to some scheduling mystery, the first poller
2060 sometimes waits for the already processed end of fork
2061 event. Doing a non blocking poll here solves the problem. */
2062 if (proc_poll_pipe[0] != -1)
2063 ioctl_result = IOCTL_STATUS (tcp);
2064 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002065 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002066#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067 ioctl_errno = errno;
2068#ifndef HAVE_POLLABLE_PROCFS
2069 if (proc_poll_pipe[0] != -1) {
2070 if (ioctl_result < 0)
2071 kill(poller_pid, SIGKILL);
2072 else
2073 kill(poller_pid, SIGUSR1);
2074 }
2075#endif /* !HAVE_POLLABLE_PROCFS */
2076 }
2077 if (interrupted)
2078 return 0;
2079
2080 if (interactive)
2081 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2082
2083 if (ioctl_result < 0) {
2084 /* Find out what happened if it failed. */
2085 switch (ioctl_errno) {
2086 case EINTR:
2087 case EBADF:
2088 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002089#ifdef FREEBSD
2090 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002091#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 case ENOENT:
2093 droptcb(tcp);
2094 continue;
2095 default:
2096 perror("PIOCWSTOP");
2097 exit(1);
2098 }
2099 }
2100
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002101#ifdef FREEBSD
2102 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2103 /* discard first event for a syscall we never entered */
2104 IOCTL (tcp->pfd, PIOCRUN, 0);
2105 continue;
2106 }
Roland McGrath553a6092002-12-16 20:40:39 +00002107#endif
2108
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002109 /* clear the just started flag */
2110 tcp->flags &= ~TCB_STARTUP;
2111
2112 /* set current output file */
2113 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002114 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002115
2116 if (cflag) {
2117 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002118#ifdef FREEBSD
2119 char buf[1024];
2120 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002122 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2123 buf[len] = '\0';
2124 sscanf(buf,
2125 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2126 &stime.tv_sec, &stime.tv_usec);
2127 } else
2128 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002129#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2131 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002132#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002133 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2134 tcp->stime = stime;
2135 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002136 what = tcp->status.PR_WHAT;
2137 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002138#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002140 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2141 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 if (trace_syscall(tcp) < 0) {
2143 fprintf(stderr, "syscall trouble\n");
2144 exit(1);
2145 }
2146 }
2147 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002148#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002149 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002150#ifdef POLL_HACK
2151 in_syscall = tcp;
2152#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 case PR_SYSEXIT:
2154 if (trace_syscall(tcp) < 0) {
2155 fprintf(stderr, "syscall trouble\n");
2156 exit(1);
2157 }
2158 break;
2159 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002160 if (cflag != CFLAG_ONLY_STATS
2161 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002162 printleader(tcp);
2163 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002164 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002165 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002166#ifdef PR_INFO
2167 if (tcp->status.PR_INFO.si_signo == what) {
2168 printleader(tcp);
2169 tprintf(" siginfo=");
2170 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002171 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002172 }
2173#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002174 }
2175 break;
2176 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002177 if (cflag != CFLAGS_ONLY_STATS
2178 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002179 printleader(tcp);
2180 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002181 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182 }
2183 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002184#ifdef FREEBSD
2185 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002186 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002187#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002189 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190 exit(1);
2191 break;
2192 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002193 /* Remember current print column before continuing. */
2194 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002195 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002196#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002197 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002198#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002199 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002200#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 perror("PIOCRUN");
2202 exit(1);
2203 }
2204 }
2205 return 0;
2206}
2207
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002208#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002210#ifdef TCB_GROUP_EXITING
2211/* Handle an exit detach or death signal that is taking all the
2212 related clone threads with it. This is called in three circumstances:
2213 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2214 SIG == 0 Continuing TCP will perform an exit_group syscall.
2215 SIG == other Continuing TCP with SIG will kill the process.
2216*/
2217static int
2218handle_group_exit(struct tcb *tcp, int sig)
2219{
2220 /* We need to locate our records of all the clone threads
2221 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002222 struct tcb *leader = NULL;
2223
2224 if (tcp->flags & TCB_CLONE_THREAD)
2225 leader = tcp->parent;
2226 else if (tcp->nclone_detached > 0)
2227 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002228
2229 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002230 if (leader != NULL && leader != tcp
2231 && !(leader->flags & TCB_GROUP_EXITING)
2232 && !(tcp->flags & TCB_STARTUP)
2233 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002234 fprintf(stderr,
2235 "PANIC: handle_group_exit: %d leader %d\n",
2236 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002237 }
2238 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002239#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002240 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002241#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002242 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002243 }
2244 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002245 /* Mark that we are taking the process down. */
2246 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002247 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002248 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002249 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002250 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002251 } else {
2252 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2253 cleanup();
2254 return -1;
2255 }
2256 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002257 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002258 if (leader != tcp)
2259 droptcb(tcp);
2260 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002261 /* The leader will report to us as parent now,
2262 and then we'll get to the SIG==-1 case. */
2263 return 0;
2264 }
2265 }
2266
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002267 return 0;
2268}
2269#endif
2270
Roland McGratheb9e2e82009-06-02 16:49:22 -07002271static int
2272trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002273{
2274 int pid;
2275 int wait_errno;
2276 int status;
2277 struct tcb *tcp;
2278#ifdef LINUX
2279 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002280#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002281 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002282#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002283#endif /* LINUX */
2284
Roland McGratheb9e2e82009-06-02 16:49:22 -07002285 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002286 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002287 return 0;
2288 if (interactive)
2289 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002290#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002291#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002292 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002293 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002294 /* this kernel does not support __WALL */
2295 wait4_options &= ~__WALL;
2296 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002297 pid = wait4(-1, &status, wait4_options,
2298 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002299 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002300 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002301 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002302 pid = wait4(-1, &status, __WCLONE,
2303 cflag ? &ru : NULL);
2304 if (pid == -1) {
2305 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002306 "failed: %s\n", strerror(errno));
2307 }
2308 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002309#else
2310 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2311#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312#endif /* LINUX */
2313#ifdef SUNOS4
2314 pid = wait(&status);
2315#endif /* SUNOS4 */
2316 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002317 if (interactive)
2318 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002319
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002320 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002321 switch (wait_errno) {
2322 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002323 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002324 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002325 /*
2326 * We would like to verify this case
2327 * but sometimes a race in Solbourne's
2328 * version of SunOS sometimes reports
2329 * ECHILD before sending us SIGCHILD.
2330 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002331 return 0;
2332 default:
2333 errno = wait_errno;
2334 perror("strace: wait");
2335 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002336 }
2337 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002338 if (pid == popen_pid) {
2339 if (WIFEXITED(status) || WIFSIGNALED(status))
2340 popen_pid = -1;
2341 continue;
2342 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343 if (debug)
2344 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2345
2346 /* Look up `pid' in our table. */
2347 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002348#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002349 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002350 /* This is needed to go with the CLONE_PTRACE
2351 changes in process.c/util.c: we might see
2352 the child's initial trap before we see the
2353 parent return from the clone syscall.
2354 Leave the child suspended until the parent
2355 returns from its system call. Only then
2356 will we have the association of parent and
2357 child so that we know how to do clearbpt
2358 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002359 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002360 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002361 if (!qflag)
2362 fprintf(stderr, "\
2363Process %d attached (waiting for parent)\n",
2364 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002365 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002366 else
2367 /* This can happen if a clone call used
2368 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002369#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002370 {
2371 fprintf(stderr, "unknown pid: %u\n", pid);
2372 if (WIFSTOPPED(status))
2373 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2374 exit(1);
2375 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002376 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002377 /* set current output file */
2378 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002379 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002380 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002381#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002382 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2383 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002384#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002386
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 if (tcp->flags & TCB_SUSPENDED) {
2388 /*
2389 * Apparently, doing any ptrace() call on a stopped
2390 * process, provokes the kernel to report the process
2391 * status again on a subsequent wait(), even if the
2392 * process has not been actually restarted.
2393 * Since we have inspected the arguments of suspended
2394 * processes we end up here testing for this case.
2395 */
2396 continue;
2397 }
2398 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002399 if (pid == strace_child)
2400 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002401 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002402 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2403 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002404 tprintf("+++ killed by %s %s+++",
2405 signame(WTERMSIG(status)),
2406#ifdef WCOREDUMP
2407 WCOREDUMP(status) ? "(core dumped) " :
2408#endif
2409 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002410 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002412#ifdef TCB_GROUP_EXITING
2413 handle_group_exit(tcp, -1);
2414#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002416#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002417 continue;
2418 }
2419 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002420 if (pid == strace_child)
2421 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002422 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002423 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2424 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002425#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002426 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002427 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002428#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002429 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002430 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002431 "PANIC: attached pid %u exited with %d\n",
2432 pid, WEXITSTATUS(status));
2433 }
Roland McGrath0a396902003-06-10 03:05:53 +00002434 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002435 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002436 tprintf(" <unfinished ... exit status %d>\n",
2437 WEXITSTATUS(status));
2438 tcp_last = NULL;
2439 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002440#ifdef TCB_GROUP_EXITING
2441 handle_group_exit(tcp, -1);
2442#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002444#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 continue;
2446 }
2447 if (!WIFSTOPPED(status)) {
2448 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2449 droptcb(tcp);
2450 continue;
2451 }
2452 if (debug)
2453 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002454 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002455
Roland McGrath02203312007-06-11 22:06:31 +00002456 /*
2457 * Interestingly, the process may stop
2458 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002459 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002460 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002461 * A no-MMU vforked child won't send up a signal,
2462 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002463 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002464 if ((tcp->flags & TCB_STARTUP) &&
2465 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002466 /*
2467 * This flag is there to keep us in sync.
2468 * Next time this process stops it should
2469 * really be entering a system call.
2470 */
2471 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002473 /*
2474 * One example is a breakpoint inherited from
2475 * parent through fork ().
2476 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002477 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2478 droptcb(tcp);
2479 cleanup();
2480 return -1;
2481 }
2482 }
2483 goto tracing;
2484 }
2485
Roland McGratheb9e2e82009-06-02 16:49:22 -07002486 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002487 if (WSTOPSIG(status) == SIGSTOP &&
2488 (tcp->flags & TCB_SIGTRAPPED)) {
2489 /*
2490 * Trapped attempt to block SIGTRAP
2491 * Hope we are back in control now.
2492 */
2493 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002494 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495 cleanup();
2496 return -1;
2497 }
2498 continue;
2499 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002500 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002501 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002502 unsigned long addr = 0;
2503 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002504#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002505# define PSR_RI 41
2506 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002507 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002508
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002509 upeek(tcp, PT_CR_IPSR, &psr);
2510 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002511
2512 pc += (psr >> PSR_RI) & 0x3;
2513 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2514 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002515#elif defined PTRACE_GETSIGINFO
2516 if (WSTOPSIG(status) == SIGSEGV ||
2517 WSTOPSIG(status) == SIGBUS) {
2518 siginfo_t si;
2519 if (ptrace(PTRACE_GETSIGINFO, pid,
2520 0, &si) == 0)
2521 addr = (unsigned long)
2522 si.si_addr;
2523 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002524#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002525 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002526 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002527 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002528 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002529 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002530 }
Roland McGrath05690952004-10-20 01:00:27 +00002531 if (((tcp->flags & TCB_ATTACHED) ||
2532 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002533 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002534#ifdef TCB_GROUP_EXITING
2535 handle_group_exit(tcp, WSTOPSIG(status));
2536#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002538#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 continue;
2540 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002541 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002542 cleanup();
2543 return -1;
2544 }
2545 tcp->flags &= ~TCB_SUSPENDED;
2546 continue;
2547 }
Roland McGrath02203312007-06-11 22:06:31 +00002548 /* we handled the STATUS, we are permitted to interrupt now. */
2549 if (interrupted)
2550 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002551 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2552 /* ptrace() failed in trace_syscall() with ESRCH.
2553 * Likely a result of process disappearing mid-flight.
2554 * Observed case: exit_group() terminating
2555 * all processes in thread group. In this case, threads
2556 * "disappear" in an unpredictable moment without any
2557 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002558 */
2559 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002560 if (tcp_last) {
2561 /* Do we have dangling line "syscall(param, param"?
2562 * Finish the line then. We cannot
2563 */
2564 tcp_last->flags |= TCB_REPRINT;
2565 tprintf(" <unfinished ...>");
2566 printtrailer();
2567 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002568 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002569 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002570 ptrace(PTRACE_KILL,
2571 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572 droptcb(tcp);
2573 }
2574 continue;
2575 }
2576 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002577#ifdef TCB_GROUP_EXITING
2578 if (tcp->flags & TCB_GROUP_EXITING) {
2579 if (handle_group_exit(tcp, 0) < 0)
2580 return -1;
2581 continue;
2582 }
2583#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 if (tcp->flags & TCB_ATTACHED)
2585 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002586 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002587 cleanup();
2588 return -1;
2589 }
2590 continue;
2591 }
2592 if (tcp->flags & TCB_SUSPENDED) {
2593 if (!qflag)
2594 fprintf(stderr, "Process %u suspended\n", pid);
2595 continue;
2596 }
2597 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002598 /* Remember current print column before continuing. */
2599 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002600 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002601 cleanup();
2602 return -1;
2603 }
2604 }
2605 return 0;
2606}
2607
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002608#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002609
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002610#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002611
2612void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002614{
2615 va_list args;
2616
Andreas Schwabe5355de2009-10-27 16:56:43 +01002617 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002618 if (outf) {
2619 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002620 if (n < 0) {
2621 if (outf != stderr)
2622 perror(outfname == NULL
2623 ? "<writing to pipe>" : outfname);
2624 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002625 curcol += n;
2626 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002627 va_end(args);
2628 return;
2629}
2630
2631void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002632printleader(tcp)
2633struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002634{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002635 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002636 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002637 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002638 tprintf(" <unavailable>)");
2639 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002640 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002641 tprintf("= ? <unavailable>\n");
2642 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002643 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002644 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002645 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002646 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002647 }
2648 curcol = 0;
2649 if ((followfork == 1 || pflag_seen > 1) && outfname)
2650 tprintf("%-5d ", tcp->pid);
2651 else if (nprocs > 1 && !outfname)
2652 tprintf("[pid %5u] ", tcp->pid);
2653 if (tflag) {
2654 char str[sizeof("HH:MM:SS")];
2655 struct timeval tv, dtv;
2656 static struct timeval otv;
2657
2658 gettimeofday(&tv, NULL);
2659 if (rflag) {
2660 if (otv.tv_sec == 0)
2661 otv = tv;
2662 tv_sub(&dtv, &tv, &otv);
2663 tprintf("%6ld.%06ld ",
2664 (long) dtv.tv_sec, (long) dtv.tv_usec);
2665 otv = tv;
2666 }
2667 else if (tflag > 2) {
2668 tprintf("%ld.%06ld ",
2669 (long) tv.tv_sec, (long) tv.tv_usec);
2670 }
2671 else {
2672 time_t local = tv.tv_sec;
2673 strftime(str, sizeof(str), "%T", localtime(&local));
2674 if (tflag > 1)
2675 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2676 else
2677 tprintf("%s ", str);
2678 }
2679 }
2680 if (iflag)
2681 printcall(tcp);
2682}
2683
2684void
2685tabto(col)
2686int col;
2687{
2688 if (curcol < col)
2689 tprintf("%*s", col - curcol, "");
2690}
2691
2692void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002693printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694{
2695 tprintf("\n");
2696 tcp_last = NULL;
2697}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002698
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002699#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002700
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002701int
2702mp_ioctl(int fd, int cmd, void *arg, int size)
2703{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002704 struct iovec iov[2];
2705 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002706
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002707 iov[0].iov_base = &cmd;
2708 iov[0].iov_len = sizeof cmd;
2709 if (arg) {
2710 ++n;
2711 iov[1].iov_base = arg;
2712 iov[1].iov_len = size;
2713 }
Roland McGrath553a6092002-12-16 20:40:39 +00002714
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002715 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002716}
2717
2718#endif