blob: 6af0e1add0a712f4a1ad7311364afea38ba50a5e [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>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#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
Denys Vlasenkob63256e2011-06-07 12:13:24 +020053# define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000054# elif defined __NR_tkill
Denys Vlasenkob63256e2011-06-07 12:13:24 +020055# define my_tgkill(pid, tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000056# 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!"
Denys Vlasenkob63256e2011-06-07 12:13:24 +020061# define my_tgkill(pid, tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000062# 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;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020087unsigned int ptrace_setoptions_followfork = 0;
Denys Vlasenkof8bc0652011-05-24 20:30:24 +020088unsigned int ptrace_setoptions_for_all = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020089/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020090static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000091int dtime = 0, xflag = 0, qflag = 0;
92cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000093static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000094/*
95 * daemonized_tracer supports -D option.
96 * With this option, strace forks twice.
97 * Unlike normal case, with -D *grandparent* process exec's,
98 * becoming a traced process. Child exits (this prevents traced process
99 * from having children it doesn't expect to have), and grandchild
100 * attaches to grandparent similarly to strace -p PID.
101 * This allows for more transparent interaction in cases
102 * when process and its parent are communicating via signals,
103 * wait() etc. Without -D, strace process gets lodged in between,
104 * disrupting parent<->child link.
105 */
106static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000108/* Sometimes we want to print only succeeding syscalls. */
109int not_failing_only = 0;
110
Grant Edwards8a082772011-04-07 20:25:40 +0000111/* Show path associated with fd arguments */
112int show_fd_path = 0;
113
114/* are we filtering traces based on paths? */
115int tracing_paths = 0;
116
Dmitry V. Levina6809652008-11-10 17:14:58 +0000117static int exit_code = 0;
118static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200119static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700120
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000121static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122uid_t run_uid;
123gid_t run_gid;
124
125int acolumn = DEFAULT_ACOLUMN;
126int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000127static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100129static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000130struct tcb **tcbtab;
131unsigned int nprocs, tcbtabsize;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000132const char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700133extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134
Andreas Schwabe5355de2009-10-27 16:56:43 +0100135static int detach(struct tcb *tcp, int sig);
136static int trace(void);
137static void cleanup(void);
138static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139static sigset_t empty_set, blocked_set;
140
141#ifdef HAVE_SIG_ATOMIC_T
142static volatile sig_atomic_t interrupted;
143#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145#endif /* !HAVE_SIG_ATOMIC_T */
146
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000147#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148
Andreas Schwabe5355de2009-10-27 16:56:43 +0100149static struct tcb *pfd2tcb(int pfd);
150static void reaper(int sig);
151static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000152static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153
154#ifndef HAVE_POLLABLE_PROCFS
155
Andreas Schwabe5355de2009-10-27 16:56:43 +0100156static void proc_poll_open(void);
157static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158
159struct proc_pollfd {
160 int fd;
161 int revents;
162 int pid;
163};
164
165static int poller_pid;
166static int proc_poll_pipe[2] = { -1, -1 };
167
168#endif /* !HAVE_POLLABLE_PROCFS */
169
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000170#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000171#define POLLWANT POLLWRNORM
172#else
173#define POLLWANT POLLPRI
174#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000175#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176
177static void
178usage(ofp, exitval)
179FILE *ofp;
180int exitval;
181{
182 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000183usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000184 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000185 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200186 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000187 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200189-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000190-f -- follow forks, -ff -- with output into separate files\n\
191-F -- attempt to follow vforks, -h -- print help message\n\
192-i -- print instruction pointer at time of syscall\n\
193-q -- suppress messages about attaching, detaching, etc.\n\
194-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
195-T -- print time spent in each syscall, -V -- print version\n\
196-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
197-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000198-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199-a column -- alignment COLUMN for printing syscall results (default %d)\n\
200-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
201 options: trace, abbrev, verbose, raw, signal, read, or write\n\
202-o file -- send trace output to FILE instead of stderr\n\
203-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
204-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000205-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
207-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
208-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000209-E var=val -- put var=val in the environment for command\n\
210-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000211-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000212" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000213-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000214 */
215, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000216 exit(exitval);
217}
218
Denys Vlasenko75422762011-05-27 14:36:01 +0200219static void die(void) __attribute__ ((noreturn));
220static void die(void)
221{
222 if (strace_tracer_pid == getpid()) {
223 cflag = 0;
224 cleanup();
225 }
226 exit(1);
227}
228
229static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200230{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000231 fflush(NULL);
232 fprintf(stderr, "%s: ", progname);
233 vfprintf(stderr, fmt, p);
234 if (err_no)
235 fprintf(stderr, ": %s\n", strerror(err_no));
236 else
237 putc('\n', stderr);
238 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200239}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200240
Denys Vlasenko75422762011-05-27 14:36:01 +0200241void error_msg(const char *fmt, ...)
242{
243 va_list p;
244 va_start(p, fmt);
245 verror_msg(0, fmt, p);
246 va_end(p);
247}
248
249void error_msg_and_die(const char *fmt, ...)
250{
251 va_list p;
252 va_start(p, fmt);
253 verror_msg(0, fmt, p);
254 die();
255}
256
257void perror_msg(const char *fmt, ...)
258{
259 va_list p;
260 va_start(p, fmt);
261 verror_msg(errno, fmt, p);
262 va_end(p);
263}
264
265void perror_msg_and_die(const char *fmt, ...)
266{
267 va_list p;
268 va_start(p, fmt);
269 verror_msg(errno, fmt, p);
270 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200271}
272
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000273#ifdef SVR4
274#ifdef MIPS
275void
276foobar()
277{
278}
279#endif /* MIPS */
280#endif /* SVR4 */
281
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400282/* Glue for systems without a MMU that cannot provide fork() */
283#ifdef HAVE_FORK
284# define strace_vforked 0
285#else
286# define strace_vforked 1
287# define fork() vfork()
288#endif
289
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000290static int
291set_cloexec_flag(int fd)
292{
293 int flags, newflags;
294
295 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
296 {
297 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
298 progname, strerror(errno));
299 return -1;
300 }
301
302 newflags = flags | FD_CLOEXEC;
303 if (flags == newflags)
304 return 0;
305
306 if (fcntl(fd, F_SETFD, newflags) < 0)
307 {
308 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
309 progname, strerror(errno));
310 return -1;
311 }
312
313 return 0;
314}
315
316/*
317 * When strace is setuid executable, we have to swap uids
318 * before and after filesystem and process management operations.
319 */
320static void
321swap_uid(void)
322{
323#ifndef SVR4
324 int euid = geteuid(), uid = getuid();
325
326 if (euid != uid && setreuid(euid, uid) < 0)
327 {
328 fprintf(stderr, "%s: setreuid: %s\n",
329 progname, strerror(errno));
330 exit(1);
331 }
332#endif
333}
334
Roland McGrath4bfa6262007-07-05 20:03:16 +0000335#if _LFS64_LARGEFILE
336# define fopen_for_output fopen64
337#else
338# define fopen_for_output fopen
339#endif
340
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000341static FILE *
342strace_fopen(const char *path, const char *mode)
343{
344 FILE *fp;
345
346 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000347 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000348 fprintf(stderr, "%s: can't fopen '%s': %s\n",
349 progname, path, strerror(errno));
350 swap_uid();
351 if (fp && set_cloexec_flag(fileno(fp)) < 0)
352 {
353 fclose(fp);
354 fp = NULL;
355 }
356 return fp;
357}
358
359static int popen_pid = -1;
360
361#ifndef _PATH_BSHELL
362# define _PATH_BSHELL "/bin/sh"
363#endif
364
365/*
366 * We cannot use standard popen(3) here because we have to distinguish
367 * popen child process from other processes we trace, and standard popen(3)
368 * does not export its child's pid.
369 */
370static FILE *
371strace_popen(const char *command)
372{
373 int fds[2];
374
375 swap_uid();
376 if (pipe(fds) < 0)
377 {
378 fprintf(stderr, "%s: pipe: %s\n",
379 progname, strerror(errno));
380 swap_uid();
381 return NULL;
382 }
383
384 if (set_cloexec_flag(fds[1]) < 0)
385 {
386 close(fds[0]);
387 close(fds[1]);
388 swap_uid();
389 return NULL;
390 }
391
392 if ((popen_pid = fork()) == -1)
393 {
394 fprintf(stderr, "%s: fork: %s\n",
395 progname, strerror(errno));
396 close(fds[0]);
397 close(fds[1]);
398 swap_uid();
399 return NULL;
400 }
401
402 if (popen_pid)
403 {
404 /* parent */
405 close(fds[0]);
406 swap_uid();
407 return fdopen(fds[1], "w");
408 } else
409 {
410 /* child */
411 close(fds[1]);
412 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
413 {
414 fprintf(stderr, "%s: dup2: %s\n",
415 progname, strerror(errno));
416 _exit(1);
417 }
418 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
419 fprintf(stderr, "%s: execl: %s: %s\n",
420 progname, _PATH_BSHELL, strerror(errno));
421 _exit(1);
422 }
423}
424
425static int
426newoutf(struct tcb *tcp)
427{
428 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000429 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000430 FILE *fp;
431
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000432 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000433 if ((fp = strace_fopen(name, "w")) == NULL)
434 return -1;
435 tcp->outf = fp;
436 }
437 return 0;
438}
439
Roland McGrath02203312007-06-11 22:06:31 +0000440static void
441startup_attach(void)
442{
443 int tcbi;
444 struct tcb *tcp;
445
446 /*
447 * Block user interruptions as we would leave the traced
448 * process stopped (process state T) if we would terminate in
449 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200450 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000451 */
452 if (interactive)
453 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
454
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000455 if (daemonized_tracer) {
456 pid_t pid = fork();
457 if (pid < 0) {
458 _exit(1);
459 }
460 if (pid) { /* parent */
461 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200462 * Wait for grandchild to attach to straced process
463 * (grandparent). Grandchild SIGKILLs us after it attached.
464 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000465 * it proceeds to exec the straced program.
466 */
467 pause();
468 _exit(0); /* paranoia */
469 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200470 /* grandchild */
471 /* We will be the tracer process. Remember our new pid: */
472 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000473 }
474
Roland McGrath02203312007-06-11 22:06:31 +0000475 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
476 tcp = tcbtab[tcbi];
477 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
478 continue;
479#ifdef LINUX
480 if (tcp->flags & TCB_CLONE_THREAD)
481 continue;
482#endif
483 /* Reinitialize the output since it may have changed. */
484 tcp->outf = outf;
485 if (newoutf(tcp) < 0)
486 exit(1);
487
488#ifdef USE_PROCFS
489 if (proc_open(tcp, 1) < 0) {
490 fprintf(stderr, "trouble opening proc file\n");
491 droptcb(tcp);
492 continue;
493 }
494#else /* !USE_PROCFS */
495# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000496 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000497 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000498 DIR *dir;
499
500 sprintf(procdir, "/proc/%d/task", tcp->pid);
501 dir = opendir(procdir);
502 if (dir != NULL) {
503 unsigned int ntid = 0, nerr = 0;
504 struct dirent *de;
505 int tid;
506 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000507 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000508 continue;
509 tid = atoi(de->d_name);
510 if (tid <= 0)
511 continue;
512 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000513 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000514 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000515 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000516 tcp = alloctcb(tid);
Wang Chao21b8db42010-08-27 17:43:16 +0800517 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000518 tcbtab[tcbi]->nchildren++;
519 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000520 tcp->parent = tcbtab[tcbi];
521 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000522 if (interactive) {
523 sigprocmask(SIG_SETMASK, &empty_set, NULL);
524 if (interrupted)
525 return;
526 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
527 }
Roland McGrath02203312007-06-11 22:06:31 +0000528 }
529 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000530 ntid -= nerr;
531 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000532 perror("attach: ptrace(PTRACE_ATTACH, ...)");
533 droptcb(tcp);
534 continue;
535 }
536 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000537 fprintf(stderr, ntid > 1
538? "Process %u attached with %u threads - interrupt to quit\n"
539: "Process %u attached - interrupt to quit\n",
540 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000541 }
542 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000543 } /* if (opendir worked) */
544 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000545# endif
546 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
547 perror("attach: ptrace(PTRACE_ATTACH, ...)");
548 droptcb(tcp);
549 continue;
550 }
551 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000552
553 if (daemonized_tracer) {
554 /*
555 * It is our grandparent we trace, not a -p PID.
556 * Don't want to just detach on exit, so...
557 */
558 tcp->flags &= ~TCB_ATTACHED;
559 /*
560 * Make parent go away.
561 * Also makes grandparent's wait() unblock.
562 */
563 kill(getppid(), SIGKILL);
564 }
565
Roland McGrath02203312007-06-11 22:06:31 +0000566#endif /* !USE_PROCFS */
567 if (!qflag)
568 fprintf(stderr,
569 "Process %u attached - interrupt to quit\n",
570 tcp->pid);
571 }
572
573 if (interactive)
574 sigprocmask(SIG_SETMASK, &empty_set, NULL);
575}
576
577static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200578startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000579{
580 struct stat statbuf;
581 const char *filename;
582 char pathname[MAXPATHLEN];
583 int pid = 0;
584 struct tcb *tcp;
585
586 filename = argv[0];
587 if (strchr(filename, '/')) {
588 if (strlen(filename) > sizeof pathname - 1) {
589 errno = ENAMETOOLONG;
590 perror("strace: exec");
591 exit(1);
592 }
593 strcpy(pathname, filename);
594 }
595#ifdef USE_DEBUGGING_EXEC
596 /*
597 * Debuggers customarily check the current directory
598 * first regardless of the path but doing that gives
599 * security geeks a panic attack.
600 */
601 else if (stat(filename, &statbuf) == 0)
602 strcpy(pathname, filename);
603#endif /* USE_DEBUGGING_EXEC */
604 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000605 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000606 int m, n, len;
607
608 for (path = getenv("PATH"); path && *path; path += m) {
609 if (strchr(path, ':')) {
610 n = strchr(path, ':') - path;
611 m = n + 1;
612 }
613 else
614 m = n = strlen(path);
615 if (n == 0) {
616 if (!getcwd(pathname, MAXPATHLEN))
617 continue;
618 len = strlen(pathname);
619 }
620 else if (n > sizeof pathname - 1)
621 continue;
622 else {
623 strncpy(pathname, path, n);
624 len = n;
625 }
626 if (len && pathname[len - 1] != '/')
627 pathname[len++] = '/';
628 strcpy(pathname + len, filename);
629 if (stat(pathname, &statbuf) == 0 &&
630 /* Accept only regular files
631 with some execute bits set.
632 XXX not perfect, might still fail */
633 S_ISREG(statbuf.st_mode) &&
634 (statbuf.st_mode & 0111))
635 break;
636 }
637 }
638 if (stat(pathname, &statbuf) < 0) {
639 fprintf(stderr, "%s: %s: command not found\n",
640 progname, filename);
641 exit(1);
642 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000643 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000644 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000645 perror("strace: fork");
646 cleanup();
647 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000648 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200649 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
650 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000651 ) {
652 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000653#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200654 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000655#ifdef MIPS
656 /* Kludge for SGI, see proc_open for details. */
657 sa.sa_handler = foobar;
658 sa.sa_flags = 0;
659 sigemptyset(&sa.sa_mask);
660 sigaction(SIGINT, &sa, NULL);
661#endif /* MIPS */
662#ifndef FREEBSD
663 pause();
664#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000665 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000666#endif /* FREEBSD */
667#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200668 if (outf != stderr)
669 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000670
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000671 if (!daemonized_tracer) {
672 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
673 perror("strace: ptrace(PTRACE_TRACEME, ...)");
674 exit(1);
675 }
676 if (debug)
677 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000678 }
Roland McGrath02203312007-06-11 22:06:31 +0000679
680 if (username != NULL || geteuid() == 0) {
681 uid_t run_euid = run_uid;
682 gid_t run_egid = run_gid;
683
684 if (statbuf.st_mode & S_ISUID)
685 run_euid = statbuf.st_uid;
686 if (statbuf.st_mode & S_ISGID)
687 run_egid = statbuf.st_gid;
688
689 /*
690 * It is important to set groups before we
691 * lose privileges on setuid.
692 */
693 if (username != NULL) {
694 if (initgroups(username, run_gid) < 0) {
695 perror("initgroups");
696 exit(1);
697 }
698 if (setregid(run_gid, run_egid) < 0) {
699 perror("setregid");
700 exit(1);
701 }
702 if (setreuid(run_uid, run_euid) < 0) {
703 perror("setreuid");
704 exit(1);
705 }
706 }
707 }
708 else
709 setreuid(run_uid, run_uid);
710
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000711 if (!daemonized_tracer) {
712 /*
713 * Induce an immediate stop so that the parent
714 * will resume us with PTRACE_SYSCALL and display
715 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400716 * Unless of course we're on a no-MMU system where
717 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000718 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400719 if (!strace_vforked)
720 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000721 } else {
722 struct sigaction sv_sigchld;
723 sigaction(SIGCHLD, NULL, &sv_sigchld);
724 /*
725 * Make sure it is not SIG_IGN, otherwise wait
726 * will not block.
727 */
728 signal(SIGCHLD, SIG_DFL);
729 /*
730 * Wait for grandchild to attach to us.
731 * It kills child after that, and wait() unblocks.
732 */
733 alarm(3);
734 wait(NULL);
735 alarm(0);
736 sigaction(SIGCHLD, &sv_sigchld, NULL);
737 }
Roland McGrath02203312007-06-11 22:06:31 +0000738#endif /* !USE_PROCFS */
739
740 execv(pathname, argv);
741 perror("strace: exec");
742 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000743 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000744
745 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200746 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
747 strace_tracer_pid = getpid();
748
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000749 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000750 if (daemonized_tracer) {
751 /* We want subsequent startup_attach() to attach to it. */
752 tcp->flags |= TCB_ATTACHED;
753 }
Roland McGrath02203312007-06-11 22:06:31 +0000754#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000755 if (proc_open(tcp, 0) < 0) {
756 fprintf(stderr, "trouble opening proc file\n");
757 cleanup();
758 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000759 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000760#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000761}
762
Wang Chaob13c0de2010-11-12 17:25:19 +0800763#ifdef LINUX
764/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000765 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800766 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000767 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800768 */
769static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200770test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800771{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000772 int pid, expected_grandchild = 0, found_grandchild = 0;
773 const unsigned int test_options = PTRACE_O_TRACECLONE |
774 PTRACE_O_TRACEFORK |
775 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800776
777 if ((pid = fork()) < 0)
778 return -1;
779 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000780 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800781 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800782 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000783 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800784 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000785
786 while (1) {
787 int status, tracee_pid;
788
789 tracee_pid = wait(&status);
790 if (tracee_pid == -1) {
791 if (errno == EINTR)
792 continue;
793 else if (errno == ECHILD)
794 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200795 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000796 return -1;
797 }
798 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000799 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000800 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
801 errno != ESRCH)
802 kill(tracee_pid, SIGKILL);
803 }
804 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000805 switch (WSTOPSIG(status)) {
806 case SIGSTOP:
807 if (ptrace(PTRACE_SETOPTIONS, pid,
808 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000809 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800810 return -1;
811 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000812 break;
813 case SIGTRAP:
814 if (status >> 16 == PTRACE_EVENT_FORK) {
815 long msg = 0;
816
817 if (ptrace(PTRACE_GETEVENTMSG, pid,
818 NULL, (long) &msg) == 0)
819 expected_grandchild = msg;
820 }
821 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800822 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000823 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
824 errno != ESRCH)
825 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800826 }
827 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000828 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200829 ptrace_setoptions_followfork |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800830 return 0;
831}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200832
833/*
834 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
835 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
836 * and then see whether it will stop with (SIGTRAP | 0x80).
837 *
838 * Use of this option enables correct handling of user-generated SIGTRAPs,
839 * and SIGTRAPs generated by special instructions such as int3 on x86:
840 * _start: .globl _start
841 * int3
842 * movl $42, %ebx
843 * movl $1, %eax
844 * int $0x80
845 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
846 */
847static void
848test_ptrace_setoptions_for_all(void)
849{
850 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
851 int pid;
852 int it_worked = 0;
853
854 pid = fork();
855 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200856 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200857
858 if (pid == 0) {
859 pid = getpid();
860 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200861 /* Note: exits with exitcode 1 */
862 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200863 kill(pid, SIGSTOP);
864 _exit(0); /* parent should see entry into this syscall */
865 }
866
867 while (1) {
868 int status, tracee_pid;
869
870 errno = 0;
871 tracee_pid = wait(&status);
872 if (tracee_pid <= 0) {
873 if (errno == EINTR)
874 continue;
875 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200876 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200877 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200878 if (WIFEXITED(status)) {
879 if (WEXITSTATUS(status) == 0)
880 break;
881 /* PTRACE_TRACEME failed in child. This is fatal. */
882 exit(1);
883 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200884 if (!WIFSTOPPED(status)) {
885 kill(pid, SIGKILL);
886 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
887 }
888 if (WSTOPSIG(status) == SIGSTOP) {
889 /*
890 * We don't check "options aren't accepted" error.
891 * If it happens, we'll never get (SIGTRAP | 0x80),
892 * and thus will decide to not use the option.
893 * IOW: the outcome of the test will be correct.
894 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200895 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
896 if (errno != EINVAL)
897 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200898 }
899 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
900 it_worked = 1;
901 }
902 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
903 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200904 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200905 }
906 }
907
908 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200909 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200910 ptrace_setoptions_for_all = test_options;
911 if (debug)
912 fprintf(stderr, "ptrace_setoptions_for_all = %#x\n",
913 ptrace_setoptions_for_all);
914 return;
915 }
916
917 fprintf(stderr,
918 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
919}
Wang Chaob13c0de2010-11-12 17:25:19 +0800920#endif
921
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000923main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925 struct tcb *tcp;
926 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000927 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928 struct sigaction sa;
929
930 static char buf[BUFSIZ];
931
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000932 progname = argv[0] ? argv[0] : "strace";
933
Denys Vlasenko75422762011-05-27 14:36:01 +0200934 strace_tracer_pid = getpid();
935
Roland McGrathee9d4352002-12-18 04:16:10 +0000936 /* Allocate the initial tcbtab. */
937 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000938 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000939 fprintf(stderr, "%s: out of memory\n", progname);
940 exit(1);
941 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000942 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000943 fprintf(stderr, "%s: out of memory\n", progname);
944 exit(1);
945 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000946 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
947 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
948
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949 outf = stderr;
950 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000951 set_sortby(DEFAULT_SORTBY);
952 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 qualify("trace=all");
954 qualify("abbrev=all");
955 qualify("verbose=all");
956 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000958 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000959#ifndef USE_PROCFS
960 "D"
961#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000962 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 switch (c) {
964 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000965 if (cflag == CFLAG_BOTH) {
966 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
967 progname);
968 exit(1);
969 }
970 cflag = CFLAG_ONLY_STATS;
971 break;
972 case 'C':
973 if (cflag == CFLAG_ONLY_STATS) {
974 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
975 progname);
976 exit(1);
977 }
978 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979 break;
980 case 'd':
981 debug++;
982 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000983#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000984 case 'D':
985 daemonized_tracer = 1;
986 break;
987#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000988 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000989 optF = 1;
990 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 case 'f':
992 followfork++;
993 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 case 'h':
995 usage(stdout, 0);
996 break;
997 case 'i':
998 iflag++;
999 break;
1000 case 'q':
1001 qflag++;
1002 break;
1003 case 'r':
1004 rflag++;
1005 tflag++;
1006 break;
1007 case 't':
1008 tflag++;
1009 break;
1010 case 'T':
1011 dtime++;
1012 break;
1013 case 'x':
1014 xflag++;
1015 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001016 case 'y':
1017 show_fd_path = 1;
1018 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 case 'v':
1020 qualify("abbrev=none");
1021 break;
1022 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001023 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024 exit(0);
1025 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001026 case 'z':
1027 not_failing_only = 1;
1028 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 case 'a':
1030 acolumn = atoi(optarg);
1031 break;
1032 case 'e':
1033 qualify(optarg);
1034 break;
1035 case 'o':
1036 outfname = strdup(optarg);
1037 break;
1038 case 'O':
1039 set_overhead(atoi(optarg));
1040 break;
1041 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +00001042 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 fprintf(stderr, "%s: Invalid process id: %s\n",
1044 progname, optarg);
1045 break;
1046 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001047 if (pid == strace_tracer_pid) {
Wichert Akkerman54a47671999-10-17 00:57:34 +00001048 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 break;
1050 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001051 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 tcp->flags |= TCB_ATTACHED;
1053 pflag_seen++;
1054 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001055 case 'P':
1056 tracing_paths = 1;
1057 if (pathtrace_select(optarg)) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001058 fprintf(stderr, "%s : failed to select path '%s'\n", progname, optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001059 exit(1);
1060 }
1061 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 case 's':
1063 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001064 if (max_strlen < 0) {
1065 fprintf(stderr,
1066 "%s: invalid -s argument: %s\n",
1067 progname, optarg);
1068 exit(1);
1069 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 break;
1071 case 'S':
1072 set_sortby(optarg);
1073 break;
1074 case 'u':
1075 username = strdup(optarg);
1076 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001077 case 'E':
1078 if (putenv(optarg) < 0) {
1079 fprintf(stderr, "%s: out of memory\n",
1080 progname);
1081 exit(1);
1082 }
1083 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 default:
1085 usage(stderr, 1);
1086 break;
1087 }
1088 }
1089
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001090 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001091 usage(stderr, 1);
1092
Wang Chaod322a4b2010-08-05 14:30:11 +08001093 if (pflag_seen && daemonized_tracer) {
1094 fprintf(stderr,
1095 "%s: -D and -p are mutually exclusive options\n",
1096 progname);
1097 exit(1);
1098 }
1099
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001100 if (!followfork)
1101 followfork = optF;
1102
Roland McGrathcb9def62006-04-25 07:48:03 +00001103 if (followfork > 1 && cflag) {
1104 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001105 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +00001106 progname);
1107 exit(1);
1108 }
1109
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 /* See if they want to run as another user. */
1111 if (username != NULL) {
1112 struct passwd *pent;
1113
1114 if (getuid() != 0 || geteuid() != 0) {
1115 fprintf(stderr,
1116 "%s: you must be root to use the -u option\n",
1117 progname);
1118 exit(1);
1119 }
1120 if ((pent = getpwnam(username)) == NULL) {
1121 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +00001122 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 exit(1);
1124 }
1125 run_uid = pent->pw_uid;
1126 run_gid = pent->pw_gid;
1127 }
1128 else {
1129 run_uid = getuid();
1130 run_gid = getgid();
1131 }
1132
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001133#ifdef LINUX
1134 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001135 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001136 fprintf(stderr,
1137 "Test for options supported by PTRACE_SETOPTIONS "
1138 "failed, giving up using this feature.\n");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001139 ptrace_setoptions_followfork = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001140 }
1141 if (debug)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001142 fprintf(stderr, "ptrace_setoptions_followfork = %#x\n",
1143 ptrace_setoptions_followfork);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001144 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001145 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001146#endif
1147
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 /* Check if they want to redirect the output. */
1149 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001150 /* See if they want to pipe the output. */
1151 if (outfname[0] == '|' || outfname[0] == '!') {
1152 /*
1153 * We can't do the <outfname>.PID funny business
1154 * when using popen, so prohibit it.
1155 */
1156 if (followfork > 1) {
1157 fprintf(stderr, "\
1158%s: piping the output and -ff are mutually exclusive options\n",
1159 progname);
1160 exit(1);
1161 }
1162
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001163 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +00001164 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001165 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001166 else if (followfork <= 1 &&
1167 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 }
1170
Roland McGrath37b9a662003-11-07 02:26:54 +00001171 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +00001173 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001176 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001177
Roland McGrath54cc1c82007-11-03 23:34:11 +00001178 /* Valid states here:
1179 optind < argc pflag_seen outfname interactive
1180 1 0 0 1
1181 0 1 0 1
1182 1 0 1 0
1183 0 1 1 1
1184 */
1185
1186 /* STARTUP_CHILD must be called before the signal handlers get
1187 installed below as they are inherited into the spawned process.
1188 Also we do not need to be protected by them as during interruption
1189 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1190 if (!pflag_seen)
1191 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193 sigemptyset(&empty_set);
1194 sigemptyset(&blocked_set);
1195 sa.sa_handler = SIG_IGN;
1196 sigemptyset(&sa.sa_mask);
1197 sa.sa_flags = 0;
1198 sigaction(SIGTTOU, &sa, NULL);
1199 sigaction(SIGTTIN, &sa, NULL);
1200 if (interactive) {
1201 sigaddset(&blocked_set, SIGHUP);
1202 sigaddset(&blocked_set, SIGINT);
1203 sigaddset(&blocked_set, SIGQUIT);
1204 sigaddset(&blocked_set, SIGPIPE);
1205 sigaddset(&blocked_set, SIGTERM);
1206 sa.sa_handler = interrupt;
1207#ifdef SUNOS4
1208 /* POSIX signals on sunos4.1 are a little broken. */
1209 sa.sa_flags = SA_INTERRUPT;
1210#endif /* SUNOS4 */
1211 }
1212 sigaction(SIGHUP, &sa, NULL);
1213 sigaction(SIGINT, &sa, NULL);
1214 sigaction(SIGQUIT, &sa, NULL);
1215 sigaction(SIGPIPE, &sa, NULL);
1216 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001217#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001218 sa.sa_handler = reaper;
1219 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001220#else
1221 /* Make sure SIGCHLD has the default action so that waitpid
1222 definitely works without losing track of children. The user
1223 should not have given us a bogus state to inherit, but he might
1224 have. Arguably we should detect SIG_IGN here and pass it on
1225 to children, but probably noone really needs that. */
1226 sa.sa_handler = SIG_DFL;
1227 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001228#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001230 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001231 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001232
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 if (trace() < 0)
1234 exit(1);
1235 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001236 fflush(NULL);
1237 if (exit_code > 0xff) {
1238 /* Child was killed by a signal, mimic that. */
1239 exit_code &= 0xff;
1240 signal(exit_code, SIG_DFL);
1241 raise(exit_code);
1242 /* Paranoia - what if this signal is not fatal?
1243 Exit with 128 + signo then. */
1244 exit_code += 128;
1245 }
1246 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247}
1248
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001249void
1250expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001251{
1252 /* Allocate some more TCBs and expand the table.
1253 We don't want to relocate the TCBs because our
1254 callers have pointers and it would be a pain.
1255 So tcbtab is a table of pointers. Since we never
1256 free the TCBs, we allocate a single chunk of many. */
1257 struct tcb **newtab = (struct tcb **)
1258 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
1259 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
1260 sizeof *newtcbs);
1261 int i;
1262 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +00001263 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
1264 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001265 cleanup();
1266 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001267 }
1268 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1269 newtab[i] = &newtcbs[i - tcbtabsize];
1270 tcbtabsize *= 2;
1271 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001272}
1273
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001275alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276{
1277 int i;
1278 struct tcb *tcp;
1279
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001280 if (nprocs == tcbtabsize)
1281 expand_tcbtab();
1282
Roland McGrathee9d4352002-12-18 04:16:10 +00001283 for (i = 0; i < tcbtabsize; i++) {
1284 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285 if ((tcp->flags & TCB_INUSE) == 0) {
1286 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001287 tcp->parent = NULL;
1288 tcp->nchildren = 0;
1289 tcp->nzombies = 0;
1290#ifdef TCB_CLONE_THREAD
Wang Chao21b8db42010-08-27 17:43:16 +08001291 tcp->nclone_threads = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001292 tcp->nclone_waiting = 0;
1293#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294 tcp->flags = TCB_INUSE | TCB_STARTUP;
1295 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001296 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001297 tcp->stime.tv_sec = 0;
1298 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299 tcp->pfd = -1;
1300 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001301 if (command_options_parsed)
1302 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001303 return tcp;
1304 }
1305 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001306 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1307 cleanup();
1308 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309}
1310
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001311#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001312int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001313proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314{
1315 char proc[32];
1316 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001318 int i;
1319 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 sigset_t signals;
1321 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001322#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323#ifndef HAVE_POLLABLE_PROCFS
1324 static int last_pfd;
1325#endif
1326
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001327#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001328 /* Open the process pseudo-files in /proc. */
1329 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1330 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331 perror("strace: open(\"/proc/...\", ...)");
1332 return -1;
1333 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001334 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335 return -1;
1336 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001337 sprintf(proc, "/proc/%d/status", tcp->pid);
1338 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1339 perror("strace: open(\"/proc/...\", ...)");
1340 return -1;
1341 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001342 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001343 return -1;
1344 }
1345 sprintf(proc, "/proc/%d/as", tcp->pid);
1346 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1347 perror("strace: open(\"/proc/...\", ...)");
1348 return -1;
1349 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001350 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001351 return -1;
1352 }
1353#else
1354 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001355#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001356 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001357 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001358#else /* FREEBSD */
1359 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001360 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001361#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001362 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001363 perror("strace: open(\"/proc/...\", ...)");
1364 return -1;
1365 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001366 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001367 return -1;
1368 }
1369#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001370#ifdef FREEBSD
1371 sprintf(proc, "/proc/%d/regs", tcp->pid);
1372 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1373 perror("strace: open(\"/proc/.../regs\", ...)");
1374 return -1;
1375 }
1376 if (cflag) {
1377 sprintf(proc, "/proc/%d/status", tcp->pid);
1378 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1379 perror("strace: open(\"/proc/.../status\", ...)");
1380 return -1;
1381 }
1382 } else
1383 tcp->pfd_status = -1;
1384#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001385 rebuild_pollv();
1386 if (!attaching) {
1387 /*
1388 * Wait for the child to pause. Because of a race
1389 * condition we have to poll for the event.
1390 */
1391 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001392 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001393 perror("strace: PIOCSTATUS");
1394 return -1;
1395 }
1396 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001397 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001398 }
1399 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001400#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001401 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001402 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001403 perror("strace: PIOCSTOP");
1404 return -1;
1405 }
Roland McGrath553a6092002-12-16 20:40:39 +00001406#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407#ifdef PIOCSET
1408 /* Set Run-on-Last-Close. */
1409 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001410 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411 perror("PIOCSET PR_RLC");
1412 return -1;
1413 }
1414 /* Set or Reset Inherit-on-Fork. */
1415 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001416 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417 perror("PIOC{SET,RESET} PR_FORK");
1418 return -1;
1419 }
1420#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001421#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1423 perror("PIOCSRLC");
1424 return -1;
1425 }
1426 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1427 perror("PIOC{S,R}FORK");
1428 return -1;
1429 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001430#else /* FREEBSD */
1431 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1432 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1433 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001434 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001435 }
1436 arg &= ~PF_LINGER;
1437 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001438 perror("PIOCSFL");
1439 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001440 }
1441#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001443#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001444 /* Enable all syscall entries we care about. */
1445 premptyset(&syscalls);
1446 for (i = 1; i < MAX_QUALS; ++i) {
1447 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001448 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001449 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001450 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001451 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001452 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001453#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001454 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001455#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001456#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001457 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001458#endif
1459#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001460 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001461#endif
1462#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001463 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001464#endif
1465 }
1466 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001467 perror("PIOCSENTRY");
1468 return -1;
1469 }
John Hughes19e49982001-10-19 08:59:12 +00001470 /* Enable the syscall exits. */
1471 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001472 perror("PIOSEXIT");
1473 return -1;
1474 }
John Hughes19e49982001-10-19 08:59:12 +00001475 /* Enable signals we care about. */
1476 premptyset(&signals);
1477 for (i = 1; i < MAX_QUALS; ++i) {
1478 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001479 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001480 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001481 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 perror("PIOCSTRACE");
1483 return -1;
1484 }
John Hughes19e49982001-10-19 08:59:12 +00001485 /* Enable faults we care about */
1486 premptyset(&faults);
1487 for (i = 1; i < MAX_QUALS; ++i) {
1488 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001489 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001490 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001491 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 perror("PIOCSFAULT");
1493 return -1;
1494 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001495#else /* FREEBSD */
1496 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001497 arg = S_SIG | S_SCE | S_SCX;
1498 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001499 perror("PIOCBIS");
1500 return -1;
1501 }
1502#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 if (!attaching) {
1504#ifdef MIPS
1505 /*
1506 * The SGI PRSABORT doesn't work for pause() so
1507 * we send it a caught signal to wake it up.
1508 */
1509 kill(tcp->pid, SIGINT);
1510#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001511#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001513 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001514 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 perror("PIOCRUN");
1516 return -1;
1517 }
Roland McGrath553a6092002-12-16 20:40:39 +00001518#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001519#endif /* !MIPS*/
1520#ifdef FREEBSD
1521 /* wake up the child if it received the SIGSTOP */
1522 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001523#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524 for (;;) {
1525 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001526 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527 perror("PIOCWSTOP");
1528 return -1;
1529 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001530 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001531 tcp->flags &= ~TCB_INSYSCALL;
1532 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001533 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534 break;
1535 }
1536 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001537#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001538 arg = 0;
1539 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001540#else /* FREEBSD */
1541 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001542#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543 perror("PIOCRUN");
1544 return -1;
1545 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001546#ifdef FREEBSD
1547 /* handle the case where we "opened" the child before
1548 it did the kill -STOP */
1549 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1550 tcp->status.PR_WHAT == SIGSTOP)
1551 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001552#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001554#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001556#else /* FREEBSD */
1557 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001558 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001559 /* We are attaching to an already running process.
1560 * Try to figure out the state of the process in syscalls,
1561 * to handle the first event well.
1562 * This is done by having a look at the "wchan" property of the
1563 * process, which tells where it is stopped (if it is). */
1564 FILE * status;
1565 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001566
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001567 sprintf(proc, "/proc/%d/status", tcp->pid);
1568 status = fopen(proc, "r");
1569 if (status &&
1570 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1571 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1572 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1573 strcmp(wchan, "stopevent")) {
1574 /* The process is asleep in the middle of a syscall.
1575 Fake the syscall entry event */
1576 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1577 tcp->status.PR_WHY = PR_SYSENTRY;
1578 trace_syscall(tcp);
1579 }
1580 if (status)
1581 fclose(status);
1582 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001583 }
1584#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585#ifndef HAVE_POLLABLE_PROCFS
1586 if (proc_poll_pipe[0] != -1)
1587 proc_poller(tcp->pfd);
1588 else if (nprocs > 1) {
1589 proc_poll_open();
1590 proc_poller(last_pfd);
1591 proc_poller(tcp->pfd);
1592 }
1593 last_pfd = tcp->pfd;
1594#endif /* !HAVE_POLLABLE_PROCFS */
1595 return 0;
1596}
1597
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001598#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001600struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001601pid2tcb(int pid)
1602{
1603 int i;
1604
1605 if (pid <= 0)
1606 return NULL;
1607
1608 for (i = 0; i < tcbtabsize; i++) {
1609 struct tcb *tcp = tcbtab[i];
1610 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1611 return tcp;
1612 }
1613
1614 return NULL;
1615}
1616
1617#ifdef USE_PROCFS
1618
1619static struct tcb *
1620first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621{
1622 int i;
1623 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001624 for (i = 0; i < tcbtabsize; i++) {
1625 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626 if (tcp->flags & TCB_INUSE)
1627 return tcp;
1628 }
1629 return NULL;
1630}
1631
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001633pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634{
1635 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636
Roland McGrathca16be82003-01-10 19:55:28 +00001637 for (i = 0; i < tcbtabsize; i++) {
1638 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 if (tcp->pfd != pfd)
1640 continue;
1641 if (tcp->flags & TCB_INUSE)
1642 return tcp;
1643 }
1644 return NULL;
1645}
1646
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001647#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648
1649void
Denys Vlasenko12014262011-05-30 14:00:14 +02001650droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651{
1652 if (tcp->pid == 0)
1653 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001654#ifdef TCB_CLONE_THREAD
1655 if (tcp->nclone_threads > 0) {
1656 /* There are other threads left in this process, but this
1657 is the one whose PID represents the whole process.
1658 We need to keep this record around as a zombie until
1659 all the threads die. */
1660 tcp->flags |= TCB_EXITING;
1661 return;
1662 }
1663#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664 nprocs--;
1665 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001666
Roland McGrathe29341c2003-01-10 20:14:20 +00001667 if (tcp->parent != NULL) {
1668 tcp->parent->nchildren--;
1669#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001670 if (tcp->flags & TCB_CLONE_THREAD)
1671 tcp->parent->nclone_threads--;
1672#endif
Wang Chao21b8db42010-08-27 17:43:16 +08001673 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001674#ifdef LINUX
1675 /* Update `tcp->parent->parent->nchildren' and the other fields
1676 like NCLONE_DETACHED, only for zombie group leader that has
1677 already reported and been short-circuited at the top of this
1678 function. The same condition as at the top of DETACH. */
1679 if ((tcp->flags & TCB_CLONE_THREAD) &&
1680 tcp->parent->nclone_threads == 0 &&
1681 (tcp->parent->flags & TCB_EXITING))
1682 droptcb(tcp->parent);
1683#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001684 tcp->parent = NULL;
1685 }
1686
1687 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688 if (tcp->pfd != -1) {
1689 close(tcp->pfd);
1690 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001691#ifdef FREEBSD
1692 if (tcp->pfd_reg != -1) {
1693 close(tcp->pfd_reg);
1694 tcp->pfd_reg = -1;
1695 }
1696 if (tcp->pfd_status != -1) {
1697 close(tcp->pfd_status);
1698 tcp->pfd_status = -1;
1699 }
Roland McGrath553a6092002-12-16 20:40:39 +00001700#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001701#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001702 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703#endif
1704 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001705
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001706 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001708
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709 tcp->outf = 0;
1710}
1711
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001712#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713
1714static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001715resume(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716{
1717 if (tcp == NULL)
1718 return -1;
1719
1720 if (!(tcp->flags & TCB_SUSPENDED)) {
1721 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1722 return -1;
1723 }
1724 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001725#ifdef TCB_CLONE_THREAD
1726 if (tcp->flags & TCB_CLONE_THREAD)
1727 tcp->parent->nclone_waiting--;
1728#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001730 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732
1733 if (!qflag)
1734 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1735 return 0;
1736}
1737
Roland McGrath1bfd3102007-08-03 10:02:00 +00001738static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001739resume_from_tcp(struct tcb *tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00001740{
1741 int error = 0;
1742 int resumed = 0;
1743
1744 /* XXX This won't always be quite right (but it never was).
1745 A waiter with argument 0 or < -1 is waiting for any pid in
1746 a particular pgrp, which this child might or might not be
1747 in. The waiter will only wake up if it's argument is -1
1748 or if it's waiting for tcp->pid's pgrp. It makes a
1749 difference to wake up a waiter when there might be more
1750 traced children, because it could get a false ECHILD
1751 error. OTOH, if this was the last child in the pgrp, then
1752 it ought to wake up and get ECHILD. We would have to
1753 search the system for all pid's in the pgrp to be sure.
1754
1755 && (t->waitpid == -1 ||
1756 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1757 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1758 */
1759
1760 if (tcp->parent &&
1761 (tcp->parent->flags & TCB_SUSPENDED) &&
1762 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001763 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001764 ++resumed;
1765 }
1766#ifdef TCB_CLONE_THREAD
1767 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1768 /* Some other threads of our parent are waiting too. */
1769 unsigned int i;
1770
1771 /* Resume all the threads that were waiting for this PID. */
1772 for (i = 0; i < tcbtabsize; i++) {
1773 struct tcb *t = tcbtab[i];
1774 if (t->parent == tcp->parent && t != tcp
1775 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1776 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1777 && t->waitpid == tcp->pid) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001778 error |= resume(t);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001779 ++resumed;
1780 }
1781 }
1782 if (resumed == 0)
1783 /* Noone was waiting for this PID in particular,
1784 so now we might need to resume some wildcarders. */
1785 for (i = 0; i < tcbtabsize; i++) {
1786 struct tcb *t = tcbtab[i];
1787 if (t->parent == tcp->parent && t != tcp
1788 && ((t->flags
1789 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1790 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1791 && t->waitpid <= 0
1792 ) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001793 error |= resume(t);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001794 break;
1795 }
1796 }
1797 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001798#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001799
1800 return error;
1801}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001802
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001803#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804
Roland McGrath0a463882007-07-05 18:43:16 +00001805/* detach traced process; continue with sig
1806 Never call DETACH twice on the same process as both unattached and
1807 attached-unstopped processes give the same ESRCH. For unattached process we
1808 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809
1810static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001811detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812{
1813 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001814#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001815 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001816 struct tcb *zombie = NULL;
1817
1818 /* If the group leader is lingering only because of this other
1819 thread now dying, then detach the leader as well. */
1820 if ((tcp->flags & TCB_CLONE_THREAD) &&
1821 tcp->parent->nclone_threads == 1 &&
1822 (tcp->parent->flags & TCB_EXITING))
1823 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001824#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825
1826 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001827 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828
1829#ifdef LINUX
1830 /*
1831 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001832 * before detaching. Arghh. We go through hoops
1833 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001835#if defined(SPARC)
1836#undef PTRACE_DETACH
1837#define PTRACE_DETACH PTRACE_SUNDETACH
1838#endif
Roland McGrath02203312007-06-11 22:06:31 +00001839 /*
1840 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1841 * expected SIGSTOP. We must catch exactly one as otherwise the
1842 * detached process would be left stopped (process state T).
1843 */
1844 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1846 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001847 }
1848 else if (errno != ESRCH) {
1849 /* Shouldn't happen. */
1850 perror("detach: ptrace(PTRACE_DETACH, ...)");
1851 }
Roland McGrath134813a2007-06-02 00:07:33 +00001852 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1853 : tcp->pid),
1854 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001855 if (errno != ESRCH)
1856 perror("detach: checking sanity");
1857 }
Roland McGrath02203312007-06-11 22:06:31 +00001858 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1859 ? tcp->parent->pid : tcp->pid),
1860 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001861 if (errno != ESRCH)
1862 perror("detach: stopping child");
1863 }
Roland McGrath02203312007-06-11 22:06:31 +00001864 else
1865 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001866 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001867 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001868#ifdef __WALL
1869 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1870 if (errno == ECHILD) /* Already gone. */
1871 break;
1872 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001873 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001874 break;
1875 }
1876#endif /* __WALL */
1877 /* No __WALL here. */
1878 if (waitpid(tcp->pid, &status, 0) < 0) {
1879 if (errno != ECHILD) {
1880 perror("detach: waiting");
1881 break;
1882 }
1883#ifdef __WCLONE
1884 /* If no processes, try clones. */
1885 if (wait4(tcp->pid, &status, __WCLONE,
1886 NULL) < 0) {
1887 if (errno != ECHILD)
1888 perror("detach: waiting");
1889 break;
1890 }
1891#endif /* __WCLONE */
1892 }
1893#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001894 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001895#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 if (!WIFSTOPPED(status)) {
1897 /* Au revoir, mon ami. */
1898 break;
1899 }
1900 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001901 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902 break;
1903 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001904 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001905 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001906 : WSTOPSIG(status));
1907 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001908 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001910 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001911#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912
1913#if defined(SUNOS4)
1914 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1915 if (sig && kill(tcp->pid, sig) < 0)
1916 perror("detach: kill");
1917 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001918 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001919#endif /* SUNOS4 */
1920
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001921#ifndef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001922 error |= resume_from_tcp(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001923#endif
1924
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001925 if (!qflag)
1926 fprintf(stderr, "Process %u detached\n", tcp->pid);
1927
1928 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001929
1930#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001931 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001932 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001933 droptcb(zombie);
1934 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001935#endif
1936
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937 return error;
1938}
1939
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001940#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001941
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001942static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001943{
1944 int pid;
1945 int status;
1946
1947 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948 }
1949}
1950
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001951#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952
1953static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001954cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955{
1956 int i;
1957 struct tcb *tcp;
1958
Roland McGrathee9d4352002-12-18 04:16:10 +00001959 for (i = 0; i < tcbtabsize; i++) {
1960 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 if (!(tcp->flags & TCB_INUSE))
1962 continue;
1963 if (debug)
1964 fprintf(stderr,
1965 "cleanup: looking at pid %u\n", tcp->pid);
1966 if (tcp_last &&
1967 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001968 tprintf(" <unfinished ...>");
1969 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001970 }
1971 if (tcp->flags & TCB_ATTACHED)
1972 detach(tcp, 0);
1973 else {
1974 kill(tcp->pid, SIGCONT);
1975 kill(tcp->pid, SIGTERM);
1976 }
1977 }
1978 if (cflag)
1979 call_summary(outf);
1980}
1981
1982static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001983interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984{
1985 interrupted = 1;
1986}
1987
1988#ifndef HAVE_STRERROR
1989
Roland McGrath6d2b3492002-12-30 00:51:30 +00001990#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001991extern int sys_nerr;
1992extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001993#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001994
1995const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001996strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997{
1998 static char buf[64];
1999
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002000 if (err_no < 1 || err_no >= sys_nerr) {
2001 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002002 return buf;
2003 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002004 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002005}
2006
2007#endif /* HAVE_STERRROR */
2008
2009#ifndef HAVE_STRSIGNAL
2010
Roland McGrath8f474e02003-01-14 07:53:33 +00002011#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00002012extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002013#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00002014#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
2015extern char *_sys_siglist[];
2016#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017
2018const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002019strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002020{
2021 static char buf[64];
2022
2023 if (sig < 1 || sig >= NSIG) {
2024 sprintf(buf, "Unknown signal %d", sig);
2025 return buf;
2026 }
2027#ifdef HAVE__SYS_SIGLIST
2028 return _sys_siglist[sig];
2029#else
2030 return sys_siglist[sig];
2031#endif
2032}
2033
2034#endif /* HAVE_STRSIGNAL */
2035
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002036#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002037
2038static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002039rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040{
2041 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042
Roland McGrathee9d4352002-12-18 04:16:10 +00002043 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002044 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00002045 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00002046 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002047 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00002048 exit(1);
2049 }
2050
Roland McGrathca16be82003-01-10 19:55:28 +00002051 for (i = j = 0; i < tcbtabsize; i++) {
2052 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 if (!(tcp->flags & TCB_INUSE))
2054 continue;
2055 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002056 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002057 j++;
2058 }
2059 if (j != nprocs) {
2060 fprintf(stderr, "strace: proc miscount\n");
2061 exit(1);
2062 }
2063}
2064
2065#ifndef HAVE_POLLABLE_PROCFS
2066
2067static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002068proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002069{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 int i;
2071
2072 if (pipe(proc_poll_pipe) < 0) {
2073 perror("pipe");
2074 exit(1);
2075 }
2076 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002077 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 exit(1);
2079 }
2080 }
2081}
2082
2083static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002084proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002085{
2086 int i;
2087 int n;
2088 struct proc_pollfd pollinfo;
2089
2090 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
2091 return n;
2092 if (n != sizeof(struct proc_pollfd)) {
2093 fprintf(stderr, "panic: short read: %d\n", n);
2094 exit(1);
2095 }
2096 for (i = 0; i < nprocs; i++) {
2097 if (pollv[i].fd == pollinfo.fd)
2098 pollv[i].revents = pollinfo.revents;
2099 else
2100 pollv[i].revents = 0;
2101 }
2102 poller_pid = pollinfo.pid;
2103 return 1;
2104}
2105
2106static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002107wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002108{
2109}
2110
2111static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002112proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002113{
2114 struct proc_pollfd pollinfo;
2115 struct sigaction sa;
2116 sigset_t blocked_set, empty_set;
2117 int i;
2118 int n;
2119 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002120#ifdef FREEBSD
2121 struct procfs_status pfs;
2122#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002123
2124 switch (fork()) {
2125 case -1:
2126 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00002127 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 case 0:
2129 break;
2130 default:
2131 return;
2132 }
2133
2134 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2135 sa.sa_flags = 0;
2136 sigemptyset(&sa.sa_mask);
2137 sigaction(SIGHUP, &sa, NULL);
2138 sigaction(SIGINT, &sa, NULL);
2139 sigaction(SIGQUIT, &sa, NULL);
2140 sigaction(SIGPIPE, &sa, NULL);
2141 sigaction(SIGTERM, &sa, NULL);
2142 sa.sa_handler = wakeup_handler;
2143 sigaction(SIGUSR1, &sa, NULL);
2144 sigemptyset(&blocked_set);
2145 sigaddset(&blocked_set, SIGUSR1);
2146 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2147 sigemptyset(&empty_set);
2148
2149 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
2150 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00002151 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002152 }
2153 n = rl.rlim_cur;
2154 for (i = 0; i < n; i++) {
2155 if (i != pfd && i != proc_poll_pipe[1])
2156 close(i);
2157 }
2158
2159 pollinfo.fd = pfd;
2160 pollinfo.pid = getpid();
2161 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002162#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002163 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2164#else
2165 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2166#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002167 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002168 switch (errno) {
2169 case EINTR:
2170 continue;
2171 case EBADF:
2172 pollinfo.revents = POLLERR;
2173 break;
2174 case ENOENT:
2175 pollinfo.revents = POLLHUP;
2176 break;
2177 default:
2178 perror("proc_poller: PIOCWSTOP");
2179 }
2180 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2181 _exit(0);
2182 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002183 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2185 sigsuspend(&empty_set);
2186 }
2187}
2188
2189#endif /* !HAVE_POLLABLE_PROCFS */
2190
2191static int
2192choose_pfd()
2193{
2194 int i, j;
2195 struct tcb *tcp;
2196
2197 static int last;
2198
2199 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002200 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 /*
2202 * The previous process is ready to run again. We'll
2203 * let it do so if it is currently in a syscall. This
2204 * heuristic improves the readability of the trace.
2205 */
2206 tcp = pfd2tcb(pollv[last].fd);
2207 if (tcp && (tcp->flags & TCB_INSYSCALL))
2208 return pollv[last].fd;
2209 }
2210
2211 for (i = 0; i < nprocs; i++) {
2212 /* Let competing children run round robin. */
2213 j = (i + last + 1) % nprocs;
2214 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2215 tcp = pfd2tcb(pollv[j].fd);
2216 if (!tcp) {
2217 fprintf(stderr, "strace: lost proc\n");
2218 exit(1);
2219 }
2220 droptcb(tcp);
2221 return -1;
2222 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002223 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002224 last = j;
2225 return pollv[j].fd;
2226 }
2227 }
2228 fprintf(stderr, "strace: nothing ready\n");
2229 exit(1);
2230}
2231
2232static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002233trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002235#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002236 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002237#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002238 struct tcb *tcp;
2239 int pfd;
2240 int what;
2241 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002242 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002243
2244 for (;;) {
2245 if (interactive)
2246 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2247
2248 if (nprocs == 0)
2249 break;
2250
2251 switch (nprocs) {
2252 case 1:
2253#ifndef HAVE_POLLABLE_PROCFS
2254 if (proc_poll_pipe[0] == -1) {
2255#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002256 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257 if (!tcp)
2258 continue;
2259 pfd = tcp->pfd;
2260 if (pfd == -1)
2261 continue;
2262 break;
2263#ifndef HAVE_POLLABLE_PROCFS
2264 }
2265 /* fall through ... */
2266#endif /* !HAVE_POLLABLE_PROCFS */
2267 default:
2268#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002269#ifdef POLL_HACK
2270 /* On some systems (e.g. UnixWare) we get too much ugly
2271 "unfinished..." stuff when multiple proceses are in
2272 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002273
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002274 if (in_syscall) {
2275 struct pollfd pv;
2276 tcp = in_syscall;
2277 in_syscall = NULL;
2278 pv.fd = tcp->pfd;
2279 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002280 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002281 if (interrupted)
2282 return 0;
2283 continue;
2284 }
2285 else if (what == 1 && pv.revents & POLLWANT) {
2286 goto FOUND;
2287 }
2288 }
2289#endif
2290
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002291 if (poll(pollv, nprocs, INFTIM) < 0) {
2292 if (interrupted)
2293 return 0;
2294 continue;
2295 }
2296#else /* !HAVE_POLLABLE_PROCFS */
2297 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2298 if (interrupted)
2299 return 0;
2300 continue;
2301 }
2302#endif /* !HAVE_POLLABLE_PROCFS */
2303 pfd = choose_pfd();
2304 if (pfd == -1)
2305 continue;
2306 break;
2307 }
2308
2309 /* Look up `pfd' in our table. */
2310 if ((tcp = pfd2tcb(pfd)) == NULL) {
2311 fprintf(stderr, "unknown pfd: %u\n", pfd);
2312 exit(1);
2313 }
John Hughesb6643082002-05-23 11:02:22 +00002314#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002315 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002316#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002317 /* Get the status of the process. */
2318 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002319#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002320 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002321#else /* FREEBSD */
2322 /* Thanks to some scheduling mystery, the first poller
2323 sometimes waits for the already processed end of fork
2324 event. Doing a non blocking poll here solves the problem. */
2325 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002326 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002327 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002328 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002329#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330 ioctl_errno = errno;
2331#ifndef HAVE_POLLABLE_PROCFS
2332 if (proc_poll_pipe[0] != -1) {
2333 if (ioctl_result < 0)
2334 kill(poller_pid, SIGKILL);
2335 else
2336 kill(poller_pid, SIGUSR1);
2337 }
2338#endif /* !HAVE_POLLABLE_PROCFS */
2339 }
2340 if (interrupted)
2341 return 0;
2342
2343 if (interactive)
2344 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2345
2346 if (ioctl_result < 0) {
2347 /* Find out what happened if it failed. */
2348 switch (ioctl_errno) {
2349 case EINTR:
2350 case EBADF:
2351 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002352#ifdef FREEBSD
2353 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002354#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002355 case ENOENT:
2356 droptcb(tcp);
2357 continue;
2358 default:
2359 perror("PIOCWSTOP");
2360 exit(1);
2361 }
2362 }
2363
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002364#ifdef FREEBSD
2365 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2366 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002367 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002368 continue;
2369 }
Roland McGrath553a6092002-12-16 20:40:39 +00002370#endif
2371
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002372 /* clear the just started flag */
2373 tcp->flags &= ~TCB_STARTUP;
2374
2375 /* set current output file */
2376 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002377 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002378
2379 if (cflag) {
2380 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002381#ifdef FREEBSD
2382 char buf[1024];
2383 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002384
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002385 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2386 buf[len] = '\0';
2387 sscanf(buf,
2388 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2389 &stime.tv_sec, &stime.tv_usec);
2390 } else
2391 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002392#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002393 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2394 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002395#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2397 tcp->stime = stime;
2398 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002399 what = tcp->status.PR_WHAT;
2400 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002401#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002402 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002403 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2404 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002405 if (trace_syscall(tcp) < 0) {
2406 fprintf(stderr, "syscall trouble\n");
2407 exit(1);
2408 }
2409 }
2410 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002411#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002412 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002413#ifdef POLL_HACK
2414 in_syscall = tcp;
2415#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002416 case PR_SYSEXIT:
2417 if (trace_syscall(tcp) < 0) {
2418 fprintf(stderr, "syscall trouble\n");
2419 exit(1);
2420 }
2421 break;
2422 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002423 if (cflag != CFLAG_ONLY_STATS
2424 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002425 printleader(tcp);
2426 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002427 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002428 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002429#ifdef PR_INFO
2430 if (tcp->status.PR_INFO.si_signo == what) {
2431 printleader(tcp);
2432 tprintf(" siginfo=");
2433 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002434 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002435 }
2436#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002437 }
2438 break;
2439 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002440 if (cflag != CFLAGS_ONLY_STATS
2441 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442 printleader(tcp);
2443 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002444 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 }
2446 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002447#ifdef FREEBSD
2448 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002449 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002450#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002451 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002452 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002453 exit(1);
2454 break;
2455 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002456 /* Remember current print column before continuing. */
2457 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002458 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002459#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002460 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002461#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002462 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002463#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002464 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002465 perror("PIOCRUN");
2466 exit(1);
2467 }
2468 }
2469 return 0;
2470}
2471
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002472#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002473
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002474#ifdef TCB_GROUP_EXITING
2475/* Handle an exit detach or death signal that is taking all the
2476 related clone threads with it. This is called in three circumstances:
2477 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2478 SIG == 0 Continuing TCP will perform an exit_group syscall.
2479 SIG == other Continuing TCP with SIG will kill the process.
2480*/
2481static int
2482handle_group_exit(struct tcb *tcp, int sig)
2483{
2484 /* We need to locate our records of all the clone threads
2485 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002486 struct tcb *leader = NULL;
2487
2488 if (tcp->flags & TCB_CLONE_THREAD)
2489 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002490
2491 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002492 if (leader != NULL && leader != tcp
2493 && !(leader->flags & TCB_GROUP_EXITING)
2494 && !(tcp->flags & TCB_STARTUP)
2495 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002496 fprintf(stderr,
2497 "PANIC: handle_group_exit: %d leader %d\n",
2498 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002499 }
2500 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002501#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002502 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002503#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002504 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002505 }
2506 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002507 /* Mark that we are taking the process down. */
2508 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002509 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002510 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002511 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002512 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002513 } else {
2514 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2515 cleanup();
2516 return -1;
2517 }
2518 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002519 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002520 if (leader != tcp)
2521 droptcb(tcp);
2522 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002523 /* The leader will report to us as parent now,
2524 and then we'll get to the SIG==-1 case. */
2525 return 0;
2526 }
2527 }
2528
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002529 return 0;
2530}
2531#endif
2532
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002533#ifdef LINUX
2534static int
2535handle_ptrace_event(int status, struct tcb *tcp)
2536{
2537 if (status >> 16 == PTRACE_EVENT_VFORK ||
2538 status >> 16 == PTRACE_EVENT_CLONE ||
2539 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002540 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002541
2542 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2543 if (errno != ESRCH) {
2544 fprintf(stderr, "\
2545%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2546 progname);
2547 cleanup();
2548 exit(1);
2549 }
2550 return -1;
2551 }
2552 return handle_new_child(tcp, childpid, 0);
2553 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002554 if (status >> 16 == PTRACE_EVENT_EXEC) {
2555 if (debug)
2556 fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
2557 return 0;
2558 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002559 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2560 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002561 return 1;
2562}
2563#endif
2564
Roland McGratheb9e2e82009-06-02 16:49:22 -07002565static int
2566trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002567{
2568 int pid;
2569 int wait_errno;
2570 int status;
2571 struct tcb *tcp;
2572#ifdef LINUX
2573 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002574#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002575 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002576#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577#endif /* LINUX */
2578
Roland McGratheb9e2e82009-06-02 16:49:22 -07002579 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002580 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002581 return 0;
2582 if (interactive)
2583 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002585#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002586 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002587 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002588 /* this kernel does not support __WALL */
2589 wait4_options &= ~__WALL;
2590 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002591 pid = wait4(-1, &status, wait4_options,
2592 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002593 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002594 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002595 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002596 pid = wait4(-1, &status, __WCLONE,
2597 cflag ? &ru : NULL);
2598 if (pid == -1) {
2599 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002600 "failed: %s\n", strerror(errno));
2601 }
2602 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002603#else
2604 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2605#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002606#endif /* LINUX */
2607#ifdef SUNOS4
2608 pid = wait(&status);
2609#endif /* SUNOS4 */
2610 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002611 if (interactive)
2612 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002614 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002615 switch (wait_errno) {
2616 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002617 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002618 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002619 /*
2620 * We would like to verify this case
2621 * but sometimes a race in Solbourne's
2622 * version of SunOS sometimes reports
2623 * ECHILD before sending us SIGCHILD.
2624 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002625 return 0;
2626 default:
2627 errno = wait_errno;
2628 perror("strace: wait");
2629 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002630 }
2631 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002632 if (pid == popen_pid) {
2633 if (WIFEXITED(status) || WIFSIGNALED(status))
2634 popen_pid = -1;
2635 continue;
2636 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002637 if (debug)
2638 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2639
2640 /* Look up `pid' in our table. */
2641 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002642#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002643 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002644 /* This is needed to go with the CLONE_PTRACE
2645 changes in process.c/util.c: we might see
2646 the child's initial trap before we see the
2647 parent return from the clone syscall.
2648 Leave the child suspended until the parent
2649 returns from its system call. Only then
2650 will we have the association of parent and
2651 child so that we know how to do clearbpt
2652 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002653 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002654 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002655 if (!qflag)
2656 fprintf(stderr, "\
2657Process %d attached (waiting for parent)\n",
2658 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002659 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002660 else
2661 /* This can happen if a clone call used
2662 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002663#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002664 {
2665 fprintf(stderr, "unknown pid: %u\n", pid);
2666 if (WIFSTOPPED(status))
2667 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2668 exit(1);
2669 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002670 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002671 /* set current output file */
2672 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002673 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002674 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002675#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002676 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2677 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002678#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002679 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002680
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002681 if (tcp->flags & TCB_SUSPENDED) {
2682 /*
2683 * Apparently, doing any ptrace() call on a stopped
2684 * process, provokes the kernel to report the process
2685 * status again on a subsequent wait(), even if the
2686 * process has not been actually restarted.
2687 * Since we have inspected the arguments of suspended
2688 * processes we end up here testing for this case.
2689 */
2690 continue;
2691 }
2692 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002693 if (pid == strace_child)
2694 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002695 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002696 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2697 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002698 tprintf("+++ killed by %s %s+++",
2699 signame(WTERMSIG(status)),
2700#ifdef WCOREDUMP
2701 WCOREDUMP(status) ? "(core dumped) " :
2702#endif
2703 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002704 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002705 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002706#ifdef TCB_GROUP_EXITING
2707 handle_group_exit(tcp, -1);
2708#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002709 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002710#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002711 continue;
2712 }
2713 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002714 if (pid == strace_child)
2715 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002716 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002717 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2718 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002719#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002720 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002721 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002722#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002723 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002724 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002725 "PANIC: attached pid %u exited with %d\n",
2726 pid, WEXITSTATUS(status));
2727 }
Roland McGrath0a396902003-06-10 03:05:53 +00002728 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002729 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002730 tprintf(" <unfinished ... exit status %d>\n",
2731 WEXITSTATUS(status));
2732 tcp_last = NULL;
2733 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002734#ifdef TCB_GROUP_EXITING
2735 handle_group_exit(tcp, -1);
2736#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002737 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002738#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002739 continue;
2740 }
2741 if (!WIFSTOPPED(status)) {
2742 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2743 droptcb(tcp);
2744 continue;
2745 }
2746 if (debug)
2747 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002748 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002749
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002750 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002751 if (handle_ptrace_event(status, tcp) != 1)
2752 goto tracing;
2753 }
2754
Roland McGrath02203312007-06-11 22:06:31 +00002755 /*
2756 * Interestingly, the process may stop
2757 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002758 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002759 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002760 * A no-MMU vforked child won't send up a signal,
2761 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002762 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002763 if ((tcp->flags & TCB_STARTUP) &&
2764 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002765 /*
2766 * This flag is there to keep us in sync.
2767 * Next time this process stops it should
2768 * really be entering a system call.
2769 */
2770 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002771 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002772 /*
2773 * One example is a breakpoint inherited from
2774 * parent through fork ().
2775 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002776 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2777 droptcb(tcp);
2778 cleanup();
2779 return -1;
2780 }
2781 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002782#ifdef LINUX
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002783 int options = ptrace_setoptions_for_all;
2784 if (followfork && (tcp->parent == NULL))
2785 options |= ptrace_setoptions_followfork;
2786 if (options) {
2787 if (debug)
2788 fprintf(stderr, "setting opts %x on pid %d\n", options, tcp->pid);
2789 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, options) < 0) {
2790 if (errno != ESRCH) {
2791 /* Should never happen, really */
Denys Vlasenko75422762011-05-27 14:36:01 +02002792 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002793 }
2794 }
2795 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002796#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002797 goto tracing;
2798 }
2799
Denys Vlasenko75422762011-05-27 14:36:01 +02002800 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002801 if (WSTOPSIG(status) == SIGSTOP &&
2802 (tcp->flags & TCB_SIGTRAPPED)) {
2803 /*
2804 * Trapped attempt to block SIGTRAP
2805 * Hope we are back in control now.
2806 */
2807 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002808 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002809 cleanup();
2810 return -1;
2811 }
2812 continue;
2813 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002814 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002815 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002816 siginfo_t si;
2817#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002818 long pc = 0;
2819 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002820
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002821 upeek(tcp, PT_CR_IPSR, &psr);
2822 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002823
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002824# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002825 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002826# define PC_FORMAT_STR " @ %lx"
2827# define PC_FORMAT_ARG pc
2828#else
2829# define PC_FORMAT_STR "%s"
2830# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002831#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002832 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002833 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2834 tprintf("--- ");
2835 printsiginfo(&si, verbose(tcp));
2836 tprintf(" (%s)" PC_FORMAT_STR " ---",
2837 strsignal(WSTOPSIG(status)),
2838 PC_FORMAT_ARG);
2839 } else
2840 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2841 strsignal(WSTOPSIG(status)),
2842 signame(WSTOPSIG(status)),
2843 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002844 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002845 }
Roland McGrath05690952004-10-20 01:00:27 +00002846 if (((tcp->flags & TCB_ATTACHED) ||
2847 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002848 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002849#ifdef TCB_GROUP_EXITING
2850 handle_group_exit(tcp, WSTOPSIG(status));
2851#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002852 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002853#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002854 continue;
2855 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002856 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002857 cleanup();
2858 return -1;
2859 }
2860 tcp->flags &= ~TCB_SUSPENDED;
2861 continue;
2862 }
Roland McGrath02203312007-06-11 22:06:31 +00002863 /* we handled the STATUS, we are permitted to interrupt now. */
2864 if (interrupted)
2865 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002866 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2867 /* ptrace() failed in trace_syscall() with ESRCH.
2868 * Likely a result of process disappearing mid-flight.
2869 * Observed case: exit_group() terminating
2870 * all processes in thread group. In this case, threads
2871 * "disappear" in an unpredictable moment without any
2872 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002873 */
2874 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002875 if (tcp_last) {
2876 /* Do we have dangling line "syscall(param, param"?
2877 * Finish the line then. We cannot
2878 */
2879 tcp_last->flags |= TCB_REPRINT;
2880 tprintf(" <unfinished ...>");
2881 printtrailer();
2882 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002883 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002884 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002885 ptrace(PTRACE_KILL,
2886 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002887 droptcb(tcp);
2888 }
2889 continue;
2890 }
2891 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002892#ifdef TCB_GROUP_EXITING
2893 if (tcp->flags & TCB_GROUP_EXITING) {
2894 if (handle_group_exit(tcp, 0) < 0)
2895 return -1;
2896 continue;
2897 }
2898#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002899 if (tcp->flags & TCB_ATTACHED)
2900 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002901 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002902 cleanup();
2903 return -1;
2904 }
2905 continue;
2906 }
2907 if (tcp->flags & TCB_SUSPENDED) {
2908 if (!qflag)
2909 fprintf(stderr, "Process %u suspended\n", pid);
2910 continue;
2911 }
2912 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002913 /* Remember current print column before continuing. */
2914 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002915 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002916 cleanup();
2917 return -1;
2918 }
2919 }
2920 return 0;
2921}
2922
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002923#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002924
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002925#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002926
2927void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002928tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002929{
2930 va_list args;
2931
Andreas Schwabe5355de2009-10-27 16:56:43 +01002932 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002933 if (outf) {
2934 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002935 if (n < 0) {
2936 if (outf != stderr)
2937 perror(outfname == NULL
2938 ? "<writing to pipe>" : outfname);
2939 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002940 curcol += n;
2941 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002942 va_end(args);
2943 return;
2944}
2945
2946void
Denys Vlasenko12014262011-05-30 14:00:14 +02002947printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002948{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002949 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002950 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002951 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002952 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002953 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002954 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002955 tprintf("= ? <unavailable>\n");
2956 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002957 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002958 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002959 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002960 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002961 }
2962 curcol = 0;
2963 if ((followfork == 1 || pflag_seen > 1) && outfname)
2964 tprintf("%-5d ", tcp->pid);
2965 else if (nprocs > 1 && !outfname)
2966 tprintf("[pid %5u] ", tcp->pid);
2967 if (tflag) {
2968 char str[sizeof("HH:MM:SS")];
2969 struct timeval tv, dtv;
2970 static struct timeval otv;
2971
2972 gettimeofday(&tv, NULL);
2973 if (rflag) {
2974 if (otv.tv_sec == 0)
2975 otv = tv;
2976 tv_sub(&dtv, &tv, &otv);
2977 tprintf("%6ld.%06ld ",
2978 (long) dtv.tv_sec, (long) dtv.tv_usec);
2979 otv = tv;
2980 }
2981 else if (tflag > 2) {
2982 tprintf("%ld.%06ld ",
2983 (long) tv.tv_sec, (long) tv.tv_usec);
2984 }
2985 else {
2986 time_t local = tv.tv_sec;
2987 strftime(str, sizeof(str), "%T", localtime(&local));
2988 if (tflag > 1)
2989 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2990 else
2991 tprintf("%s ", str);
2992 }
2993 }
2994 if (iflag)
2995 printcall(tcp);
2996}
2997
2998void
Denys Vlasenko12014262011-05-30 14:00:14 +02002999tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003000{
3001 if (curcol < col)
3002 tprintf("%*s", col - curcol, "");
3003}
3004
3005void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003006printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003007{
3008 tprintf("\n");
3009 tcp_last = NULL;
3010}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003011
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00003012#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003013
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003014int
3015mp_ioctl(int fd, int cmd, void *arg, int size)
3016{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003017 struct iovec iov[2];
3018 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00003019
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003020 iov[0].iov_base = &cmd;
3021 iov[0].iov_len = sizeof cmd;
3022 if (arg) {
3023 ++n;
3024 iov[1].iov_base = arg;
3025 iov[1].iov_len = size;
3026 }
Roland McGrath553a6092002-12-16 20:40:39 +00003027
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003028 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003029}
3030
3031#endif