blob: 7294e8ee1ef5572059c8a79cfc5edb77438c0aae [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;
Andreas Schwabccdff482009-10-27 16:27:13 +0100116static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000117struct tcb **tcbtab;
118unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700120extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
Roland McGrath0a463882007-07-05 18:43:16 +0000122static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123static int trace P((void));
124static void cleanup P((void));
125static void interrupt P((int sig));
126static sigset_t empty_set, blocked_set;
127
128#ifdef HAVE_SIG_ATOMIC_T
129static volatile sig_atomic_t interrupted;
130#else /* !HAVE_SIG_ATOMIC_T */
131#ifdef __STDC__
132static volatile int interrupted;
133#else /* !__STDC__ */
134static int interrupted;
135#endif /* !__STDC__ */
136#endif /* !HAVE_SIG_ATOMIC_T */
137
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000138#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139
140static struct tcb *pfd2tcb P((int pfd));
141static void reaper P((int sig));
142static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000143static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144
145#ifndef HAVE_POLLABLE_PROCFS
146
147static void proc_poll_open P((void));
148static void proc_poller P((int pfd));
149
150struct proc_pollfd {
151 int fd;
152 int revents;
153 int pid;
154};
155
156static int poller_pid;
157static int proc_poll_pipe[2] = { -1, -1 };
158
159#endif /* !HAVE_POLLABLE_PROCFS */
160
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000161#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000162#define POLLWANT POLLWRNORM
163#else
164#define POLLWANT POLLPRI
165#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000166#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167
168static void
169usage(ofp, exitval)
170FILE *ofp;
171int exitval;
172{
173 fprintf(ofp, "\
174usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000175 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
176 [command [arg ...]]\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000177 or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000178 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000179-c -- count time, calls, and errors for each syscall and report summary\n\
180-f -- follow forks, -ff -- with output into separate files\n\
181-F -- attempt to follow vforks, -h -- print help message\n\
182-i -- print instruction pointer at time of syscall\n\
183-q -- suppress messages about attaching, detaching, etc.\n\
184-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
185-T -- print time spent in each syscall, -V -- print version\n\
186-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
187-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
188-a column -- alignment COLUMN for printing syscall results (default %d)\n\
189-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
190 options: trace, abbrev, verbose, raw, signal, read, or write\n\
191-o file -- send trace output to FILE instead of stderr\n\
192-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
193-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000194-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
196-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
197-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000198-E var=val -- put var=val in the environment for command\n\
199-E var -- remove var from the environment for command\n\
200" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000201-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000202 */
203, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204 exit(exitval);
205}
206
207#ifdef SVR4
208#ifdef MIPS
209void
210foobar()
211{
212}
213#endif /* MIPS */
214#endif /* SVR4 */
215
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400216/* Glue for systems without a MMU that cannot provide fork() */
217#ifdef HAVE_FORK
218# define strace_vforked 0
219#else
220# define strace_vforked 1
221# define fork() vfork()
222#endif
223
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000224static int
225set_cloexec_flag(int fd)
226{
227 int flags, newflags;
228
229 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
230 {
231 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
232 progname, strerror(errno));
233 return -1;
234 }
235
236 newflags = flags | FD_CLOEXEC;
237 if (flags == newflags)
238 return 0;
239
240 if (fcntl(fd, F_SETFD, newflags) < 0)
241 {
242 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
243 progname, strerror(errno));
244 return -1;
245 }
246
247 return 0;
248}
249
250/*
251 * When strace is setuid executable, we have to swap uids
252 * before and after filesystem and process management operations.
253 */
254static void
255swap_uid(void)
256{
257#ifndef SVR4
258 int euid = geteuid(), uid = getuid();
259
260 if (euid != uid && setreuid(euid, uid) < 0)
261 {
262 fprintf(stderr, "%s: setreuid: %s\n",
263 progname, strerror(errno));
264 exit(1);
265 }
266#endif
267}
268
Roland McGrath4bfa6262007-07-05 20:03:16 +0000269#if _LFS64_LARGEFILE
270# define fopen_for_output fopen64
271#else
272# define fopen_for_output fopen
273#endif
274
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000275static FILE *
276strace_fopen(const char *path, const char *mode)
277{
278 FILE *fp;
279
280 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000281 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000282 fprintf(stderr, "%s: can't fopen '%s': %s\n",
283 progname, path, strerror(errno));
284 swap_uid();
285 if (fp && set_cloexec_flag(fileno(fp)) < 0)
286 {
287 fclose(fp);
288 fp = NULL;
289 }
290 return fp;
291}
292
293static int popen_pid = -1;
294
295#ifndef _PATH_BSHELL
296# define _PATH_BSHELL "/bin/sh"
297#endif
298
299/*
300 * We cannot use standard popen(3) here because we have to distinguish
301 * popen child process from other processes we trace, and standard popen(3)
302 * does not export its child's pid.
303 */
304static FILE *
305strace_popen(const char *command)
306{
307 int fds[2];
308
309 swap_uid();
310 if (pipe(fds) < 0)
311 {
312 fprintf(stderr, "%s: pipe: %s\n",
313 progname, strerror(errno));
314 swap_uid();
315 return NULL;
316 }
317
318 if (set_cloexec_flag(fds[1]) < 0)
319 {
320 close(fds[0]);
321 close(fds[1]);
322 swap_uid();
323 return NULL;
324 }
325
326 if ((popen_pid = fork()) == -1)
327 {
328 fprintf(stderr, "%s: fork: %s\n",
329 progname, strerror(errno));
330 close(fds[0]);
331 close(fds[1]);
332 swap_uid();
333 return NULL;
334 }
335
336 if (popen_pid)
337 {
338 /* parent */
339 close(fds[0]);
340 swap_uid();
341 return fdopen(fds[1], "w");
342 } else
343 {
344 /* child */
345 close(fds[1]);
346 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
347 {
348 fprintf(stderr, "%s: dup2: %s\n",
349 progname, strerror(errno));
350 _exit(1);
351 }
352 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
353 fprintf(stderr, "%s: execl: %s: %s\n",
354 progname, _PATH_BSHELL, strerror(errno));
355 _exit(1);
356 }
357}
358
359static int
360newoutf(struct tcb *tcp)
361{
362 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000363 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364 FILE *fp;
365
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000366 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000367 if ((fp = strace_fopen(name, "w")) == NULL)
368 return -1;
369 tcp->outf = fp;
370 }
371 return 0;
372}
373
Roland McGrath02203312007-06-11 22:06:31 +0000374static void
375startup_attach(void)
376{
377 int tcbi;
378 struct tcb *tcp;
379
380 /*
381 * Block user interruptions as we would leave the traced
382 * process stopped (process state T) if we would terminate in
383 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
384 * We rely on cleanup () from this point on.
385 */
386 if (interactive)
387 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
388
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000389 if (daemonized_tracer) {
390 pid_t pid = fork();
391 if (pid < 0) {
392 _exit(1);
393 }
394 if (pid) { /* parent */
395 /*
396 * Wait for child to attach to straced process
397 * (our parent). Child SIGKILLs us after it attached.
398 * Parent's wait() is unblocked by our death,
399 * it proceeds to exec the straced program.
400 */
401 pause();
402 _exit(0); /* paranoia */
403 }
404 }
405
Roland McGrath02203312007-06-11 22:06:31 +0000406 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
407 tcp = tcbtab[tcbi];
408 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
409 continue;
410#ifdef LINUX
411 if (tcp->flags & TCB_CLONE_THREAD)
412 continue;
413#endif
414 /* Reinitialize the output since it may have changed. */
415 tcp->outf = outf;
416 if (newoutf(tcp) < 0)
417 exit(1);
418
419#ifdef USE_PROCFS
420 if (proc_open(tcp, 1) < 0) {
421 fprintf(stderr, "trouble opening proc file\n");
422 droptcb(tcp);
423 continue;
424 }
425#else /* !USE_PROCFS */
426# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000427 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000428 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000429 DIR *dir;
430
431 sprintf(procdir, "/proc/%d/task", tcp->pid);
432 dir = opendir(procdir);
433 if (dir != NULL) {
434 unsigned int ntid = 0, nerr = 0;
435 struct dirent *de;
436 int tid;
437 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000438 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000439 continue;
440 tid = atoi(de->d_name);
441 if (tid <= 0)
442 continue;
443 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000444 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000445 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000446 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000447 tcp = alloctcb(tid);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700448 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000449 tcbtab[tcbi]->nchildren++;
450 tcbtab[tcbi]->nclone_threads++;
451 tcbtab[tcbi]->nclone_detached++;
452 tcp->parent = tcbtab[tcbi];
453 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000454 if (interactive) {
455 sigprocmask(SIG_SETMASK, &empty_set, NULL);
456 if (interrupted)
457 return;
458 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
459 }
Roland McGrath02203312007-06-11 22:06:31 +0000460 }
461 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000462 ntid -= nerr;
463 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000464 perror("attach: ptrace(PTRACE_ATTACH, ...)");
465 droptcb(tcp);
466 continue;
467 }
468 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000469 fprintf(stderr, ntid > 1
470? "Process %u attached with %u threads - interrupt to quit\n"
471: "Process %u attached - interrupt to quit\n",
472 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000473 }
474 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000475 } /* if (opendir worked) */
476 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000477# endif
478 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
479 perror("attach: ptrace(PTRACE_ATTACH, ...)");
480 droptcb(tcp);
481 continue;
482 }
483 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000484
485 if (daemonized_tracer) {
486 /*
487 * It is our grandparent we trace, not a -p PID.
488 * Don't want to just detach on exit, so...
489 */
490 tcp->flags &= ~TCB_ATTACHED;
491 /*
492 * Make parent go away.
493 * Also makes grandparent's wait() unblock.
494 */
495 kill(getppid(), SIGKILL);
496 }
497
Roland McGrath02203312007-06-11 22:06:31 +0000498#endif /* !USE_PROCFS */
499 if (!qflag)
500 fprintf(stderr,
501 "Process %u attached - interrupt to quit\n",
502 tcp->pid);
503 }
504
505 if (interactive)
506 sigprocmask(SIG_SETMASK, &empty_set, NULL);
507}
508
509static void
510startup_child (char **argv)
511{
512 struct stat statbuf;
513 const char *filename;
514 char pathname[MAXPATHLEN];
515 int pid = 0;
516 struct tcb *tcp;
517
518 filename = argv[0];
519 if (strchr(filename, '/')) {
520 if (strlen(filename) > sizeof pathname - 1) {
521 errno = ENAMETOOLONG;
522 perror("strace: exec");
523 exit(1);
524 }
525 strcpy(pathname, filename);
526 }
527#ifdef USE_DEBUGGING_EXEC
528 /*
529 * Debuggers customarily check the current directory
530 * first regardless of the path but doing that gives
531 * security geeks a panic attack.
532 */
533 else if (stat(filename, &statbuf) == 0)
534 strcpy(pathname, filename);
535#endif /* USE_DEBUGGING_EXEC */
536 else {
537 char *path;
538 int m, n, len;
539
540 for (path = getenv("PATH"); path && *path; path += m) {
541 if (strchr(path, ':')) {
542 n = strchr(path, ':') - path;
543 m = n + 1;
544 }
545 else
546 m = n = strlen(path);
547 if (n == 0) {
548 if (!getcwd(pathname, MAXPATHLEN))
549 continue;
550 len = strlen(pathname);
551 }
552 else if (n > sizeof pathname - 1)
553 continue;
554 else {
555 strncpy(pathname, path, n);
556 len = n;
557 }
558 if (len && pathname[len - 1] != '/')
559 pathname[len++] = '/';
560 strcpy(pathname + len, filename);
561 if (stat(pathname, &statbuf) == 0 &&
562 /* Accept only regular files
563 with some execute bits set.
564 XXX not perfect, might still fail */
565 S_ISREG(statbuf.st_mode) &&
566 (statbuf.st_mode & 0111))
567 break;
568 }
569 }
570 if (stat(pathname, &statbuf) < 0) {
571 fprintf(stderr, "%s: %s: command not found\n",
572 progname, filename);
573 exit(1);
574 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000575 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000576 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000577 perror("strace: fork");
578 cleanup();
579 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000580 }
581 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
582 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
583 ) {
584 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000585#ifdef USE_PROCFS
586 if (outf != stderr) close (fileno (outf));
587#ifdef MIPS
588 /* Kludge for SGI, see proc_open for details. */
589 sa.sa_handler = foobar;
590 sa.sa_flags = 0;
591 sigemptyset(&sa.sa_mask);
592 sigaction(SIGINT, &sa, NULL);
593#endif /* MIPS */
594#ifndef FREEBSD
595 pause();
596#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000597 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000598#endif /* FREEBSD */
599#else /* !USE_PROCFS */
600 if (outf!=stderr)
601 close(fileno (outf));
602
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000603 if (!daemonized_tracer) {
604 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
605 perror("strace: ptrace(PTRACE_TRACEME, ...)");
606 exit(1);
607 }
608 if (debug)
609 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000610 }
Roland McGrath02203312007-06-11 22:06:31 +0000611
612 if (username != NULL || geteuid() == 0) {
613 uid_t run_euid = run_uid;
614 gid_t run_egid = run_gid;
615
616 if (statbuf.st_mode & S_ISUID)
617 run_euid = statbuf.st_uid;
618 if (statbuf.st_mode & S_ISGID)
619 run_egid = statbuf.st_gid;
620
621 /*
622 * It is important to set groups before we
623 * lose privileges on setuid.
624 */
625 if (username != NULL) {
626 if (initgroups(username, run_gid) < 0) {
627 perror("initgroups");
628 exit(1);
629 }
630 if (setregid(run_gid, run_egid) < 0) {
631 perror("setregid");
632 exit(1);
633 }
634 if (setreuid(run_uid, run_euid) < 0) {
635 perror("setreuid");
636 exit(1);
637 }
638 }
639 }
640 else
641 setreuid(run_uid, run_uid);
642
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000643 if (!daemonized_tracer) {
644 /*
645 * Induce an immediate stop so that the parent
646 * will resume us with PTRACE_SYSCALL and display
647 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400648 * Unless of course we're on a no-MMU system where
649 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000650 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400651 if (!strace_vforked)
652 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000653 } else {
654 struct sigaction sv_sigchld;
655 sigaction(SIGCHLD, NULL, &sv_sigchld);
656 /*
657 * Make sure it is not SIG_IGN, otherwise wait
658 * will not block.
659 */
660 signal(SIGCHLD, SIG_DFL);
661 /*
662 * Wait for grandchild to attach to us.
663 * It kills child after that, and wait() unblocks.
664 */
665 alarm(3);
666 wait(NULL);
667 alarm(0);
668 sigaction(SIGCHLD, &sv_sigchld, NULL);
669 }
Roland McGrath02203312007-06-11 22:06:31 +0000670#endif /* !USE_PROCFS */
671
672 execv(pathname, argv);
673 perror("strace: exec");
674 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000675 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676
677 /* We are the tracer. */
678 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000679 if (daemonized_tracer) {
680 /* We want subsequent startup_attach() to attach to it. */
681 tcp->flags |= TCB_ATTACHED;
682 }
Roland McGrath02203312007-06-11 22:06:31 +0000683#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000684 if (proc_open(tcp, 0) < 0) {
685 fprintf(stderr, "trouble opening proc file\n");
686 cleanup();
687 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000688 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000689#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000690}
691
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000693main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 struct tcb *tcp;
696 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000697 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000698 struct sigaction sa;
699
700 static char buf[BUFSIZ];
701
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000702 progname = argv[0] ? argv[0] : "strace";
703
Roland McGrathee9d4352002-12-18 04:16:10 +0000704 /* Allocate the initial tcbtab. */
705 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000706 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000707 fprintf(stderr, "%s: out of memory\n", progname);
708 exit(1);
709 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000710 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000711 fprintf(stderr, "%s: out of memory\n", progname);
712 exit(1);
713 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000714 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
715 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
716
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000717 outf = stderr;
718 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000719 set_sortby(DEFAULT_SORTBY);
720 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000721 qualify("trace=all");
722 qualify("abbrev=all");
723 qualify("verbose=all");
724 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000725 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000726 "+cdfFhiqrtTvVxz"
727#ifndef USE_PROCFS
728 "D"
729#endif
730 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000731 switch (c) {
732 case 'c':
733 cflag++;
734 dtime++;
735 break;
736 case 'd':
737 debug++;
738 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000739#ifndef USE_PROCFS
740 /* Experimental, not documented in manpage yet. */
741 case 'D':
742 daemonized_tracer = 1;
743 break;
744#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000745 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000746 optF = 1;
747 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000748 case 'f':
749 followfork++;
750 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751 case 'h':
752 usage(stdout, 0);
753 break;
754 case 'i':
755 iflag++;
756 break;
757 case 'q':
758 qflag++;
759 break;
760 case 'r':
761 rflag++;
762 tflag++;
763 break;
764 case 't':
765 tflag++;
766 break;
767 case 'T':
768 dtime++;
769 break;
770 case 'x':
771 xflag++;
772 break;
773 case 'v':
774 qualify("abbrev=none");
775 break;
776 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000777 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 exit(0);
779 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000780 case 'z':
781 not_failing_only = 1;
782 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 case 'a':
784 acolumn = atoi(optarg);
785 break;
786 case 'e':
787 qualify(optarg);
788 break;
789 case 'o':
790 outfname = strdup(optarg);
791 break;
792 case 'O':
793 set_overhead(atoi(optarg));
794 break;
795 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000796 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000797 fprintf(stderr, "%s: Invalid process id: %s\n",
798 progname, optarg);
799 break;
800 }
801 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000802 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 break;
804 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000805 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 tcp->flags |= TCB_ATTACHED;
807 pflag_seen++;
808 break;
809 case 's':
810 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000811 if (max_strlen < 0) {
812 fprintf(stderr,
813 "%s: invalid -s argument: %s\n",
814 progname, optarg);
815 exit(1);
816 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000817 break;
818 case 'S':
819 set_sortby(optarg);
820 break;
821 case 'u':
822 username = strdup(optarg);
823 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000824 case 'E':
825 if (putenv(optarg) < 0) {
826 fprintf(stderr, "%s: out of memory\n",
827 progname);
828 exit(1);
829 }
830 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000831 default:
832 usage(stderr, 1);
833 break;
834 }
835 }
836
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000837 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000838 usage(stderr, 1);
839
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000840 if (!followfork)
841 followfork = optF;
842
Roland McGrathcb9def62006-04-25 07:48:03 +0000843 if (followfork > 1 && cflag) {
844 fprintf(stderr,
845 "%s: -c and -ff are mutually exclusive options\n",
846 progname);
847 exit(1);
848 }
849
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 /* See if they want to run as another user. */
851 if (username != NULL) {
852 struct passwd *pent;
853
854 if (getuid() != 0 || geteuid() != 0) {
855 fprintf(stderr,
856 "%s: you must be root to use the -u option\n",
857 progname);
858 exit(1);
859 }
860 if ((pent = getpwnam(username)) == NULL) {
861 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000862 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863 exit(1);
864 }
865 run_uid = pent->pw_uid;
866 run_gid = pent->pw_gid;
867 }
868 else {
869 run_uid = getuid();
870 run_gid = getgid();
871 }
872
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000873 /* Check if they want to redirect the output. */
874 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000875 /* See if they want to pipe the output. */
876 if (outfname[0] == '|' || outfname[0] == '!') {
877 /*
878 * We can't do the <outfname>.PID funny business
879 * when using popen, so prohibit it.
880 */
881 if (followfork > 1) {
882 fprintf(stderr, "\
883%s: piping the output and -ff are mutually exclusive options\n",
884 progname);
885 exit(1);
886 }
887
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000888 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000889 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000890 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000891 else if (followfork <= 1 &&
892 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 }
895
Roland McGrath37b9a662003-11-07 02:26:54 +0000896 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000898 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000899 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000901 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000902 /* Valid states here:
903 optind < argc pflag_seen outfname interactive
904 1 0 0 1
905 0 1 0 1
906 1 0 1 0
907 0 1 1 1
908 */
909
910 /* STARTUP_CHILD must be called before the signal handlers get
911 installed below as they are inherited into the spawned process.
912 Also we do not need to be protected by them as during interruption
913 in the STARTUP_CHILD mode we kill the spawned process anyway. */
914 if (!pflag_seen)
915 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 sigemptyset(&empty_set);
918 sigemptyset(&blocked_set);
919 sa.sa_handler = SIG_IGN;
920 sigemptyset(&sa.sa_mask);
921 sa.sa_flags = 0;
922 sigaction(SIGTTOU, &sa, NULL);
923 sigaction(SIGTTIN, &sa, NULL);
924 if (interactive) {
925 sigaddset(&blocked_set, SIGHUP);
926 sigaddset(&blocked_set, SIGINT);
927 sigaddset(&blocked_set, SIGQUIT);
928 sigaddset(&blocked_set, SIGPIPE);
929 sigaddset(&blocked_set, SIGTERM);
930 sa.sa_handler = interrupt;
931#ifdef SUNOS4
932 /* POSIX signals on sunos4.1 are a little broken. */
933 sa.sa_flags = SA_INTERRUPT;
934#endif /* SUNOS4 */
935 }
936 sigaction(SIGHUP, &sa, NULL);
937 sigaction(SIGINT, &sa, NULL);
938 sigaction(SIGQUIT, &sa, NULL);
939 sigaction(SIGPIPE, &sa, NULL);
940 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000941#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 sa.sa_handler = reaper;
943 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000944#else
945 /* Make sure SIGCHLD has the default action so that waitpid
946 definitely works without losing track of children. The user
947 should not have given us a bogus state to inherit, but he might
948 have. Arguably we should detect SIG_IGN here and pass it on
949 to children, but probably noone really needs that. */
950 sa.sa_handler = SIG_DFL;
951 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000952#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000954 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000955 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000956
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 if (trace() < 0)
958 exit(1);
959 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000960 fflush(NULL);
961 if (exit_code > 0xff) {
962 /* Child was killed by a signal, mimic that. */
963 exit_code &= 0xff;
964 signal(exit_code, SIG_DFL);
965 raise(exit_code);
966 /* Paranoia - what if this signal is not fatal?
967 Exit with 128 + signo then. */
968 exit_code += 128;
969 }
970 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971}
972
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000973void
974expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000975{
976 /* Allocate some more TCBs and expand the table.
977 We don't want to relocate the TCBs because our
978 callers have pointers and it would be a pain.
979 So tcbtab is a table of pointers. Since we never
980 free the TCBs, we allocate a single chunk of many. */
981 struct tcb **newtab = (struct tcb **)
982 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
983 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
984 sizeof *newtcbs);
985 int i;
986 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000987 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
988 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000989 cleanup();
990 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000991 }
992 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
993 newtab[i] = &newtcbs[i - tcbtabsize];
994 tcbtabsize *= 2;
995 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000996}
997
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000999alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000{
1001 int i;
1002 struct tcb *tcp;
1003
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001004 if (nprocs == tcbtabsize)
1005 expand_tcbtab();
1006
Roland McGrathee9d4352002-12-18 04:16:10 +00001007 for (i = 0; i < tcbtabsize; i++) {
1008 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 if ((tcp->flags & TCB_INUSE) == 0) {
1010 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001011 tcp->parent = NULL;
1012 tcp->nchildren = 0;
1013 tcp->nzombies = 0;
1014#ifdef TCB_CLONE_THREAD
1015 tcp->nclone_threads = tcp->nclone_detached = 0;
1016 tcp->nclone_waiting = 0;
1017#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 tcp->flags = TCB_INUSE | TCB_STARTUP;
1019 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001020 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001021 tcp->stime.tv_sec = 0;
1022 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023 tcp->pfd = -1;
1024 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001025 if (command_options_parsed)
1026 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 return tcp;
1028 }
1029 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001030 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1031 cleanup();
1032 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033}
1034
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001035#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001037proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038{
1039 char proc[32];
1040 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001041#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001042 int i;
1043 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001044 sigset_t signals;
1045 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001046#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047#ifndef HAVE_POLLABLE_PROCFS
1048 static int last_pfd;
1049#endif
1050
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001051#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001052 /* Open the process pseudo-files in /proc. */
1053 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1054 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 perror("strace: open(\"/proc/...\", ...)");
1056 return -1;
1057 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001058 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 return -1;
1060 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001061 sprintf(proc, "/proc/%d/status", tcp->pid);
1062 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1063 perror("strace: open(\"/proc/...\", ...)");
1064 return -1;
1065 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001066 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001067 return -1;
1068 }
1069 sprintf(proc, "/proc/%d/as", tcp->pid);
1070 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1071 perror("strace: open(\"/proc/...\", ...)");
1072 return -1;
1073 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001074 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001075 return -1;
1076 }
1077#else
1078 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001079#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001080 sprintf(proc, "/proc/%d", tcp->pid);
1081 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001082#else /* FREEBSD */
1083 sprintf(proc, "/proc/%d/mem", tcp->pid);
1084 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1085#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001086 perror("strace: open(\"/proc/...\", ...)");
1087 return -1;
1088 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001089 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001090 return -1;
1091 }
1092#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001093#ifdef FREEBSD
1094 sprintf(proc, "/proc/%d/regs", tcp->pid);
1095 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1096 perror("strace: open(\"/proc/.../regs\", ...)");
1097 return -1;
1098 }
1099 if (cflag) {
1100 sprintf(proc, "/proc/%d/status", tcp->pid);
1101 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1102 perror("strace: open(\"/proc/.../status\", ...)");
1103 return -1;
1104 }
1105 } else
1106 tcp->pfd_status = -1;
1107#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001108 rebuild_pollv();
1109 if (!attaching) {
1110 /*
1111 * Wait for the child to pause. Because of a race
1112 * condition we have to poll for the event.
1113 */
1114 for (;;) {
1115 if (IOCTL_STATUS (tcp) < 0) {
1116 perror("strace: PIOCSTATUS");
1117 return -1;
1118 }
1119 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001120 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001121 }
1122 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001123#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001124 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001125 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001126 perror("strace: PIOCSTOP");
1127 return -1;
1128 }
Roland McGrath553a6092002-12-16 20:40:39 +00001129#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130#ifdef PIOCSET
1131 /* Set Run-on-Last-Close. */
1132 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001133 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001134 perror("PIOCSET PR_RLC");
1135 return -1;
1136 }
1137 /* Set or Reset Inherit-on-Fork. */
1138 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001139 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140 perror("PIOC{SET,RESET} PR_FORK");
1141 return -1;
1142 }
1143#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001144#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1146 perror("PIOCSRLC");
1147 return -1;
1148 }
1149 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1150 perror("PIOC{S,R}FORK");
1151 return -1;
1152 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001153#else /* FREEBSD */
1154 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1155 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1156 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001157 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001158 }
1159 arg &= ~PF_LINGER;
1160 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001161 perror("PIOCSFL");
1162 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001163 }
1164#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001166#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001167 /* Enable all syscall entries we care about. */
1168 premptyset(&syscalls);
1169 for (i = 1; i < MAX_QUALS; ++i) {
1170 if (i > (sizeof syscalls) * CHAR_BIT) break;
1171 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1172 }
1173 praddset (&syscalls, SYS_execve);
1174 if (followfork) {
1175 praddset (&syscalls, SYS_fork);
1176#ifdef SYS_forkall
1177 praddset (&syscalls, SYS_forkall);
1178#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001179#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001180 praddset (&syscalls, SYS_fork1);
1181#endif
1182#ifdef SYS_rfork1
1183 praddset (&syscalls, SYS_rfork1);
1184#endif
1185#ifdef SYS_rforkall
1186 praddset (&syscalls, SYS_rforkall);
1187#endif
1188 }
1189 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 perror("PIOCSENTRY");
1191 return -1;
1192 }
John Hughes19e49982001-10-19 08:59:12 +00001193 /* Enable the syscall exits. */
1194 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195 perror("PIOSEXIT");
1196 return -1;
1197 }
John Hughes19e49982001-10-19 08:59:12 +00001198 /* Enable signals we care about. */
1199 premptyset(&signals);
1200 for (i = 1; i < MAX_QUALS; ++i) {
1201 if (i > (sizeof signals) * CHAR_BIT) break;
1202 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1203 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001204 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 perror("PIOCSTRACE");
1206 return -1;
1207 }
John Hughes19e49982001-10-19 08:59:12 +00001208 /* Enable faults we care about */
1209 premptyset(&faults);
1210 for (i = 1; i < MAX_QUALS; ++i) {
1211 if (i > (sizeof faults) * CHAR_BIT) break;
1212 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1213 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001214 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 perror("PIOCSFAULT");
1216 return -1;
1217 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001218#else /* FREEBSD */
1219 /* set events flags. */
1220 arg = S_SIG | S_SCE | S_SCX ;
1221 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1222 perror("PIOCBIS");
1223 return -1;
1224 }
1225#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226 if (!attaching) {
1227#ifdef MIPS
1228 /*
1229 * The SGI PRSABORT doesn't work for pause() so
1230 * we send it a caught signal to wake it up.
1231 */
1232 kill(tcp->pid, SIGINT);
1233#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001234#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001235 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001236 arg = PRSABORT;
1237 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238 perror("PIOCRUN");
1239 return -1;
1240 }
Roland McGrath553a6092002-12-16 20:40:39 +00001241#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001242#endif /* !MIPS*/
1243#ifdef FREEBSD
1244 /* wake up the child if it received the SIGSTOP */
1245 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001246#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247 for (;;) {
1248 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001249 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250 perror("PIOCWSTOP");
1251 return -1;
1252 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001253 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001254 tcp->flags &= ~TCB_INSYSCALL;
1255 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001256 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257 break;
1258 }
1259 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001260#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001261 arg = 0;
1262 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001263#else /* FREEBSD */
1264 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001265#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 perror("PIOCRUN");
1267 return -1;
1268 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001269#ifdef FREEBSD
1270 /* handle the case where we "opened" the child before
1271 it did the kill -STOP */
1272 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1273 tcp->status.PR_WHAT == SIGSTOP)
1274 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001275#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001277#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001278 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001279#else /* FREEBSD */
1280 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001281 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001282 /* We are attaching to an already running process.
1283 * Try to figure out the state of the process in syscalls,
1284 * to handle the first event well.
1285 * This is done by having a look at the "wchan" property of the
1286 * process, which tells where it is stopped (if it is). */
1287 FILE * status;
1288 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001289
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001290 sprintf(proc, "/proc/%d/status", tcp->pid);
1291 status = fopen(proc, "r");
1292 if (status &&
1293 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1294 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1295 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1296 strcmp(wchan, "stopevent")) {
1297 /* The process is asleep in the middle of a syscall.
1298 Fake the syscall entry event */
1299 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1300 tcp->status.PR_WHY = PR_SYSENTRY;
1301 trace_syscall(tcp);
1302 }
1303 if (status)
1304 fclose(status);
1305 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001306 }
1307#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001308#ifndef HAVE_POLLABLE_PROCFS
1309 if (proc_poll_pipe[0] != -1)
1310 proc_poller(tcp->pfd);
1311 else if (nprocs > 1) {
1312 proc_poll_open();
1313 proc_poller(last_pfd);
1314 proc_poller(tcp->pfd);
1315 }
1316 last_pfd = tcp->pfd;
1317#endif /* !HAVE_POLLABLE_PROCFS */
1318 return 0;
1319}
1320
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001321#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001322
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001323struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001324pid2tcb(pid)
1325int pid;
1326{
1327 int i;
1328 struct tcb *tcp;
1329
Roland McGrathee9d4352002-12-18 04:16:10 +00001330 for (i = 0; i < tcbtabsize; i++) {
1331 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332 if (pid && tcp->pid != pid)
1333 continue;
1334 if (tcp->flags & TCB_INUSE)
1335 return tcp;
1336 }
1337 return NULL;
1338}
1339
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001340#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341
1342static struct tcb *
1343pfd2tcb(pfd)
1344int pfd;
1345{
1346 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001347
Roland McGrathca16be82003-01-10 19:55:28 +00001348 for (i = 0; i < tcbtabsize; i++) {
1349 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350 if (tcp->pfd != pfd)
1351 continue;
1352 if (tcp->flags & TCB_INUSE)
1353 return tcp;
1354 }
1355 return NULL;
1356}
1357
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001358#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001359
1360void
1361droptcb(tcp)
1362struct tcb *tcp;
1363{
1364 if (tcp->pid == 0)
1365 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001366#ifdef TCB_CLONE_THREAD
1367 if (tcp->nclone_threads > 0) {
1368 /* There are other threads left in this process, but this
1369 is the one whose PID represents the whole process.
1370 We need to keep this record around as a zombie until
1371 all the threads die. */
1372 tcp->flags |= TCB_EXITING;
1373 return;
1374 }
1375#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376 nprocs--;
1377 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001378
Roland McGrathe29341c2003-01-10 20:14:20 +00001379 if (tcp->parent != NULL) {
1380 tcp->parent->nchildren--;
1381#ifdef TCB_CLONE_THREAD
1382 if (tcp->flags & TCB_CLONE_DETACHED)
1383 tcp->parent->nclone_detached--;
1384 if (tcp->flags & TCB_CLONE_THREAD)
1385 tcp->parent->nclone_threads--;
1386#endif
Roland McGrath09623452003-05-23 02:27:13 +00001387#ifdef TCB_CLONE_DETACHED
1388 if (!(tcp->flags & TCB_CLONE_DETACHED))
1389#endif
1390 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001391#ifdef LINUX
1392 /* Update `tcp->parent->parent->nchildren' and the other fields
1393 like NCLONE_DETACHED, only for zombie group leader that has
1394 already reported and been short-circuited at the top of this
1395 function. The same condition as at the top of DETACH. */
1396 if ((tcp->flags & TCB_CLONE_THREAD) &&
1397 tcp->parent->nclone_threads == 0 &&
1398 (tcp->parent->flags & TCB_EXITING))
1399 droptcb(tcp->parent);
1400#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001401 tcp->parent = NULL;
1402 }
1403
1404 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405 if (tcp->pfd != -1) {
1406 close(tcp->pfd);
1407 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001408#ifdef FREEBSD
1409 if (tcp->pfd_reg != -1) {
1410 close(tcp->pfd_reg);
1411 tcp->pfd_reg = -1;
1412 }
1413 if (tcp->pfd_status != -1) {
1414 close(tcp->pfd_status);
1415 tcp->pfd_status = -1;
1416 }
Roland McGrath553a6092002-12-16 20:40:39 +00001417#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001418#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001419 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001420#endif
1421 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001422
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001423 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001425
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426 tcp->outf = 0;
1427}
1428
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001429#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430
1431static int
1432resume(tcp)
1433struct tcb *tcp;
1434{
1435 if (tcp == NULL)
1436 return -1;
1437
1438 if (!(tcp->flags & TCB_SUSPENDED)) {
1439 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1440 return -1;
1441 }
1442 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001443#ifdef TCB_CLONE_THREAD
1444 if (tcp->flags & TCB_CLONE_THREAD)
1445 tcp->parent->nclone_waiting--;
1446#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001448 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450
1451 if (!qflag)
1452 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1453 return 0;
1454}
1455
Roland McGrath1bfd3102007-08-03 10:02:00 +00001456static int
1457resume_from_tcp (struct tcb *tcp)
1458{
1459 int error = 0;
1460 int resumed = 0;
1461
1462 /* XXX This won't always be quite right (but it never was).
1463 A waiter with argument 0 or < -1 is waiting for any pid in
1464 a particular pgrp, which this child might or might not be
1465 in. The waiter will only wake up if it's argument is -1
1466 or if it's waiting for tcp->pid's pgrp. It makes a
1467 difference to wake up a waiter when there might be more
1468 traced children, because it could get a false ECHILD
1469 error. OTOH, if this was the last child in the pgrp, then
1470 it ought to wake up and get ECHILD. We would have to
1471 search the system for all pid's in the pgrp to be sure.
1472
1473 && (t->waitpid == -1 ||
1474 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1475 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1476 */
1477
1478 if (tcp->parent &&
1479 (tcp->parent->flags & TCB_SUSPENDED) &&
1480 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001481 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001482 ++resumed;
1483 }
1484#ifdef TCB_CLONE_THREAD
1485 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1486 /* Some other threads of our parent are waiting too. */
1487 unsigned int i;
1488
1489 /* Resume all the threads that were waiting for this PID. */
1490 for (i = 0; i < tcbtabsize; i++) {
1491 struct tcb *t = tcbtab[i];
1492 if (t->parent == tcp->parent && t != tcp
1493 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1494 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1495 && t->waitpid == tcp->pid) {
1496 error |= resume (t);
1497 ++resumed;
1498 }
1499 }
1500 if (resumed == 0)
1501 /* Noone was waiting for this PID in particular,
1502 so now we might need to resume some wildcarders. */
1503 for (i = 0; i < tcbtabsize; i++) {
1504 struct tcb *t = tcbtab[i];
1505 if (t->parent == tcp->parent && t != tcp
1506 && ((t->flags
1507 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1508 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1509 && t->waitpid <= 0
1510 ) {
1511 error |= resume (t);
1512 break;
1513 }
1514 }
1515 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001516#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001517
1518 return error;
1519}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001520
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001521#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522
Roland McGrath0a463882007-07-05 18:43:16 +00001523/* detach traced process; continue with sig
1524 Never call DETACH twice on the same process as both unattached and
1525 attached-unstopped processes give the same ESRCH. For unattached process we
1526 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527
1528static int
1529detach(tcp, sig)
1530struct tcb *tcp;
1531int sig;
1532{
1533 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001534#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001535 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001536 struct tcb *zombie = NULL;
1537
1538 /* If the group leader is lingering only because of this other
1539 thread now dying, then detach the leader as well. */
1540 if ((tcp->flags & TCB_CLONE_THREAD) &&
1541 tcp->parent->nclone_threads == 1 &&
1542 (tcp->parent->flags & TCB_EXITING))
1543 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001544#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545
1546 if (tcp->flags & TCB_BPTSET)
1547 sig = SIGKILL;
1548
1549#ifdef LINUX
1550 /*
1551 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001552 * before detaching. Arghh. We go through hoops
1553 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001555#if defined(SPARC)
1556#undef PTRACE_DETACH
1557#define PTRACE_DETACH PTRACE_SUNDETACH
1558#endif
Roland McGrath02203312007-06-11 22:06:31 +00001559 /*
1560 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1561 * expected SIGSTOP. We must catch exactly one as otherwise the
1562 * detached process would be left stopped (process state T).
1563 */
1564 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1566 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001567 }
1568 else if (errno != ESRCH) {
1569 /* Shouldn't happen. */
1570 perror("detach: ptrace(PTRACE_DETACH, ...)");
1571 }
Roland McGrath134813a2007-06-02 00:07:33 +00001572 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1573 : tcp->pid),
1574 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001575 if (errno != ESRCH)
1576 perror("detach: checking sanity");
1577 }
Roland McGrath02203312007-06-11 22:06:31 +00001578 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1579 ? tcp->parent->pid : tcp->pid),
1580 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001581 if (errno != ESRCH)
1582 perror("detach: stopping child");
1583 }
Roland McGrath02203312007-06-11 22:06:31 +00001584 else
1585 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001586 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001588#ifdef __WALL
1589 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1590 if (errno == ECHILD) /* Already gone. */
1591 break;
1592 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001593 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001594 break;
1595 }
1596#endif /* __WALL */
1597 /* No __WALL here. */
1598 if (waitpid(tcp->pid, &status, 0) < 0) {
1599 if (errno != ECHILD) {
1600 perror("detach: waiting");
1601 break;
1602 }
1603#ifdef __WCLONE
1604 /* If no processes, try clones. */
1605 if (wait4(tcp->pid, &status, __WCLONE,
1606 NULL) < 0) {
1607 if (errno != ECHILD)
1608 perror("detach: waiting");
1609 break;
1610 }
1611#endif /* __WCLONE */
1612 }
1613#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001614 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001615#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616 if (!WIFSTOPPED(status)) {
1617 /* Au revoir, mon ami. */
1618 break;
1619 }
1620 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001621 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 break;
1623 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001624 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001625 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001626 : WSTOPSIG(status));
1627 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001628 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001630 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001631#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632
1633#if defined(SUNOS4)
1634 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1635 if (sig && kill(tcp->pid, sig) < 0)
1636 perror("detach: kill");
1637 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001638 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639#endif /* SUNOS4 */
1640
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001641#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001642 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001643#endif
1644
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645 if (!qflag)
1646 fprintf(stderr, "Process %u detached\n", tcp->pid);
1647
1648 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001649
1650#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001651 if (zombie != NULL) {
1652 /* TCP no longer exists therefore you must not detach () it. */
1653 droptcb(zombie);
1654 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001655#endif
1656
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657 return error;
1658}
1659
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001660#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661
1662static void
1663reaper(sig)
1664int sig;
1665{
1666 int pid;
1667 int status;
1668
1669 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1670#if 0
1671 struct tcb *tcp;
1672
1673 tcp = pid2tcb(pid);
1674 if (tcp)
1675 droptcb(tcp);
1676#endif
1677 }
1678}
1679
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001680#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681
1682static void
1683cleanup()
1684{
1685 int i;
1686 struct tcb *tcp;
1687
Roland McGrathee9d4352002-12-18 04:16:10 +00001688 for (i = 0; i < tcbtabsize; i++) {
1689 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 if (!(tcp->flags & TCB_INUSE))
1691 continue;
1692 if (debug)
1693 fprintf(stderr,
1694 "cleanup: looking at pid %u\n", tcp->pid);
1695 if (tcp_last &&
1696 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001697 tprintf(" <unfinished ...>");
1698 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699 }
1700 if (tcp->flags & TCB_ATTACHED)
1701 detach(tcp, 0);
1702 else {
1703 kill(tcp->pid, SIGCONT);
1704 kill(tcp->pid, SIGTERM);
1705 }
1706 }
1707 if (cflag)
1708 call_summary(outf);
1709}
1710
1711static void
1712interrupt(sig)
1713int sig;
1714{
1715 interrupted = 1;
1716}
1717
1718#ifndef HAVE_STRERROR
1719
Roland McGrath6d2b3492002-12-30 00:51:30 +00001720#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001721extern int sys_nerr;
1722extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001723#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724
1725const char *
1726strerror(errno)
1727int errno;
1728{
1729 static char buf[64];
1730
1731 if (errno < 1 || errno >= sys_nerr) {
1732 sprintf(buf, "Unknown error %d", errno);
1733 return buf;
1734 }
1735 return sys_errlist[errno];
1736}
1737
1738#endif /* HAVE_STERRROR */
1739
1740#ifndef HAVE_STRSIGNAL
1741
Roland McGrath8f474e02003-01-14 07:53:33 +00001742#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001743extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001745#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1746extern char *_sys_siglist[];
1747#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748
1749const char *
1750strsignal(sig)
1751int sig;
1752{
1753 static char buf[64];
1754
1755 if (sig < 1 || sig >= NSIG) {
1756 sprintf(buf, "Unknown signal %d", sig);
1757 return buf;
1758 }
1759#ifdef HAVE__SYS_SIGLIST
1760 return _sys_siglist[sig];
1761#else
1762 return sys_siglist[sig];
1763#endif
1764}
1765
1766#endif /* HAVE_STRSIGNAL */
1767
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001768#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769
1770static void
1771rebuild_pollv()
1772{
1773 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774
Roland McGrathee9d4352002-12-18 04:16:10 +00001775 if (pollv != NULL)
1776 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001777 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001778 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001779 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001780 exit(1);
1781 }
1782
Roland McGrathca16be82003-01-10 19:55:28 +00001783 for (i = j = 0; i < tcbtabsize; i++) {
1784 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 if (!(tcp->flags & TCB_INUSE))
1786 continue;
1787 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001788 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789 j++;
1790 }
1791 if (j != nprocs) {
1792 fprintf(stderr, "strace: proc miscount\n");
1793 exit(1);
1794 }
1795}
1796
1797#ifndef HAVE_POLLABLE_PROCFS
1798
1799static void
1800proc_poll_open()
1801{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802 int i;
1803
1804 if (pipe(proc_poll_pipe) < 0) {
1805 perror("pipe");
1806 exit(1);
1807 }
1808 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001809 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810 exit(1);
1811 }
1812 }
1813}
1814
1815static int
1816proc_poll(pollv, nfds, timeout)
1817struct pollfd *pollv;
1818int nfds;
1819int timeout;
1820{
1821 int i;
1822 int n;
1823 struct proc_pollfd pollinfo;
1824
1825 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1826 return n;
1827 if (n != sizeof(struct proc_pollfd)) {
1828 fprintf(stderr, "panic: short read: %d\n", n);
1829 exit(1);
1830 }
1831 for (i = 0; i < nprocs; i++) {
1832 if (pollv[i].fd == pollinfo.fd)
1833 pollv[i].revents = pollinfo.revents;
1834 else
1835 pollv[i].revents = 0;
1836 }
1837 poller_pid = pollinfo.pid;
1838 return 1;
1839}
1840
1841static void
1842wakeup_handler(sig)
1843int sig;
1844{
1845}
1846
1847static void
1848proc_poller(pfd)
1849int pfd;
1850{
1851 struct proc_pollfd pollinfo;
1852 struct sigaction sa;
1853 sigset_t blocked_set, empty_set;
1854 int i;
1855 int n;
1856 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001857#ifdef FREEBSD
1858 struct procfs_status pfs;
1859#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001860
1861 switch (fork()) {
1862 case -1:
1863 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001864 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 case 0:
1866 break;
1867 default:
1868 return;
1869 }
1870
1871 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1872 sa.sa_flags = 0;
1873 sigemptyset(&sa.sa_mask);
1874 sigaction(SIGHUP, &sa, NULL);
1875 sigaction(SIGINT, &sa, NULL);
1876 sigaction(SIGQUIT, &sa, NULL);
1877 sigaction(SIGPIPE, &sa, NULL);
1878 sigaction(SIGTERM, &sa, NULL);
1879 sa.sa_handler = wakeup_handler;
1880 sigaction(SIGUSR1, &sa, NULL);
1881 sigemptyset(&blocked_set);
1882 sigaddset(&blocked_set, SIGUSR1);
1883 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1884 sigemptyset(&empty_set);
1885
1886 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1887 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001888 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001889 }
1890 n = rl.rlim_cur;
1891 for (i = 0; i < n; i++) {
1892 if (i != pfd && i != proc_poll_pipe[1])
1893 close(i);
1894 }
1895
1896 pollinfo.fd = pfd;
1897 pollinfo.pid = getpid();
1898 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001899#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001900 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1901#else
1902 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1903#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001904 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 switch (errno) {
1906 case EINTR:
1907 continue;
1908 case EBADF:
1909 pollinfo.revents = POLLERR;
1910 break;
1911 case ENOENT:
1912 pollinfo.revents = POLLHUP;
1913 break;
1914 default:
1915 perror("proc_poller: PIOCWSTOP");
1916 }
1917 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1918 _exit(0);
1919 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001920 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1922 sigsuspend(&empty_set);
1923 }
1924}
1925
1926#endif /* !HAVE_POLLABLE_PROCFS */
1927
1928static int
1929choose_pfd()
1930{
1931 int i, j;
1932 struct tcb *tcp;
1933
1934 static int last;
1935
1936 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001937 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 /*
1939 * The previous process is ready to run again. We'll
1940 * let it do so if it is currently in a syscall. This
1941 * heuristic improves the readability of the trace.
1942 */
1943 tcp = pfd2tcb(pollv[last].fd);
1944 if (tcp && (tcp->flags & TCB_INSYSCALL))
1945 return pollv[last].fd;
1946 }
1947
1948 for (i = 0; i < nprocs; i++) {
1949 /* Let competing children run round robin. */
1950 j = (i + last + 1) % nprocs;
1951 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1952 tcp = pfd2tcb(pollv[j].fd);
1953 if (!tcp) {
1954 fprintf(stderr, "strace: lost proc\n");
1955 exit(1);
1956 }
1957 droptcb(tcp);
1958 return -1;
1959 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001960 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 last = j;
1962 return pollv[j].fd;
1963 }
1964 }
1965 fprintf(stderr, "strace: nothing ready\n");
1966 exit(1);
1967}
1968
1969static int
1970trace()
1971{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001972#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001973 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001974#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 struct tcb *tcp;
1976 int pfd;
1977 int what;
1978 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001979 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001980
1981 for (;;) {
1982 if (interactive)
1983 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1984
1985 if (nprocs == 0)
1986 break;
1987
1988 switch (nprocs) {
1989 case 1:
1990#ifndef HAVE_POLLABLE_PROCFS
1991 if (proc_poll_pipe[0] == -1) {
1992#endif
1993 tcp = pid2tcb(0);
1994 if (!tcp)
1995 continue;
1996 pfd = tcp->pfd;
1997 if (pfd == -1)
1998 continue;
1999 break;
2000#ifndef HAVE_POLLABLE_PROCFS
2001 }
2002 /* fall through ... */
2003#endif /* !HAVE_POLLABLE_PROCFS */
2004 default:
2005#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002006#ifdef POLL_HACK
2007 /* On some systems (e.g. UnixWare) we get too much ugly
2008 "unfinished..." stuff when multiple proceses are in
2009 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002010
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002011 if (in_syscall) {
2012 struct pollfd pv;
2013 tcp = in_syscall;
2014 in_syscall = NULL;
2015 pv.fd = tcp->pfd;
2016 pv.events = POLLWANT;
2017 if ((what = poll (&pv, 1, 1)) < 0) {
2018 if (interrupted)
2019 return 0;
2020 continue;
2021 }
2022 else if (what == 1 && pv.revents & POLLWANT) {
2023 goto FOUND;
2024 }
2025 }
2026#endif
2027
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028 if (poll(pollv, nprocs, INFTIM) < 0) {
2029 if (interrupted)
2030 return 0;
2031 continue;
2032 }
2033#else /* !HAVE_POLLABLE_PROCFS */
2034 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2035 if (interrupted)
2036 return 0;
2037 continue;
2038 }
2039#endif /* !HAVE_POLLABLE_PROCFS */
2040 pfd = choose_pfd();
2041 if (pfd == -1)
2042 continue;
2043 break;
2044 }
2045
2046 /* Look up `pfd' in our table. */
2047 if ((tcp = pfd2tcb(pfd)) == NULL) {
2048 fprintf(stderr, "unknown pfd: %u\n", pfd);
2049 exit(1);
2050 }
John Hughesb6643082002-05-23 11:02:22 +00002051#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002052 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002053#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054 /* Get the status of the process. */
2055 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002056#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002057 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002058#else /* FREEBSD */
2059 /* Thanks to some scheduling mystery, the first poller
2060 sometimes waits for the already processed end of fork
2061 event. Doing a non blocking poll here solves the problem. */
2062 if (proc_poll_pipe[0] != -1)
2063 ioctl_result = IOCTL_STATUS (tcp);
2064 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002065 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002066#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067 ioctl_errno = errno;
2068#ifndef HAVE_POLLABLE_PROCFS
2069 if (proc_poll_pipe[0] != -1) {
2070 if (ioctl_result < 0)
2071 kill(poller_pid, SIGKILL);
2072 else
2073 kill(poller_pid, SIGUSR1);
2074 }
2075#endif /* !HAVE_POLLABLE_PROCFS */
2076 }
2077 if (interrupted)
2078 return 0;
2079
2080 if (interactive)
2081 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2082
2083 if (ioctl_result < 0) {
2084 /* Find out what happened if it failed. */
2085 switch (ioctl_errno) {
2086 case EINTR:
2087 case EBADF:
2088 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002089#ifdef FREEBSD
2090 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002091#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 case ENOENT:
2093 droptcb(tcp);
2094 continue;
2095 default:
2096 perror("PIOCWSTOP");
2097 exit(1);
2098 }
2099 }
2100
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002101#ifdef FREEBSD
2102 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2103 /* discard first event for a syscall we never entered */
2104 IOCTL (tcp->pfd, PIOCRUN, 0);
2105 continue;
2106 }
Roland McGrath553a6092002-12-16 20:40:39 +00002107#endif
2108
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002109 /* clear the just started flag */
2110 tcp->flags &= ~TCB_STARTUP;
2111
2112 /* set current output file */
2113 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002114 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002115
2116 if (cflag) {
2117 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002118#ifdef FREEBSD
2119 char buf[1024];
2120 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002122 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2123 buf[len] = '\0';
2124 sscanf(buf,
2125 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2126 &stime.tv_sec, &stime.tv_usec);
2127 } else
2128 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002129#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2131 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002132#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002133 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2134 tcp->stime = stime;
2135 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002136 what = tcp->status.PR_WHAT;
2137 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002138#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002140 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2141 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 if (trace_syscall(tcp) < 0) {
2143 fprintf(stderr, "syscall trouble\n");
2144 exit(1);
2145 }
2146 }
2147 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002148#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002149 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002150#ifdef POLL_HACK
2151 in_syscall = tcp;
2152#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 case PR_SYSEXIT:
2154 if (trace_syscall(tcp) < 0) {
2155 fprintf(stderr, "syscall trouble\n");
2156 exit(1);
2157 }
2158 break;
2159 case PR_SIGNALLED:
2160 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2161 printleader(tcp);
2162 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002163 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002164 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002165#ifdef PR_INFO
2166 if (tcp->status.PR_INFO.si_signo == what) {
2167 printleader(tcp);
2168 tprintf(" siginfo=");
2169 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002170 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002171 }
2172#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002173 }
2174 break;
2175 case PR_FAULTED:
2176 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2177 printleader(tcp);
2178 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002179 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002180 }
2181 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002182#ifdef FREEBSD
2183 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002184 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002185#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002187 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188 exit(1);
2189 break;
2190 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002191 /* Remember current print column before continuing. */
2192 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002193 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002194#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002195 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002196#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002197 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002198#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199 perror("PIOCRUN");
2200 exit(1);
2201 }
2202 }
2203 return 0;
2204}
2205
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002206#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002208#ifdef TCB_GROUP_EXITING
2209/* Handle an exit detach or death signal that is taking all the
2210 related clone threads with it. This is called in three circumstances:
2211 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2212 SIG == 0 Continuing TCP will perform an exit_group syscall.
2213 SIG == other Continuing TCP with SIG will kill the process.
2214*/
2215static int
2216handle_group_exit(struct tcb *tcp, int sig)
2217{
2218 /* We need to locate our records of all the clone threads
2219 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002220 struct tcb *leader = NULL;
2221
2222 if (tcp->flags & TCB_CLONE_THREAD)
2223 leader = tcp->parent;
2224 else if (tcp->nclone_detached > 0)
2225 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002226
2227 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002228 if (leader != NULL && leader != tcp
2229 && !(leader->flags & TCB_GROUP_EXITING)
2230 && !(tcp->flags & TCB_STARTUP)
2231 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002232 fprintf(stderr,
2233 "PANIC: handle_group_exit: %d leader %d\n",
2234 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002235 }
2236 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002237#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002238 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002239#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002240 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002241 }
2242 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002243 /* Mark that we are taking the process down. */
2244 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002245 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002246 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002247 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002248 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002249 } else {
2250 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2251 cleanup();
2252 return -1;
2253 }
2254 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002255 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002256 if (leader != tcp)
2257 droptcb(tcp);
2258 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002259 /* The leader will report to us as parent now,
2260 and then we'll get to the SIG==-1 case. */
2261 return 0;
2262 }
2263 }
2264
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002265 return 0;
2266}
2267#endif
2268
Roland McGratheb9e2e82009-06-02 16:49:22 -07002269static int
2270trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002271{
2272 int pid;
2273 int wait_errno;
2274 int status;
2275 struct tcb *tcp;
2276#ifdef LINUX
2277 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002278#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002279 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002280#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002281#endif /* LINUX */
2282
Roland McGratheb9e2e82009-06-02 16:49:22 -07002283 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002284 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002285 return 0;
2286 if (interactive)
2287 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002289#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002290 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002291 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002292 /* this kernel does not support __WALL */
2293 wait4_options &= ~__WALL;
2294 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002295 pid = wait4(-1, &status, wait4_options,
2296 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002297 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002298 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002299 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002300 pid = wait4(-1, &status, __WCLONE,
2301 cflag ? &ru : NULL);
2302 if (pid == -1) {
2303 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002304 "failed: %s\n", strerror(errno));
2305 }
2306 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002307#else
2308 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2309#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002310#endif /* LINUX */
2311#ifdef SUNOS4
2312 pid = wait(&status);
2313#endif /* SUNOS4 */
2314 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002315 if (interactive)
2316 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002317
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002318 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002319 switch (wait_errno) {
2320 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002321 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002322 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002323 /*
2324 * We would like to verify this case
2325 * but sometimes a race in Solbourne's
2326 * version of SunOS sometimes reports
2327 * ECHILD before sending us SIGCHILD.
2328 */
2329#if 0
Roland McGratheb9e2e82009-06-02 16:49:22 -07002330 if (nprocs == 0)
2331 return 0;
2332 fprintf(stderr, "strace: proc miscount\n");
2333 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002335 return 0;
2336 default:
2337 errno = wait_errno;
2338 perror("strace: wait");
2339 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002340 }
2341 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002342 if (pid == popen_pid) {
2343 if (WIFEXITED(status) || WIFSIGNALED(status))
2344 popen_pid = -1;
2345 continue;
2346 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 if (debug)
2348 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2349
2350 /* Look up `pid' in our table. */
2351 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002352#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002353 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002354 /* This is needed to go with the CLONE_PTRACE
2355 changes in process.c/util.c: we might see
2356 the child's initial trap before we see the
2357 parent return from the clone syscall.
2358 Leave the child suspended until the parent
2359 returns from its system call. Only then
2360 will we have the association of parent and
2361 child so that we know how to do clearbpt
2362 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002363 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002364 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002365 if (!qflag)
2366 fprintf(stderr, "\
2367Process %d attached (waiting for parent)\n",
2368 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002369 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002370 else
2371 /* This can happen if a clone call used
2372 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002373#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002374 {
2375 fprintf(stderr, "unknown pid: %u\n", pid);
2376 if (WIFSTOPPED(status))
2377 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2378 exit(1);
2379 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002380 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002381 /* set current output file */
2382 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002383 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002384 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002385#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2387 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002388#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002389 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002390
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002391 if (tcp->flags & TCB_SUSPENDED) {
2392 /*
2393 * Apparently, doing any ptrace() call on a stopped
2394 * process, provokes the kernel to report the process
2395 * status again on a subsequent wait(), even if the
2396 * process has not been actually restarted.
2397 * Since we have inspected the arguments of suspended
2398 * processes we end up here testing for this case.
2399 */
2400 continue;
2401 }
2402 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002403 if (pid == strace_child)
2404 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002405 if (!cflag
2406 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2407 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002408 tprintf("+++ killed by %s %s+++",
2409 signame(WTERMSIG(status)),
2410#ifdef WCOREDUMP
2411 WCOREDUMP(status) ? "(core dumped) " :
2412#endif
2413 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002414 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002416#ifdef TCB_GROUP_EXITING
2417 handle_group_exit(tcp, -1);
2418#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002419 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002420#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002421 continue;
2422 }
2423 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002424 if (pid == strace_child)
2425 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002426 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002427 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2428 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002429#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002430 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002431 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002432#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002433 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002435 "PANIC: attached pid %u exited with %d\n",
2436 pid, WEXITSTATUS(status));
2437 }
Roland McGrath0a396902003-06-10 03:05:53 +00002438 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002439 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002440 tprintf(" <unfinished ... exit status %d>\n",
2441 WEXITSTATUS(status));
2442 tcp_last = NULL;
2443 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002444#ifdef TCB_GROUP_EXITING
2445 handle_group_exit(tcp, -1);
2446#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002447 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002448#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449 continue;
2450 }
2451 if (!WIFSTOPPED(status)) {
2452 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2453 droptcb(tcp);
2454 continue;
2455 }
2456 if (debug)
2457 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002458 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002459
Roland McGrath02203312007-06-11 22:06:31 +00002460 /*
2461 * Interestingly, the process may stop
2462 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002463 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002464 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002465 * A no-MMU vforked child won't send up a signal,
2466 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002467 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002468 if ((tcp->flags & TCB_STARTUP) &&
2469 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002470 /*
2471 * This flag is there to keep us in sync.
2472 * Next time this process stops it should
2473 * really be entering a system call.
2474 */
2475 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002476 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002477 /*
2478 * One example is a breakpoint inherited from
2479 * parent through fork ().
2480 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002481 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2482 droptcb(tcp);
2483 cleanup();
2484 return -1;
2485 }
2486 }
2487 goto tracing;
2488 }
2489
Roland McGratheb9e2e82009-06-02 16:49:22 -07002490 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002491 if (WSTOPSIG(status) == SIGSTOP &&
2492 (tcp->flags & TCB_SIGTRAPPED)) {
2493 /*
2494 * Trapped attempt to block SIGTRAP
2495 * Hope we are back in control now.
2496 */
2497 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002498 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002499 cleanup();
2500 return -1;
2501 }
2502 continue;
2503 }
2504 if (!cflag
2505 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002506 unsigned long addr = 0;
2507 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002508#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002509# define PSR_RI 41
2510 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002511 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002512
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002513 upeek(tcp, PT_CR_IPSR, &psr);
2514 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002515
2516 pc += (psr >> PSR_RI) & 0x3;
2517 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2518 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002519#elif defined PTRACE_GETSIGINFO
2520 if (WSTOPSIG(status) == SIGSEGV ||
2521 WSTOPSIG(status) == SIGBUS) {
2522 siginfo_t si;
2523 if (ptrace(PTRACE_GETSIGINFO, pid,
2524 0, &si) == 0)
2525 addr = (unsigned long)
2526 si.si_addr;
2527 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002528#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002529 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002530 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002531 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002532 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002533 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 }
Roland McGrath05690952004-10-20 01:00:27 +00002535 if (((tcp->flags & TCB_ATTACHED) ||
2536 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002538#ifdef TCB_GROUP_EXITING
2539 handle_group_exit(tcp, WSTOPSIG(status));
2540#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002541 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002542#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 continue;
2544 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002545 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002546 cleanup();
2547 return -1;
2548 }
2549 tcp->flags &= ~TCB_SUSPENDED;
2550 continue;
2551 }
Roland McGrath02203312007-06-11 22:06:31 +00002552 /* we handled the STATUS, we are permitted to interrupt now. */
2553 if (interrupted)
2554 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002555 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2556 /* ptrace() failed in trace_syscall() with ESRCH.
2557 * Likely a result of process disappearing mid-flight.
2558 * Observed case: exit_group() terminating
2559 * all processes in thread group. In this case, threads
2560 * "disappear" in an unpredictable moment without any
2561 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002562 */
2563 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002564 if (tcp_last) {
2565 /* Do we have dangling line "syscall(param, param"?
2566 * Finish the line then. We cannot
2567 */
2568 tcp_last->flags |= TCB_REPRINT;
2569 tprintf(" <unfinished ...>");
2570 printtrailer();
2571 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002573 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002574 ptrace(PTRACE_KILL,
2575 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002576 droptcb(tcp);
2577 }
2578 continue;
2579 }
2580 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002581#ifdef TCB_GROUP_EXITING
2582 if (tcp->flags & TCB_GROUP_EXITING) {
2583 if (handle_group_exit(tcp, 0) < 0)
2584 return -1;
2585 continue;
2586 }
2587#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002588 if (tcp->flags & TCB_ATTACHED)
2589 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002590 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002591 cleanup();
2592 return -1;
2593 }
2594 continue;
2595 }
2596 if (tcp->flags & TCB_SUSPENDED) {
2597 if (!qflag)
2598 fprintf(stderr, "Process %u suspended\n", pid);
2599 continue;
2600 }
2601 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002602 /* Remember current print column before continuing. */
2603 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002604 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605 cleanup();
2606 return -1;
2607 }
2608 }
2609 return 0;
2610}
2611
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002612#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002614#ifdef __STDC__
2615#include <stdarg.h>
2616#define VA_START(a, b) va_start(a, b)
2617#else
2618#include <varargs.h>
2619#define VA_START(a, b) va_start(a)
2620#endif
2621
2622void
2623#ifdef __STDC__
2624tprintf(const char *fmt, ...)
2625#else
2626tprintf(fmt, va_alist)
2627char *fmt;
2628va_dcl
2629#endif
2630{
2631 va_list args;
2632
2633 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002634 if (outf) {
2635 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002636 if (n < 0) {
2637 if (outf != stderr)
2638 perror(outfname == NULL
2639 ? "<writing to pipe>" : outfname);
2640 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002641 curcol += n;
2642 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002643 va_end(args);
2644 return;
2645}
2646
2647void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002648printleader(tcp)
2649struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002650{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002651 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002652 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002653 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002654 tprintf(" <unavailable>)");
2655 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002656 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002657 tprintf("= ? <unavailable>\n");
2658 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002659 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002660 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002661 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002662 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002663 }
2664 curcol = 0;
2665 if ((followfork == 1 || pflag_seen > 1) && outfname)
2666 tprintf("%-5d ", tcp->pid);
2667 else if (nprocs > 1 && !outfname)
2668 tprintf("[pid %5u] ", tcp->pid);
2669 if (tflag) {
2670 char str[sizeof("HH:MM:SS")];
2671 struct timeval tv, dtv;
2672 static struct timeval otv;
2673
2674 gettimeofday(&tv, NULL);
2675 if (rflag) {
2676 if (otv.tv_sec == 0)
2677 otv = tv;
2678 tv_sub(&dtv, &tv, &otv);
2679 tprintf("%6ld.%06ld ",
2680 (long) dtv.tv_sec, (long) dtv.tv_usec);
2681 otv = tv;
2682 }
2683 else if (tflag > 2) {
2684 tprintf("%ld.%06ld ",
2685 (long) tv.tv_sec, (long) tv.tv_usec);
2686 }
2687 else {
2688 time_t local = tv.tv_sec;
2689 strftime(str, sizeof(str), "%T", localtime(&local));
2690 if (tflag > 1)
2691 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2692 else
2693 tprintf("%s ", str);
2694 }
2695 }
2696 if (iflag)
2697 printcall(tcp);
2698}
2699
2700void
2701tabto(col)
2702int col;
2703{
2704 if (curcol < col)
2705 tprintf("%*s", col - curcol, "");
2706}
2707
2708void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002709printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002710{
2711 tprintf("\n");
2712 tcp_last = NULL;
2713}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002714
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002715#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002716
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002717int
2718mp_ioctl(int fd, int cmd, void *arg, int size)
2719{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002720 struct iovec iov[2];
2721 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002722
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002723 iov[0].iov_base = &cmd;
2724 iov[0].iov_len = sizeof cmd;
2725 if (arg) {
2726 ++n;
2727 iov[1].iov_base = arg;
2728 iov[1].iov_len = size;
2729 }
Roland McGrath553a6092002-12-16 20:40:39 +00002730
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002731 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002732}
2733
2734#endif