blob: 40d1e8d58b1ed78f4ff86288c4ffdee0a1ffa733 [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;
Denys Vlasenko96d5a762008-12-29 19:13:27 +0000107static int ptrace_stop_sig = SIGTRAP;
108static bool ptrace_opts_set;
Dmitry V. Levina6809652008-11-10 17:14:58 +0000109
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000110static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111uid_t run_uid;
112gid_t run_gid;
113
114int acolumn = DEFAULT_ACOLUMN;
115int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000116static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +0000118struct tcb **tcbtab;
119unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120char *progname;
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
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000216static int
217set_cloexec_flag(int fd)
218{
219 int flags, newflags;
220
221 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
222 {
223 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
224 progname, strerror(errno));
225 return -1;
226 }
227
228 newflags = flags | FD_CLOEXEC;
229 if (flags == newflags)
230 return 0;
231
232 if (fcntl(fd, F_SETFD, newflags) < 0)
233 {
234 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
235 progname, strerror(errno));
236 return -1;
237 }
238
239 return 0;
240}
241
242/*
243 * When strace is setuid executable, we have to swap uids
244 * before and after filesystem and process management operations.
245 */
246static void
247swap_uid(void)
248{
249#ifndef SVR4
250 int euid = geteuid(), uid = getuid();
251
252 if (euid != uid && setreuid(euid, uid) < 0)
253 {
254 fprintf(stderr, "%s: setreuid: %s\n",
255 progname, strerror(errno));
256 exit(1);
257 }
258#endif
259}
260
Roland McGrath4bfa6262007-07-05 20:03:16 +0000261#if _LFS64_LARGEFILE
262# define fopen_for_output fopen64
263#else
264# define fopen_for_output fopen
265#endif
266
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000267static FILE *
268strace_fopen(const char *path, const char *mode)
269{
270 FILE *fp;
271
272 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000273 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000274 fprintf(stderr, "%s: can't fopen '%s': %s\n",
275 progname, path, strerror(errno));
276 swap_uid();
277 if (fp && set_cloexec_flag(fileno(fp)) < 0)
278 {
279 fclose(fp);
280 fp = NULL;
281 }
282 return fp;
283}
284
285static int popen_pid = -1;
286
287#ifndef _PATH_BSHELL
288# define _PATH_BSHELL "/bin/sh"
289#endif
290
291/*
292 * We cannot use standard popen(3) here because we have to distinguish
293 * popen child process from other processes we trace, and standard popen(3)
294 * does not export its child's pid.
295 */
296static FILE *
297strace_popen(const char *command)
298{
299 int fds[2];
300
301 swap_uid();
302 if (pipe(fds) < 0)
303 {
304 fprintf(stderr, "%s: pipe: %s\n",
305 progname, strerror(errno));
306 swap_uid();
307 return NULL;
308 }
309
310 if (set_cloexec_flag(fds[1]) < 0)
311 {
312 close(fds[0]);
313 close(fds[1]);
314 swap_uid();
315 return NULL;
316 }
317
318 if ((popen_pid = fork()) == -1)
319 {
320 fprintf(stderr, "%s: fork: %s\n",
321 progname, strerror(errno));
322 close(fds[0]);
323 close(fds[1]);
324 swap_uid();
325 return NULL;
326 }
327
328 if (popen_pid)
329 {
330 /* parent */
331 close(fds[0]);
332 swap_uid();
333 return fdopen(fds[1], "w");
334 } else
335 {
336 /* child */
337 close(fds[1]);
338 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
339 {
340 fprintf(stderr, "%s: dup2: %s\n",
341 progname, strerror(errno));
342 _exit(1);
343 }
344 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
345 fprintf(stderr, "%s: execl: %s: %s\n",
346 progname, _PATH_BSHELL, strerror(errno));
347 _exit(1);
348 }
349}
350
351static int
352newoutf(struct tcb *tcp)
353{
354 if (outfname && followfork > 1) {
355 char name[MAXPATHLEN];
356 FILE *fp;
357
358 sprintf(name, "%s.%u", outfname, tcp->pid);
359 if ((fp = strace_fopen(name, "w")) == NULL)
360 return -1;
361 tcp->outf = fp;
362 }
363 return 0;
364}
365
Roland McGrath02203312007-06-11 22:06:31 +0000366static void
367startup_attach(void)
368{
369 int tcbi;
370 struct tcb *tcp;
371
372 /*
373 * Block user interruptions as we would leave the traced
374 * process stopped (process state T) if we would terminate in
375 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
376 * We rely on cleanup () from this point on.
377 */
378 if (interactive)
379 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
380
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000381 if (daemonized_tracer) {
382 pid_t pid = fork();
383 if (pid < 0) {
384 _exit(1);
385 }
386 if (pid) { /* parent */
387 /*
388 * Wait for child to attach to straced process
389 * (our parent). Child SIGKILLs us after it attached.
390 * Parent's wait() is unblocked by our death,
391 * it proceeds to exec the straced program.
392 */
393 pause();
394 _exit(0); /* paranoia */
395 }
396 }
397
Roland McGrath02203312007-06-11 22:06:31 +0000398 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
399 tcp = tcbtab[tcbi];
400 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
401 continue;
402#ifdef LINUX
403 if (tcp->flags & TCB_CLONE_THREAD)
404 continue;
405#endif
406 /* Reinitialize the output since it may have changed. */
407 tcp->outf = outf;
408 if (newoutf(tcp) < 0)
409 exit(1);
410
411#ifdef USE_PROCFS
412 if (proc_open(tcp, 1) < 0) {
413 fprintf(stderr, "trouble opening proc file\n");
414 droptcb(tcp);
415 continue;
416 }
417#else /* !USE_PROCFS */
418# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000419 if (followfork && !daemonized_tracer) {
Roland McGrath02203312007-06-11 22:06:31 +0000420 char procdir[MAXPATHLEN];
421 DIR *dir;
422
423 sprintf(procdir, "/proc/%d/task", tcp->pid);
424 dir = opendir(procdir);
425 if (dir != NULL) {
426 unsigned int ntid = 0, nerr = 0;
427 struct dirent *de;
428 int tid;
429 while ((de = readdir(dir)) != NULL) {
430 if (de->d_fileno == 0 ||
431 de->d_name[0] == '.')
432 continue;
433 tid = atoi(de->d_name);
434 if (tid <= 0)
435 continue;
436 ++ntid;
437 if (ptrace(PTRACE_ATTACH, tid,
438 (char *) 1, 0) < 0)
439 ++nerr;
440 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000441 tcp = alloctcb(tid);
Roland McGrath02203312007-06-11 22:06:31 +0000442 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
443 tcbtab[tcbi]->nchildren++;
444 tcbtab[tcbi]->nclone_threads++;
445 tcbtab[tcbi]->nclone_detached++;
446 tcp->parent = tcbtab[tcbi];
447 }
448 if (interactive) {
449 sigprocmask(SIG_SETMASK, &empty_set, NULL);
450 if (interrupted)
451 return;
452 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
453 }
454 }
455 closedir(dir);
456 if (nerr == ntid) {
457 perror("attach: ptrace(PTRACE_ATTACH, ...)");
458 droptcb(tcp);
459 continue;
460 }
461 if (!qflag) {
462 ntid -= nerr;
463 if (ntid > 1)
464 fprintf(stderr, "\
465Process %u attached with %u threads - interrupt to quit\n",
466 tcp->pid, ntid);
467 else
468 fprintf(stderr, "\
469Process %u attached - interrupt to quit\n",
470 tcp->pid);
471 }
472 continue;
473 }
474 }
475# endif
476 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
477 perror("attach: ptrace(PTRACE_ATTACH, ...)");
478 droptcb(tcp);
479 continue;
480 }
481 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000482
483 if (daemonized_tracer) {
484 /*
485 * It is our grandparent we trace, not a -p PID.
486 * Don't want to just detach on exit, so...
487 */
488 tcp->flags &= ~TCB_ATTACHED;
489 /*
490 * Make parent go away.
491 * Also makes grandparent's wait() unblock.
492 */
493 kill(getppid(), SIGKILL);
494 }
495
Roland McGrath02203312007-06-11 22:06:31 +0000496#endif /* !USE_PROCFS */
497 if (!qflag)
498 fprintf(stderr,
499 "Process %u attached - interrupt to quit\n",
500 tcp->pid);
501 }
502
503 if (interactive)
504 sigprocmask(SIG_SETMASK, &empty_set, NULL);
505}
506
507static void
508startup_child (char **argv)
509{
510 struct stat statbuf;
511 const char *filename;
512 char pathname[MAXPATHLEN];
513 int pid = 0;
514 struct tcb *tcp;
515
516 filename = argv[0];
517 if (strchr(filename, '/')) {
518 if (strlen(filename) > sizeof pathname - 1) {
519 errno = ENAMETOOLONG;
520 perror("strace: exec");
521 exit(1);
522 }
523 strcpy(pathname, filename);
524 }
525#ifdef USE_DEBUGGING_EXEC
526 /*
527 * Debuggers customarily check the current directory
528 * first regardless of the path but doing that gives
529 * security geeks a panic attack.
530 */
531 else if (stat(filename, &statbuf) == 0)
532 strcpy(pathname, filename);
533#endif /* USE_DEBUGGING_EXEC */
534 else {
535 char *path;
536 int m, n, len;
537
538 for (path = getenv("PATH"); path && *path; path += m) {
539 if (strchr(path, ':')) {
540 n = strchr(path, ':') - path;
541 m = n + 1;
542 }
543 else
544 m = n = strlen(path);
545 if (n == 0) {
546 if (!getcwd(pathname, MAXPATHLEN))
547 continue;
548 len = strlen(pathname);
549 }
550 else if (n > sizeof pathname - 1)
551 continue;
552 else {
553 strncpy(pathname, path, n);
554 len = n;
555 }
556 if (len && pathname[len - 1] != '/')
557 pathname[len++] = '/';
558 strcpy(pathname + len, filename);
559 if (stat(pathname, &statbuf) == 0 &&
560 /* Accept only regular files
561 with some execute bits set.
562 XXX not perfect, might still fail */
563 S_ISREG(statbuf.st_mode) &&
564 (statbuf.st_mode & 0111))
565 break;
566 }
567 }
568 if (stat(pathname, &statbuf) < 0) {
569 fprintf(stderr, "%s: %s: command not found\n",
570 progname, filename);
571 exit(1);
572 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000573 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000574 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000575 perror("strace: fork");
576 cleanup();
577 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000578 }
579 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
580 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
581 ) {
582 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000583#ifdef USE_PROCFS
584 if (outf != stderr) close (fileno (outf));
585#ifdef MIPS
586 /* Kludge for SGI, see proc_open for details. */
587 sa.sa_handler = foobar;
588 sa.sa_flags = 0;
589 sigemptyset(&sa.sa_mask);
590 sigaction(SIGINT, &sa, NULL);
591#endif /* MIPS */
592#ifndef FREEBSD
593 pause();
594#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000595 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000596#endif /* FREEBSD */
597#else /* !USE_PROCFS */
598 if (outf!=stderr)
599 close(fileno (outf));
600
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000601 if (!daemonized_tracer) {
602 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
603 perror("strace: ptrace(PTRACE_TRACEME, ...)");
604 exit(1);
605 }
606 if (debug)
607 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000608 }
Roland McGrath02203312007-06-11 22:06:31 +0000609
610 if (username != NULL || geteuid() == 0) {
611 uid_t run_euid = run_uid;
612 gid_t run_egid = run_gid;
613
614 if (statbuf.st_mode & S_ISUID)
615 run_euid = statbuf.st_uid;
616 if (statbuf.st_mode & S_ISGID)
617 run_egid = statbuf.st_gid;
618
619 /*
620 * It is important to set groups before we
621 * lose privileges on setuid.
622 */
623 if (username != NULL) {
624 if (initgroups(username, run_gid) < 0) {
625 perror("initgroups");
626 exit(1);
627 }
628 if (setregid(run_gid, run_egid) < 0) {
629 perror("setregid");
630 exit(1);
631 }
632 if (setreuid(run_uid, run_euid) < 0) {
633 perror("setreuid");
634 exit(1);
635 }
636 }
637 }
638 else
639 setreuid(run_uid, run_uid);
640
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000641 if (!daemonized_tracer) {
642 /*
643 * Induce an immediate stop so that the parent
644 * will resume us with PTRACE_SYSCALL and display
645 * this execve call normally.
646 */
647 kill(getpid(), SIGSTOP);
648 } else {
649 struct sigaction sv_sigchld;
650 sigaction(SIGCHLD, NULL, &sv_sigchld);
651 /*
652 * Make sure it is not SIG_IGN, otherwise wait
653 * will not block.
654 */
655 signal(SIGCHLD, SIG_DFL);
656 /*
657 * Wait for grandchild to attach to us.
658 * It kills child after that, and wait() unblocks.
659 */
660 alarm(3);
661 wait(NULL);
662 alarm(0);
663 sigaction(SIGCHLD, &sv_sigchld, NULL);
664 }
Roland McGrath02203312007-06-11 22:06:31 +0000665#endif /* !USE_PROCFS */
666
667 execv(pathname, argv);
668 perror("strace: exec");
669 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000670 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000671
672 /* We are the tracer. */
673 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000674 if (daemonized_tracer) {
675 /* We want subsequent startup_attach() to attach to it. */
676 tcp->flags |= TCB_ATTACHED;
677 }
Roland McGrath02203312007-06-11 22:06:31 +0000678#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000679 if (proc_open(tcp, 0) < 0) {
680 fprintf(stderr, "trouble opening proc file\n");
681 cleanup();
682 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000683 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000684#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000685}
686
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000687int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000688main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690 struct tcb *tcp;
691 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000692 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693 struct sigaction sa;
694
695 static char buf[BUFSIZ];
696
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000697 progname = argv[0] ? argv[0] : "strace";
698
Roland McGrathee9d4352002-12-18 04:16:10 +0000699 /* Allocate the initial tcbtab. */
700 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000701 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000702 fprintf(stderr, "%s: out of memory\n", progname);
703 exit(1);
704 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000705 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000706 fprintf(stderr, "%s: out of memory\n", progname);
707 exit(1);
708 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000709 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
710 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
711
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712 outf = stderr;
713 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000714 set_sortby(DEFAULT_SORTBY);
715 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000716 qualify("trace=all");
717 qualify("abbrev=all");
718 qualify("verbose=all");
719 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000721 "+cdfFhiqrtTvVxz"
722#ifndef USE_PROCFS
723 "D"
724#endif
725 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000726 switch (c) {
727 case 'c':
728 cflag++;
729 dtime++;
730 break;
731 case 'd':
732 debug++;
733 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000734#ifndef USE_PROCFS
735 /* Experimental, not documented in manpage yet. */
736 case 'D':
737 daemonized_tracer = 1;
738 break;
739#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000740 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000741 optF = 1;
742 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000743 case 'f':
744 followfork++;
745 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000746 case 'h':
747 usage(stdout, 0);
748 break;
749 case 'i':
750 iflag++;
751 break;
752 case 'q':
753 qflag++;
754 break;
755 case 'r':
756 rflag++;
757 tflag++;
758 break;
759 case 't':
760 tflag++;
761 break;
762 case 'T':
763 dtime++;
764 break;
765 case 'x':
766 xflag++;
767 break;
768 case 'v':
769 qualify("abbrev=none");
770 break;
771 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000772 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000773 exit(0);
774 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000775 case 'z':
776 not_failing_only = 1;
777 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 case 'a':
779 acolumn = atoi(optarg);
780 break;
781 case 'e':
782 qualify(optarg);
783 break;
784 case 'o':
785 outfname = strdup(optarg);
786 break;
787 case 'O':
788 set_overhead(atoi(optarg));
789 break;
790 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000791 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 fprintf(stderr, "%s: Invalid process id: %s\n",
793 progname, optarg);
794 break;
795 }
796 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000797 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000798 break;
799 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000800 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000801 tcp->flags |= TCB_ATTACHED;
802 pflag_seen++;
803 break;
804 case 's':
805 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000806 if (max_strlen < 0) {
807 fprintf(stderr,
808 "%s: invalid -s argument: %s\n",
809 progname, optarg);
810 exit(1);
811 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 break;
813 case 'S':
814 set_sortby(optarg);
815 break;
816 case 'u':
817 username = strdup(optarg);
818 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000819 case 'E':
820 if (putenv(optarg) < 0) {
821 fprintf(stderr, "%s: out of memory\n",
822 progname);
823 exit(1);
824 }
825 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 default:
827 usage(stderr, 1);
828 break;
829 }
830 }
831
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000832 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000833 usage(stderr, 1);
834
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000835 if (!followfork)
836 followfork = optF;
837
Roland McGrathcb9def62006-04-25 07:48:03 +0000838 if (followfork > 1 && cflag) {
839 fprintf(stderr,
840 "%s: -c and -ff are mutually exclusive options\n",
841 progname);
842 exit(1);
843 }
844
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845 /* See if they want to run as another user. */
846 if (username != NULL) {
847 struct passwd *pent;
848
849 if (getuid() != 0 || geteuid() != 0) {
850 fprintf(stderr,
851 "%s: you must be root to use the -u option\n",
852 progname);
853 exit(1);
854 }
855 if ((pent = getpwnam(username)) == NULL) {
856 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000857 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 exit(1);
859 }
860 run_uid = pent->pw_uid;
861 run_gid = pent->pw_gid;
862 }
863 else {
864 run_uid = getuid();
865 run_gid = getgid();
866 }
867
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868 /* Check if they want to redirect the output. */
869 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000870 /* See if they want to pipe the output. */
871 if (outfname[0] == '|' || outfname[0] == '!') {
872 /*
873 * We can't do the <outfname>.PID funny business
874 * when using popen, so prohibit it.
875 */
876 if (followfork > 1) {
877 fprintf(stderr, "\
878%s: piping the output and -ff are mutually exclusive options\n",
879 progname);
880 exit(1);
881 }
882
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000883 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000884 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000885 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000886 else if (followfork <= 1 &&
887 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889 }
890
Roland McGrath37b9a662003-11-07 02:26:54 +0000891 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000892 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000893 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000896 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000897 /* Valid states here:
898 optind < argc pflag_seen outfname interactive
899 1 0 0 1
900 0 1 0 1
901 1 0 1 0
902 0 1 1 1
903 */
904
905 /* STARTUP_CHILD must be called before the signal handlers get
906 installed below as they are inherited into the spawned process.
907 Also we do not need to be protected by them as during interruption
908 in the STARTUP_CHILD mode we kill the spawned process anyway. */
909 if (!pflag_seen)
910 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000911
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 sigemptyset(&empty_set);
913 sigemptyset(&blocked_set);
914 sa.sa_handler = SIG_IGN;
915 sigemptyset(&sa.sa_mask);
916 sa.sa_flags = 0;
917 sigaction(SIGTTOU, &sa, NULL);
918 sigaction(SIGTTIN, &sa, NULL);
919 if (interactive) {
920 sigaddset(&blocked_set, SIGHUP);
921 sigaddset(&blocked_set, SIGINT);
922 sigaddset(&blocked_set, SIGQUIT);
923 sigaddset(&blocked_set, SIGPIPE);
924 sigaddset(&blocked_set, SIGTERM);
925 sa.sa_handler = interrupt;
926#ifdef SUNOS4
927 /* POSIX signals on sunos4.1 are a little broken. */
928 sa.sa_flags = SA_INTERRUPT;
929#endif /* SUNOS4 */
930 }
931 sigaction(SIGHUP, &sa, NULL);
932 sigaction(SIGINT, &sa, NULL);
933 sigaction(SIGQUIT, &sa, NULL);
934 sigaction(SIGPIPE, &sa, NULL);
935 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000936#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000937 sa.sa_handler = reaper;
938 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000939#else
940 /* Make sure SIGCHLD has the default action so that waitpid
941 definitely works without losing track of children. The user
942 should not have given us a bogus state to inherit, but he might
943 have. Arguably we should detect SIG_IGN here and pass it on
944 to children, but probably noone really needs that. */
945 sa.sa_handler = SIG_DFL;
946 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000947#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000949 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000950 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000951
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952 if (trace() < 0)
953 exit(1);
954 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000955 fflush(NULL);
956 if (exit_code > 0xff) {
957 /* Child was killed by a signal, mimic that. */
958 exit_code &= 0xff;
959 signal(exit_code, SIG_DFL);
960 raise(exit_code);
961 /* Paranoia - what if this signal is not fatal?
962 Exit with 128 + signo then. */
963 exit_code += 128;
964 }
965 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966}
967
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000968void
969expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000970{
971 /* Allocate some more TCBs and expand the table.
972 We don't want to relocate the TCBs because our
973 callers have pointers and it would be a pain.
974 So tcbtab is a table of pointers. Since we never
975 free the TCBs, we allocate a single chunk of many. */
976 struct tcb **newtab = (struct tcb **)
977 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
978 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
979 sizeof *newtcbs);
980 int i;
981 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000982 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
983 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000984 cleanup();
985 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000986 }
987 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
988 newtab[i] = &newtcbs[i - tcbtabsize];
989 tcbtabsize *= 2;
990 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000991}
992
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000994alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995{
996 int i;
997 struct tcb *tcp;
998
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000999 if (nprocs == tcbtabsize)
1000 expand_tcbtab();
1001
Roland McGrathee9d4352002-12-18 04:16:10 +00001002 for (i = 0; i < tcbtabsize; i++) {
1003 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004 if ((tcp->flags & TCB_INUSE) == 0) {
1005 tcp->pid = pid;
1006 tcp->parent = NULL;
1007 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +00001008 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001009#ifdef TCB_CLONE_THREAD
1010 tcp->nclone_threads = tcp->nclone_detached = 0;
1011 tcp->nclone_waiting = 0;
1012#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013 tcp->flags = TCB_INUSE | TCB_STARTUP;
1014 tcp->outf = outf; /* Initialise to current out file */
1015 tcp->stime.tv_sec = 0;
1016 tcp->stime.tv_usec = 0;
1017 tcp->pfd = -1;
1018 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001019 if (command_options_parsed)
1020 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 return tcp;
1022 }
1023 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001024 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1025 cleanup();
1026 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027}
1028
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001029#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001030int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001031proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032{
1033 char proc[32];
1034 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001035#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001036 int i;
1037 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 sigset_t signals;
1039 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001040#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041#ifndef HAVE_POLLABLE_PROCFS
1042 static int last_pfd;
1043#endif
1044
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001045#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001046 /* Open the process pseudo-files in /proc. */
1047 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1048 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 perror("strace: open(\"/proc/...\", ...)");
1050 return -1;
1051 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001052 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 return -1;
1054 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001055 sprintf(proc, "/proc/%d/status", tcp->pid);
1056 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1057 perror("strace: open(\"/proc/...\", ...)");
1058 return -1;
1059 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001060 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001061 return -1;
1062 }
1063 sprintf(proc, "/proc/%d/as", tcp->pid);
1064 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1065 perror("strace: open(\"/proc/...\", ...)");
1066 return -1;
1067 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001068 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001069 return -1;
1070 }
1071#else
1072 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001073#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001074 sprintf(proc, "/proc/%d", tcp->pid);
1075 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001076#else /* FREEBSD */
1077 sprintf(proc, "/proc/%d/mem", tcp->pid);
1078 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1079#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001080 perror("strace: open(\"/proc/...\", ...)");
1081 return -1;
1082 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001083 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001084 return -1;
1085 }
1086#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001087#ifdef FREEBSD
1088 sprintf(proc, "/proc/%d/regs", tcp->pid);
1089 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1090 perror("strace: open(\"/proc/.../regs\", ...)");
1091 return -1;
1092 }
1093 if (cflag) {
1094 sprintf(proc, "/proc/%d/status", tcp->pid);
1095 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1096 perror("strace: open(\"/proc/.../status\", ...)");
1097 return -1;
1098 }
1099 } else
1100 tcp->pfd_status = -1;
1101#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001102 rebuild_pollv();
1103 if (!attaching) {
1104 /*
1105 * Wait for the child to pause. Because of a race
1106 * condition we have to poll for the event.
1107 */
1108 for (;;) {
1109 if (IOCTL_STATUS (tcp) < 0) {
1110 perror("strace: PIOCSTATUS");
1111 return -1;
1112 }
1113 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001114 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001115 }
1116 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001117#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001118 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001119 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001120 perror("strace: PIOCSTOP");
1121 return -1;
1122 }
Roland McGrath553a6092002-12-16 20:40:39 +00001123#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124#ifdef PIOCSET
1125 /* Set Run-on-Last-Close. */
1126 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001127 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 perror("PIOCSET PR_RLC");
1129 return -1;
1130 }
1131 /* Set or Reset Inherit-on-Fork. */
1132 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001133 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001134 perror("PIOC{SET,RESET} PR_FORK");
1135 return -1;
1136 }
1137#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001138#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1140 perror("PIOCSRLC");
1141 return -1;
1142 }
1143 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1144 perror("PIOC{S,R}FORK");
1145 return -1;
1146 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001147#else /* FREEBSD */
1148 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1149 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1150 perror("PIOCGFL");
1151 return -1;
1152 }
1153 arg &= ~PF_LINGER;
1154 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1155 perror("PIOCSFL");
1156 return -1;
1157 }
1158#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001160#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001161 /* Enable all syscall entries we care about. */
1162 premptyset(&syscalls);
1163 for (i = 1; i < MAX_QUALS; ++i) {
1164 if (i > (sizeof syscalls) * CHAR_BIT) break;
1165 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1166 }
1167 praddset (&syscalls, SYS_execve);
1168 if (followfork) {
1169 praddset (&syscalls, SYS_fork);
1170#ifdef SYS_forkall
1171 praddset (&syscalls, SYS_forkall);
1172#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001173#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001174 praddset (&syscalls, SYS_fork1);
1175#endif
1176#ifdef SYS_rfork1
1177 praddset (&syscalls, SYS_rfork1);
1178#endif
1179#ifdef SYS_rforkall
1180 praddset (&syscalls, SYS_rforkall);
1181#endif
1182 }
1183 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184 perror("PIOCSENTRY");
1185 return -1;
1186 }
John Hughes19e49982001-10-19 08:59:12 +00001187 /* Enable the syscall exits. */
1188 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 perror("PIOSEXIT");
1190 return -1;
1191 }
John Hughes19e49982001-10-19 08:59:12 +00001192 /* Enable signals we care about. */
1193 premptyset(&signals);
1194 for (i = 1; i < MAX_QUALS; ++i) {
1195 if (i > (sizeof signals) * CHAR_BIT) break;
1196 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1197 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001198 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 perror("PIOCSTRACE");
1200 return -1;
1201 }
John Hughes19e49982001-10-19 08:59:12 +00001202 /* Enable faults we care about */
1203 premptyset(&faults);
1204 for (i = 1; i < MAX_QUALS; ++i) {
1205 if (i > (sizeof faults) * CHAR_BIT) break;
1206 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1207 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001208 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 perror("PIOCSFAULT");
1210 return -1;
1211 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001212#else /* FREEBSD */
1213 /* set events flags. */
1214 arg = S_SIG | S_SCE | S_SCX ;
1215 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1216 perror("PIOCBIS");
1217 return -1;
1218 }
1219#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220 if (!attaching) {
1221#ifdef MIPS
1222 /*
1223 * The SGI PRSABORT doesn't work for pause() so
1224 * we send it a caught signal to wake it up.
1225 */
1226 kill(tcp->pid, SIGINT);
1227#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001228#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001230 arg = PRSABORT;
1231 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232 perror("PIOCRUN");
1233 return -1;
1234 }
Roland McGrath553a6092002-12-16 20:40:39 +00001235#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001236#endif /* !MIPS*/
1237#ifdef FREEBSD
1238 /* wake up the child if it received the SIGSTOP */
1239 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001240#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 for (;;) {
1242 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001243 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244 perror("PIOCWSTOP");
1245 return -1;
1246 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001247 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001248 tcp->flags &= ~TCB_INSYSCALL;
1249 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001250 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251 break;
1252 }
1253 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001254#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001255 arg = 0;
1256 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001257#else /* FREEBSD */
1258 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001259#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 perror("PIOCRUN");
1261 return -1;
1262 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001263#ifdef FREEBSD
1264 /* handle the case where we "opened" the child before
1265 it did the kill -STOP */
1266 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1267 tcp->status.PR_WHAT == SIGSTOP)
1268 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001269#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001271#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001273#else /* FREEBSD */
1274 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001275 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001276 /* We are attaching to an already running process.
1277 * Try to figure out the state of the process in syscalls,
1278 * to handle the first event well.
1279 * This is done by having a look at the "wchan" property of the
1280 * process, which tells where it is stopped (if it is). */
1281 FILE * status;
1282 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001283
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001284 sprintf(proc, "/proc/%d/status", tcp->pid);
1285 status = fopen(proc, "r");
1286 if (status &&
1287 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1288 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1289 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1290 strcmp(wchan, "stopevent")) {
1291 /* The process is asleep in the middle of a syscall.
1292 Fake the syscall entry event */
1293 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1294 tcp->status.PR_WHY = PR_SYSENTRY;
1295 trace_syscall(tcp);
1296 }
1297 if (status)
1298 fclose(status);
1299 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001300 }
1301#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302#ifndef HAVE_POLLABLE_PROCFS
1303 if (proc_poll_pipe[0] != -1)
1304 proc_poller(tcp->pfd);
1305 else if (nprocs > 1) {
1306 proc_poll_open();
1307 proc_poller(last_pfd);
1308 proc_poller(tcp->pfd);
1309 }
1310 last_pfd = tcp->pfd;
1311#endif /* !HAVE_POLLABLE_PROCFS */
1312 return 0;
1313}
1314
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001315#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001317struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318pid2tcb(pid)
1319int pid;
1320{
1321 int i;
1322 struct tcb *tcp;
1323
Roland McGrathee9d4352002-12-18 04:16:10 +00001324 for (i = 0; i < tcbtabsize; i++) {
1325 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326 if (pid && tcp->pid != pid)
1327 continue;
1328 if (tcp->flags & TCB_INUSE)
1329 return tcp;
1330 }
1331 return NULL;
1332}
1333
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001334#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335
1336static struct tcb *
1337pfd2tcb(pfd)
1338int pfd;
1339{
1340 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341
Roland McGrathca16be82003-01-10 19:55:28 +00001342 for (i = 0; i < tcbtabsize; i++) {
1343 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001344 if (tcp->pfd != pfd)
1345 continue;
1346 if (tcp->flags & TCB_INUSE)
1347 return tcp;
1348 }
1349 return NULL;
1350}
1351
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001352#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353
1354void
1355droptcb(tcp)
1356struct tcb *tcp;
1357{
1358 if (tcp->pid == 0)
1359 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001360#ifdef TCB_CLONE_THREAD
1361 if (tcp->nclone_threads > 0) {
1362 /* There are other threads left in this process, but this
1363 is the one whose PID represents the whole process.
1364 We need to keep this record around as a zombie until
1365 all the threads die. */
1366 tcp->flags |= TCB_EXITING;
1367 return;
1368 }
1369#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001370 nprocs--;
1371 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001372
Roland McGrathe29341c2003-01-10 20:14:20 +00001373 if (tcp->parent != NULL) {
1374 tcp->parent->nchildren--;
1375#ifdef TCB_CLONE_THREAD
1376 if (tcp->flags & TCB_CLONE_DETACHED)
1377 tcp->parent->nclone_detached--;
1378 if (tcp->flags & TCB_CLONE_THREAD)
1379 tcp->parent->nclone_threads--;
1380#endif
Roland McGrath09623452003-05-23 02:27:13 +00001381#ifdef TCB_CLONE_DETACHED
1382 if (!(tcp->flags & TCB_CLONE_DETACHED))
1383#endif
1384 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001385#ifdef LINUX
1386 /* Update `tcp->parent->parent->nchildren' and the other fields
1387 like NCLONE_DETACHED, only for zombie group leader that has
1388 already reported and been short-circuited at the top of this
1389 function. The same condition as at the top of DETACH. */
1390 if ((tcp->flags & TCB_CLONE_THREAD) &&
1391 tcp->parent->nclone_threads == 0 &&
1392 (tcp->parent->flags & TCB_EXITING))
1393 droptcb(tcp->parent);
1394#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001395 tcp->parent = NULL;
1396 }
1397
1398 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001399 if (tcp->pfd != -1) {
1400 close(tcp->pfd);
1401 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001402#ifdef FREEBSD
1403 if (tcp->pfd_reg != -1) {
1404 close(tcp->pfd_reg);
1405 tcp->pfd_reg = -1;
1406 }
1407 if (tcp->pfd_status != -1) {
1408 close(tcp->pfd_status);
1409 tcp->pfd_status = -1;
1410 }
Roland McGrath553a6092002-12-16 20:40:39 +00001411#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001412#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001413 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001414#endif
1415 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001416
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001417 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001419
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001420 tcp->outf = 0;
1421}
1422
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001423#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424
1425static int
1426resume(tcp)
1427struct tcb *tcp;
1428{
1429 if (tcp == NULL)
1430 return -1;
1431
1432 if (!(tcp->flags & TCB_SUSPENDED)) {
1433 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1434 return -1;
1435 }
1436 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001437#ifdef TCB_CLONE_THREAD
1438 if (tcp->flags & TCB_CLONE_THREAD)
1439 tcp->parent->nclone_waiting--;
1440#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001441
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001442 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444
1445 if (!qflag)
1446 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1447 return 0;
1448}
1449
Roland McGrath1bfd3102007-08-03 10:02:00 +00001450static int
1451resume_from_tcp (struct tcb *tcp)
1452{
1453 int error = 0;
1454 int resumed = 0;
1455
1456 /* XXX This won't always be quite right (but it never was).
1457 A waiter with argument 0 or < -1 is waiting for any pid in
1458 a particular pgrp, which this child might or might not be
1459 in. The waiter will only wake up if it's argument is -1
1460 or if it's waiting for tcp->pid's pgrp. It makes a
1461 difference to wake up a waiter when there might be more
1462 traced children, because it could get a false ECHILD
1463 error. OTOH, if this was the last child in the pgrp, then
1464 it ought to wake up and get ECHILD. We would have to
1465 search the system for all pid's in the pgrp to be sure.
1466
1467 && (t->waitpid == -1 ||
1468 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1469 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1470 */
1471
1472 if (tcp->parent &&
1473 (tcp->parent->flags & TCB_SUSPENDED) &&
1474 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1475 error = resume(tcp->parent);
1476 ++resumed;
1477 }
1478#ifdef TCB_CLONE_THREAD
1479 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1480 /* Some other threads of our parent are waiting too. */
1481 unsigned int i;
1482
1483 /* Resume all the threads that were waiting for this PID. */
1484 for (i = 0; i < tcbtabsize; i++) {
1485 struct tcb *t = tcbtab[i];
1486 if (t->parent == tcp->parent && t != tcp
1487 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1488 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1489 && t->waitpid == tcp->pid) {
1490 error |= resume (t);
1491 ++resumed;
1492 }
1493 }
1494 if (resumed == 0)
1495 /* Noone was waiting for this PID in particular,
1496 so now we might need to resume some wildcarders. */
1497 for (i = 0; i < tcbtabsize; i++) {
1498 struct tcb *t = tcbtab[i];
1499 if (t->parent == tcp->parent && t != tcp
1500 && ((t->flags
1501 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1502 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1503 && t->waitpid <= 0
1504 ) {
1505 error |= resume (t);
1506 break;
1507 }
1508 }
1509 }
1510
1511 return error;
1512}
1513#endif
1514
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001515#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001516
Roland McGrath0a463882007-07-05 18:43:16 +00001517/* detach traced process; continue with sig
1518 Never call DETACH twice on the same process as both unattached and
1519 attached-unstopped processes give the same ESRCH. For unattached process we
1520 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521
1522static int
1523detach(tcp, sig)
1524struct tcb *tcp;
1525int sig;
1526{
1527 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001528#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001529 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001530 struct tcb *zombie = NULL;
1531
1532 /* If the group leader is lingering only because of this other
1533 thread now dying, then detach the leader as well. */
1534 if ((tcp->flags & TCB_CLONE_THREAD) &&
1535 tcp->parent->nclone_threads == 1 &&
1536 (tcp->parent->flags & TCB_EXITING))
1537 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001538#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539
1540 if (tcp->flags & TCB_BPTSET)
1541 sig = SIGKILL;
1542
1543#ifdef LINUX
1544 /*
1545 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001546 * before detaching. Arghh. We go through hoops
1547 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001548 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001549#if defined(SPARC)
1550#undef PTRACE_DETACH
1551#define PTRACE_DETACH PTRACE_SUNDETACH
1552#endif
Roland McGrath02203312007-06-11 22:06:31 +00001553 /*
1554 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1555 * expected SIGSTOP. We must catch exactly one as otherwise the
1556 * detached process would be left stopped (process state T).
1557 */
1558 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1560 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001561 }
1562 else if (errno != ESRCH) {
1563 /* Shouldn't happen. */
1564 perror("detach: ptrace(PTRACE_DETACH, ...)");
1565 }
Roland McGrath134813a2007-06-02 00:07:33 +00001566 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1567 : tcp->pid),
1568 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001569 if (errno != ESRCH)
1570 perror("detach: checking sanity");
1571 }
Roland McGrath02203312007-06-11 22:06:31 +00001572 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1573 ? tcp->parent->pid : tcp->pid),
1574 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001575 if (errno != ESRCH)
1576 perror("detach: stopping child");
1577 }
Roland McGrath02203312007-06-11 22:06:31 +00001578 else
1579 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001580 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001582#ifdef __WALL
1583 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1584 if (errno == ECHILD) /* Already gone. */
1585 break;
1586 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001587 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001588 break;
1589 }
1590#endif /* __WALL */
1591 /* No __WALL here. */
1592 if (waitpid(tcp->pid, &status, 0) < 0) {
1593 if (errno != ECHILD) {
1594 perror("detach: waiting");
1595 break;
1596 }
1597#ifdef __WCLONE
1598 /* If no processes, try clones. */
1599 if (wait4(tcp->pid, &status, __WCLONE,
1600 NULL) < 0) {
1601 if (errno != ECHILD)
1602 perror("detach: waiting");
1603 break;
1604 }
1605#endif /* __WCLONE */
1606 }
1607#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001608 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001609#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610 if (!WIFSTOPPED(status)) {
1611 /* Au revoir, mon ami. */
1612 break;
1613 }
1614 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001615 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616 break;
1617 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001618 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko96d5a762008-12-29 19:13:27 +00001619 WSTOPSIG(status) == ptrace_stop_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001620 : WSTOPSIG(status));
1621 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001624 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001625#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626
1627#if defined(SUNOS4)
1628 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1629 if (sig && kill(tcp->pid, sig) < 0)
1630 perror("detach: kill");
1631 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001632 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633#endif /* SUNOS4 */
1634
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001635#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001636 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001637#endif
1638
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 if (!qflag)
1640 fprintf(stderr, "Process %u detached\n", tcp->pid);
1641
1642 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001643
1644#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001645 if (zombie != NULL) {
1646 /* TCP no longer exists therefore you must not detach () it. */
1647 droptcb(zombie);
1648 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001649#endif
1650
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651 return error;
1652}
1653
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001654#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655
1656static void
1657reaper(sig)
1658int sig;
1659{
1660 int pid;
1661 int status;
1662
1663 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1664#if 0
1665 struct tcb *tcp;
1666
1667 tcp = pid2tcb(pid);
1668 if (tcp)
1669 droptcb(tcp);
1670#endif
1671 }
1672}
1673
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001674#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675
1676static void
1677cleanup()
1678{
1679 int i;
1680 struct tcb *tcp;
1681
Roland McGrathee9d4352002-12-18 04:16:10 +00001682 for (i = 0; i < tcbtabsize; i++) {
1683 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684 if (!(tcp->flags & TCB_INUSE))
1685 continue;
1686 if (debug)
1687 fprintf(stderr,
1688 "cleanup: looking at pid %u\n", tcp->pid);
1689 if (tcp_last &&
1690 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001691 tprintf(" <unfinished ...>");
1692 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693 }
1694 if (tcp->flags & TCB_ATTACHED)
1695 detach(tcp, 0);
1696 else {
1697 kill(tcp->pid, SIGCONT);
1698 kill(tcp->pid, SIGTERM);
1699 }
1700 }
1701 if (cflag)
1702 call_summary(outf);
1703}
1704
1705static void
1706interrupt(sig)
1707int sig;
1708{
1709 interrupted = 1;
1710}
1711
1712#ifndef HAVE_STRERROR
1713
Roland McGrath6d2b3492002-12-30 00:51:30 +00001714#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715extern int sys_nerr;
1716extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001717#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718
1719const char *
1720strerror(errno)
1721int errno;
1722{
1723 static char buf[64];
1724
1725 if (errno < 1 || errno >= sys_nerr) {
1726 sprintf(buf, "Unknown error %d", errno);
1727 return buf;
1728 }
1729 return sys_errlist[errno];
1730}
1731
1732#endif /* HAVE_STERRROR */
1733
1734#ifndef HAVE_STRSIGNAL
1735
Roland McGrath8f474e02003-01-14 07:53:33 +00001736#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001737extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001738#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001739#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1740extern char *_sys_siglist[];
1741#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742
1743const char *
1744strsignal(sig)
1745int sig;
1746{
1747 static char buf[64];
1748
1749 if (sig < 1 || sig >= NSIG) {
1750 sprintf(buf, "Unknown signal %d", sig);
1751 return buf;
1752 }
1753#ifdef HAVE__SYS_SIGLIST
1754 return _sys_siglist[sig];
1755#else
1756 return sys_siglist[sig];
1757#endif
1758}
1759
1760#endif /* HAVE_STRSIGNAL */
1761
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001762#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763
1764static void
1765rebuild_pollv()
1766{
1767 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768
Roland McGrathee9d4352002-12-18 04:16:10 +00001769 if (pollv != NULL)
1770 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001771 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001772 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001773 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001774 exit(1);
1775 }
1776
Roland McGrathca16be82003-01-10 19:55:28 +00001777 for (i = j = 0; i < tcbtabsize; i++) {
1778 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779 if (!(tcp->flags & TCB_INUSE))
1780 continue;
1781 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001782 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783 j++;
1784 }
1785 if (j != nprocs) {
1786 fprintf(stderr, "strace: proc miscount\n");
1787 exit(1);
1788 }
1789}
1790
1791#ifndef HAVE_POLLABLE_PROCFS
1792
1793static void
1794proc_poll_open()
1795{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 int i;
1797
1798 if (pipe(proc_poll_pipe) < 0) {
1799 perror("pipe");
1800 exit(1);
1801 }
1802 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001803 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 exit(1);
1805 }
1806 }
1807}
1808
1809static int
1810proc_poll(pollv, nfds, timeout)
1811struct pollfd *pollv;
1812int nfds;
1813int timeout;
1814{
1815 int i;
1816 int n;
1817 struct proc_pollfd pollinfo;
1818
1819 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1820 return n;
1821 if (n != sizeof(struct proc_pollfd)) {
1822 fprintf(stderr, "panic: short read: %d\n", n);
1823 exit(1);
1824 }
1825 for (i = 0; i < nprocs; i++) {
1826 if (pollv[i].fd == pollinfo.fd)
1827 pollv[i].revents = pollinfo.revents;
1828 else
1829 pollv[i].revents = 0;
1830 }
1831 poller_pid = pollinfo.pid;
1832 return 1;
1833}
1834
1835static void
1836wakeup_handler(sig)
1837int sig;
1838{
1839}
1840
1841static void
1842proc_poller(pfd)
1843int pfd;
1844{
1845 struct proc_pollfd pollinfo;
1846 struct sigaction sa;
1847 sigset_t blocked_set, empty_set;
1848 int i;
1849 int n;
1850 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001851#ifdef FREEBSD
1852 struct procfs_status pfs;
1853#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001854
1855 switch (fork()) {
1856 case -1:
1857 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001858 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859 case 0:
1860 break;
1861 default:
1862 return;
1863 }
1864
1865 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1866 sa.sa_flags = 0;
1867 sigemptyset(&sa.sa_mask);
1868 sigaction(SIGHUP, &sa, NULL);
1869 sigaction(SIGINT, &sa, NULL);
1870 sigaction(SIGQUIT, &sa, NULL);
1871 sigaction(SIGPIPE, &sa, NULL);
1872 sigaction(SIGTERM, &sa, NULL);
1873 sa.sa_handler = wakeup_handler;
1874 sigaction(SIGUSR1, &sa, NULL);
1875 sigemptyset(&blocked_set);
1876 sigaddset(&blocked_set, SIGUSR1);
1877 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1878 sigemptyset(&empty_set);
1879
1880 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1881 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001882 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001883 }
1884 n = rl.rlim_cur;
1885 for (i = 0; i < n; i++) {
1886 if (i != pfd && i != proc_poll_pipe[1])
1887 close(i);
1888 }
1889
1890 pollinfo.fd = pfd;
1891 pollinfo.pid = getpid();
1892 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001893#ifndef FREEBSD
1894 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1895#else /* FREEBSD */
1896 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1897#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001898 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 switch (errno) {
1900 case EINTR:
1901 continue;
1902 case EBADF:
1903 pollinfo.revents = POLLERR;
1904 break;
1905 case ENOENT:
1906 pollinfo.revents = POLLHUP;
1907 break;
1908 default:
1909 perror("proc_poller: PIOCWSTOP");
1910 }
1911 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1912 _exit(0);
1913 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001914 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001915 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1916 sigsuspend(&empty_set);
1917 }
1918}
1919
1920#endif /* !HAVE_POLLABLE_PROCFS */
1921
1922static int
1923choose_pfd()
1924{
1925 int i, j;
1926 struct tcb *tcp;
1927
1928 static int last;
1929
1930 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001931 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001932 /*
1933 * The previous process is ready to run again. We'll
1934 * let it do so if it is currently in a syscall. This
1935 * heuristic improves the readability of the trace.
1936 */
1937 tcp = pfd2tcb(pollv[last].fd);
1938 if (tcp && (tcp->flags & TCB_INSYSCALL))
1939 return pollv[last].fd;
1940 }
1941
1942 for (i = 0; i < nprocs; i++) {
1943 /* Let competing children run round robin. */
1944 j = (i + last + 1) % nprocs;
1945 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1946 tcp = pfd2tcb(pollv[j].fd);
1947 if (!tcp) {
1948 fprintf(stderr, "strace: lost proc\n");
1949 exit(1);
1950 }
1951 droptcb(tcp);
1952 return -1;
1953 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001954 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955 last = j;
1956 return pollv[j].fd;
1957 }
1958 }
1959 fprintf(stderr, "strace: nothing ready\n");
1960 exit(1);
1961}
1962
1963static int
1964trace()
1965{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001966#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001967 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001968#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 struct tcb *tcp;
1970 int pfd;
1971 int what;
1972 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001973 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001974
1975 for (;;) {
1976 if (interactive)
1977 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1978
1979 if (nprocs == 0)
1980 break;
1981
1982 switch (nprocs) {
1983 case 1:
1984#ifndef HAVE_POLLABLE_PROCFS
1985 if (proc_poll_pipe[0] == -1) {
1986#endif
1987 tcp = pid2tcb(0);
1988 if (!tcp)
1989 continue;
1990 pfd = tcp->pfd;
1991 if (pfd == -1)
1992 continue;
1993 break;
1994#ifndef HAVE_POLLABLE_PROCFS
1995 }
1996 /* fall through ... */
1997#endif /* !HAVE_POLLABLE_PROCFS */
1998 default:
1999#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002000#ifdef POLL_HACK
2001 /* On some systems (e.g. UnixWare) we get too much ugly
2002 "unfinished..." stuff when multiple proceses are in
2003 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002004
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002005 if (in_syscall) {
2006 struct pollfd pv;
2007 tcp = in_syscall;
2008 in_syscall = NULL;
2009 pv.fd = tcp->pfd;
2010 pv.events = POLLWANT;
2011 if ((what = poll (&pv, 1, 1)) < 0) {
2012 if (interrupted)
2013 return 0;
2014 continue;
2015 }
2016 else if (what == 1 && pv.revents & POLLWANT) {
2017 goto FOUND;
2018 }
2019 }
2020#endif
2021
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002022 if (poll(pollv, nprocs, INFTIM) < 0) {
2023 if (interrupted)
2024 return 0;
2025 continue;
2026 }
2027#else /* !HAVE_POLLABLE_PROCFS */
2028 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2029 if (interrupted)
2030 return 0;
2031 continue;
2032 }
2033#endif /* !HAVE_POLLABLE_PROCFS */
2034 pfd = choose_pfd();
2035 if (pfd == -1)
2036 continue;
2037 break;
2038 }
2039
2040 /* Look up `pfd' in our table. */
2041 if ((tcp = pfd2tcb(pfd)) == NULL) {
2042 fprintf(stderr, "unknown pfd: %u\n", pfd);
2043 exit(1);
2044 }
John Hughesb6643082002-05-23 11:02:22 +00002045#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002046 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002047#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048 /* Get the status of the process. */
2049 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002050#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002051 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002052#else /* FREEBSD */
2053 /* Thanks to some scheduling mystery, the first poller
2054 sometimes waits for the already processed end of fork
2055 event. Doing a non blocking poll here solves the problem. */
2056 if (proc_poll_pipe[0] != -1)
2057 ioctl_result = IOCTL_STATUS (tcp);
2058 else
2059 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002060#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002061 ioctl_errno = errno;
2062#ifndef HAVE_POLLABLE_PROCFS
2063 if (proc_poll_pipe[0] != -1) {
2064 if (ioctl_result < 0)
2065 kill(poller_pid, SIGKILL);
2066 else
2067 kill(poller_pid, SIGUSR1);
2068 }
2069#endif /* !HAVE_POLLABLE_PROCFS */
2070 }
2071 if (interrupted)
2072 return 0;
2073
2074 if (interactive)
2075 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2076
2077 if (ioctl_result < 0) {
2078 /* Find out what happened if it failed. */
2079 switch (ioctl_errno) {
2080 case EINTR:
2081 case EBADF:
2082 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002083#ifdef FREEBSD
2084 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002085#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002086 case ENOENT:
2087 droptcb(tcp);
2088 continue;
2089 default:
2090 perror("PIOCWSTOP");
2091 exit(1);
2092 }
2093 }
2094
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002095#ifdef FREEBSD
2096 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2097 /* discard first event for a syscall we never entered */
2098 IOCTL (tcp->pfd, PIOCRUN, 0);
2099 continue;
2100 }
Roland McGrath553a6092002-12-16 20:40:39 +00002101#endif
2102
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002103 /* clear the just started flag */
2104 tcp->flags &= ~TCB_STARTUP;
2105
2106 /* set current output file */
2107 outf = tcp->outf;
2108
2109 if (cflag) {
2110 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002111#ifdef FREEBSD
2112 char buf[1024];
2113 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002115 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2116 buf[len] = '\0';
2117 sscanf(buf,
2118 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2119 &stime.tv_sec, &stime.tv_usec);
2120 } else
2121 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002122#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002123 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2124 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002125#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002126 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2127 tcp->stime = stime;
2128 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002129 what = tcp->status.PR_WHAT;
2130 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002131#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002132 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002133 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2134 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002135 if (trace_syscall(tcp) < 0) {
2136 fprintf(stderr, "syscall trouble\n");
2137 exit(1);
2138 }
2139 }
2140 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002141#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002143#ifdef POLL_HACK
2144 in_syscall = tcp;
2145#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 case PR_SYSEXIT:
2147 if (trace_syscall(tcp) < 0) {
2148 fprintf(stderr, "syscall trouble\n");
2149 exit(1);
2150 }
2151 break;
2152 case PR_SIGNALLED:
2153 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2154 printleader(tcp);
2155 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002156 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002157 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002158#ifdef PR_INFO
2159 if (tcp->status.PR_INFO.si_signo == what) {
2160 printleader(tcp);
2161 tprintf(" siginfo=");
2162 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002163 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002164 }
2165#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002166 }
2167 break;
2168 case PR_FAULTED:
2169 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2170 printleader(tcp);
2171 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002172 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002173 }
2174 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002175#ifdef FREEBSD
2176 case 0: /* handle case we polled for nothing */
2177 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002178#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002179 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002180 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002181 exit(1);
2182 break;
2183 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002184 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002185#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002186 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002187#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002188 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002189#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190 perror("PIOCRUN");
2191 exit(1);
2192 }
2193 }
2194 return 0;
2195}
2196
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002197#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002198
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002199#ifdef TCB_GROUP_EXITING
2200/* Handle an exit detach or death signal that is taking all the
2201 related clone threads with it. This is called in three circumstances:
2202 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2203 SIG == 0 Continuing TCP will perform an exit_group syscall.
2204 SIG == other Continuing TCP with SIG will kill the process.
2205*/
2206static int
2207handle_group_exit(struct tcb *tcp, int sig)
2208{
2209 /* We need to locate our records of all the clone threads
2210 related to TCP, either its children or siblings. */
2211 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2212 ? tcp->parent
2213 : tcp->nclone_detached > 0
2214 ? tcp : NULL);
2215
2216 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002217 if (leader != NULL && leader != tcp &&
2218 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002219 fprintf(stderr,
2220 "PANIC: handle_group_exit: %d leader %d\n",
2221 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002222 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002223#ifndef USE_PROCFS
2224 resume_from_tcp (tcp);
2225#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002226 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002227 }
2228 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002229 /* Mark that we are taking the process down. */
2230 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002231 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002232 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002233 if (leader != NULL && leader != tcp)
2234 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002235 } else {
2236 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2237 cleanup();
2238 return -1;
2239 }
2240 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002241 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002242 if (leader != tcp)
2243 droptcb(tcp);
2244 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002245 /* The leader will report to us as parent now,
2246 and then we'll get to the SIG==-1 case. */
2247 return 0;
2248 }
2249 }
2250
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002251 return 0;
2252}
2253#endif
2254
Denys Vlasenko215cc272009-01-09 17:22:56 +00002255static struct tcb *
2256collect_stopped_tcbs(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257{
2258 int pid;
2259 int wait_errno;
2260 int status;
2261 struct tcb *tcp;
2262#ifdef LINUX
2263 struct rusage ru;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002264 struct rusage* ru_ptr = cflag ? &ru : NULL;
2265 int wnohang = 0;
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002266 struct tcb *found_tcps;
2267 struct tcb **nextp = &found_tcps;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002268#ifdef __WALL
Denys Vlasenko215cc272009-01-09 17:22:56 +00002269 int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002270#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002271#endif /* LINUX */
2272
Denys Vlasenko215cc272009-01-09 17:22:56 +00002273 while (1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002274#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002275#ifdef __WALL
Denys Vlasenko215cc272009-01-09 17:22:56 +00002276 pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
Roland McGrath5bc05552002-12-17 04:50:47 +00002277 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002278 /* this kernel does not support __WALL */
2279 wait4_options &= ~__WALL;
2280 errno = 0;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002281 pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002282 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002283 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002284 /* most likely a "cloned" process */
Denys Vlasenko215cc272009-01-09 17:22:56 +00002285 pid = wait4(-1, &status, __WCLONE | wnohang, ru_ptr);
2286 if (pid < 0 && errno != ECHILD) {
2287 fprintf(stderr, "strace: wait4(WCLONE) "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002288 "failed: %s\n", strerror(errno));
2289 }
2290 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002291#else /* !__WALL */
2292 pid = wait4(-1, &status, wnohang, ru_ptr);
2293#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294#endif /* LINUX */
2295#ifdef SUNOS4
2296 pid = wait(&status);
2297#endif /* SUNOS4 */
2298 wait_errno = errno;
2299 if (interactive)
2300 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2301
Denys Vlasenko215cc272009-01-09 17:22:56 +00002302 if (pid == 0 && wnohang) {
2303 /* We had at least one successful
2304 * wait() before. We waited
2305 * with WNOHANG second time.
2306 * Stop collecting more tracees,
2307 * process what we already have.
2308 */
2309 break;
2310 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002311 if (pid == -1) {
2312 switch (wait_errno) {
2313 case EINTR:
2314 continue;
2315 case ECHILD:
2316 /*
2317 * We would like to verify this case
2318 * but sometimes a race in Solbourne's
2319 * version of SunOS sometimes reports
2320 * ECHILD before sending us SIGCHILD.
2321 */
2322#if 0
2323 if (nprocs == 0)
Denys Vlasenko215cc272009-01-09 17:22:56 +00002324 return NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002325 fprintf(stderr, "strace: proc miscount\n");
2326 exit(1);
2327#endif
Denys Vlasenko215cc272009-01-09 17:22:56 +00002328 return NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 default:
2330 errno = wait_errno;
2331 perror("strace: wait");
Denys Vlasenko215cc272009-01-09 17:22:56 +00002332 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002333 }
2334 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002335 if (pid == popen_pid) {
2336 if (WIFEXITED(status) || WIFSIGNALED(status))
2337 popen_pid = -1;
2338 continue;
2339 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002340 if (debug)
2341 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2342
2343 /* Look up `pid' in our table. */
2344 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002345#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002346 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002347 /* This is needed to go with the CLONE_PTRACE
2348 changes in process.c/util.c: we might see
2349 the child's initial trap before we see the
2350 parent return from the clone syscall.
2351 Leave the child suspended until the parent
2352 returns from its system call. Only then
2353 will we have the association of parent and
2354 child so that we know how to do clearbpt
2355 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002356 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002357 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002358 if (!qflag)
2359 fprintf(stderr, "\
2360Process %d attached (waiting for parent)\n",
2361 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002362 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002363 else
2364 /* This can happen if a clone call used
2365 CLONE_PTRACE itself. */
Denys Vlasenko215cc272009-01-09 17:22:56 +00002366#endif /* LINUX */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002367 {
2368 fprintf(stderr, "unknown pid: %u\n", pid);
2369 if (WIFSTOPPED(status))
2370 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2371 exit(1);
2372 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002373 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002374
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002375 if (cflag) {
2376#ifdef LINUX
2377 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2378 tcp->stime = ru.ru_stime;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002379#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002380 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002381 if (tcp->flags & TCB_SUSPENDED) {
2382 /*
2383 * Apparently, doing any ptrace() call on a stopped
2384 * process, provokes the kernel to report the process
2385 * status again on a subsequent wait(), even if the
2386 * process has not been actually restarted.
2387 * Since we have inspected the arguments of suspended
2388 * processes we end up here testing for this case.
2389 */
2390 continue;
2391 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002392
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002393 tcp->wait_status = status;
2394#ifdef LINUX
2395 /* It is important to not invert the order of tasks
2396 * to process. For one, alloc_tcb() above picks newly forked
2397 * threads in some order, processing of them and their parent
2398 * should be in the same order, otherwise bad things happen
2399 * (misinterpreted SIGSTOPs and such).
2400 */
2401 *nextp = tcp;
2402 nextp = &tcp->next_need_service;
2403 wnohang = WNOHANG;
2404#endif
2405#ifdef SUNOS4
2406 /* Probably need to replace wait with waitpid
2407 * and loop on Sun too, but I can't test it. Volunteers?
2408 */
2409 break;
2410#endif
2411 }
2412
2413 *nextp = NULL;
2414 return found_tcps;
2415}
2416
2417static int
2418handle_stopped_tcbs(struct tcb *tcp)
2419{
2420 for (; tcp; tcp = tcp->next_need_service) {
2421 int pid;
2422 int status;
2423
Denys Vlasenko215cc272009-01-09 17:22:56 +00002424 outf = tcp->outf;
2425 status = tcp->wait_status;
2426 pid = tcp->pid;
2427
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002428 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002429 if (pid == strace_child)
2430 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002431 if (!cflag
2432 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2433 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002434 tprintf("+++ killed by %s %s+++",
2435 signame(WTERMSIG(status)),
2436#ifdef WCOREDUMP
2437 WCOREDUMP(status) ? "(core dumped) " :
2438#endif
2439 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002440 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002441 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002442#ifdef TCB_GROUP_EXITING
2443 handle_group_exit(tcp, -1);
2444#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002446#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002447 continue;
2448 }
2449 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002450 if (pid == strace_child)
2451 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002452 if (debug)
2453 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002454 if ((tcp->flags & TCB_ATTACHED)
2455#ifdef TCB_GROUP_EXITING
2456 && !(tcp->parent && (tcp->parent->flags &
2457 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002458 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002459#endif
2460 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002461 fprintf(stderr,
2462 "PANIC: attached pid %u exited\n",
2463 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002464 if (tcp == tcp_last) {
2465 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2466 == TCB_INSYSCALL)
2467 tprintf(" <unfinished ... exit status %d>\n",
2468 WEXITSTATUS(status));
2469 tcp_last = NULL;
2470 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002471#ifdef TCB_GROUP_EXITING
2472 handle_group_exit(tcp, -1);
2473#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002474 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002475#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002476 continue;
2477 }
2478 if (!WIFSTOPPED(status)) {
2479 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2480 droptcb(tcp);
2481 continue;
2482 }
2483 if (debug)
2484 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002485 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002486
Roland McGrath02203312007-06-11 22:06:31 +00002487 /*
2488 * Interestingly, the process may stop
2489 * with STOPSIG equal to some other signal
2490 * than SIGSTOP if we happend to attach
2491 * just before the process takes a signal.
2492 */
2493 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002494 /*
2495 * This flag is there to keep us in sync.
2496 * Next time this process stops it should
2497 * really be entering a system call.
2498 */
2499 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002500 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002501 /*
2502 * One example is a breakpoint inherited from
2503 * parent through fork ().
2504 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002505 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2506 droptcb(tcp);
2507 cleanup();
2508 return -1;
2509 }
2510 }
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002511/* Add more OSes after you verified it works for them. */
Denys Vlasenkof535b542009-01-13 18:30:55 +00002512/* PTRACE_SETOPTIONS may be an enum, not a #define.
2513 * But sometimes we can test for it by checking PT_SETOPTIONS.
2514 */
2515#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
Denys Vlasenko0861ecb2009-01-02 16:55:24 +00002516# ifndef PTRACE_O_TRACESYSGOOD
2517# define PTRACE_O_TRACESYSGOOD 0x00000001
2518# endif
2519# ifndef PTRACE_O_TRACEEXEC
2520# define PTRACE_O_TRACEEXEC 0x00000010
2521# endif
2522# ifndef PTRACE_EVENT_EXEC
2523# define PTRACE_EVENT_EXEC 4
2524# endif
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002525 /*
2526 * Ask kernel to set signo to SIGTRAP | 0x80
2527 * on ptrace-generated SIGTRAPs, and mark
2528 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
2529 */
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002530 if (!ptrace_opts_set) {
2531 ptrace_opts_set = 1;
2532 /*
2533 * NB: even if this "succeeds", we can
2534 * revert back to SIGTRAP if we later see
2535 * that it didnt really work.
2536 * Old kernels are known to lie here.
2537 */
2538 if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
2539 (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
2540 ptrace_stop_sig = SIGTRAP | 0x80;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002541 }
2542#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 goto tracing;
2544 }
2545
Denys Vlasenkof535b542009-01-13 18:30:55 +00002546#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002547 if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002548 /*
2549 * We told ptrace to report SIGTRAP | 0x80 on this process
2550 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
2551 * kill(pid, SIGTRAP), trap insn, etc;
2552 * but be paranoid about it.
2553 */
2554 if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
Denys Vlasenko1d5b1132009-01-17 01:06:18 +00002555 /* It's post-exec ptrace stop. Ignore it,
2556 * we will get syscall exit ptrace stop later.
2557 */
2558#ifdef TCB_WAITEXECVE
2559 tcp->flags &= ~TCB_WAITEXECVE;
2560#endif
2561 goto tracing;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002562 } else {
2563 /* Take a better look... */
2564 siginfo_t si;
Denys Vlasenko1d5b1132009-01-17 01:06:18 +00002565 si.si_signo = 0;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002566 ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
2567 /*
2568 * Check some fields to make sure we see
2569 * real SIGTRAP.
2570 * Otherwise interpret it as ptrace stop.
2571 * Real SIGTRAPs (int3 insn on x86, kill() etc)
2572 * have these values:
2573 * int3: kill -TRAP $pid:
2574 * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
2575 * si_errno:0 si_errno:(?)
2576 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
2577 * si_pid:0 si_pid:(>0?)
2578 * si_band:0 si_band:(?)
2579 * Ptrace stops have garbage there instead.
2580 */
2581 if (si.si_signo != SIGTRAP
2582 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
2583 ) {
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002584 fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
2585 ptrace_stop_sig = SIGTRAP;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002586 }
2587 }
2588 }
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002589#endif
2590
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002591 if (WSTOPSIG(status) != ptrace_stop_sig) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002592 /* This isn't a ptrace stop. */
2593
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002594 if (WSTOPSIG(status) == SIGSTOP &&
2595 (tcp->flags & TCB_SIGTRAPPED)) {
2596 /*
2597 * Trapped attempt to block SIGTRAP
2598 * Hope we are back in control now.
2599 */
2600 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002601 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002602 cleanup();
2603 return -1;
2604 }
2605 continue;
2606 }
2607 if (!cflag
2608 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002609 unsigned long addr = 0;
2610 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002611#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002612# define PSR_RI 41
2613 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002614 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002615
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002616 upeek(tcp, PT_CR_IPSR, &psr);
2617 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002618
2619 pc += (psr >> PSR_RI) & 0x3;
2620 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2621 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002622#elif defined PTRACE_GETSIGINFO
2623 if (WSTOPSIG(status) == SIGSEGV ||
2624 WSTOPSIG(status) == SIGBUS) {
2625 siginfo_t si;
2626 if (ptrace(PTRACE_GETSIGINFO, pid,
2627 0, &si) == 0)
2628 addr = (unsigned long)
2629 si.si_addr;
2630 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002631#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002632 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002633 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002634 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002635 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002636 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002637 }
Roland McGrath05690952004-10-20 01:00:27 +00002638 if (((tcp->flags & TCB_ATTACHED) ||
2639 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002640 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002641#ifdef TCB_GROUP_EXITING
2642 handle_group_exit(tcp, WSTOPSIG(status));
2643#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002644 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002645#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002646 continue;
2647 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002648 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002649 cleanup();
2650 return -1;
2651 }
2652 tcp->flags &= ~TCB_SUSPENDED;
2653 continue;
2654 }
Roland McGrath02203312007-06-11 22:06:31 +00002655 /* we handled the STATUS, we are permitted to interrupt now. */
2656 if (interrupted)
2657 return 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002658 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002659 /* ptrace() failed in trace_syscall() with ESRCH.
2660 * Likely a result of process disappearing mid-flight.
2661 * Observed case: exit_group() terminating
2662 * all processes in thread group. In this case, threads
2663 * "disappear" in an unpredictable moment without any
2664 * notification to strace via wait().
2665 */
2666 if (tcp->flags & TCB_ATTACHED) {
2667 if (tcp_last) {
2668 /* Do we have dangling line "syscall(param, param"?
2669 * Finish the line then. We cannot
2670 */
2671 tcp_last->flags |= TCB_REPRINT;
2672 tprintf(" <unfinished ...>");
2673 printtrailer();
2674 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002675 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002676 } else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002677 ptrace(PTRACE_KILL,
2678 tcp->pid, (char *) 1, SIGTERM);
2679 droptcb(tcp);
2680 }
2681 continue;
2682 }
2683 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002684#ifdef TCB_GROUP_EXITING
2685 if (tcp->flags & TCB_GROUP_EXITING) {
2686 if (handle_group_exit(tcp, 0) < 0)
2687 return -1;
2688 continue;
2689 }
2690#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002691 if (tcp->flags & TCB_ATTACHED)
2692 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002693 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694 cleanup();
2695 return -1;
2696 }
2697 continue;
2698 }
2699 if (tcp->flags & TCB_SUSPENDED) {
2700 if (!qflag)
2701 fprintf(stderr, "Process %u suspended\n", pid);
2702 continue;
2703 }
2704 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002705 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002706 cleanup();
2707 return -1;
2708 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002709 } /* for each tcp */
2710
2711 return 0;
2712}
2713
2714static int
2715trace()
2716{
2717 int rc;
2718 struct tcb *tcbs;
2719
2720 while (nprocs != 0) {
2721 if (interrupted)
2722 return 0;
2723 if (interactive)
2724 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2725
2726 /* The loop of "wait for one tracee, serve it, repeat"
2727 * may leave some tracees never served.
2728 * Kernel provides no guarantees of fairness when you have
2729 * many waitable tasks.
2730 * Try strace -f with test/many_looping_threads.c example.
2731 * To fix it, we collect *all* waitable tasks, then handle
2732 * them all, then repeat.
2733 */
2734 tcbs = collect_stopped_tcbs();
2735 if (!tcbs)
2736 break;
2737 rc = handle_stopped_tcbs(tcbs);
2738 if (rc)
2739 return rc;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002740 }
2741 return 0;
2742}
2743
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002744#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002745
2746static int curcol;
2747
2748#ifdef __STDC__
2749#include <stdarg.h>
2750#define VA_START(a, b) va_start(a, b)
2751#else
2752#include <varargs.h>
2753#define VA_START(a, b) va_start(a)
2754#endif
2755
2756void
2757#ifdef __STDC__
2758tprintf(const char *fmt, ...)
2759#else
2760tprintf(fmt, va_alist)
2761char *fmt;
2762va_dcl
2763#endif
2764{
2765 va_list args;
2766
2767 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002768 if (outf) {
2769 int n = vfprintf(outf, fmt, args);
2770 if (n < 0 && outf != stderr)
2771 perror(outfname == NULL
2772 ? "<writing to pipe>" : outfname);
2773 else
2774 curcol += n;
2775 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002776 va_end(args);
2777 return;
2778}
2779
2780void
2781printleader(tcp)
2782struct tcb *tcp;
2783{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002784 if (tcp_last) {
2785 if (tcp_last->ptrace_errno) {
2786 if (tcp_last->flags & TCB_INSYSCALL) {
2787 tprintf(" <unavailable>)");
2788 tabto(acolumn);
2789 }
2790 tprintf("= ? <unavailable>\n");
2791 tcp_last->ptrace_errno = 0;
2792 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
2793 tcp_last->flags |= TCB_REPRINT;
2794 tprintf(" <unfinished ...>\n");
2795 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002796 }
2797 curcol = 0;
2798 if ((followfork == 1 || pflag_seen > 1) && outfname)
2799 tprintf("%-5d ", tcp->pid);
2800 else if (nprocs > 1 && !outfname)
2801 tprintf("[pid %5u] ", tcp->pid);
2802 if (tflag) {
2803 char str[sizeof("HH:MM:SS")];
2804 struct timeval tv, dtv;
2805 static struct timeval otv;
2806
2807 gettimeofday(&tv, NULL);
2808 if (rflag) {
2809 if (otv.tv_sec == 0)
2810 otv = tv;
2811 tv_sub(&dtv, &tv, &otv);
2812 tprintf("%6ld.%06ld ",
2813 (long) dtv.tv_sec, (long) dtv.tv_usec);
2814 otv = tv;
2815 }
2816 else if (tflag > 2) {
2817 tprintf("%ld.%06ld ",
2818 (long) tv.tv_sec, (long) tv.tv_usec);
2819 }
2820 else {
2821 time_t local = tv.tv_sec;
2822 strftime(str, sizeof(str), "%T", localtime(&local));
2823 if (tflag > 1)
2824 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2825 else
2826 tprintf("%s ", str);
2827 }
2828 }
2829 if (iflag)
2830 printcall(tcp);
2831}
2832
2833void
2834tabto(col)
2835int col;
2836{
2837 if (curcol < col)
2838 tprintf("%*s", col - curcol, "");
2839}
2840
2841void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002842printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002843{
2844 tprintf("\n");
2845 tcp_last = NULL;
2846}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002847
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002848#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002849
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002850int
2851mp_ioctl(int fd, int cmd, void *arg, int size)
2852{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002853 struct iovec iov[2];
2854 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002855
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002856 iov[0].iov_base = &cmd;
2857 iov[0].iov_len = sizeof cmd;
2858 if (arg) {
2859 ++n;
2860 iov[1].iov_base = arg;
2861 iov[1].iov_len = size;
2862 }
Roland McGrath553a6092002-12-16 20:40:39 +00002863
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002864 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002865}
2866
2867#endif