blob: af485619a6c8dcbd46bf0cd73696a743e7138d3b [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>
Denys Vlasenko7e0615f2009-01-28 19:00:54 +000043#include <sys/utsname.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000044#include <pwd.h>
45#include <grp.h>
46#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000047#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000048#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
52# if defined __NR_tgkill
53# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
54# elif defined __NR_tkill
55# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
56# else
57 /* kill() may choose arbitrarily the target task of the process group
58 while we later wait on a that specific TID. PID process waits become
59 TID task specific waits for a process under ptrace(2). */
60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
62# endif
63#endif
64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000065#if defined(IA64) && defined(LINUX)
66# include <asm/ptrace_offsets.h>
67#endif
68
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000069#ifdef USE_PROCFS
70#include <poll.h>
71#endif
72
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#ifdef SVR4
74#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000075#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000076#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000077#include <sys/uio.h>
78#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000080#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000082extern int optind;
83extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000084
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085
Roland McGrath41c48222008-07-18 00:25:10 +000086int debug = 0, followfork = 0;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000087int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
88static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000089/*
90 * daemonized_tracer supports -D option.
91 * With this option, strace forks twice.
92 * Unlike normal case, with -D *grandparent* process exec's,
93 * becoming a traced process. Child exits (this prevents traced process
94 * from having children it doesn't expect to have), and grandchild
95 * attaches to grandparent similarly to strace -p PID.
96 * This allows for more transparent interaction in cases
97 * when process and its parent are communicating via signals,
98 * wait() etc. Without -D, strace process gets lodged in between,
99 * disrupting parent<->child link.
100 */
101static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
Denys Vlasenko7e0615f2009-01-28 19:00:54 +0000103static struct utsname utsname_buf;
104
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000105/* Sometimes we want to print only succeeding syscalls. */
106int not_failing_only = 0;
107
Dmitry V. Levina6809652008-11-10 17:14:58 +0000108static int exit_code = 0;
109static int strace_child = 0;
Denys Vlasenko96d5a762008-12-29 19:13:27 +0000110static int ptrace_stop_sig = SIGTRAP;
111static bool ptrace_opts_set;
Dmitry V. Levina6809652008-11-10 17:14:58 +0000112
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000113static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000114uid_t run_uid;
115gid_t run_gid;
116
117int acolumn = DEFAULT_ACOLUMN;
118int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000119static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +0000121struct tcb **tcbtab;
122unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124
Roland McGrath0a463882007-07-05 18:43:16 +0000125static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126static int trace P((void));
127static void cleanup P((void));
128static void interrupt P((int sig));
129static sigset_t empty_set, blocked_set;
130
131#ifdef HAVE_SIG_ATOMIC_T
132static volatile sig_atomic_t interrupted;
133#else /* !HAVE_SIG_ATOMIC_T */
134#ifdef __STDC__
135static volatile int interrupted;
136#else /* !__STDC__ */
137static int interrupted;
138#endif /* !__STDC__ */
139#endif /* !HAVE_SIG_ATOMIC_T */
140
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000141#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142
143static struct tcb *pfd2tcb P((int pfd));
144static void reaper P((int sig));
145static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000146static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147
148#ifndef HAVE_POLLABLE_PROCFS
149
150static void proc_poll_open P((void));
151static void proc_poller P((int pfd));
152
153struct proc_pollfd {
154 int fd;
155 int revents;
156 int pid;
157};
158
159static int poller_pid;
160static int proc_poll_pipe[2] = { -1, -1 };
161
162#endif /* !HAVE_POLLABLE_PROCFS */
163
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000164#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000165#define POLLWANT POLLWRNORM
166#else
167#define POLLWANT POLLPRI
168#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000169#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
171static void
172usage(ofp, exitval)
173FILE *ofp;
174int exitval;
175{
176 fprintf(ofp, "\
177usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000178 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
179 [command [arg ...]]\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000180 or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000181 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182-c -- count time, calls, and errors for each syscall and report summary\n\
183-f -- follow forks, -ff -- with output into separate files\n\
184-F -- attempt to follow vforks, -h -- print help message\n\
185-i -- print instruction pointer at time of syscall\n\
186-q -- suppress messages about attaching, detaching, etc.\n\
187-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
188-T -- print time spent in each syscall, -V -- print version\n\
189-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
190-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
191-a column -- alignment COLUMN for printing syscall results (default %d)\n\
192-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
193 options: trace, abbrev, verbose, raw, signal, read, or write\n\
194-o file -- send trace output to FILE instead of stderr\n\
195-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
196-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000197-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
199-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
200-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000201-E var=val -- put var=val in the environment for command\n\
202-E var -- remove var from the environment for command\n\
203" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000204-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000205 */
206, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000207 exit(exitval);
208}
209
210#ifdef SVR4
211#ifdef MIPS
212void
213foobar()
214{
215}
216#endif /* MIPS */
217#endif /* SVR4 */
218
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000219static int
220set_cloexec_flag(int fd)
221{
222 int flags, newflags;
223
224 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
225 {
226 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
227 progname, strerror(errno));
228 return -1;
229 }
230
231 newflags = flags | FD_CLOEXEC;
232 if (flags == newflags)
233 return 0;
234
235 if (fcntl(fd, F_SETFD, newflags) < 0)
236 {
237 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
238 progname, strerror(errno));
239 return -1;
240 }
241
242 return 0;
243}
244
245/*
246 * When strace is setuid executable, we have to swap uids
247 * before and after filesystem and process management operations.
248 */
249static void
250swap_uid(void)
251{
252#ifndef SVR4
253 int euid = geteuid(), uid = getuid();
254
255 if (euid != uid && setreuid(euid, uid) < 0)
256 {
257 fprintf(stderr, "%s: setreuid: %s\n",
258 progname, strerror(errno));
259 exit(1);
260 }
261#endif
262}
263
Roland McGrath4bfa6262007-07-05 20:03:16 +0000264#if _LFS64_LARGEFILE
265# define fopen_for_output fopen64
266#else
267# define fopen_for_output fopen
268#endif
269
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000270static FILE *
271strace_fopen(const char *path, const char *mode)
272{
273 FILE *fp;
274
275 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000276 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000277 fprintf(stderr, "%s: can't fopen '%s': %s\n",
278 progname, path, strerror(errno));
279 swap_uid();
280 if (fp && set_cloexec_flag(fileno(fp)) < 0)
281 {
282 fclose(fp);
283 fp = NULL;
284 }
285 return fp;
286}
287
288static int popen_pid = -1;
289
290#ifndef _PATH_BSHELL
291# define _PATH_BSHELL "/bin/sh"
292#endif
293
294/*
295 * We cannot use standard popen(3) here because we have to distinguish
296 * popen child process from other processes we trace, and standard popen(3)
297 * does not export its child's pid.
298 */
299static FILE *
300strace_popen(const char *command)
301{
302 int fds[2];
303
304 swap_uid();
305 if (pipe(fds) < 0)
306 {
307 fprintf(stderr, "%s: pipe: %s\n",
308 progname, strerror(errno));
309 swap_uid();
310 return NULL;
311 }
312
313 if (set_cloexec_flag(fds[1]) < 0)
314 {
315 close(fds[0]);
316 close(fds[1]);
317 swap_uid();
318 return NULL;
319 }
320
321 if ((popen_pid = fork()) == -1)
322 {
323 fprintf(stderr, "%s: fork: %s\n",
324 progname, strerror(errno));
325 close(fds[0]);
326 close(fds[1]);
327 swap_uid();
328 return NULL;
329 }
330
331 if (popen_pid)
332 {
333 /* parent */
334 close(fds[0]);
335 swap_uid();
336 return fdopen(fds[1], "w");
337 } else
338 {
339 /* child */
340 close(fds[1]);
341 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
342 {
343 fprintf(stderr, "%s: dup2: %s\n",
344 progname, strerror(errno));
345 _exit(1);
346 }
347 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
348 fprintf(stderr, "%s: execl: %s: %s\n",
349 progname, _PATH_BSHELL, strerror(errno));
350 _exit(1);
351 }
352}
353
354static int
355newoutf(struct tcb *tcp)
356{
357 if (outfname && followfork > 1) {
358 char name[MAXPATHLEN];
359 FILE *fp;
360
361 sprintf(name, "%s.%u", outfname, tcp->pid);
362 if ((fp = strace_fopen(name, "w")) == NULL)
363 return -1;
364 tcp->outf = fp;
365 }
366 return 0;
367}
368
Roland McGrath02203312007-06-11 22:06:31 +0000369static void
370startup_attach(void)
371{
372 int tcbi;
373 struct tcb *tcp;
374
375 /*
376 * Block user interruptions as we would leave the traced
377 * process stopped (process state T) if we would terminate in
378 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
379 * We rely on cleanup () from this point on.
380 */
381 if (interactive)
382 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
383
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000384 if (daemonized_tracer) {
385 pid_t pid = fork();
386 if (pid < 0) {
387 _exit(1);
388 }
389 if (pid) { /* parent */
390 /*
391 * Wait for child to attach to straced process
392 * (our parent). Child SIGKILLs us after it attached.
393 * Parent's wait() is unblocked by our death,
394 * it proceeds to exec the straced program.
395 */
396 pause();
397 _exit(0); /* paranoia */
398 }
399 }
400
Roland McGrath02203312007-06-11 22:06:31 +0000401 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
402 tcp = tcbtab[tcbi];
403 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
404 continue;
405#ifdef LINUX
406 if (tcp->flags & TCB_CLONE_THREAD)
407 continue;
408#endif
409 /* Reinitialize the output since it may have changed. */
410 tcp->outf = outf;
411 if (newoutf(tcp) < 0)
412 exit(1);
413
414#ifdef USE_PROCFS
415 if (proc_open(tcp, 1) < 0) {
416 fprintf(stderr, "trouble opening proc file\n");
417 droptcb(tcp);
418 continue;
419 }
420#else /* !USE_PROCFS */
421# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000422 if (followfork && !daemonized_tracer) {
Roland McGrath02203312007-06-11 22:06:31 +0000423 char procdir[MAXPATHLEN];
424 DIR *dir;
425
426 sprintf(procdir, "/proc/%d/task", tcp->pid);
427 dir = opendir(procdir);
428 if (dir != NULL) {
429 unsigned int ntid = 0, nerr = 0;
430 struct dirent *de;
431 int tid;
432 while ((de = readdir(dir)) != NULL) {
433 if (de->d_fileno == 0 ||
434 de->d_name[0] == '.')
435 continue;
436 tid = atoi(de->d_name);
437 if (tid <= 0)
438 continue;
439 ++ntid;
440 if (ptrace(PTRACE_ATTACH, tid,
441 (char *) 1, 0) < 0)
442 ++nerr;
443 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000444 tcp = alloctcb(tid);
Roland McGrath02203312007-06-11 22:06:31 +0000445 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
446 tcbtab[tcbi]->nchildren++;
447 tcbtab[tcbi]->nclone_threads++;
448 tcbtab[tcbi]->nclone_detached++;
449 tcp->parent = tcbtab[tcbi];
450 }
451 if (interactive) {
452 sigprocmask(SIG_SETMASK, &empty_set, NULL);
453 if (interrupted)
454 return;
455 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
456 }
457 }
458 closedir(dir);
459 if (nerr == ntid) {
460 perror("attach: ptrace(PTRACE_ATTACH, ...)");
461 droptcb(tcp);
462 continue;
463 }
464 if (!qflag) {
465 ntid -= nerr;
466 if (ntid > 1)
467 fprintf(stderr, "\
468Process %u attached with %u threads - interrupt to quit\n",
469 tcp->pid, ntid);
470 else
471 fprintf(stderr, "\
472Process %u attached - interrupt to quit\n",
473 tcp->pid);
474 }
475 continue;
476 }
477 }
478# endif
479 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
480 perror("attach: ptrace(PTRACE_ATTACH, ...)");
481 droptcb(tcp);
482 continue;
483 }
484 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000485
486 if (daemonized_tracer) {
487 /*
488 * It is our grandparent we trace, not a -p PID.
489 * Don't want to just detach on exit, so...
490 */
491 tcp->flags &= ~TCB_ATTACHED;
492 /*
493 * Make parent go away.
494 * Also makes grandparent's wait() unblock.
495 */
496 kill(getppid(), SIGKILL);
497 }
498
Roland McGrath02203312007-06-11 22:06:31 +0000499#endif /* !USE_PROCFS */
500 if (!qflag)
501 fprintf(stderr,
502 "Process %u attached - interrupt to quit\n",
503 tcp->pid);
504 }
505
506 if (interactive)
507 sigprocmask(SIG_SETMASK, &empty_set, NULL);
508}
509
510static void
511startup_child (char **argv)
512{
513 struct stat statbuf;
514 const char *filename;
515 char pathname[MAXPATHLEN];
516 int pid = 0;
517 struct tcb *tcp;
518
519 filename = argv[0];
520 if (strchr(filename, '/')) {
521 if (strlen(filename) > sizeof pathname - 1) {
522 errno = ENAMETOOLONG;
523 perror("strace: exec");
524 exit(1);
525 }
526 strcpy(pathname, filename);
527 }
528#ifdef USE_DEBUGGING_EXEC
529 /*
530 * Debuggers customarily check the current directory
531 * first regardless of the path but doing that gives
532 * security geeks a panic attack.
533 */
534 else if (stat(filename, &statbuf) == 0)
535 strcpy(pathname, filename);
536#endif /* USE_DEBUGGING_EXEC */
537 else {
538 char *path;
539 int m, n, len;
540
541 for (path = getenv("PATH"); path && *path; path += m) {
542 if (strchr(path, ':')) {
543 n = strchr(path, ':') - path;
544 m = n + 1;
545 }
546 else
547 m = n = strlen(path);
548 if (n == 0) {
549 if (!getcwd(pathname, MAXPATHLEN))
550 continue;
551 len = strlen(pathname);
552 }
553 else if (n > sizeof pathname - 1)
554 continue;
555 else {
556 strncpy(pathname, path, n);
557 len = n;
558 }
559 if (len && pathname[len - 1] != '/')
560 pathname[len++] = '/';
561 strcpy(pathname + len, filename);
562 if (stat(pathname, &statbuf) == 0 &&
563 /* Accept only regular files
564 with some execute bits set.
565 XXX not perfect, might still fail */
566 S_ISREG(statbuf.st_mode) &&
567 (statbuf.st_mode & 0111))
568 break;
569 }
570 }
571 if (stat(pathname, &statbuf) < 0) {
572 fprintf(stderr, "%s: %s: command not found\n",
573 progname, filename);
574 exit(1);
575 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000576 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000577 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000578 perror("strace: fork");
579 cleanup();
580 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000581 }
582 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
583 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
584 ) {
585 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000586#ifdef USE_PROCFS
587 if (outf != stderr) close (fileno (outf));
588#ifdef MIPS
589 /* Kludge for SGI, see proc_open for details. */
590 sa.sa_handler = foobar;
591 sa.sa_flags = 0;
592 sigemptyset(&sa.sa_mask);
593 sigaction(SIGINT, &sa, NULL);
594#endif /* MIPS */
595#ifndef FREEBSD
596 pause();
597#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000598 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000599#endif /* FREEBSD */
600#else /* !USE_PROCFS */
601 if (outf!=stderr)
602 close(fileno (outf));
603
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000604 if (!daemonized_tracer) {
605 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
606 perror("strace: ptrace(PTRACE_TRACEME, ...)");
607 exit(1);
608 }
609 if (debug)
610 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000611 }
Roland McGrath02203312007-06-11 22:06:31 +0000612
613 if (username != NULL || geteuid() == 0) {
614 uid_t run_euid = run_uid;
615 gid_t run_egid = run_gid;
616
617 if (statbuf.st_mode & S_ISUID)
618 run_euid = statbuf.st_uid;
619 if (statbuf.st_mode & S_ISGID)
620 run_egid = statbuf.st_gid;
621
622 /*
623 * It is important to set groups before we
624 * lose privileges on setuid.
625 */
626 if (username != NULL) {
627 if (initgroups(username, run_gid) < 0) {
628 perror("initgroups");
629 exit(1);
630 }
631 if (setregid(run_gid, run_egid) < 0) {
632 perror("setregid");
633 exit(1);
634 }
635 if (setreuid(run_uid, run_euid) < 0) {
636 perror("setreuid");
637 exit(1);
638 }
639 }
640 }
641 else
642 setreuid(run_uid, run_uid);
643
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000644 if (!daemonized_tracer) {
645 /*
646 * Induce an immediate stop so that the parent
647 * will resume us with PTRACE_SYSCALL and display
648 * this execve call normally.
649 */
650 kill(getpid(), SIGSTOP);
651 } else {
652 struct sigaction sv_sigchld;
653 sigaction(SIGCHLD, NULL, &sv_sigchld);
654 /*
655 * Make sure it is not SIG_IGN, otherwise wait
656 * will not block.
657 */
658 signal(SIGCHLD, SIG_DFL);
659 /*
660 * Wait for grandchild to attach to us.
661 * It kills child after that, and wait() unblocks.
662 */
663 alarm(3);
664 wait(NULL);
665 alarm(0);
666 sigaction(SIGCHLD, &sv_sigchld, NULL);
667 }
Roland McGrath02203312007-06-11 22:06:31 +0000668#endif /* !USE_PROCFS */
669
670 execv(pathname, argv);
671 perror("strace: exec");
672 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000673 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000674
675 /* We are the tracer. */
676 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677 if (daemonized_tracer) {
678 /* We want subsequent startup_attach() to attach to it. */
679 tcp->flags |= TCB_ATTACHED;
680 }
Roland McGrath02203312007-06-11 22:06:31 +0000681#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000682 if (proc_open(tcp, 0) < 0) {
683 fprintf(stderr, "trouble opening proc file\n");
684 cleanup();
685 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000686 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000687#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000688}
689
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000691main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693 struct tcb *tcp;
694 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000695 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000696 struct sigaction sa;
697
698 static char buf[BUFSIZ];
699
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000700 progname = argv[0] ? argv[0] : "strace";
701
Denys Vlasenko7e0615f2009-01-28 19:00:54 +0000702 uname(&utsname_buf);
703
Roland McGrathee9d4352002-12-18 04:16:10 +0000704 /* Allocate the initial tcbtab. */
705 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000706 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000707 fprintf(stderr, "%s: out of memory\n", progname);
708 exit(1);
709 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000710 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000711 fprintf(stderr, "%s: out of memory\n", progname);
712 exit(1);
713 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000714 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
715 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
716
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000717 outf = stderr;
718 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000719 set_sortby(DEFAULT_SORTBY);
720 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000721 qualify("trace=all");
722 qualify("abbrev=all");
723 qualify("verbose=all");
724 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000725 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000726 "+cdfFhiqrtTvVxz"
727#ifndef USE_PROCFS
728 "D"
729#endif
730 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000731 switch (c) {
732 case 'c':
733 cflag++;
734 dtime++;
735 break;
736 case 'd':
737 debug++;
738 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000739#ifndef USE_PROCFS
740 /* Experimental, not documented in manpage yet. */
741 case 'D':
742 daemonized_tracer = 1;
743 break;
744#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000745 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000746 optF = 1;
747 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000748 case 'f':
749 followfork++;
750 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751 case 'h':
752 usage(stdout, 0);
753 break;
754 case 'i':
755 iflag++;
756 break;
757 case 'q':
758 qflag++;
759 break;
760 case 'r':
761 rflag++;
762 tflag++;
763 break;
764 case 't':
765 tflag++;
766 break;
767 case 'T':
768 dtime++;
769 break;
770 case 'x':
771 xflag++;
772 break;
773 case 'v':
774 qualify("abbrev=none");
775 break;
776 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000777 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 exit(0);
779 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000780 case 'z':
781 not_failing_only = 1;
782 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 case 'a':
784 acolumn = atoi(optarg);
785 break;
786 case 'e':
787 qualify(optarg);
788 break;
789 case 'o':
790 outfname = strdup(optarg);
791 break;
792 case 'O':
793 set_overhead(atoi(optarg));
794 break;
795 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000796 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000797 fprintf(stderr, "%s: Invalid process id: %s\n",
798 progname, optarg);
799 break;
800 }
801 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000802 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 break;
804 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000805 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 tcp->flags |= TCB_ATTACHED;
807 pflag_seen++;
808 break;
809 case 's':
810 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000811 if (max_strlen < 0) {
812 fprintf(stderr,
813 "%s: invalid -s argument: %s\n",
814 progname, optarg);
815 exit(1);
816 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000817 break;
818 case 'S':
819 set_sortby(optarg);
820 break;
821 case 'u':
822 username = strdup(optarg);
823 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000824 case 'E':
825 if (putenv(optarg) < 0) {
826 fprintf(stderr, "%s: out of memory\n",
827 progname);
828 exit(1);
829 }
830 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000831 default:
832 usage(stderr, 1);
833 break;
834 }
835 }
836
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000837 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000838 usage(stderr, 1);
839
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000840 if (!followfork)
841 followfork = optF;
842
Roland McGrathcb9def62006-04-25 07:48:03 +0000843 if (followfork > 1 && cflag) {
844 fprintf(stderr,
845 "%s: -c and -ff are mutually exclusive options\n",
846 progname);
847 exit(1);
848 }
849
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 /* See if they want to run as another user. */
851 if (username != NULL) {
852 struct passwd *pent;
853
854 if (getuid() != 0 || geteuid() != 0) {
855 fprintf(stderr,
856 "%s: you must be root to use the -u option\n",
857 progname);
858 exit(1);
859 }
860 if ((pent = getpwnam(username)) == NULL) {
861 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000862 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863 exit(1);
864 }
865 run_uid = pent->pw_uid;
866 run_gid = pent->pw_gid;
867 }
868 else {
869 run_uid = getuid();
870 run_gid = getgid();
871 }
872
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000873 /* Check if they want to redirect the output. */
874 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000875 /* See if they want to pipe the output. */
876 if (outfname[0] == '|' || outfname[0] == '!') {
877 /*
878 * We can't do the <outfname>.PID funny business
879 * when using popen, so prohibit it.
880 */
881 if (followfork > 1) {
882 fprintf(stderr, "\
883%s: piping the output and -ff are mutually exclusive options\n",
884 progname);
885 exit(1);
886 }
887
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000888 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000889 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000890 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000891 else if (followfork <= 1 &&
892 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 }
895
Roland McGrath37b9a662003-11-07 02:26:54 +0000896 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000898 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000899 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000901 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000902 /* Valid states here:
903 optind < argc pflag_seen outfname interactive
904 1 0 0 1
905 0 1 0 1
906 1 0 1 0
907 0 1 1 1
908 */
909
910 /* STARTUP_CHILD must be called before the signal handlers get
911 installed below as they are inherited into the spawned process.
912 Also we do not need to be protected by them as during interruption
913 in the STARTUP_CHILD mode we kill the spawned process anyway. */
914 if (!pflag_seen)
915 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 sigemptyset(&empty_set);
918 sigemptyset(&blocked_set);
919 sa.sa_handler = SIG_IGN;
920 sigemptyset(&sa.sa_mask);
921 sa.sa_flags = 0;
922 sigaction(SIGTTOU, &sa, NULL);
923 sigaction(SIGTTIN, &sa, NULL);
924 if (interactive) {
925 sigaddset(&blocked_set, SIGHUP);
926 sigaddset(&blocked_set, SIGINT);
927 sigaddset(&blocked_set, SIGQUIT);
928 sigaddset(&blocked_set, SIGPIPE);
929 sigaddset(&blocked_set, SIGTERM);
930 sa.sa_handler = interrupt;
931#ifdef SUNOS4
932 /* POSIX signals on sunos4.1 are a little broken. */
933 sa.sa_flags = SA_INTERRUPT;
934#endif /* SUNOS4 */
935 }
936 sigaction(SIGHUP, &sa, NULL);
937 sigaction(SIGINT, &sa, NULL);
938 sigaction(SIGQUIT, &sa, NULL);
939 sigaction(SIGPIPE, &sa, NULL);
940 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000941#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 sa.sa_handler = reaper;
943 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000944#else
945 /* Make sure SIGCHLD has the default action so that waitpid
946 definitely works without losing track of children. The user
947 should not have given us a bogus state to inherit, but he might
948 have. Arguably we should detect SIG_IGN here and pass it on
949 to children, but probably noone really needs that. */
950 sa.sa_handler = SIG_DFL;
951 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000952#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000954 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000955 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000956
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 if (trace() < 0)
958 exit(1);
959 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000960 fflush(NULL);
961 if (exit_code > 0xff) {
962 /* Child was killed by a signal, mimic that. */
963 exit_code &= 0xff;
964 signal(exit_code, SIG_DFL);
965 raise(exit_code);
966 /* Paranoia - what if this signal is not fatal?
967 Exit with 128 + signo then. */
968 exit_code += 128;
969 }
970 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971}
972
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000973void
974expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000975{
976 /* Allocate some more TCBs and expand the table.
977 We don't want to relocate the TCBs because our
978 callers have pointers and it would be a pain.
979 So tcbtab is a table of pointers. Since we never
980 free the TCBs, we allocate a single chunk of many. */
981 struct tcb **newtab = (struct tcb **)
982 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
983 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
984 sizeof *newtcbs);
985 int i;
986 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000987 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
988 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000989 cleanup();
990 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000991 }
992 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
993 newtab[i] = &newtcbs[i - tcbtabsize];
994 tcbtabsize *= 2;
995 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000996}
997
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000999alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000{
1001 int i;
1002 struct tcb *tcp;
1003
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001004 if (nprocs == tcbtabsize)
1005 expand_tcbtab();
1006
Roland McGrathee9d4352002-12-18 04:16:10 +00001007 for (i = 0; i < tcbtabsize; i++) {
1008 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00001010 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001011 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 tcp->flags = TCB_INUSE | TCB_STARTUP;
1013 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 tcp->pfd = -1;
1015 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001016 if (command_options_parsed)
1017 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 return tcp;
1019 }
1020 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001021 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1022 cleanup();
1023 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024}
1025
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001026#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001028proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029{
1030 char proc[32];
1031 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001032#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001033 int i;
1034 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035 sigset_t signals;
1036 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001037#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038#ifndef HAVE_POLLABLE_PROCFS
1039 static int last_pfd;
1040#endif
1041
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001042#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001043 /* Open the process pseudo-files in /proc. */
1044 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1045 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 perror("strace: open(\"/proc/...\", ...)");
1047 return -1;
1048 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001049 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 return -1;
1051 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001052 sprintf(proc, "/proc/%d/status", tcp->pid);
1053 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1054 perror("strace: open(\"/proc/...\", ...)");
1055 return -1;
1056 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001057 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001058 return -1;
1059 }
1060 sprintf(proc, "/proc/%d/as", tcp->pid);
1061 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1062 perror("strace: open(\"/proc/...\", ...)");
1063 return -1;
1064 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001065 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001066 return -1;
1067 }
1068#else
1069 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001070#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001071 sprintf(proc, "/proc/%d", tcp->pid);
1072 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001073#else /* FREEBSD */
1074 sprintf(proc, "/proc/%d/mem", tcp->pid);
1075 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1076#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001077 perror("strace: open(\"/proc/...\", ...)");
1078 return -1;
1079 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001080 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001081 return -1;
1082 }
1083#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001084#ifdef FREEBSD
1085 sprintf(proc, "/proc/%d/regs", tcp->pid);
1086 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1087 perror("strace: open(\"/proc/.../regs\", ...)");
1088 return -1;
1089 }
1090 if (cflag) {
1091 sprintf(proc, "/proc/%d/status", tcp->pid);
1092 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1093 perror("strace: open(\"/proc/.../status\", ...)");
1094 return -1;
1095 }
1096 } else
1097 tcp->pfd_status = -1;
1098#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001099 rebuild_pollv();
1100 if (!attaching) {
1101 /*
1102 * Wait for the child to pause. Because of a race
1103 * condition we have to poll for the event.
1104 */
1105 for (;;) {
1106 if (IOCTL_STATUS (tcp) < 0) {
1107 perror("strace: PIOCSTATUS");
1108 return -1;
1109 }
1110 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001111 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001112 }
1113 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001114#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001115 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001116 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001117 perror("strace: PIOCSTOP");
1118 return -1;
1119 }
Roland McGrath553a6092002-12-16 20:40:39 +00001120#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121#ifdef PIOCSET
1122 /* Set Run-on-Last-Close. */
1123 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001124 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125 perror("PIOCSET PR_RLC");
1126 return -1;
1127 }
1128 /* Set or Reset Inherit-on-Fork. */
1129 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001130 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 perror("PIOC{SET,RESET} PR_FORK");
1132 return -1;
1133 }
1134#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001135#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1137 perror("PIOCSRLC");
1138 return -1;
1139 }
1140 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1141 perror("PIOC{S,R}FORK");
1142 return -1;
1143 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001144#else /* FREEBSD */
1145 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1146 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1147 perror("PIOCGFL");
1148 return -1;
1149 }
1150 arg &= ~PF_LINGER;
1151 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1152 perror("PIOCSFL");
1153 return -1;
1154 }
1155#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001157#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001158 /* Enable all syscall entries we care about. */
1159 premptyset(&syscalls);
1160 for (i = 1; i < MAX_QUALS; ++i) {
1161 if (i > (sizeof syscalls) * CHAR_BIT) break;
1162 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1163 }
1164 praddset (&syscalls, SYS_execve);
1165 if (followfork) {
1166 praddset (&syscalls, SYS_fork);
1167#ifdef SYS_forkall
1168 praddset (&syscalls, SYS_forkall);
1169#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001170#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001171 praddset (&syscalls, SYS_fork1);
1172#endif
1173#ifdef SYS_rfork1
1174 praddset (&syscalls, SYS_rfork1);
1175#endif
1176#ifdef SYS_rforkall
1177 praddset (&syscalls, SYS_rforkall);
1178#endif
1179 }
1180 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181 perror("PIOCSENTRY");
1182 return -1;
1183 }
John Hughes19e49982001-10-19 08:59:12 +00001184 /* Enable the syscall exits. */
1185 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186 perror("PIOSEXIT");
1187 return -1;
1188 }
John Hughes19e49982001-10-19 08:59:12 +00001189 /* Enable signals we care about. */
1190 premptyset(&signals);
1191 for (i = 1; i < MAX_QUALS; ++i) {
1192 if (i > (sizeof signals) * CHAR_BIT) break;
1193 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1194 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001195 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001196 perror("PIOCSTRACE");
1197 return -1;
1198 }
John Hughes19e49982001-10-19 08:59:12 +00001199 /* Enable faults we care about */
1200 premptyset(&faults);
1201 for (i = 1; i < MAX_QUALS; ++i) {
1202 if (i > (sizeof faults) * CHAR_BIT) break;
1203 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1204 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001205 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206 perror("PIOCSFAULT");
1207 return -1;
1208 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001209#else /* FREEBSD */
1210 /* set events flags. */
1211 arg = S_SIG | S_SCE | S_SCX ;
1212 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1213 perror("PIOCBIS");
1214 return -1;
1215 }
1216#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217 if (!attaching) {
1218#ifdef MIPS
1219 /*
1220 * The SGI PRSABORT doesn't work for pause() so
1221 * we send it a caught signal to wake it up.
1222 */
1223 kill(tcp->pid, SIGINT);
1224#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001225#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001227 arg = PRSABORT;
1228 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 perror("PIOCRUN");
1230 return -1;
1231 }
Roland McGrath553a6092002-12-16 20:40:39 +00001232#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001233#endif /* !MIPS*/
1234#ifdef FREEBSD
1235 /* wake up the child if it received the SIGSTOP */
1236 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001237#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238 for (;;) {
1239 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001240 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 perror("PIOCWSTOP");
1242 return -1;
1243 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001244 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001245 tcp->flags &= ~TCB_INSYSCALL;
1246 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001247 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 break;
1249 }
1250 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001251#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001252 arg = 0;
1253 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001254#else /* FREEBSD */
1255 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001256#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257 perror("PIOCRUN");
1258 return -1;
1259 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001260#ifdef FREEBSD
1261 /* handle the case where we "opened" the child before
1262 it did the kill -STOP */
1263 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1264 tcp->status.PR_WHAT == SIGSTOP)
1265 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001266#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001268#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001270#else /* FREEBSD */
1271 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001272 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001273 /* We are attaching to an already running process.
1274 * Try to figure out the state of the process in syscalls,
1275 * to handle the first event well.
1276 * This is done by having a look at the "wchan" property of the
1277 * process, which tells where it is stopped (if it is). */
1278 FILE * status;
1279 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001280
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001281 sprintf(proc, "/proc/%d/status", tcp->pid);
1282 status = fopen(proc, "r");
1283 if (status &&
1284 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1285 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1286 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1287 strcmp(wchan, "stopevent")) {
1288 /* The process is asleep in the middle of a syscall.
1289 Fake the syscall entry event */
1290 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1291 tcp->status.PR_WHY = PR_SYSENTRY;
1292 trace_syscall(tcp);
1293 }
1294 if (status)
1295 fclose(status);
1296 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001297 }
1298#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299#ifndef HAVE_POLLABLE_PROCFS
1300 if (proc_poll_pipe[0] != -1)
1301 proc_poller(tcp->pfd);
1302 else if (nprocs > 1) {
1303 proc_poll_open();
1304 proc_poller(last_pfd);
1305 proc_poller(tcp->pfd);
1306 }
1307 last_pfd = tcp->pfd;
1308#endif /* !HAVE_POLLABLE_PROCFS */
1309 return 0;
1310}
1311
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001312#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001314struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315pid2tcb(pid)
1316int pid;
1317{
1318 int i;
1319 struct tcb *tcp;
1320
Roland McGrathee9d4352002-12-18 04:16:10 +00001321 for (i = 0; i < tcbtabsize; i++) {
1322 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323 if (pid && tcp->pid != pid)
1324 continue;
1325 if (tcp->flags & TCB_INUSE)
1326 return tcp;
1327 }
1328 return NULL;
1329}
1330
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001331#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332
1333static struct tcb *
1334pfd2tcb(pfd)
1335int pfd;
1336{
1337 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001338
Roland McGrathca16be82003-01-10 19:55:28 +00001339 for (i = 0; i < tcbtabsize; i++) {
1340 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341 if (tcp->pfd != pfd)
1342 continue;
1343 if (tcp->flags & TCB_INUSE)
1344 return tcp;
1345 }
1346 return NULL;
1347}
1348
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001349#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350
1351void
1352droptcb(tcp)
1353struct tcb *tcp;
1354{
1355 if (tcp->pid == 0)
1356 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001357#ifdef TCB_CLONE_THREAD
1358 if (tcp->nclone_threads > 0) {
1359 /* There are other threads left in this process, but this
1360 is the one whose PID represents the whole process.
1361 We need to keep this record around as a zombie until
1362 all the threads die. */
1363 tcp->flags |= TCB_EXITING;
1364 return;
1365 }
1366#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001367 nprocs--;
1368 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001369
Roland McGrathe29341c2003-01-10 20:14:20 +00001370 if (tcp->parent != NULL) {
1371 tcp->parent->nchildren--;
1372#ifdef TCB_CLONE_THREAD
1373 if (tcp->flags & TCB_CLONE_DETACHED)
1374 tcp->parent->nclone_detached--;
1375 if (tcp->flags & TCB_CLONE_THREAD)
1376 tcp->parent->nclone_threads--;
1377#endif
Roland McGrath09623452003-05-23 02:27:13 +00001378#ifdef TCB_CLONE_DETACHED
1379 if (!(tcp->flags & TCB_CLONE_DETACHED))
1380#endif
1381 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001382#ifdef LINUX
1383 /* Update `tcp->parent->parent->nchildren' and the other fields
1384 like NCLONE_DETACHED, only for zombie group leader that has
1385 already reported and been short-circuited at the top of this
1386 function. The same condition as at the top of DETACH. */
1387 if ((tcp->flags & TCB_CLONE_THREAD) &&
1388 tcp->parent->nclone_threads == 0 &&
1389 (tcp->parent->flags & TCB_EXITING))
1390 droptcb(tcp->parent);
1391#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001392 tcp->parent = NULL;
1393 }
1394
1395 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396 if (tcp->pfd != -1) {
1397 close(tcp->pfd);
1398 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001399#ifdef FREEBSD
1400 if (tcp->pfd_reg != -1) {
1401 close(tcp->pfd_reg);
1402 tcp->pfd_reg = -1;
1403 }
1404 if (tcp->pfd_status != -1) {
1405 close(tcp->pfd_status);
1406 tcp->pfd_status = -1;
1407 }
Roland McGrath553a6092002-12-16 20:40:39 +00001408#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001409#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001410 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411#endif
1412 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001413
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001414 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001416
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417 tcp->outf = 0;
1418}
1419
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001420#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421
1422static int
1423resume(tcp)
1424struct tcb *tcp;
1425{
1426 if (tcp == NULL)
1427 return -1;
1428
1429 if (!(tcp->flags & TCB_SUSPENDED)) {
1430 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1431 return -1;
1432 }
1433 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001434#ifdef TCB_CLONE_THREAD
1435 if (tcp->flags & TCB_CLONE_THREAD)
1436 tcp->parent->nclone_waiting--;
1437#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001439 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001440 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001441
1442 if (!qflag)
1443 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1444 return 0;
1445}
1446
Roland McGrath1bfd3102007-08-03 10:02:00 +00001447static int
1448resume_from_tcp (struct tcb *tcp)
1449{
1450 int error = 0;
1451 int resumed = 0;
1452
1453 /* XXX This won't always be quite right (but it never was).
1454 A waiter with argument 0 or < -1 is waiting for any pid in
1455 a particular pgrp, which this child might or might not be
1456 in. The waiter will only wake up if it's argument is -1
1457 or if it's waiting for tcp->pid's pgrp. It makes a
1458 difference to wake up a waiter when there might be more
1459 traced children, because it could get a false ECHILD
1460 error. OTOH, if this was the last child in the pgrp, then
1461 it ought to wake up and get ECHILD. We would have to
1462 search the system for all pid's in the pgrp to be sure.
1463
1464 && (t->waitpid == -1 ||
1465 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1466 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1467 */
1468
1469 if (tcp->parent &&
1470 (tcp->parent->flags & TCB_SUSPENDED) &&
1471 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1472 error = resume(tcp->parent);
1473 ++resumed;
1474 }
1475#ifdef TCB_CLONE_THREAD
1476 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1477 /* Some other threads of our parent are waiting too. */
1478 unsigned int i;
1479
1480 /* Resume all the threads that were waiting for this PID. */
1481 for (i = 0; i < tcbtabsize; i++) {
1482 struct tcb *t = tcbtab[i];
1483 if (t->parent == tcp->parent && t != tcp
1484 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1485 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1486 && t->waitpid == tcp->pid) {
1487 error |= resume (t);
1488 ++resumed;
1489 }
1490 }
1491 if (resumed == 0)
1492 /* Noone was waiting for this PID in particular,
1493 so now we might need to resume some wildcarders. */
1494 for (i = 0; i < tcbtabsize; i++) {
1495 struct tcb *t = tcbtab[i];
1496 if (t->parent == tcp->parent && t != tcp
1497 && ((t->flags
1498 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1499 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1500 && t->waitpid <= 0
1501 ) {
1502 error |= resume (t);
1503 break;
1504 }
1505 }
1506 }
1507
1508 return error;
1509}
1510#endif
1511
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001512#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513
Roland McGrath0a463882007-07-05 18:43:16 +00001514/* detach traced process; continue with sig
1515 Never call DETACH twice on the same process as both unattached and
1516 attached-unstopped processes give the same ESRCH. For unattached process we
1517 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518
1519static int
1520detach(tcp, sig)
1521struct tcb *tcp;
1522int sig;
1523{
1524 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001525#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001526 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001527 struct tcb *zombie = NULL;
1528
1529 /* If the group leader is lingering only because of this other
1530 thread now dying, then detach the leader as well. */
1531 if ((tcp->flags & TCB_CLONE_THREAD) &&
1532 tcp->parent->nclone_threads == 1 &&
1533 (tcp->parent->flags & TCB_EXITING))
1534 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001535#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536
1537 if (tcp->flags & TCB_BPTSET)
1538 sig = SIGKILL;
1539
1540#ifdef LINUX
1541 /*
1542 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001543 * before detaching. Arghh. We go through hoops
1544 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001546#if defined(SPARC)
1547#undef PTRACE_DETACH
1548#define PTRACE_DETACH PTRACE_SUNDETACH
1549#endif
Roland McGrath02203312007-06-11 22:06:31 +00001550 /*
1551 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1552 * expected SIGSTOP. We must catch exactly one as otherwise the
1553 * detached process would be left stopped (process state T).
1554 */
1555 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1557 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001558 }
1559 else if (errno != ESRCH) {
1560 /* Shouldn't happen. */
1561 perror("detach: ptrace(PTRACE_DETACH, ...)");
1562 }
Roland McGrath134813a2007-06-02 00:07:33 +00001563 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1564 : tcp->pid),
1565 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001566 if (errno != ESRCH)
1567 perror("detach: checking sanity");
1568 }
Roland McGrath02203312007-06-11 22:06:31 +00001569 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1570 ? tcp->parent->pid : tcp->pid),
1571 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001572 if (errno != ESRCH)
1573 perror("detach: stopping child");
1574 }
Roland McGrath02203312007-06-11 22:06:31 +00001575 else
1576 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001577 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001579#ifdef __WALL
1580 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1581 if (errno == ECHILD) /* Already gone. */
1582 break;
1583 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001584 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001585 break;
1586 }
1587#endif /* __WALL */
1588 /* No __WALL here. */
1589 if (waitpid(tcp->pid, &status, 0) < 0) {
1590 if (errno != ECHILD) {
1591 perror("detach: waiting");
1592 break;
1593 }
1594#ifdef __WCLONE
1595 /* If no processes, try clones. */
1596 if (wait4(tcp->pid, &status, __WCLONE,
1597 NULL) < 0) {
1598 if (errno != ECHILD)
1599 perror("detach: waiting");
1600 break;
1601 }
1602#endif /* __WCLONE */
1603 }
1604#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001605 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001606#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607 if (!WIFSTOPPED(status)) {
1608 /* Au revoir, mon ami. */
1609 break;
1610 }
1611 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001612 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613 break;
1614 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001615 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko96d5a762008-12-29 19:13:27 +00001616 WSTOPSIG(status) == ptrace_stop_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001617 : WSTOPSIG(status));
1618 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001621 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001622#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623
1624#if defined(SUNOS4)
1625 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1626 if (sig && kill(tcp->pid, sig) < 0)
1627 perror("detach: kill");
1628 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001629 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630#endif /* SUNOS4 */
1631
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001632#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001633 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001634#endif
1635
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636 if (!qflag)
1637 fprintf(stderr, "Process %u detached\n", tcp->pid);
1638
1639 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001640
1641#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001642 if (zombie != NULL) {
1643 /* TCP no longer exists therefore you must not detach () it. */
1644 droptcb(zombie);
1645 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001646#endif
1647
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 return error;
1649}
1650
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001651#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652
1653static void
1654reaper(sig)
1655int sig;
1656{
1657 int pid;
1658 int status;
1659
1660 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1661#if 0
1662 struct tcb *tcp;
1663
1664 tcp = pid2tcb(pid);
1665 if (tcp)
1666 droptcb(tcp);
1667#endif
1668 }
1669}
1670
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001671#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672
1673static void
1674cleanup()
1675{
1676 int i;
1677 struct tcb *tcp;
1678
Roland McGrathee9d4352002-12-18 04:16:10 +00001679 for (i = 0; i < tcbtabsize; i++) {
1680 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 if (!(tcp->flags & TCB_INUSE))
1682 continue;
1683 if (debug)
1684 fprintf(stderr,
1685 "cleanup: looking at pid %u\n", tcp->pid);
1686 if (tcp_last &&
1687 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001688 tprintf(" <unfinished ...>");
1689 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 }
1691 if (tcp->flags & TCB_ATTACHED)
1692 detach(tcp, 0);
1693 else {
1694 kill(tcp->pid, SIGCONT);
1695 kill(tcp->pid, SIGTERM);
1696 }
1697 }
1698 if (cflag)
1699 call_summary(outf);
1700}
1701
1702static void
1703interrupt(sig)
1704int sig;
1705{
1706 interrupted = 1;
1707}
1708
1709#ifndef HAVE_STRERROR
1710
Roland McGrath6d2b3492002-12-30 00:51:30 +00001711#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712extern int sys_nerr;
1713extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001714#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715
1716const char *
1717strerror(errno)
1718int errno;
1719{
1720 static char buf[64];
1721
1722 if (errno < 1 || errno >= sys_nerr) {
1723 sprintf(buf, "Unknown error %d", errno);
1724 return buf;
1725 }
1726 return sys_errlist[errno];
1727}
1728
1729#endif /* HAVE_STERRROR */
1730
1731#ifndef HAVE_STRSIGNAL
1732
Roland McGrath8f474e02003-01-14 07:53:33 +00001733#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001734extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001736#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1737extern char *_sys_siglist[];
1738#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739
1740const char *
1741strsignal(sig)
1742int sig;
1743{
1744 static char buf[64];
1745
1746 if (sig < 1 || sig >= NSIG) {
1747 sprintf(buf, "Unknown signal %d", sig);
1748 return buf;
1749 }
1750#ifdef HAVE__SYS_SIGLIST
1751 return _sys_siglist[sig];
1752#else
1753 return sys_siglist[sig];
1754#endif
1755}
1756
1757#endif /* HAVE_STRSIGNAL */
1758
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001759#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760
1761static void
1762rebuild_pollv()
1763{
1764 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765
Roland McGrathee9d4352002-12-18 04:16:10 +00001766 if (pollv != NULL)
1767 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001768 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001769 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001770 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001771 exit(1);
1772 }
1773
Roland McGrathca16be82003-01-10 19:55:28 +00001774 for (i = j = 0; i < tcbtabsize; i++) {
1775 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 if (!(tcp->flags & TCB_INUSE))
1777 continue;
1778 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001779 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780 j++;
1781 }
1782 if (j != nprocs) {
1783 fprintf(stderr, "strace: proc miscount\n");
1784 exit(1);
1785 }
1786}
1787
1788#ifndef HAVE_POLLABLE_PROCFS
1789
1790static void
1791proc_poll_open()
1792{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793 int i;
1794
1795 if (pipe(proc_poll_pipe) < 0) {
1796 perror("pipe");
1797 exit(1);
1798 }
1799 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001800 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801 exit(1);
1802 }
1803 }
1804}
1805
1806static int
1807proc_poll(pollv, nfds, timeout)
1808struct pollfd *pollv;
1809int nfds;
1810int timeout;
1811{
1812 int i;
1813 int n;
1814 struct proc_pollfd pollinfo;
1815
1816 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1817 return n;
1818 if (n != sizeof(struct proc_pollfd)) {
1819 fprintf(stderr, "panic: short read: %d\n", n);
1820 exit(1);
1821 }
1822 for (i = 0; i < nprocs; i++) {
1823 if (pollv[i].fd == pollinfo.fd)
1824 pollv[i].revents = pollinfo.revents;
1825 else
1826 pollv[i].revents = 0;
1827 }
1828 poller_pid = pollinfo.pid;
1829 return 1;
1830}
1831
1832static void
1833wakeup_handler(sig)
1834int sig;
1835{
1836}
1837
1838static void
1839proc_poller(pfd)
1840int pfd;
1841{
1842 struct proc_pollfd pollinfo;
1843 struct sigaction sa;
1844 sigset_t blocked_set, empty_set;
1845 int i;
1846 int n;
1847 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001848#ifdef FREEBSD
1849 struct procfs_status pfs;
1850#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851
1852 switch (fork()) {
1853 case -1:
1854 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001855 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856 case 0:
1857 break;
1858 default:
1859 return;
1860 }
1861
1862 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1863 sa.sa_flags = 0;
1864 sigemptyset(&sa.sa_mask);
1865 sigaction(SIGHUP, &sa, NULL);
1866 sigaction(SIGINT, &sa, NULL);
1867 sigaction(SIGQUIT, &sa, NULL);
1868 sigaction(SIGPIPE, &sa, NULL);
1869 sigaction(SIGTERM, &sa, NULL);
1870 sa.sa_handler = wakeup_handler;
1871 sigaction(SIGUSR1, &sa, NULL);
1872 sigemptyset(&blocked_set);
1873 sigaddset(&blocked_set, SIGUSR1);
1874 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1875 sigemptyset(&empty_set);
1876
1877 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1878 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001879 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 }
1881 n = rl.rlim_cur;
1882 for (i = 0; i < n; i++) {
1883 if (i != pfd && i != proc_poll_pipe[1])
1884 close(i);
1885 }
1886
1887 pollinfo.fd = pfd;
1888 pollinfo.pid = getpid();
1889 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001890#ifndef FREEBSD
1891 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1892#else /* FREEBSD */
1893 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1894#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001895 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 switch (errno) {
1897 case EINTR:
1898 continue;
1899 case EBADF:
1900 pollinfo.revents = POLLERR;
1901 break;
1902 case ENOENT:
1903 pollinfo.revents = POLLHUP;
1904 break;
1905 default:
1906 perror("proc_poller: PIOCWSTOP");
1907 }
1908 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1909 _exit(0);
1910 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001911 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1913 sigsuspend(&empty_set);
1914 }
1915}
1916
1917#endif /* !HAVE_POLLABLE_PROCFS */
1918
1919static int
1920choose_pfd()
1921{
1922 int i, j;
1923 struct tcb *tcp;
1924
1925 static int last;
1926
1927 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001928 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001929 /*
1930 * The previous process is ready to run again. We'll
1931 * let it do so if it is currently in a syscall. This
1932 * heuristic improves the readability of the trace.
1933 */
1934 tcp = pfd2tcb(pollv[last].fd);
1935 if (tcp && (tcp->flags & TCB_INSYSCALL))
1936 return pollv[last].fd;
1937 }
1938
1939 for (i = 0; i < nprocs; i++) {
1940 /* Let competing children run round robin. */
1941 j = (i + last + 1) % nprocs;
1942 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1943 tcp = pfd2tcb(pollv[j].fd);
1944 if (!tcp) {
1945 fprintf(stderr, "strace: lost proc\n");
1946 exit(1);
1947 }
1948 droptcb(tcp);
1949 return -1;
1950 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001951 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 last = j;
1953 return pollv[j].fd;
1954 }
1955 }
1956 fprintf(stderr, "strace: nothing ready\n");
1957 exit(1);
1958}
1959
1960static int
1961trace()
1962{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001963#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001964 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001965#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 struct tcb *tcp;
1967 int pfd;
1968 int what;
1969 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001970 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971
1972 for (;;) {
1973 if (interactive)
1974 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1975
1976 if (nprocs == 0)
1977 break;
1978
1979 switch (nprocs) {
1980 case 1:
1981#ifndef HAVE_POLLABLE_PROCFS
1982 if (proc_poll_pipe[0] == -1) {
1983#endif
1984 tcp = pid2tcb(0);
1985 if (!tcp)
1986 continue;
1987 pfd = tcp->pfd;
1988 if (pfd == -1)
1989 continue;
1990 break;
1991#ifndef HAVE_POLLABLE_PROCFS
1992 }
1993 /* fall through ... */
1994#endif /* !HAVE_POLLABLE_PROCFS */
1995 default:
1996#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001997#ifdef POLL_HACK
1998 /* On some systems (e.g. UnixWare) we get too much ugly
1999 "unfinished..." stuff when multiple proceses are in
2000 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002001
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002002 if (in_syscall) {
2003 struct pollfd pv;
2004 tcp = in_syscall;
2005 in_syscall = NULL;
2006 pv.fd = tcp->pfd;
2007 pv.events = POLLWANT;
2008 if ((what = poll (&pv, 1, 1)) < 0) {
2009 if (interrupted)
2010 return 0;
2011 continue;
2012 }
2013 else if (what == 1 && pv.revents & POLLWANT) {
2014 goto FOUND;
2015 }
2016 }
2017#endif
2018
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019 if (poll(pollv, nprocs, INFTIM) < 0) {
2020 if (interrupted)
2021 return 0;
2022 continue;
2023 }
2024#else /* !HAVE_POLLABLE_PROCFS */
2025 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2026 if (interrupted)
2027 return 0;
2028 continue;
2029 }
2030#endif /* !HAVE_POLLABLE_PROCFS */
2031 pfd = choose_pfd();
2032 if (pfd == -1)
2033 continue;
2034 break;
2035 }
2036
2037 /* Look up `pfd' in our table. */
2038 if ((tcp = pfd2tcb(pfd)) == NULL) {
2039 fprintf(stderr, "unknown pfd: %u\n", pfd);
2040 exit(1);
2041 }
John Hughesb6643082002-05-23 11:02:22 +00002042#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002043 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002044#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045 /* Get the status of the process. */
2046 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002047#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002048 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002049#else /* FREEBSD */
2050 /* Thanks to some scheduling mystery, the first poller
2051 sometimes waits for the already processed end of fork
2052 event. Doing a non blocking poll here solves the problem. */
2053 if (proc_poll_pipe[0] != -1)
2054 ioctl_result = IOCTL_STATUS (tcp);
2055 else
2056 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002057#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058 ioctl_errno = errno;
2059#ifndef HAVE_POLLABLE_PROCFS
2060 if (proc_poll_pipe[0] != -1) {
2061 if (ioctl_result < 0)
2062 kill(poller_pid, SIGKILL);
2063 else
2064 kill(poller_pid, SIGUSR1);
2065 }
2066#endif /* !HAVE_POLLABLE_PROCFS */
2067 }
2068 if (interrupted)
2069 return 0;
2070
2071 if (interactive)
2072 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2073
2074 if (ioctl_result < 0) {
2075 /* Find out what happened if it failed. */
2076 switch (ioctl_errno) {
2077 case EINTR:
2078 case EBADF:
2079 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002080#ifdef FREEBSD
2081 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002082#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083 case ENOENT:
2084 droptcb(tcp);
2085 continue;
2086 default:
2087 perror("PIOCWSTOP");
2088 exit(1);
2089 }
2090 }
2091
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002092#ifdef FREEBSD
2093 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2094 /* discard first event for a syscall we never entered */
2095 IOCTL (tcp->pfd, PIOCRUN, 0);
2096 continue;
2097 }
Roland McGrath553a6092002-12-16 20:40:39 +00002098#endif
2099
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100 /* clear the just started flag */
2101 tcp->flags &= ~TCB_STARTUP;
2102
2103 /* set current output file */
2104 outf = tcp->outf;
2105
2106 if (cflag) {
2107 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002108#ifdef FREEBSD
2109 char buf[1024];
2110 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002111
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002112 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2113 buf[len] = '\0';
2114 sscanf(buf,
2115 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2116 &stime.tv_sec, &stime.tv_usec);
2117 } else
2118 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002119#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002120 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2121 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002122#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002123 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2124 tcp->stime = stime;
2125 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002126 what = tcp->status.PR_WHAT;
2127 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002128#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002130 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2131 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002132 if (trace_syscall(tcp) < 0) {
2133 fprintf(stderr, "syscall trouble\n");
2134 exit(1);
2135 }
2136 }
2137 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002138#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002140#ifdef POLL_HACK
2141 in_syscall = tcp;
2142#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002143 case PR_SYSEXIT:
2144 if (trace_syscall(tcp) < 0) {
2145 fprintf(stderr, "syscall trouble\n");
2146 exit(1);
2147 }
2148 break;
2149 case PR_SIGNALLED:
2150 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2151 printleader(tcp);
2152 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002153 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002154 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002155#ifdef PR_INFO
2156 if (tcp->status.PR_INFO.si_signo == what) {
2157 printleader(tcp);
2158 tprintf(" siginfo=");
2159 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002160 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002161 }
2162#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002163 }
2164 break;
2165 case PR_FAULTED:
2166 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2167 printleader(tcp);
2168 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002169 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 }
2171 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002172#ifdef FREEBSD
2173 case 0: /* handle case we polled for nothing */
2174 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002175#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002176 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002177 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002178 exit(1);
2179 break;
2180 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002181 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002182#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002183 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002184#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002185 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002186#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 perror("PIOCRUN");
2188 exit(1);
2189 }
2190 }
2191 return 0;
2192}
2193
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002194#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002196#ifdef TCB_GROUP_EXITING
2197/* Handle an exit detach or death signal that is taking all the
2198 related clone threads with it. This is called in three circumstances:
2199 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2200 SIG == 0 Continuing TCP will perform an exit_group syscall.
2201 SIG == other Continuing TCP with SIG will kill the process.
2202*/
2203static int
2204handle_group_exit(struct tcb *tcp, int sig)
2205{
2206 /* We need to locate our records of all the clone threads
2207 related to TCP, either its children or siblings. */
2208 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2209 ? tcp->parent
2210 : tcp->nclone_detached > 0
2211 ? tcp : NULL);
2212
2213 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002214 if (leader != NULL && leader != tcp &&
2215 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002216 fprintf(stderr,
2217 "PANIC: handle_group_exit: %d leader %d\n",
2218 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002219 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002220#ifndef USE_PROCFS
2221 resume_from_tcp (tcp);
2222#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002223 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002224 }
2225 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002226 /* Mark that we are taking the process down. */
2227 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002228 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002229 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002230 if (leader != NULL && leader != tcp)
2231 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002232 } else {
2233 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2234 cleanup();
2235 return -1;
2236 }
2237 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002238 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002239 if (leader != tcp)
2240 droptcb(tcp);
2241 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002242 /* The leader will report to us as parent now,
2243 and then we'll get to the SIG==-1 case. */
2244 return 0;
2245 }
2246 }
2247
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002248 return 0;
2249}
2250#endif
2251
Denys Vlasenko215cc272009-01-09 17:22:56 +00002252static struct tcb *
2253collect_stopped_tcbs(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002254{
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002255#ifdef LINUX
2256 static int remembered_pid;
2257 static int remembered_status;
2258#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002259 int pid;
2260 int wait_errno;
2261 int status;
2262 struct tcb *tcp;
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002263 struct tcb *found_tcps;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002264#ifdef LINUX
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002265 struct tcb **nextp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266 struct rusage ru;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002267 struct rusage* ru_ptr = cflag ? &ru : NULL;
2268 int wnohang = 0;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002269#ifdef __WALL
Denys Vlasenko215cc272009-01-09 17:22:56 +00002270 int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002271#endif
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002272
2273 if (remembered_pid > 0) {
2274 pid = remembered_pid;
2275 remembered_pid = 0;
2276 if (debug)
2277 fprintf(stderr, " [remembered wait(%#x) = %u]\n",
2278 remembered_status, pid);
2279 tcp = pid2tcb(pid); /* can't be NULL */
2280 tcp->wait_status = remembered_status;
2281 tcp->next_need_service = NULL;
2282 return tcp;
2283 }
2284 nextp = &found_tcps;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285#endif /* LINUX */
2286
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002287 found_tcps = NULL;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002288 while (1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002289#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002290#ifdef __WALL
Denys Vlasenko215cc272009-01-09 17:22:56 +00002291 pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
Roland McGrath5bc05552002-12-17 04:50:47 +00002292 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002293 /* this kernel does not support __WALL */
2294 wait4_options &= ~__WALL;
2295 errno = 0;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002296 pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002297 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002298 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002299 /* most likely a "cloned" process */
Denys Vlasenko215cc272009-01-09 17:22:56 +00002300 pid = wait4(-1, &status, __WCLONE | wnohang, ru_ptr);
2301 if (pid < 0 && errno != ECHILD) {
2302 fprintf(stderr, "strace: wait4(WCLONE) "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002303 "failed: %s\n", strerror(errno));
2304 }
2305 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002306#else /* !__WALL */
2307 pid = wait4(-1, &status, wnohang, ru_ptr);
2308#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002309#endif /* LINUX */
2310#ifdef SUNOS4
2311 pid = wait(&status);
2312#endif /* SUNOS4 */
2313 wait_errno = errno;
2314 if (interactive)
2315 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2316
Denys Vlasenko215cc272009-01-09 17:22:56 +00002317 if (pid == 0 && wnohang) {
2318 /* We had at least one successful
2319 * wait() before. We waited
2320 * with WNOHANG second time.
2321 * Stop collecting more tracees,
2322 * process what we already have.
2323 */
2324 break;
2325 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002326 if (pid == -1) {
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002327 if (wait_errno == EINTR)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002328 continue;
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002329 if (wait_errno == ECHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330 /*
2331 * We would like to verify this case
2332 * but sometimes a race in Solbourne's
2333 * version of SunOS sometimes reports
2334 * ECHILD before sending us SIGCHILD.
2335 */
2336#if 0
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002337 if (nprocs != 0) {
2338 fprintf(stderr, "strace: proc miscount\n");
2339 exit(1);
2340 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341#endif
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002342 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343 }
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002344 errno = wait_errno;
2345 perror("strace: wait");
2346 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002348 if (pid == popen_pid) {
2349 if (WIFEXITED(status) || WIFSIGNALED(status))
2350 popen_pid = -1;
2351 continue;
2352 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002353 if (debug)
2354 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2355
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002356 /* RHEL5 bug workaround.
2357 * It can re-report stopped tasks. Happens on SIGSTOPs here.
2358 * Second (bogus) report has signal# set to 0.
2359 * Stop collecting and process what we have.
2360 */
2361 if (WIFSTOPPED(status) && WSTOPSIG(status) == 0)
2362 break;
2363
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002364 /* Look up `pid' in our table. */
2365 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002366#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002367 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002368 /* This is needed to go with the CLONE_PTRACE
2369 changes in process.c/util.c: we might see
2370 the child's initial trap before we see the
2371 parent return from the clone syscall.
2372 Leave the child suspended until the parent
2373 returns from its system call. Only then
2374 will we have the association of parent and
2375 child so that we know how to do clearbpt
2376 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002377 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002378 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002379 if (!qflag)
2380 fprintf(stderr, "\
2381Process %d attached (waiting for parent)\n",
2382 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002383 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002384 else
2385 /* This can happen if a clone call used
2386 CLONE_PTRACE itself. */
Denys Vlasenko215cc272009-01-09 17:22:56 +00002387#endif /* LINUX */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002388 {
2389 fprintf(stderr, "unknown pid: %u\n", pid);
2390 if (WIFSTOPPED(status))
2391 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2392 exit(1);
2393 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002395
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 if (cflag) {
2397#ifdef LINUX
2398 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2399 tcp->stime = ru.ru_stime;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002400#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002401 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002402 if (tcp->flags & TCB_SUSPENDED) {
2403 /*
2404 * Apparently, doing any ptrace() call on a stopped
2405 * process, provokes the kernel to report the process
2406 * status again on a subsequent wait(), even if the
2407 * process has not been actually restarted.
2408 * Since we have inspected the arguments of suspended
2409 * processes we end up here testing for this case.
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002410 *
2411 * We also end up here when we catch new pid of
2412 * CLONE_PTRACEd process. Do not process/restart it
2413 * until we see corresponding clone() syscall exit
2414 * in its parent.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415 */
2416 continue;
2417 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002418
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002419#ifdef LINUX
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002420 /* So far observed only on RHEL5 ia64, but I imagine this
2421 * can legitimately happen elsewhere.
2422 * If we waited and got a stopped task notification,
2423 * subsequent wait may return the same pid again, for example,
2424 * with SIGKILL notification. SIGKILL kills even stopped tasks.
2425 * We must not add it to the list
2426 * (one task can't be inserted twice in the list).
2427 */
2428 {
2429 struct tcb *f = found_tcps;
2430 while (f) {
2431 if (f == tcp) {
2432 remembered_pid = pid;
2433 remembered_status = status;
2434 return found_tcps;
2435 }
2436 f = f->next_need_service;
2437 }
2438 }
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002439 /* It is important to not invert the order of tasks
2440 * to process. For one, alloc_tcb() above picks newly forked
2441 * threads in some order, processing of them and their parent
2442 * should be in the same order, otherwise bad things happen
2443 * (misinterpreted SIGSTOPs and such).
2444 */
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002445 tcp->wait_status = status;
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002446 *nextp = tcp;
2447 nextp = &tcp->next_need_service;
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002448 *nextp = NULL;
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002449 wnohang = WNOHANG;
2450#endif
2451#ifdef SUNOS4
2452 /* Probably need to replace wait with waitpid
2453 * and loop on Sun too, but I can't test it. Volunteers?
2454 */
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002455 tcp->wait_status = status;
2456 tcp->next_need_service = NULL;
2457 found_tcps = tcp;
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002458 break;
2459#endif
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002460 } /* while (1) - collecting all stopped/exited tracees */
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002461
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002462 return found_tcps;
2463}
2464
2465static int
2466handle_stopped_tcbs(struct tcb *tcp)
2467{
2468 for (; tcp; tcp = tcp->next_need_service) {
2469 int pid;
2470 int status;
2471
Denys Vlasenko215cc272009-01-09 17:22:56 +00002472 outf = tcp->outf;
2473 status = tcp->wait_status;
2474 pid = tcp->pid;
2475
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002476 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002477 if (pid == strace_child)
2478 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002479 if (!cflag
2480 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2481 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002482 tprintf("+++ killed by %s %s+++",
2483 signame(WTERMSIG(status)),
2484#ifdef WCOREDUMP
2485 WCOREDUMP(status) ? "(core dumped) " :
2486#endif
2487 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002488 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002489 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002490#ifdef TCB_GROUP_EXITING
2491 handle_group_exit(tcp, -1);
2492#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002493 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002494#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495 continue;
2496 }
2497 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002498 if (pid == strace_child)
2499 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002500 if (debug)
2501 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002502 if ((tcp->flags & TCB_ATTACHED)
2503#ifdef TCB_GROUP_EXITING
2504 && !(tcp->parent && (tcp->parent->flags &
2505 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002506 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002507#endif
2508 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002509 fprintf(stderr,
2510 "PANIC: attached pid %u exited\n",
2511 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002512 if (tcp == tcp_last) {
2513 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2514 == TCB_INSYSCALL)
2515 tprintf(" <unfinished ... exit status %d>\n",
2516 WEXITSTATUS(status));
2517 tcp_last = NULL;
2518 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002519#ifdef TCB_GROUP_EXITING
2520 handle_group_exit(tcp, -1);
2521#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002522 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002523#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002524 continue;
2525 }
2526 if (!WIFSTOPPED(status)) {
2527 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2528 droptcb(tcp);
2529 continue;
2530 }
2531 if (debug)
2532 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002533 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534
Roland McGrath02203312007-06-11 22:06:31 +00002535 /*
2536 * Interestingly, the process may stop
2537 * with STOPSIG equal to some other signal
2538 * than SIGSTOP if we happend to attach
2539 * just before the process takes a signal.
2540 */
2541 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002542 /*
2543 * This flag is there to keep us in sync.
2544 * Next time this process stops it should
2545 * really be entering a system call.
2546 */
2547 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002548 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002549 /*
2550 * One example is a breakpoint inherited from
2551 * parent through fork ().
2552 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002553 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2554 droptcb(tcp);
2555 cleanup();
2556 return -1;
2557 }
2558 }
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002559/* Add more OSes after you verified it works for them. */
Denys Vlasenkof535b542009-01-13 18:30:55 +00002560/* PTRACE_SETOPTIONS may be an enum, not a #define.
2561 * But sometimes we can test for it by checking PT_SETOPTIONS.
2562 */
2563#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
Denys Vlasenko0861ecb2009-01-02 16:55:24 +00002564# ifndef PTRACE_O_TRACESYSGOOD
2565# define PTRACE_O_TRACESYSGOOD 0x00000001
2566# endif
2567# ifndef PTRACE_O_TRACEEXEC
2568# define PTRACE_O_TRACEEXEC 0x00000010
2569# endif
2570# ifndef PTRACE_EVENT_EXEC
2571# define PTRACE_EVENT_EXEC 4
2572# endif
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002573 /*
2574 * Ask kernel to set signo to SIGTRAP | 0x80
2575 * on ptrace-generated SIGTRAPs, and mark
2576 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
2577 */
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002578 if (!ptrace_opts_set) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002579 char *p;
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002580 ptrace_opts_set = 1;
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002581
2582 /* RHEL 2.6.18 definitely has crippling bugs */
2583 /* Vanilla and Fedora 2.6.29 seems to work */
2584 p = utsname_buf.release;
2585 if (strtoul(p, &p, 10) < 2 || *p != '.')
2586 goto tracing;
2587 if (strtoul(++p, &p, 10) < 6 || *p != '.')
2588 goto tracing;
2589 if (strtoul(++p, &p, 10) < 29)
2590 goto tracing;
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002591 /*
2592 * NB: even if this "succeeds", we can
2593 * revert back to SIGTRAP if we later see
2594 * that it didnt really work.
2595 * Old kernels are known to lie here.
2596 */
2597 if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
2598 (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
2599 ptrace_stop_sig = SIGTRAP | 0x80;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002600 }
2601#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002602 goto tracing;
2603 }
2604
Denys Vlasenkof535b542009-01-13 18:30:55 +00002605#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002606 if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002607 /*
2608 * We told ptrace to report SIGTRAP | 0x80 on this process
2609 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
2610 * kill(pid, SIGTRAP), trap insn, etc;
2611 * but be paranoid about it.
2612 */
2613 if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
Denys Vlasenko1d5b1132009-01-17 01:06:18 +00002614 /* It's post-exec ptrace stop. Ignore it,
2615 * we will get syscall exit ptrace stop later.
2616 */
2617#ifdef TCB_WAITEXECVE
2618 tcp->flags &= ~TCB_WAITEXECVE;
2619#endif
2620 goto tracing;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002621 } else {
2622 /* Take a better look... */
2623 siginfo_t si;
Denys Vlasenko1d5b1132009-01-17 01:06:18 +00002624 si.si_signo = 0;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002625 ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
2626 /*
2627 * Check some fields to make sure we see
2628 * real SIGTRAP.
2629 * Otherwise interpret it as ptrace stop.
2630 * Real SIGTRAPs (int3 insn on x86, kill() etc)
2631 * have these values:
2632 * int3: kill -TRAP $pid:
2633 * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
2634 * si_errno:0 si_errno:(?)
2635 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
2636 * si_pid:0 si_pid:(>0?)
2637 * si_band:0 si_band:(?)
2638 * Ptrace stops have garbage there instead.
2639 */
2640 if (si.si_signo != SIGTRAP
2641 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
2642 ) {
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002643 fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
2644 ptrace_stop_sig = SIGTRAP;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002645 }
2646 }
2647 }
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002648#endif
2649
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002650 if (WSTOPSIG(status) != ptrace_stop_sig) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002651 /* This isn't a ptrace stop. */
2652
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002653 if (WSTOPSIG(status) == SIGSTOP &&
2654 (tcp->flags & TCB_SIGTRAPPED)) {
2655 /*
2656 * Trapped attempt to block SIGTRAP
2657 * Hope we are back in control now.
2658 */
2659 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002660 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 cleanup();
2662 return -1;
2663 }
2664 continue;
2665 }
2666 if (!cflag
2667 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002668 unsigned long addr = 0;
2669 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002670#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002671# define PSR_RI 41
2672 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002673 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002674
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002675 upeek(tcp, PT_CR_IPSR, &psr);
2676 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002677
2678 pc += (psr >> PSR_RI) & 0x3;
2679 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2680 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002681#elif defined PTRACE_GETSIGINFO
2682 if (WSTOPSIG(status) == SIGSEGV ||
2683 WSTOPSIG(status) == SIGBUS) {
2684 siginfo_t si;
2685 if (ptrace(PTRACE_GETSIGINFO, pid,
2686 0, &si) == 0)
2687 addr = (unsigned long)
2688 si.si_addr;
2689 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002690#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002691 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002692 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002693 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002694 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002695 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002696 }
Roland McGrath05690952004-10-20 01:00:27 +00002697 if (((tcp->flags & TCB_ATTACHED) ||
2698 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002699 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002700#ifdef TCB_GROUP_EXITING
2701 handle_group_exit(tcp, WSTOPSIG(status));
2702#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002703 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002704#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002705 continue;
2706 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002707 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002708 cleanup();
2709 return -1;
2710 }
2711 tcp->flags &= ~TCB_SUSPENDED;
2712 continue;
2713 }
Roland McGrath02203312007-06-11 22:06:31 +00002714 /* we handled the STATUS, we are permitted to interrupt now. */
2715 if (interrupted)
2716 return 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002717 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002718 /* ptrace() failed in trace_syscall() with ESRCH.
2719 * Likely a result of process disappearing mid-flight.
2720 * Observed case: exit_group() terminating
2721 * all processes in thread group. In this case, threads
2722 * "disappear" in an unpredictable moment without any
2723 * notification to strace via wait().
2724 */
2725 if (tcp->flags & TCB_ATTACHED) {
2726 if (tcp_last) {
2727 /* Do we have dangling line "syscall(param, param"?
2728 * Finish the line then. We cannot
2729 */
2730 tcp_last->flags |= TCB_REPRINT;
2731 tprintf(" <unfinished ...>");
2732 printtrailer();
2733 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002734 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002735 } else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002736 ptrace(PTRACE_KILL,
2737 tcp->pid, (char *) 1, SIGTERM);
2738 droptcb(tcp);
2739 }
2740 continue;
2741 }
2742 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002743#ifdef TCB_GROUP_EXITING
2744 if (tcp->flags & TCB_GROUP_EXITING) {
2745 if (handle_group_exit(tcp, 0) < 0)
2746 return -1;
2747 continue;
2748 }
2749#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002750 if (tcp->flags & TCB_ATTACHED)
2751 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002752 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002753 cleanup();
2754 return -1;
2755 }
2756 continue;
2757 }
2758 if (tcp->flags & TCB_SUSPENDED) {
2759 if (!qflag)
2760 fprintf(stderr, "Process %u suspended\n", pid);
2761 continue;
2762 }
2763 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002764 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002765 cleanup();
2766 return -1;
2767 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002768 } /* for each tcp */
2769
2770 return 0;
2771}
2772
2773static int
2774trace()
2775{
2776 int rc;
2777 struct tcb *tcbs;
2778
2779 while (nprocs != 0) {
2780 if (interrupted)
2781 return 0;
2782 if (interactive)
2783 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2784
2785 /* The loop of "wait for one tracee, serve it, repeat"
2786 * may leave some tracees never served.
2787 * Kernel provides no guarantees of fairness when you have
2788 * many waitable tasks.
2789 * Try strace -f with test/many_looping_threads.c example.
2790 * To fix it, we collect *all* waitable tasks, then handle
2791 * them all, then repeat.
2792 */
2793 tcbs = collect_stopped_tcbs();
2794 if (!tcbs)
2795 break;
2796 rc = handle_stopped_tcbs(tcbs);
2797 if (rc)
2798 return rc;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002799 }
2800 return 0;
2801}
2802
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002803#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002804
2805static int curcol;
2806
2807#ifdef __STDC__
2808#include <stdarg.h>
2809#define VA_START(a, b) va_start(a, b)
2810#else
2811#include <varargs.h>
2812#define VA_START(a, b) va_start(a)
2813#endif
2814
2815void
2816#ifdef __STDC__
2817tprintf(const char *fmt, ...)
2818#else
2819tprintf(fmt, va_alist)
2820char *fmt;
2821va_dcl
2822#endif
2823{
2824 va_list args;
2825
2826 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002827 if (outf) {
2828 int n = vfprintf(outf, fmt, args);
2829 if (n < 0 && outf != stderr)
2830 perror(outfname == NULL
2831 ? "<writing to pipe>" : outfname);
2832 else
2833 curcol += n;
2834 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002835 va_end(args);
2836 return;
2837}
2838
2839void
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002840printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002841{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002842 if (tcp_last) {
2843 if (tcp_last->ptrace_errno) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002844 tcp_last->ptrace_errno = 0;
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002845 if (tcp_last->flags & TCB_INSYSCALL) {
2846 tprintf(" <unavailable ...>\n");
2847 tcp_last->flags |= TCB_REPRINT;
2848 } else {
2849 tprintf("= ? <unavailable>\n");
2850 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002851 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002852 tprintf(" <unfinished ...>\n");
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002853 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002854 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002855 }
2856 curcol = 0;
2857 if ((followfork == 1 || pflag_seen > 1) && outfname)
2858 tprintf("%-5d ", tcp->pid);
2859 else if (nprocs > 1 && !outfname)
2860 tprintf("[pid %5u] ", tcp->pid);
2861 if (tflag) {
2862 char str[sizeof("HH:MM:SS")];
2863 struct timeval tv, dtv;
2864 static struct timeval otv;
2865
2866 gettimeofday(&tv, NULL);
2867 if (rflag) {
2868 if (otv.tv_sec == 0)
2869 otv = tv;
2870 tv_sub(&dtv, &tv, &otv);
2871 tprintf("%6ld.%06ld ",
2872 (long) dtv.tv_sec, (long) dtv.tv_usec);
2873 otv = tv;
2874 }
2875 else if (tflag > 2) {
2876 tprintf("%ld.%06ld ",
2877 (long) tv.tv_sec, (long) tv.tv_usec);
2878 }
2879 else {
2880 time_t local = tv.tv_sec;
2881 strftime(str, sizeof(str), "%T", localtime(&local));
2882 if (tflag > 1)
2883 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2884 else
2885 tprintf("%s ", str);
2886 }
2887 }
2888 if (iflag)
2889 printcall(tcp);
2890}
2891
2892void
2893tabto(col)
2894int col;
2895{
2896 if (curcol < col)
2897 tprintf("%*s", col - curcol, "");
2898}
2899
2900void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002901printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002902{
2903 tprintf("\n");
2904 tcp_last = NULL;
2905}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002906
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002907#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002908
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002909int
2910mp_ioctl(int fd, int cmd, void *arg, int size)
2911{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002912 struct iovec iov[2];
2913 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002914
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002915 iov[0].iov_base = &cmd;
2916 iov[0].iov_len = sizeof cmd;
2917 if (arg) {
2918 ++n;
2919 iov[1].iov_base = arg;
2920 iov[1].iov_len = size;
2921 }
Roland McGrath553a6092002-12-16 20:40:39 +00002922
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002923 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002924}
2925
2926#endif