blob: da8cc4a559c85df4906bc51605125dfbc628f8f3 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <signal.h>
37#include <errno.h>
38#include <sys/param.h>
39#include <fcntl.h>
40#include <sys/resource.h>
41#include <sys/wait.h>
42#include <sys/stat.h>
43#include <pwd.h>
44#include <grp.h>
45#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000046#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# include <asm/unistd.h>
51# if defined __NR_tgkill
52# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53# elif defined __NR_tkill
54# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55# else
56 /* kill() may choose arbitrarily the target task of the process group
57 while we later wait on a that specific TID. PID process waits become
58 TID task specific waits for a process under ptrace(2). */
59# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61# endif
62#endif
63
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000064#if defined(IA64) && defined(LINUX)
65# include <asm/ptrace_offsets.h>
66#endif
67
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000068#ifdef USE_PROCFS
69#include <poll.h>
70#endif
71
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000072#ifdef SVR4
73#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000074#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000075#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000076#include <sys/uio.h>
77#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000079#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000080extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000081extern int optind;
82extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000083
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
Roland McGrath41c48222008-07-18 00:25:10 +000085int debug = 0, followfork = 0;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000086int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
87static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000088/*
89 * daemonized_tracer supports -D option.
90 * With this option, strace forks twice.
91 * Unlike normal case, with -D *grandparent* process exec's,
92 * becoming a traced process. Child exits (this prevents traced process
93 * from having children it doesn't expect to have), and grandchild
94 * attaches to grandparent similarly to strace -p PID.
95 * This allows for more transparent interaction in cases
96 * when process and its parent are communicating via signals,
97 * wait() etc. Without -D, strace process gets lodged in between,
98 * disrupting parent<->child link.
99 */
100static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000102/* Sometimes we want to print only succeeding syscalls. */
103int not_failing_only = 0;
104
Dmitry V. Levina6809652008-11-10 17:14:58 +0000105static int exit_code = 0;
106static int strace_child = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700107
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000108static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109uid_t run_uid;
110gid_t run_gid;
111
112int acolumn = DEFAULT_ACOLUMN;
113int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000114static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +0000116struct tcb **tcbtab;
117unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700119extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120
Roland McGrath0a463882007-07-05 18:43:16 +0000121static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122static int trace P((void));
123static void cleanup P((void));
124static void interrupt P((int sig));
125static sigset_t empty_set, blocked_set;
126
127#ifdef HAVE_SIG_ATOMIC_T
128static volatile sig_atomic_t interrupted;
129#else /* !HAVE_SIG_ATOMIC_T */
130#ifdef __STDC__
131static volatile int interrupted;
132#else /* !__STDC__ */
133static int interrupted;
134#endif /* !__STDC__ */
135#endif /* !HAVE_SIG_ATOMIC_T */
136
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000137#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138
139static struct tcb *pfd2tcb P((int pfd));
140static void reaper P((int sig));
141static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000142static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
144#ifndef HAVE_POLLABLE_PROCFS
145
146static void proc_poll_open P((void));
147static void proc_poller P((int pfd));
148
149struct proc_pollfd {
150 int fd;
151 int revents;
152 int pid;
153};
154
155static int poller_pid;
156static int proc_poll_pipe[2] = { -1, -1 };
157
158#endif /* !HAVE_POLLABLE_PROCFS */
159
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000160#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000161#define POLLWANT POLLWRNORM
162#else
163#define POLLWANT POLLPRI
164#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000165#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166
167static void
168usage(ofp, exitval)
169FILE *ofp;
170int exitval;
171{
172 fprintf(ofp, "\
173usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000174 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
175 [command [arg ...]]\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000176 or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000177 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178-c -- count time, calls, and errors for each syscall and report summary\n\
179-f -- follow forks, -ff -- with output into separate files\n\
180-F -- attempt to follow vforks, -h -- print help message\n\
181-i -- print instruction pointer at time of syscall\n\
182-q -- suppress messages about attaching, detaching, etc.\n\
183-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
184-T -- print time spent in each syscall, -V -- print version\n\
185-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
186-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
187-a column -- alignment COLUMN for printing syscall results (default %d)\n\
188-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
189 options: trace, abbrev, verbose, raw, signal, read, or write\n\
190-o file -- send trace output to FILE instead of stderr\n\
191-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
192-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000193-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
195-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
196-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000197-E var=val -- put var=val in the environment for command\n\
198-E var -- remove var from the environment for command\n\
199" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000200-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000201 */
202, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000203 exit(exitval);
204}
205
206#ifdef SVR4
207#ifdef MIPS
208void
209foobar()
210{
211}
212#endif /* MIPS */
213#endif /* SVR4 */
214
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000215static int
216set_cloexec_flag(int fd)
217{
218 int flags, newflags;
219
220 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
221 {
222 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
223 progname, strerror(errno));
224 return -1;
225 }
226
227 newflags = flags | FD_CLOEXEC;
228 if (flags == newflags)
229 return 0;
230
231 if (fcntl(fd, F_SETFD, newflags) < 0)
232 {
233 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
234 progname, strerror(errno));
235 return -1;
236 }
237
238 return 0;
239}
240
241/*
242 * When strace is setuid executable, we have to swap uids
243 * before and after filesystem and process management operations.
244 */
245static void
246swap_uid(void)
247{
248#ifndef SVR4
249 int euid = geteuid(), uid = getuid();
250
251 if (euid != uid && setreuid(euid, uid) < 0)
252 {
253 fprintf(stderr, "%s: setreuid: %s\n",
254 progname, strerror(errno));
255 exit(1);
256 }
257#endif
258}
259
Roland McGrath4bfa6262007-07-05 20:03:16 +0000260#if _LFS64_LARGEFILE
261# define fopen_for_output fopen64
262#else
263# define fopen_for_output fopen
264#endif
265
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000266static FILE *
267strace_fopen(const char *path, const char *mode)
268{
269 FILE *fp;
270
271 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000272 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000273 fprintf(stderr, "%s: can't fopen '%s': %s\n",
274 progname, path, strerror(errno));
275 swap_uid();
276 if (fp && set_cloexec_flag(fileno(fp)) < 0)
277 {
278 fclose(fp);
279 fp = NULL;
280 }
281 return fp;
282}
283
284static int popen_pid = -1;
285
286#ifndef _PATH_BSHELL
287# define _PATH_BSHELL "/bin/sh"
288#endif
289
290/*
291 * We cannot use standard popen(3) here because we have to distinguish
292 * popen child process from other processes we trace, and standard popen(3)
293 * does not export its child's pid.
294 */
295static FILE *
296strace_popen(const char *command)
297{
298 int fds[2];
299
300 swap_uid();
301 if (pipe(fds) < 0)
302 {
303 fprintf(stderr, "%s: pipe: %s\n",
304 progname, strerror(errno));
305 swap_uid();
306 return NULL;
307 }
308
309 if (set_cloexec_flag(fds[1]) < 0)
310 {
311 close(fds[0]);
312 close(fds[1]);
313 swap_uid();
314 return NULL;
315 }
316
317 if ((popen_pid = fork()) == -1)
318 {
319 fprintf(stderr, "%s: fork: %s\n",
320 progname, strerror(errno));
321 close(fds[0]);
322 close(fds[1]);
323 swap_uid();
324 return NULL;
325 }
326
327 if (popen_pid)
328 {
329 /* parent */
330 close(fds[0]);
331 swap_uid();
332 return fdopen(fds[1], "w");
333 } else
334 {
335 /* child */
336 close(fds[1]);
337 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
338 {
339 fprintf(stderr, "%s: dup2: %s\n",
340 progname, strerror(errno));
341 _exit(1);
342 }
343 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
344 fprintf(stderr, "%s: execl: %s: %s\n",
345 progname, _PATH_BSHELL, strerror(errno));
346 _exit(1);
347 }
348}
349
350static int
351newoutf(struct tcb *tcp)
352{
353 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000354 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000355 FILE *fp;
356
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000357 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000358 if ((fp = strace_fopen(name, "w")) == NULL)
359 return -1;
360 tcp->outf = fp;
361 }
362 return 0;
363}
364
Roland McGrath02203312007-06-11 22:06:31 +0000365static void
366startup_attach(void)
367{
368 int tcbi;
369 struct tcb *tcp;
370
371 /*
372 * Block user interruptions as we would leave the traced
373 * process stopped (process state T) if we would terminate in
374 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
375 * We rely on cleanup () from this point on.
376 */
377 if (interactive)
378 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
379
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000380 if (daemonized_tracer) {
381 pid_t pid = fork();
382 if (pid < 0) {
383 _exit(1);
384 }
385 if (pid) { /* parent */
386 /*
387 * Wait for child to attach to straced process
388 * (our parent). Child SIGKILLs us after it attached.
389 * Parent's wait() is unblocked by our death,
390 * it proceeds to exec the straced program.
391 */
392 pause();
393 _exit(0); /* paranoia */
394 }
395 }
396
Roland McGrath02203312007-06-11 22:06:31 +0000397 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
398 tcp = tcbtab[tcbi];
399 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
400 continue;
401#ifdef LINUX
402 if (tcp->flags & TCB_CLONE_THREAD)
403 continue;
404#endif
405 /* Reinitialize the output since it may have changed. */
406 tcp->outf = outf;
407 if (newoutf(tcp) < 0)
408 exit(1);
409
410#ifdef USE_PROCFS
411 if (proc_open(tcp, 1) < 0) {
412 fprintf(stderr, "trouble opening proc file\n");
413 droptcb(tcp);
414 continue;
415 }
416#else /* !USE_PROCFS */
417# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000418 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000419 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000420 DIR *dir;
421
422 sprintf(procdir, "/proc/%d/task", tcp->pid);
423 dir = opendir(procdir);
424 if (dir != NULL) {
425 unsigned int ntid = 0, nerr = 0;
426 struct dirent *de;
427 int tid;
428 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000429 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000430 continue;
431 tid = atoi(de->d_name);
432 if (tid <= 0)
433 continue;
434 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000435 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000436 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000437 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000438 tcp = alloctcb(tid);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700439 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000440 tcbtab[tcbi]->nchildren++;
441 tcbtab[tcbi]->nclone_threads++;
442 tcbtab[tcbi]->nclone_detached++;
443 tcp->parent = tcbtab[tcbi];
444 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000445 if (interactive) {
446 sigprocmask(SIG_SETMASK, &empty_set, NULL);
447 if (interrupted)
448 return;
449 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
450 }
Roland McGrath02203312007-06-11 22:06:31 +0000451 }
452 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000453 ntid -= nerr;
454 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000455 perror("attach: ptrace(PTRACE_ATTACH, ...)");
456 droptcb(tcp);
457 continue;
458 }
459 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000460 fprintf(stderr, ntid > 1
461? "Process %u attached with %u threads - interrupt to quit\n"
462: "Process %u attached - interrupt to quit\n",
463 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000464 }
465 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000466 } /* if (opendir worked) */
467 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000468# endif
469 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
470 perror("attach: ptrace(PTRACE_ATTACH, ...)");
471 droptcb(tcp);
472 continue;
473 }
474 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000475
476 if (daemonized_tracer) {
477 /*
478 * It is our grandparent we trace, not a -p PID.
479 * Don't want to just detach on exit, so...
480 */
481 tcp->flags &= ~TCB_ATTACHED;
482 /*
483 * Make parent go away.
484 * Also makes grandparent's wait() unblock.
485 */
486 kill(getppid(), SIGKILL);
487 }
488
Roland McGrath02203312007-06-11 22:06:31 +0000489#endif /* !USE_PROCFS */
490 if (!qflag)
491 fprintf(stderr,
492 "Process %u attached - interrupt to quit\n",
493 tcp->pid);
494 }
495
496 if (interactive)
497 sigprocmask(SIG_SETMASK, &empty_set, NULL);
498}
499
500static void
501startup_child (char **argv)
502{
503 struct stat statbuf;
504 const char *filename;
505 char pathname[MAXPATHLEN];
506 int pid = 0;
507 struct tcb *tcp;
508
509 filename = argv[0];
510 if (strchr(filename, '/')) {
511 if (strlen(filename) > sizeof pathname - 1) {
512 errno = ENAMETOOLONG;
513 perror("strace: exec");
514 exit(1);
515 }
516 strcpy(pathname, filename);
517 }
518#ifdef USE_DEBUGGING_EXEC
519 /*
520 * Debuggers customarily check the current directory
521 * first regardless of the path but doing that gives
522 * security geeks a panic attack.
523 */
524 else if (stat(filename, &statbuf) == 0)
525 strcpy(pathname, filename);
526#endif /* USE_DEBUGGING_EXEC */
527 else {
528 char *path;
529 int m, n, len;
530
531 for (path = getenv("PATH"); path && *path; path += m) {
532 if (strchr(path, ':')) {
533 n = strchr(path, ':') - path;
534 m = n + 1;
535 }
536 else
537 m = n = strlen(path);
538 if (n == 0) {
539 if (!getcwd(pathname, MAXPATHLEN))
540 continue;
541 len = strlen(pathname);
542 }
543 else if (n > sizeof pathname - 1)
544 continue;
545 else {
546 strncpy(pathname, path, n);
547 len = n;
548 }
549 if (len && pathname[len - 1] != '/')
550 pathname[len++] = '/';
551 strcpy(pathname + len, filename);
552 if (stat(pathname, &statbuf) == 0 &&
553 /* Accept only regular files
554 with some execute bits set.
555 XXX not perfect, might still fail */
556 S_ISREG(statbuf.st_mode) &&
557 (statbuf.st_mode & 0111))
558 break;
559 }
560 }
561 if (stat(pathname, &statbuf) < 0) {
562 fprintf(stderr, "%s: %s: command not found\n",
563 progname, filename);
564 exit(1);
565 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000566 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000567 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000568 perror("strace: fork");
569 cleanup();
570 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000571 }
572 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
573 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
574 ) {
575 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000576#ifdef USE_PROCFS
577 if (outf != stderr) close (fileno (outf));
578#ifdef MIPS
579 /* Kludge for SGI, see proc_open for details. */
580 sa.sa_handler = foobar;
581 sa.sa_flags = 0;
582 sigemptyset(&sa.sa_mask);
583 sigaction(SIGINT, &sa, NULL);
584#endif /* MIPS */
585#ifndef FREEBSD
586 pause();
587#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000588 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000589#endif /* FREEBSD */
590#else /* !USE_PROCFS */
591 if (outf!=stderr)
592 close(fileno (outf));
593
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000594 if (!daemonized_tracer) {
595 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
596 perror("strace: ptrace(PTRACE_TRACEME, ...)");
597 exit(1);
598 }
599 if (debug)
600 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000601 }
Roland McGrath02203312007-06-11 22:06:31 +0000602
603 if (username != NULL || geteuid() == 0) {
604 uid_t run_euid = run_uid;
605 gid_t run_egid = run_gid;
606
607 if (statbuf.st_mode & S_ISUID)
608 run_euid = statbuf.st_uid;
609 if (statbuf.st_mode & S_ISGID)
610 run_egid = statbuf.st_gid;
611
612 /*
613 * It is important to set groups before we
614 * lose privileges on setuid.
615 */
616 if (username != NULL) {
617 if (initgroups(username, run_gid) < 0) {
618 perror("initgroups");
619 exit(1);
620 }
621 if (setregid(run_gid, run_egid) < 0) {
622 perror("setregid");
623 exit(1);
624 }
625 if (setreuid(run_uid, run_euid) < 0) {
626 perror("setreuid");
627 exit(1);
628 }
629 }
630 }
631 else
632 setreuid(run_uid, run_uid);
633
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000634 if (!daemonized_tracer) {
635 /*
636 * Induce an immediate stop so that the parent
637 * will resume us with PTRACE_SYSCALL and display
638 * this execve call normally.
639 */
640 kill(getpid(), SIGSTOP);
641 } else {
642 struct sigaction sv_sigchld;
643 sigaction(SIGCHLD, NULL, &sv_sigchld);
644 /*
645 * Make sure it is not SIG_IGN, otherwise wait
646 * will not block.
647 */
648 signal(SIGCHLD, SIG_DFL);
649 /*
650 * Wait for grandchild to attach to us.
651 * It kills child after that, and wait() unblocks.
652 */
653 alarm(3);
654 wait(NULL);
655 alarm(0);
656 sigaction(SIGCHLD, &sv_sigchld, NULL);
657 }
Roland McGrath02203312007-06-11 22:06:31 +0000658#endif /* !USE_PROCFS */
659
660 execv(pathname, argv);
661 perror("strace: exec");
662 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000663 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000664
665 /* We are the tracer. */
666 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000667 if (daemonized_tracer) {
668 /* We want subsequent startup_attach() to attach to it. */
669 tcp->flags |= TCB_ATTACHED;
670 }
Roland McGrath02203312007-06-11 22:06:31 +0000671#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000672 if (proc_open(tcp, 0) < 0) {
673 fprintf(stderr, "trouble opening proc file\n");
674 cleanup();
675 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000676 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000678}
679
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000681main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000682{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683 struct tcb *tcp;
684 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000685 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000686 struct sigaction sa;
687
688 static char buf[BUFSIZ];
689
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000690 progname = argv[0] ? argv[0] : "strace";
691
Roland McGrathee9d4352002-12-18 04:16:10 +0000692 /* Allocate the initial tcbtab. */
693 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000694 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000695 fprintf(stderr, "%s: out of memory\n", progname);
696 exit(1);
697 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000698 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000699 fprintf(stderr, "%s: out of memory\n", progname);
700 exit(1);
701 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000702 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
703 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
704
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705 outf = stderr;
706 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000707 set_sortby(DEFAULT_SORTBY);
708 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000709 qualify("trace=all");
710 qualify("abbrev=all");
711 qualify("verbose=all");
712 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000713 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 "+cdfFhiqrtTvVxz"
715#ifndef USE_PROCFS
716 "D"
717#endif
718 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 switch (c) {
720 case 'c':
721 cflag++;
722 dtime++;
723 break;
724 case 'd':
725 debug++;
726 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000727#ifndef USE_PROCFS
728 /* Experimental, not documented in manpage yet. */
729 case 'D':
730 daemonized_tracer = 1;
731 break;
732#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000733 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000734 optF = 1;
735 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000736 case 'f':
737 followfork++;
738 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000739 case 'h':
740 usage(stdout, 0);
741 break;
742 case 'i':
743 iflag++;
744 break;
745 case 'q':
746 qflag++;
747 break;
748 case 'r':
749 rflag++;
750 tflag++;
751 break;
752 case 't':
753 tflag++;
754 break;
755 case 'T':
756 dtime++;
757 break;
758 case 'x':
759 xflag++;
760 break;
761 case 'v':
762 qualify("abbrev=none");
763 break;
764 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000765 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000766 exit(0);
767 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000768 case 'z':
769 not_failing_only = 1;
770 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000771 case 'a':
772 acolumn = atoi(optarg);
773 break;
774 case 'e':
775 qualify(optarg);
776 break;
777 case 'o':
778 outfname = strdup(optarg);
779 break;
780 case 'O':
781 set_overhead(atoi(optarg));
782 break;
783 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000784 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000785 fprintf(stderr, "%s: Invalid process id: %s\n",
786 progname, optarg);
787 break;
788 }
789 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000790 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791 break;
792 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000793 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 tcp->flags |= TCB_ATTACHED;
795 pflag_seen++;
796 break;
797 case 's':
798 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000799 if (max_strlen < 0) {
800 fprintf(stderr,
801 "%s: invalid -s argument: %s\n",
802 progname, optarg);
803 exit(1);
804 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805 break;
806 case 'S':
807 set_sortby(optarg);
808 break;
809 case 'u':
810 username = strdup(optarg);
811 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000812 case 'E':
813 if (putenv(optarg) < 0) {
814 fprintf(stderr, "%s: out of memory\n",
815 progname);
816 exit(1);
817 }
818 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000819 default:
820 usage(stderr, 1);
821 break;
822 }
823 }
824
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000825 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000826 usage(stderr, 1);
827
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000828 if (!followfork)
829 followfork = optF;
830
Roland McGrathcb9def62006-04-25 07:48:03 +0000831 if (followfork > 1 && cflag) {
832 fprintf(stderr,
833 "%s: -c and -ff are mutually exclusive options\n",
834 progname);
835 exit(1);
836 }
837
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000838 /* See if they want to run as another user. */
839 if (username != NULL) {
840 struct passwd *pent;
841
842 if (getuid() != 0 || geteuid() != 0) {
843 fprintf(stderr,
844 "%s: you must be root to use the -u option\n",
845 progname);
846 exit(1);
847 }
848 if ((pent = getpwnam(username)) == NULL) {
849 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000850 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000851 exit(1);
852 }
853 run_uid = pent->pw_uid;
854 run_gid = pent->pw_gid;
855 }
856 else {
857 run_uid = getuid();
858 run_gid = getgid();
859 }
860
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000861 /* Check if they want to redirect the output. */
862 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000863 /* See if they want to pipe the output. */
864 if (outfname[0] == '|' || outfname[0] == '!') {
865 /*
866 * We can't do the <outfname>.PID funny business
867 * when using popen, so prohibit it.
868 */
869 if (followfork > 1) {
870 fprintf(stderr, "\
871%s: piping the output and -ff are mutually exclusive options\n",
872 progname);
873 exit(1);
874 }
875
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000876 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000877 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000878 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000879 else if (followfork <= 1 &&
880 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 }
883
Roland McGrath37b9a662003-11-07 02:26:54 +0000884 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000886 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000887 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000889 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000890 /* Valid states here:
891 optind < argc pflag_seen outfname interactive
892 1 0 0 1
893 0 1 0 1
894 1 0 1 0
895 0 1 1 1
896 */
897
898 /* STARTUP_CHILD must be called before the signal handlers get
899 installed below as they are inherited into the spawned process.
900 Also we do not need to be protected by them as during interruption
901 in the STARTUP_CHILD mode we kill the spawned process anyway. */
902 if (!pflag_seen)
903 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000904
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905 sigemptyset(&empty_set);
906 sigemptyset(&blocked_set);
907 sa.sa_handler = SIG_IGN;
908 sigemptyset(&sa.sa_mask);
909 sa.sa_flags = 0;
910 sigaction(SIGTTOU, &sa, NULL);
911 sigaction(SIGTTIN, &sa, NULL);
912 if (interactive) {
913 sigaddset(&blocked_set, SIGHUP);
914 sigaddset(&blocked_set, SIGINT);
915 sigaddset(&blocked_set, SIGQUIT);
916 sigaddset(&blocked_set, SIGPIPE);
917 sigaddset(&blocked_set, SIGTERM);
918 sa.sa_handler = interrupt;
919#ifdef SUNOS4
920 /* POSIX signals on sunos4.1 are a little broken. */
921 sa.sa_flags = SA_INTERRUPT;
922#endif /* SUNOS4 */
923 }
924 sigaction(SIGHUP, &sa, NULL);
925 sigaction(SIGINT, &sa, NULL);
926 sigaction(SIGQUIT, &sa, NULL);
927 sigaction(SIGPIPE, &sa, NULL);
928 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000929#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000930 sa.sa_handler = reaper;
931 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000932#else
933 /* Make sure SIGCHLD has the default action so that waitpid
934 definitely works without losing track of children. The user
935 should not have given us a bogus state to inherit, but he might
936 have. Arguably we should detect SIG_IGN here and pass it on
937 to children, but probably noone really needs that. */
938 sa.sa_handler = SIG_DFL;
939 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000940#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000942 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000943 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000944
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 if (trace() < 0)
946 exit(1);
947 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000948 fflush(NULL);
949 if (exit_code > 0xff) {
950 /* Child was killed by a signal, mimic that. */
951 exit_code &= 0xff;
952 signal(exit_code, SIG_DFL);
953 raise(exit_code);
954 /* Paranoia - what if this signal is not fatal?
955 Exit with 128 + signo then. */
956 exit_code += 128;
957 }
958 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000959}
960
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000961void
962expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000963{
964 /* Allocate some more TCBs and expand the table.
965 We don't want to relocate the TCBs because our
966 callers have pointers and it would be a pain.
967 So tcbtab is a table of pointers. Since we never
968 free the TCBs, we allocate a single chunk of many. */
969 struct tcb **newtab = (struct tcb **)
970 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
971 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
972 sizeof *newtcbs);
973 int i;
974 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000975 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
976 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000977 cleanup();
978 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000979 }
980 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
981 newtab[i] = &newtcbs[i - tcbtabsize];
982 tcbtabsize *= 2;
983 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000984}
985
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000987alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988{
989 int i;
990 struct tcb *tcp;
991
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000992 if (nprocs == tcbtabsize)
993 expand_tcbtab();
994
Roland McGrathee9d4352002-12-18 04:16:10 +0000995 for (i = 0; i < tcbtabsize; i++) {
996 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997 if ((tcp->flags & TCB_INUSE) == 0) {
998 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700999 tcp->parent = NULL;
1000 tcp->nchildren = 0;
1001 tcp->nzombies = 0;
1002#ifdef TCB_CLONE_THREAD
1003 tcp->nclone_threads = tcp->nclone_detached = 0;
1004 tcp->nclone_waiting = 0;
1005#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 tcp->flags = TCB_INUSE | TCB_STARTUP;
1007 tcp->outf = outf; /* Initialise to current out file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001008 tcp->stime.tv_sec = 0;
1009 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010 tcp->pfd = -1;
1011 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001012 if (command_options_parsed)
1013 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 return tcp;
1015 }
1016 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001017 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1018 cleanup();
1019 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001020}
1021
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001022#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001024proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025{
1026 char proc[32];
1027 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001028#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001029 int i;
1030 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 sigset_t signals;
1032 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001033#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034#ifndef HAVE_POLLABLE_PROCFS
1035 static int last_pfd;
1036#endif
1037
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001038#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001039 /* Open the process pseudo-files in /proc. */
1040 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1041 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 perror("strace: open(\"/proc/...\", ...)");
1043 return -1;
1044 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001045 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 return -1;
1047 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001048 sprintf(proc, "/proc/%d/status", tcp->pid);
1049 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1050 perror("strace: open(\"/proc/...\", ...)");
1051 return -1;
1052 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001053 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001054 return -1;
1055 }
1056 sprintf(proc, "/proc/%d/as", tcp->pid);
1057 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1058 perror("strace: open(\"/proc/...\", ...)");
1059 return -1;
1060 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001061 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001062 return -1;
1063 }
1064#else
1065 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001066#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001067 sprintf(proc, "/proc/%d", tcp->pid);
1068 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001069#else /* FREEBSD */
1070 sprintf(proc, "/proc/%d/mem", tcp->pid);
1071 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1072#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001073 perror("strace: open(\"/proc/...\", ...)");
1074 return -1;
1075 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001076 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001077 return -1;
1078 }
1079#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001080#ifdef FREEBSD
1081 sprintf(proc, "/proc/%d/regs", tcp->pid);
1082 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1083 perror("strace: open(\"/proc/.../regs\", ...)");
1084 return -1;
1085 }
1086 if (cflag) {
1087 sprintf(proc, "/proc/%d/status", tcp->pid);
1088 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1089 perror("strace: open(\"/proc/.../status\", ...)");
1090 return -1;
1091 }
1092 } else
1093 tcp->pfd_status = -1;
1094#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001095 rebuild_pollv();
1096 if (!attaching) {
1097 /*
1098 * Wait for the child to pause. Because of a race
1099 * condition we have to poll for the event.
1100 */
1101 for (;;) {
1102 if (IOCTL_STATUS (tcp) < 0) {
1103 perror("strace: PIOCSTATUS");
1104 return -1;
1105 }
1106 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001107 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001108 }
1109 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001110#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001111 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001112 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001113 perror("strace: PIOCSTOP");
1114 return -1;
1115 }
Roland McGrath553a6092002-12-16 20:40:39 +00001116#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117#ifdef PIOCSET
1118 /* Set Run-on-Last-Close. */
1119 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001120 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121 perror("PIOCSET PR_RLC");
1122 return -1;
1123 }
1124 /* Set or Reset Inherit-on-Fork. */
1125 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001126 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001127 perror("PIOC{SET,RESET} PR_FORK");
1128 return -1;
1129 }
1130#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001131#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1133 perror("PIOCSRLC");
1134 return -1;
1135 }
1136 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1137 perror("PIOC{S,R}FORK");
1138 return -1;
1139 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001140#else /* FREEBSD */
1141 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1142 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1143 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001144 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001145 }
1146 arg &= ~PF_LINGER;
1147 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001148 perror("PIOCSFL");
1149 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001150 }
1151#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001153#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001154 /* Enable all syscall entries we care about. */
1155 premptyset(&syscalls);
1156 for (i = 1; i < MAX_QUALS; ++i) {
1157 if (i > (sizeof syscalls) * CHAR_BIT) break;
1158 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1159 }
1160 praddset (&syscalls, SYS_execve);
1161 if (followfork) {
1162 praddset (&syscalls, SYS_fork);
1163#ifdef SYS_forkall
1164 praddset (&syscalls, SYS_forkall);
1165#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001166#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001167 praddset (&syscalls, SYS_fork1);
1168#endif
1169#ifdef SYS_rfork1
1170 praddset (&syscalls, SYS_rfork1);
1171#endif
1172#ifdef SYS_rforkall
1173 praddset (&syscalls, SYS_rforkall);
1174#endif
1175 }
1176 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 perror("PIOCSENTRY");
1178 return -1;
1179 }
John Hughes19e49982001-10-19 08:59:12 +00001180 /* Enable the syscall exits. */
1181 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 perror("PIOSEXIT");
1183 return -1;
1184 }
John Hughes19e49982001-10-19 08:59:12 +00001185 /* Enable signals we care about. */
1186 premptyset(&signals);
1187 for (i = 1; i < MAX_QUALS; ++i) {
1188 if (i > (sizeof signals) * CHAR_BIT) break;
1189 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1190 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001191 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192 perror("PIOCSTRACE");
1193 return -1;
1194 }
John Hughes19e49982001-10-19 08:59:12 +00001195 /* Enable faults we care about */
1196 premptyset(&faults);
1197 for (i = 1; i < MAX_QUALS; ++i) {
1198 if (i > (sizeof faults) * CHAR_BIT) break;
1199 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1200 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001201 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 perror("PIOCSFAULT");
1203 return -1;
1204 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001205#else /* FREEBSD */
1206 /* set events flags. */
1207 arg = S_SIG | S_SCE | S_SCX ;
1208 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1209 perror("PIOCBIS");
1210 return -1;
1211 }
1212#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213 if (!attaching) {
1214#ifdef MIPS
1215 /*
1216 * The SGI PRSABORT doesn't work for pause() so
1217 * we send it a caught signal to wake it up.
1218 */
1219 kill(tcp->pid, SIGINT);
1220#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001221#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001223 arg = PRSABORT;
1224 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225 perror("PIOCRUN");
1226 return -1;
1227 }
Roland McGrath553a6092002-12-16 20:40:39 +00001228#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001229#endif /* !MIPS*/
1230#ifdef FREEBSD
1231 /* wake up the child if it received the SIGSTOP */
1232 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001233#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234 for (;;) {
1235 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001236 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237 perror("PIOCWSTOP");
1238 return -1;
1239 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001240 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001241 tcp->flags &= ~TCB_INSYSCALL;
1242 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001243 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244 break;
1245 }
1246 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001247#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001248 arg = 0;
1249 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001250#else /* FREEBSD */
1251 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001252#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 perror("PIOCRUN");
1254 return -1;
1255 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001256#ifdef FREEBSD
1257 /* handle the case where we "opened" the child before
1258 it did the kill -STOP */
1259 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1260 tcp->status.PR_WHAT == SIGSTOP)
1261 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001262#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001264#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001266#else /* FREEBSD */
1267 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001268 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001269 /* We are attaching to an already running process.
1270 * Try to figure out the state of the process in syscalls,
1271 * to handle the first event well.
1272 * This is done by having a look at the "wchan" property of the
1273 * process, which tells where it is stopped (if it is). */
1274 FILE * status;
1275 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001276
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001277 sprintf(proc, "/proc/%d/status", tcp->pid);
1278 status = fopen(proc, "r");
1279 if (status &&
1280 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1281 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1282 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1283 strcmp(wchan, "stopevent")) {
1284 /* The process is asleep in the middle of a syscall.
1285 Fake the syscall entry event */
1286 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1287 tcp->status.PR_WHY = PR_SYSENTRY;
1288 trace_syscall(tcp);
1289 }
1290 if (status)
1291 fclose(status);
1292 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001293 }
1294#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295#ifndef HAVE_POLLABLE_PROCFS
1296 if (proc_poll_pipe[0] != -1)
1297 proc_poller(tcp->pfd);
1298 else if (nprocs > 1) {
1299 proc_poll_open();
1300 proc_poller(last_pfd);
1301 proc_poller(tcp->pfd);
1302 }
1303 last_pfd = tcp->pfd;
1304#endif /* !HAVE_POLLABLE_PROCFS */
1305 return 0;
1306}
1307
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001308#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001310struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311pid2tcb(pid)
1312int pid;
1313{
1314 int i;
1315 struct tcb *tcp;
1316
Roland McGrathee9d4352002-12-18 04:16:10 +00001317 for (i = 0; i < tcbtabsize; i++) {
1318 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 if (pid && tcp->pid != pid)
1320 continue;
1321 if (tcp->flags & TCB_INUSE)
1322 return tcp;
1323 }
1324 return NULL;
1325}
1326
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001327#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328
1329static struct tcb *
1330pfd2tcb(pfd)
1331int pfd;
1332{
1333 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334
Roland McGrathca16be82003-01-10 19:55:28 +00001335 for (i = 0; i < tcbtabsize; i++) {
1336 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337 if (tcp->pfd != pfd)
1338 continue;
1339 if (tcp->flags & TCB_INUSE)
1340 return tcp;
1341 }
1342 return NULL;
1343}
1344
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001345#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346
1347void
1348droptcb(tcp)
1349struct tcb *tcp;
1350{
1351 if (tcp->pid == 0)
1352 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001353#ifdef TCB_CLONE_THREAD
1354 if (tcp->nclone_threads > 0) {
1355 /* There are other threads left in this process, but this
1356 is the one whose PID represents the whole process.
1357 We need to keep this record around as a zombie until
1358 all the threads die. */
1359 tcp->flags |= TCB_EXITING;
1360 return;
1361 }
1362#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 nprocs--;
1364 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001365
Roland McGrathe29341c2003-01-10 20:14:20 +00001366 if (tcp->parent != NULL) {
1367 tcp->parent->nchildren--;
1368#ifdef TCB_CLONE_THREAD
1369 if (tcp->flags & TCB_CLONE_DETACHED)
1370 tcp->parent->nclone_detached--;
1371 if (tcp->flags & TCB_CLONE_THREAD)
1372 tcp->parent->nclone_threads--;
1373#endif
Roland McGrath09623452003-05-23 02:27:13 +00001374#ifdef TCB_CLONE_DETACHED
1375 if (!(tcp->flags & TCB_CLONE_DETACHED))
1376#endif
1377 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001378#ifdef LINUX
1379 /* Update `tcp->parent->parent->nchildren' and the other fields
1380 like NCLONE_DETACHED, only for zombie group leader that has
1381 already reported and been short-circuited at the top of this
1382 function. The same condition as at the top of DETACH. */
1383 if ((tcp->flags & TCB_CLONE_THREAD) &&
1384 tcp->parent->nclone_threads == 0 &&
1385 (tcp->parent->flags & TCB_EXITING))
1386 droptcb(tcp->parent);
1387#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001388 tcp->parent = NULL;
1389 }
1390
1391 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392 if (tcp->pfd != -1) {
1393 close(tcp->pfd);
1394 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001395#ifdef FREEBSD
1396 if (tcp->pfd_reg != -1) {
1397 close(tcp->pfd_reg);
1398 tcp->pfd_reg = -1;
1399 }
1400 if (tcp->pfd_status != -1) {
1401 close(tcp->pfd_status);
1402 tcp->pfd_status = -1;
1403 }
Roland McGrath553a6092002-12-16 20:40:39 +00001404#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001405#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001406 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407#endif
1408 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001409
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001410 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001412
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001413 tcp->outf = 0;
1414}
1415
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001416#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417
1418static int
1419resume(tcp)
1420struct tcb *tcp;
1421{
1422 if (tcp == NULL)
1423 return -1;
1424
1425 if (!(tcp->flags & TCB_SUSPENDED)) {
1426 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1427 return -1;
1428 }
1429 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001430#ifdef TCB_CLONE_THREAD
1431 if (tcp->flags & TCB_CLONE_THREAD)
1432 tcp->parent->nclone_waiting--;
1433#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001434
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001435 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437
1438 if (!qflag)
1439 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1440 return 0;
1441}
1442
Roland McGrath1bfd3102007-08-03 10:02:00 +00001443static int
1444resume_from_tcp (struct tcb *tcp)
1445{
1446 int error = 0;
1447 int resumed = 0;
1448
1449 /* XXX This won't always be quite right (but it never was).
1450 A waiter with argument 0 or < -1 is waiting for any pid in
1451 a particular pgrp, which this child might or might not be
1452 in. The waiter will only wake up if it's argument is -1
1453 or if it's waiting for tcp->pid's pgrp. It makes a
1454 difference to wake up a waiter when there might be more
1455 traced children, because it could get a false ECHILD
1456 error. OTOH, if this was the last child in the pgrp, then
1457 it ought to wake up and get ECHILD. We would have to
1458 search the system for all pid's in the pgrp to be sure.
1459
1460 && (t->waitpid == -1 ||
1461 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1462 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1463 */
1464
1465 if (tcp->parent &&
1466 (tcp->parent->flags & TCB_SUSPENDED) &&
1467 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001468 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001469 ++resumed;
1470 }
1471#ifdef TCB_CLONE_THREAD
1472 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1473 /* Some other threads of our parent are waiting too. */
1474 unsigned int i;
1475
1476 /* Resume all the threads that were waiting for this PID. */
1477 for (i = 0; i < tcbtabsize; i++) {
1478 struct tcb *t = tcbtab[i];
1479 if (t->parent == tcp->parent && t != tcp
1480 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1481 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1482 && t->waitpid == tcp->pid) {
1483 error |= resume (t);
1484 ++resumed;
1485 }
1486 }
1487 if (resumed == 0)
1488 /* Noone was waiting for this PID in particular,
1489 so now we might need to resume some wildcarders. */
1490 for (i = 0; i < tcbtabsize; i++) {
1491 struct tcb *t = tcbtab[i];
1492 if (t->parent == tcp->parent && t != tcp
1493 && ((t->flags
1494 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1495 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1496 && t->waitpid <= 0
1497 ) {
1498 error |= resume (t);
1499 break;
1500 }
1501 }
1502 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001503#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001504
1505 return error;
1506}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001507
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001508#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509
Roland McGrath0a463882007-07-05 18:43:16 +00001510/* detach traced process; continue with sig
1511 Never call DETACH twice on the same process as both unattached and
1512 attached-unstopped processes give the same ESRCH. For unattached process we
1513 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001514
1515static int
1516detach(tcp, sig)
1517struct tcb *tcp;
1518int sig;
1519{
1520 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001521#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001522 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001523 struct tcb *zombie = NULL;
1524
1525 /* If the group leader is lingering only because of this other
1526 thread now dying, then detach the leader as well. */
1527 if ((tcp->flags & TCB_CLONE_THREAD) &&
1528 tcp->parent->nclone_threads == 1 &&
1529 (tcp->parent->flags & TCB_EXITING))
1530 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001531#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532
1533 if (tcp->flags & TCB_BPTSET)
1534 sig = SIGKILL;
1535
1536#ifdef LINUX
1537 /*
1538 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001539 * before detaching. Arghh. We go through hoops
1540 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001542#if defined(SPARC)
1543#undef PTRACE_DETACH
1544#define PTRACE_DETACH PTRACE_SUNDETACH
1545#endif
Roland McGrath02203312007-06-11 22:06:31 +00001546 /*
1547 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1548 * expected SIGSTOP. We must catch exactly one as otherwise the
1549 * detached process would be left stopped (process state T).
1550 */
1551 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1553 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001554 }
1555 else if (errno != ESRCH) {
1556 /* Shouldn't happen. */
1557 perror("detach: ptrace(PTRACE_DETACH, ...)");
1558 }
Roland McGrath134813a2007-06-02 00:07:33 +00001559 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1560 : tcp->pid),
1561 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001562 if (errno != ESRCH)
1563 perror("detach: checking sanity");
1564 }
Roland McGrath02203312007-06-11 22:06:31 +00001565 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1566 ? tcp->parent->pid : tcp->pid),
1567 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001568 if (errno != ESRCH)
1569 perror("detach: stopping child");
1570 }
Roland McGrath02203312007-06-11 22:06:31 +00001571 else
1572 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001573 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001575#ifdef __WALL
1576 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1577 if (errno == ECHILD) /* Already gone. */
1578 break;
1579 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001580 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001581 break;
1582 }
1583#endif /* __WALL */
1584 /* No __WALL here. */
1585 if (waitpid(tcp->pid, &status, 0) < 0) {
1586 if (errno != ECHILD) {
1587 perror("detach: waiting");
1588 break;
1589 }
1590#ifdef __WCLONE
1591 /* If no processes, try clones. */
1592 if (wait4(tcp->pid, &status, __WCLONE,
1593 NULL) < 0) {
1594 if (errno != ECHILD)
1595 perror("detach: waiting");
1596 break;
1597 }
1598#endif /* __WCLONE */
1599 }
1600#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001601 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001602#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603 if (!WIFSTOPPED(status)) {
1604 /* Au revoir, mon ami. */
1605 break;
1606 }
1607 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001608 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609 break;
1610 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001611 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001612 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001613 : WSTOPSIG(status));
1614 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001617 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001618#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619
1620#if defined(SUNOS4)
1621 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1622 if (sig && kill(tcp->pid, sig) < 0)
1623 perror("detach: kill");
1624 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001625 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626#endif /* SUNOS4 */
1627
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001628#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001629 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001630#endif
1631
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632 if (!qflag)
1633 fprintf(stderr, "Process %u detached\n", tcp->pid);
1634
1635 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001636
1637#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001638 if (zombie != NULL) {
1639 /* TCP no longer exists therefore you must not detach () it. */
1640 droptcb(zombie);
1641 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001642#endif
1643
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644 return error;
1645}
1646
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001647#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648
1649static void
1650reaper(sig)
1651int sig;
1652{
1653 int pid;
1654 int status;
1655
1656 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1657#if 0
1658 struct tcb *tcp;
1659
1660 tcp = pid2tcb(pid);
1661 if (tcp)
1662 droptcb(tcp);
1663#endif
1664 }
1665}
1666
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001667#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668
1669static void
1670cleanup()
1671{
1672 int i;
1673 struct tcb *tcp;
1674
Roland McGrathee9d4352002-12-18 04:16:10 +00001675 for (i = 0; i < tcbtabsize; i++) {
1676 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 if (!(tcp->flags & TCB_INUSE))
1678 continue;
1679 if (debug)
1680 fprintf(stderr,
1681 "cleanup: looking at pid %u\n", tcp->pid);
1682 if (tcp_last &&
1683 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001684 tprintf(" <unfinished ...>");
1685 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686 }
1687 if (tcp->flags & TCB_ATTACHED)
1688 detach(tcp, 0);
1689 else {
1690 kill(tcp->pid, SIGCONT);
1691 kill(tcp->pid, SIGTERM);
1692 }
1693 }
1694 if (cflag)
1695 call_summary(outf);
1696}
1697
1698static void
1699interrupt(sig)
1700int sig;
1701{
1702 interrupted = 1;
1703}
1704
1705#ifndef HAVE_STRERROR
1706
Roland McGrath6d2b3492002-12-30 00:51:30 +00001707#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708extern int sys_nerr;
1709extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001710#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711
1712const char *
1713strerror(errno)
1714int errno;
1715{
1716 static char buf[64];
1717
1718 if (errno < 1 || errno >= sys_nerr) {
1719 sprintf(buf, "Unknown error %d", errno);
1720 return buf;
1721 }
1722 return sys_errlist[errno];
1723}
1724
1725#endif /* HAVE_STERRROR */
1726
1727#ifndef HAVE_STRSIGNAL
1728
Roland McGrath8f474e02003-01-14 07:53:33 +00001729#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001730extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001732#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1733extern char *_sys_siglist[];
1734#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735
1736const char *
1737strsignal(sig)
1738int sig;
1739{
1740 static char buf[64];
1741
1742 if (sig < 1 || sig >= NSIG) {
1743 sprintf(buf, "Unknown signal %d", sig);
1744 return buf;
1745 }
1746#ifdef HAVE__SYS_SIGLIST
1747 return _sys_siglist[sig];
1748#else
1749 return sys_siglist[sig];
1750#endif
1751}
1752
1753#endif /* HAVE_STRSIGNAL */
1754
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001755#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756
1757static void
1758rebuild_pollv()
1759{
1760 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761
Roland McGrathee9d4352002-12-18 04:16:10 +00001762 if (pollv != NULL)
1763 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001764 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001765 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001766 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001767 exit(1);
1768 }
1769
Roland McGrathca16be82003-01-10 19:55:28 +00001770 for (i = j = 0; i < tcbtabsize; i++) {
1771 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 if (!(tcp->flags & TCB_INUSE))
1773 continue;
1774 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001775 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 j++;
1777 }
1778 if (j != nprocs) {
1779 fprintf(stderr, "strace: proc miscount\n");
1780 exit(1);
1781 }
1782}
1783
1784#ifndef HAVE_POLLABLE_PROCFS
1785
1786static void
1787proc_poll_open()
1788{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789 int i;
1790
1791 if (pipe(proc_poll_pipe) < 0) {
1792 perror("pipe");
1793 exit(1);
1794 }
1795 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001796 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 exit(1);
1798 }
1799 }
1800}
1801
1802static int
1803proc_poll(pollv, nfds, timeout)
1804struct pollfd *pollv;
1805int nfds;
1806int timeout;
1807{
1808 int i;
1809 int n;
1810 struct proc_pollfd pollinfo;
1811
1812 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1813 return n;
1814 if (n != sizeof(struct proc_pollfd)) {
1815 fprintf(stderr, "panic: short read: %d\n", n);
1816 exit(1);
1817 }
1818 for (i = 0; i < nprocs; i++) {
1819 if (pollv[i].fd == pollinfo.fd)
1820 pollv[i].revents = pollinfo.revents;
1821 else
1822 pollv[i].revents = 0;
1823 }
1824 poller_pid = pollinfo.pid;
1825 return 1;
1826}
1827
1828static void
1829wakeup_handler(sig)
1830int sig;
1831{
1832}
1833
1834static void
1835proc_poller(pfd)
1836int pfd;
1837{
1838 struct proc_pollfd pollinfo;
1839 struct sigaction sa;
1840 sigset_t blocked_set, empty_set;
1841 int i;
1842 int n;
1843 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001844#ifdef FREEBSD
1845 struct procfs_status pfs;
1846#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847
1848 switch (fork()) {
1849 case -1:
1850 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001851 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852 case 0:
1853 break;
1854 default:
1855 return;
1856 }
1857
1858 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1859 sa.sa_flags = 0;
1860 sigemptyset(&sa.sa_mask);
1861 sigaction(SIGHUP, &sa, NULL);
1862 sigaction(SIGINT, &sa, NULL);
1863 sigaction(SIGQUIT, &sa, NULL);
1864 sigaction(SIGPIPE, &sa, NULL);
1865 sigaction(SIGTERM, &sa, NULL);
1866 sa.sa_handler = wakeup_handler;
1867 sigaction(SIGUSR1, &sa, NULL);
1868 sigemptyset(&blocked_set);
1869 sigaddset(&blocked_set, SIGUSR1);
1870 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1871 sigemptyset(&empty_set);
1872
1873 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1874 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001875 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876 }
1877 n = rl.rlim_cur;
1878 for (i = 0; i < n; i++) {
1879 if (i != pfd && i != proc_poll_pipe[1])
1880 close(i);
1881 }
1882
1883 pollinfo.fd = pfd;
1884 pollinfo.pid = getpid();
1885 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001886#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001887 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1888#else
1889 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1890#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001891 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001892 switch (errno) {
1893 case EINTR:
1894 continue;
1895 case EBADF:
1896 pollinfo.revents = POLLERR;
1897 break;
1898 case ENOENT:
1899 pollinfo.revents = POLLHUP;
1900 break;
1901 default:
1902 perror("proc_poller: PIOCWSTOP");
1903 }
1904 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1905 _exit(0);
1906 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001907 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001908 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1909 sigsuspend(&empty_set);
1910 }
1911}
1912
1913#endif /* !HAVE_POLLABLE_PROCFS */
1914
1915static int
1916choose_pfd()
1917{
1918 int i, j;
1919 struct tcb *tcp;
1920
1921 static int last;
1922
1923 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001924 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001925 /*
1926 * The previous process is ready to run again. We'll
1927 * let it do so if it is currently in a syscall. This
1928 * heuristic improves the readability of the trace.
1929 */
1930 tcp = pfd2tcb(pollv[last].fd);
1931 if (tcp && (tcp->flags & TCB_INSYSCALL))
1932 return pollv[last].fd;
1933 }
1934
1935 for (i = 0; i < nprocs; i++) {
1936 /* Let competing children run round robin. */
1937 j = (i + last + 1) % nprocs;
1938 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1939 tcp = pfd2tcb(pollv[j].fd);
1940 if (!tcp) {
1941 fprintf(stderr, "strace: lost proc\n");
1942 exit(1);
1943 }
1944 droptcb(tcp);
1945 return -1;
1946 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001947 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948 last = j;
1949 return pollv[j].fd;
1950 }
1951 }
1952 fprintf(stderr, "strace: nothing ready\n");
1953 exit(1);
1954}
1955
1956static int
1957trace()
1958{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001959#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001960 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001961#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962 struct tcb *tcp;
1963 int pfd;
1964 int what;
1965 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001966 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001967
1968 for (;;) {
1969 if (interactive)
1970 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1971
1972 if (nprocs == 0)
1973 break;
1974
1975 switch (nprocs) {
1976 case 1:
1977#ifndef HAVE_POLLABLE_PROCFS
1978 if (proc_poll_pipe[0] == -1) {
1979#endif
1980 tcp = pid2tcb(0);
1981 if (!tcp)
1982 continue;
1983 pfd = tcp->pfd;
1984 if (pfd == -1)
1985 continue;
1986 break;
1987#ifndef HAVE_POLLABLE_PROCFS
1988 }
1989 /* fall through ... */
1990#endif /* !HAVE_POLLABLE_PROCFS */
1991 default:
1992#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001993#ifdef POLL_HACK
1994 /* On some systems (e.g. UnixWare) we get too much ugly
1995 "unfinished..." stuff when multiple proceses are in
1996 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001997
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001998 if (in_syscall) {
1999 struct pollfd pv;
2000 tcp = in_syscall;
2001 in_syscall = NULL;
2002 pv.fd = tcp->pfd;
2003 pv.events = POLLWANT;
2004 if ((what = poll (&pv, 1, 1)) < 0) {
2005 if (interrupted)
2006 return 0;
2007 continue;
2008 }
2009 else if (what == 1 && pv.revents & POLLWANT) {
2010 goto FOUND;
2011 }
2012 }
2013#endif
2014
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 if (poll(pollv, nprocs, INFTIM) < 0) {
2016 if (interrupted)
2017 return 0;
2018 continue;
2019 }
2020#else /* !HAVE_POLLABLE_PROCFS */
2021 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2022 if (interrupted)
2023 return 0;
2024 continue;
2025 }
2026#endif /* !HAVE_POLLABLE_PROCFS */
2027 pfd = choose_pfd();
2028 if (pfd == -1)
2029 continue;
2030 break;
2031 }
2032
2033 /* Look up `pfd' in our table. */
2034 if ((tcp = pfd2tcb(pfd)) == NULL) {
2035 fprintf(stderr, "unknown pfd: %u\n", pfd);
2036 exit(1);
2037 }
John Hughesb6643082002-05-23 11:02:22 +00002038#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002039 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002040#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041 /* Get the status of the process. */
2042 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002043#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002044 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002045#else /* FREEBSD */
2046 /* Thanks to some scheduling mystery, the first poller
2047 sometimes waits for the already processed end of fork
2048 event. Doing a non blocking poll here solves the problem. */
2049 if (proc_poll_pipe[0] != -1)
2050 ioctl_result = IOCTL_STATUS (tcp);
2051 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002052 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002053#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054 ioctl_errno = errno;
2055#ifndef HAVE_POLLABLE_PROCFS
2056 if (proc_poll_pipe[0] != -1) {
2057 if (ioctl_result < 0)
2058 kill(poller_pid, SIGKILL);
2059 else
2060 kill(poller_pid, SIGUSR1);
2061 }
2062#endif /* !HAVE_POLLABLE_PROCFS */
2063 }
2064 if (interrupted)
2065 return 0;
2066
2067 if (interactive)
2068 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2069
2070 if (ioctl_result < 0) {
2071 /* Find out what happened if it failed. */
2072 switch (ioctl_errno) {
2073 case EINTR:
2074 case EBADF:
2075 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002076#ifdef FREEBSD
2077 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002078#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079 case ENOENT:
2080 droptcb(tcp);
2081 continue;
2082 default:
2083 perror("PIOCWSTOP");
2084 exit(1);
2085 }
2086 }
2087
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002088#ifdef FREEBSD
2089 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2090 /* discard first event for a syscall we never entered */
2091 IOCTL (tcp->pfd, PIOCRUN, 0);
2092 continue;
2093 }
Roland McGrath553a6092002-12-16 20:40:39 +00002094#endif
2095
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002096 /* clear the just started flag */
2097 tcp->flags &= ~TCB_STARTUP;
2098
2099 /* set current output file */
2100 outf = tcp->outf;
2101
2102 if (cflag) {
2103 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002104#ifdef FREEBSD
2105 char buf[1024];
2106 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002108 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2109 buf[len] = '\0';
2110 sscanf(buf,
2111 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2112 &stime.tv_sec, &stime.tv_usec);
2113 } else
2114 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002115#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2117 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002118#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002119 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2120 tcp->stime = stime;
2121 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002122 what = tcp->status.PR_WHAT;
2123 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002124#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002125 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002126 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2127 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 if (trace_syscall(tcp) < 0) {
2129 fprintf(stderr, "syscall trouble\n");
2130 exit(1);
2131 }
2132 }
2133 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002134#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002135 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002136#ifdef POLL_HACK
2137 in_syscall = tcp;
2138#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 case PR_SYSEXIT:
2140 if (trace_syscall(tcp) < 0) {
2141 fprintf(stderr, "syscall trouble\n");
2142 exit(1);
2143 }
2144 break;
2145 case PR_SIGNALLED:
2146 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2147 printleader(tcp);
2148 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002149 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002150 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002151#ifdef PR_INFO
2152 if (tcp->status.PR_INFO.si_signo == what) {
2153 printleader(tcp);
2154 tprintf(" siginfo=");
2155 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002156 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002157 }
2158#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002159 }
2160 break;
2161 case PR_FAULTED:
2162 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2163 printleader(tcp);
2164 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002165 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002166 }
2167 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002168#ifdef FREEBSD
2169 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002170 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002171#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002172 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002173 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002174 exit(1);
2175 break;
2176 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002177 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002178#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002179 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002180#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002181 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002182#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002183 perror("PIOCRUN");
2184 exit(1);
2185 }
2186 }
2187 return 0;
2188}
2189
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002190#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002191
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002192#ifdef TCB_GROUP_EXITING
2193/* Handle an exit detach or death signal that is taking all the
2194 related clone threads with it. This is called in three circumstances:
2195 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2196 SIG == 0 Continuing TCP will perform an exit_group syscall.
2197 SIG == other Continuing TCP with SIG will kill the process.
2198*/
2199static int
2200handle_group_exit(struct tcb *tcp, int sig)
2201{
2202 /* We need to locate our records of all the clone threads
2203 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002204 struct tcb *leader = NULL;
2205
2206 if (tcp->flags & TCB_CLONE_THREAD)
2207 leader = tcp->parent;
2208 else if (tcp->nclone_detached > 0)
2209 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002210
2211 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002212 if (leader != NULL && leader != tcp
2213 && !(leader->flags & TCB_GROUP_EXITING)
2214 && !(tcp->flags & TCB_STARTUP)
2215 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002216 fprintf(stderr,
2217 "PANIC: handle_group_exit: %d leader %d\n",
2218 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002219 }
2220 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002221#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002222 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002223#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002224 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002225 }
2226 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002227 /* Mark that we are taking the process down. */
2228 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002229 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002230 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002231 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002232 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002233 } else {
2234 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2235 cleanup();
2236 return -1;
2237 }
2238 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002239 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002240 if (leader != tcp)
2241 droptcb(tcp);
2242 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002243 /* The leader will report to us as parent now,
2244 and then we'll get to the SIG==-1 case. */
2245 return 0;
2246 }
2247 }
2248
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002249 return 0;
2250}
2251#endif
2252
Roland McGratheb9e2e82009-06-02 16:49:22 -07002253static int
2254trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002255{
2256 int pid;
2257 int wait_errno;
2258 int status;
2259 struct tcb *tcp;
2260#ifdef LINUX
2261 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002262#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002263 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002264#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265#endif /* LINUX */
2266
Roland McGratheb9e2e82009-06-02 16:49:22 -07002267 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002268 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002269 return 0;
2270 if (interactive)
2271 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002272#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002273#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002274 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002275 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002276 /* this kernel does not support __WALL */
2277 wait4_options &= ~__WALL;
2278 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002279 pid = wait4(-1, &status, wait4_options,
2280 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002281 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002282 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002283 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002284 pid = wait4(-1, &status, __WCLONE,
2285 cflag ? &ru : NULL);
2286 if (pid == -1) {
2287 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002288 "failed: %s\n", strerror(errno));
2289 }
2290 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002291#else
2292 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2293#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294#endif /* LINUX */
2295#ifdef SUNOS4
2296 pid = wait(&status);
2297#endif /* SUNOS4 */
2298 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002299 if (interactive)
2300 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002301
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002302 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002303 switch (wait_errno) {
2304 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002306 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002307 /*
2308 * We would like to verify this case
2309 * but sometimes a race in Solbourne's
2310 * version of SunOS sometimes reports
2311 * ECHILD before sending us SIGCHILD.
2312 */
2313#if 0
Roland McGratheb9e2e82009-06-02 16:49:22 -07002314 if (nprocs == 0)
2315 return 0;
2316 fprintf(stderr, "strace: proc miscount\n");
2317 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002318#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002319 return 0;
2320 default:
2321 errno = wait_errno;
2322 perror("strace: wait");
2323 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324 }
2325 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002326 if (pid == popen_pid) {
2327 if (WIFEXITED(status) || WIFSIGNALED(status))
2328 popen_pid = -1;
2329 continue;
2330 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002331 if (debug)
2332 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2333
2334 /* Look up `pid' in our table. */
2335 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002336#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002337 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002338 /* This is needed to go with the CLONE_PTRACE
2339 changes in process.c/util.c: we might see
2340 the child's initial trap before we see the
2341 parent return from the clone syscall.
2342 Leave the child suspended until the parent
2343 returns from its system call. Only then
2344 will we have the association of parent and
2345 child so that we know how to do clearbpt
2346 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002347 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002348 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002349 if (!qflag)
2350 fprintf(stderr, "\
2351Process %d attached (waiting for parent)\n",
2352 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002353 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002354 else
2355 /* This can happen if a clone call used
2356 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002357#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002358 {
2359 fprintf(stderr, "unknown pid: %u\n", pid);
2360 if (WIFSTOPPED(status))
2361 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2362 exit(1);
2363 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002364 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002365 /* set current output file */
2366 outf = tcp->outf;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002367 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002368#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002369 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2370 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002371#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002372 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002373
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374 if (tcp->flags & TCB_SUSPENDED) {
2375 /*
2376 * Apparently, doing any ptrace() call on a stopped
2377 * process, provokes the kernel to report the process
2378 * status again on a subsequent wait(), even if the
2379 * process has not been actually restarted.
2380 * Since we have inspected the arguments of suspended
2381 * processes we end up here testing for this case.
2382 */
2383 continue;
2384 }
2385 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002386 if (pid == strace_child)
2387 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388 if (!cflag
2389 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2390 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002391 tprintf("+++ killed by %s %s+++",
2392 signame(WTERMSIG(status)),
2393#ifdef WCOREDUMP
2394 WCOREDUMP(status) ? "(core dumped) " :
2395#endif
2396 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002397 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002399#ifdef TCB_GROUP_EXITING
2400 handle_group_exit(tcp, -1);
2401#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002402 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002403#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002404 continue;
2405 }
2406 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002407 if (pid == strace_child)
2408 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002409 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002410 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2411 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002412#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002413 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002414 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002415#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002416 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002417 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002418 "PANIC: attached pid %u exited with %d\n",
2419 pid, WEXITSTATUS(status));
2420 }
Roland McGrath0a396902003-06-10 03:05:53 +00002421 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002422 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002423 tprintf(" <unfinished ... exit status %d>\n",
2424 WEXITSTATUS(status));
2425 tcp_last = NULL;
2426 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002427#ifdef TCB_GROUP_EXITING
2428 handle_group_exit(tcp, -1);
2429#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002430 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002431#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002432 continue;
2433 }
2434 if (!WIFSTOPPED(status)) {
2435 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2436 droptcb(tcp);
2437 continue;
2438 }
2439 if (debug)
2440 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002441 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442
Roland McGrath02203312007-06-11 22:06:31 +00002443 /*
2444 * Interestingly, the process may stop
2445 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002446 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002447 * just before the process takes a signal.
2448 */
2449 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002450 /*
2451 * This flag is there to keep us in sync.
2452 * Next time this process stops it should
2453 * really be entering a system call.
2454 */
2455 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002457 /*
2458 * One example is a breakpoint inherited from
2459 * parent through fork ().
2460 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002461 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2462 droptcb(tcp);
2463 cleanup();
2464 return -1;
2465 }
2466 }
2467 goto tracing;
2468 }
2469
Roland McGratheb9e2e82009-06-02 16:49:22 -07002470 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002471 if (WSTOPSIG(status) == SIGSTOP &&
2472 (tcp->flags & TCB_SIGTRAPPED)) {
2473 /*
2474 * Trapped attempt to block SIGTRAP
2475 * Hope we are back in control now.
2476 */
2477 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002478 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002479 cleanup();
2480 return -1;
2481 }
2482 continue;
2483 }
2484 if (!cflag
2485 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002486 unsigned long addr = 0;
2487 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002488#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002489# define PSR_RI 41
2490 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002491 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002492
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002493 upeek(tcp, PT_CR_IPSR, &psr);
2494 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002495
2496 pc += (psr >> PSR_RI) & 0x3;
2497 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2498 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002499#elif defined PTRACE_GETSIGINFO
2500 if (WSTOPSIG(status) == SIGSEGV ||
2501 WSTOPSIG(status) == SIGBUS) {
2502 siginfo_t si;
2503 if (ptrace(PTRACE_GETSIGINFO, pid,
2504 0, &si) == 0)
2505 addr = (unsigned long)
2506 si.si_addr;
2507 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002508#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002509 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002510 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002511 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002512 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002513 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002514 }
Roland McGrath05690952004-10-20 01:00:27 +00002515 if (((tcp->flags & TCB_ATTACHED) ||
2516 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002517 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002518#ifdef TCB_GROUP_EXITING
2519 handle_group_exit(tcp, WSTOPSIG(status));
2520#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002521 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002522#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002523 continue;
2524 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002525 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002526 cleanup();
2527 return -1;
2528 }
2529 tcp->flags &= ~TCB_SUSPENDED;
2530 continue;
2531 }
Roland McGrath02203312007-06-11 22:06:31 +00002532 /* we handled the STATUS, we are permitted to interrupt now. */
2533 if (interrupted)
2534 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002535 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2536 /* ptrace() failed in trace_syscall() with ESRCH.
2537 * Likely a result of process disappearing mid-flight.
2538 * Observed case: exit_group() terminating
2539 * all processes in thread group. In this case, threads
2540 * "disappear" in an unpredictable moment without any
2541 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002542 */
2543 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002544 if (tcp_last) {
2545 /* Do we have dangling line "syscall(param, param"?
2546 * Finish the line then. We cannot
2547 */
2548 tcp_last->flags |= TCB_REPRINT;
2549 tprintf(" <unfinished ...>");
2550 printtrailer();
2551 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002552 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002553 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002554 ptrace(PTRACE_KILL,
2555 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002556 droptcb(tcp);
2557 }
2558 continue;
2559 }
2560 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002561#ifdef TCB_GROUP_EXITING
2562 if (tcp->flags & TCB_GROUP_EXITING) {
2563 if (handle_group_exit(tcp, 0) < 0)
2564 return -1;
2565 continue;
2566 }
2567#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002568 if (tcp->flags & TCB_ATTACHED)
2569 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002570 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002571 cleanup();
2572 return -1;
2573 }
2574 continue;
2575 }
2576 if (tcp->flags & TCB_SUSPENDED) {
2577 if (!qflag)
2578 fprintf(stderr, "Process %u suspended\n", pid);
2579 continue;
2580 }
2581 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002582 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002583 cleanup();
2584 return -1;
2585 }
2586 }
2587 return 0;
2588}
2589
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002590#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002591
2592static int curcol;
2593
2594#ifdef __STDC__
2595#include <stdarg.h>
2596#define VA_START(a, b) va_start(a, b)
2597#else
2598#include <varargs.h>
2599#define VA_START(a, b) va_start(a)
2600#endif
2601
2602void
2603#ifdef __STDC__
2604tprintf(const char *fmt, ...)
2605#else
2606tprintf(fmt, va_alist)
2607char *fmt;
2608va_dcl
2609#endif
2610{
2611 va_list args;
2612
2613 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002614 if (outf) {
2615 int n = vfprintf(outf, fmt, args);
2616 if (n < 0 && outf != stderr)
2617 perror(outfname == NULL
2618 ? "<writing to pipe>" : outfname);
2619 else
2620 curcol += n;
2621 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002622 va_end(args);
2623 return;
2624}
2625
2626void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002627printleader(tcp)
2628struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002629{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002630 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002631 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002632 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002633 tprintf(" <unavailable>)");
2634 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002635 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002636 tprintf("= ? <unavailable>\n");
2637 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002638 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002639 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002640 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002641 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002642 }
2643 curcol = 0;
2644 if ((followfork == 1 || pflag_seen > 1) && outfname)
2645 tprintf("%-5d ", tcp->pid);
2646 else if (nprocs > 1 && !outfname)
2647 tprintf("[pid %5u] ", tcp->pid);
2648 if (tflag) {
2649 char str[sizeof("HH:MM:SS")];
2650 struct timeval tv, dtv;
2651 static struct timeval otv;
2652
2653 gettimeofday(&tv, NULL);
2654 if (rflag) {
2655 if (otv.tv_sec == 0)
2656 otv = tv;
2657 tv_sub(&dtv, &tv, &otv);
2658 tprintf("%6ld.%06ld ",
2659 (long) dtv.tv_sec, (long) dtv.tv_usec);
2660 otv = tv;
2661 }
2662 else if (tflag > 2) {
2663 tprintf("%ld.%06ld ",
2664 (long) tv.tv_sec, (long) tv.tv_usec);
2665 }
2666 else {
2667 time_t local = tv.tv_sec;
2668 strftime(str, sizeof(str), "%T", localtime(&local));
2669 if (tflag > 1)
2670 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2671 else
2672 tprintf("%s ", str);
2673 }
2674 }
2675 if (iflag)
2676 printcall(tcp);
2677}
2678
2679void
2680tabto(col)
2681int col;
2682{
2683 if (curcol < col)
2684 tprintf("%*s", col - curcol, "");
2685}
2686
2687void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002688printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002689{
2690 tprintf("\n");
2691 tcp_last = NULL;
2692}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002693
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002694#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002695
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002696int
2697mp_ioctl(int fd, int cmd, void *arg, int size)
2698{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002699 struct iovec iov[2];
2700 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002701
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002702 iov[0].iov_base = &cmd;
2703 iov[0].iov_len = sizeof cmd;
2704 if (arg) {
2705 ++n;
2706 iov[1].iov_base = arg;
2707 iov[1].iov_len = size;
2708 }
Roland McGrath553a6092002-12-16 20:40:39 +00002709
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002710 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002711}
2712
2713#endif