blob: 94559a5ca507ac3b4466a17a004d81e78f41eb9d [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 Vlasenkof44cce42011-06-21 14:34:10 +020087unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020088/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020089static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000090int dtime = 0, xflag = 0, qflag = 0;
91cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000092static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000093/*
94 * daemonized_tracer supports -D option.
95 * With this option, strace forks twice.
96 * Unlike normal case, with -D *grandparent* process exec's,
97 * becoming a traced process. Child exits (this prevents traced process
98 * from having children it doesn't expect to have), and grandchild
99 * attaches to grandparent similarly to strace -p PID.
100 * This allows for more transparent interaction in cases
101 * when process and its parent are communicating via signals,
102 * wait() etc. Without -D, strace process gets lodged in between,
103 * disrupting parent<->child link.
104 */
105static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000107/* Sometimes we want to print only succeeding syscalls. */
108int not_failing_only = 0;
109
Grant Edwards8a082772011-04-07 20:25:40 +0000110/* Show path associated with fd arguments */
111int show_fd_path = 0;
112
113/* are we filtering traces based on paths? */
114int tracing_paths = 0;
115
Dmitry V. Levina6809652008-11-10 17:14:58 +0000116static int exit_code = 0;
117static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200118static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700119
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000120static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121uid_t run_uid;
122gid_t run_gid;
123
124int acolumn = DEFAULT_ACOLUMN;
125int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100128static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000129struct tcb **tcbtab;
130unsigned int nprocs, tcbtabsize;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000131const char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700132extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133
Andreas Schwabe5355de2009-10-27 16:56:43 +0100134static int detach(struct tcb *tcp, int sig);
135static int trace(void);
136static void cleanup(void);
137static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138static sigset_t empty_set, blocked_set;
139
140#ifdef HAVE_SIG_ATOMIC_T
141static volatile sig_atomic_t interrupted;
142#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144#endif /* !HAVE_SIG_ATOMIC_T */
145
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000146#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147
Andreas Schwabe5355de2009-10-27 16:56:43 +0100148static struct tcb *pfd2tcb(int pfd);
149static void reaper(int sig);
150static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000151static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152
153#ifndef HAVE_POLLABLE_PROCFS
154
Andreas Schwabe5355de2009-10-27 16:56:43 +0100155static void proc_poll_open(void);
156static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157
158struct proc_pollfd {
159 int fd;
160 int revents;
161 int pid;
162};
163
164static int poller_pid;
165static int proc_poll_pipe[2] = { -1, -1 };
166
167#endif /* !HAVE_POLLABLE_PROCFS */
168
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000169#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000170#define POLLWANT POLLWRNORM
171#else
172#define POLLWANT POLLPRI
173#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000174#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175
176static void
177usage(ofp, exitval)
178FILE *ofp;
179int exitval;
180{
181 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000182usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000183 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000184 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200185 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000186 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200188-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000189-f -- follow forks, -ff -- with output into separate files\n\
190-F -- attempt to follow vforks, -h -- print help message\n\
191-i -- print instruction pointer at time of syscall\n\
192-q -- suppress messages about attaching, detaching, etc.\n\
193-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
194-T -- print time spent in each syscall, -V -- print version\n\
195-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
196-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000197-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198-a column -- alignment COLUMN for printing syscall results (default %d)\n\
199-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
200 options: trace, abbrev, verbose, raw, signal, read, or write\n\
201-o file -- send trace output to FILE instead of stderr\n\
202-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
203-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000204-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
206-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
207-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000208-E var=val -- put var=val in the environment for command\n\
209-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000210-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000211" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000212-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000213 */
214, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215 exit(exitval);
216}
217
Denys Vlasenko75422762011-05-27 14:36:01 +0200218static void die(void) __attribute__ ((noreturn));
219static void die(void)
220{
221 if (strace_tracer_pid == getpid()) {
222 cflag = 0;
223 cleanup();
224 }
225 exit(1);
226}
227
228static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200229{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000230 fflush(NULL);
231 fprintf(stderr, "%s: ", progname);
232 vfprintf(stderr, fmt, p);
233 if (err_no)
234 fprintf(stderr, ": %s\n", strerror(err_no));
235 else
236 putc('\n', stderr);
237 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200238}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200239
Denys Vlasenko75422762011-05-27 14:36:01 +0200240void error_msg(const char *fmt, ...)
241{
242 va_list p;
243 va_start(p, fmt);
244 verror_msg(0, fmt, p);
245 va_end(p);
246}
247
248void error_msg_and_die(const char *fmt, ...)
249{
250 va_list p;
251 va_start(p, fmt);
252 verror_msg(0, fmt, p);
253 die();
254}
255
256void perror_msg(const char *fmt, ...)
257{
258 va_list p;
259 va_start(p, fmt);
260 verror_msg(errno, fmt, p);
261 va_end(p);
262}
263
264void perror_msg_and_die(const char *fmt, ...)
265{
266 va_list p;
267 va_start(p, fmt);
268 verror_msg(errno, fmt, p);
269 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200270}
271
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000272#ifdef SVR4
273#ifdef MIPS
274void
275foobar()
276{
277}
278#endif /* MIPS */
279#endif /* SVR4 */
280
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400281/* Glue for systems without a MMU that cannot provide fork() */
282#ifdef HAVE_FORK
283# define strace_vforked 0
284#else
285# define strace_vforked 1
286# define fork() vfork()
287#endif
288
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000289static int
290set_cloexec_flag(int fd)
291{
292 int flags, newflags;
293
294 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
295 {
296 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
297 progname, strerror(errno));
298 return -1;
299 }
300
301 newflags = flags | FD_CLOEXEC;
302 if (flags == newflags)
303 return 0;
304
305 if (fcntl(fd, F_SETFD, newflags) < 0)
306 {
307 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
308 progname, strerror(errno));
309 return -1;
310 }
311
312 return 0;
313}
314
315/*
316 * When strace is setuid executable, we have to swap uids
317 * before and after filesystem and process management operations.
318 */
319static void
320swap_uid(void)
321{
322#ifndef SVR4
323 int euid = geteuid(), uid = getuid();
324
325 if (euid != uid && setreuid(euid, uid) < 0)
326 {
327 fprintf(stderr, "%s: setreuid: %s\n",
328 progname, strerror(errno));
329 exit(1);
330 }
331#endif
332}
333
Roland McGrath4bfa6262007-07-05 20:03:16 +0000334#if _LFS64_LARGEFILE
335# define fopen_for_output fopen64
336#else
337# define fopen_for_output fopen
338#endif
339
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000340static FILE *
341strace_fopen(const char *path, const char *mode)
342{
343 FILE *fp;
344
345 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000346 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000347 fprintf(stderr, "%s: can't fopen '%s': %s\n",
348 progname, path, strerror(errno));
349 swap_uid();
350 if (fp && set_cloexec_flag(fileno(fp)) < 0)
351 {
352 fclose(fp);
353 fp = NULL;
354 }
355 return fp;
356}
357
358static int popen_pid = -1;
359
360#ifndef _PATH_BSHELL
361# define _PATH_BSHELL "/bin/sh"
362#endif
363
364/*
365 * We cannot use standard popen(3) here because we have to distinguish
366 * popen child process from other processes we trace, and standard popen(3)
367 * does not export its child's pid.
368 */
369static FILE *
370strace_popen(const char *command)
371{
372 int fds[2];
373
374 swap_uid();
375 if (pipe(fds) < 0)
376 {
377 fprintf(stderr, "%s: pipe: %s\n",
378 progname, strerror(errno));
379 swap_uid();
380 return NULL;
381 }
382
383 if (set_cloexec_flag(fds[1]) < 0)
384 {
385 close(fds[0]);
386 close(fds[1]);
387 swap_uid();
388 return NULL;
389 }
390
391 if ((popen_pid = fork()) == -1)
392 {
393 fprintf(stderr, "%s: fork: %s\n",
394 progname, strerror(errno));
395 close(fds[0]);
396 close(fds[1]);
397 swap_uid();
398 return NULL;
399 }
400
401 if (popen_pid)
402 {
403 /* parent */
404 close(fds[0]);
405 swap_uid();
406 return fdopen(fds[1], "w");
407 } else
408 {
409 /* child */
410 close(fds[1]);
411 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
412 {
413 fprintf(stderr, "%s: dup2: %s\n",
414 progname, strerror(errno));
415 _exit(1);
416 }
417 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
418 fprintf(stderr, "%s: execl: %s: %s\n",
419 progname, _PATH_BSHELL, strerror(errno));
420 _exit(1);
421 }
422}
423
424static int
425newoutf(struct tcb *tcp)
426{
427 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000428 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000429 FILE *fp;
430
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000431 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000432 if ((fp = strace_fopen(name, "w")) == NULL)
433 return -1;
434 tcp->outf = fp;
435 }
436 return 0;
437}
438
Roland McGrath02203312007-06-11 22:06:31 +0000439static void
440startup_attach(void)
441{
442 int tcbi;
443 struct tcb *tcp;
444
445 /*
446 * Block user interruptions as we would leave the traced
447 * process stopped (process state T) if we would terminate in
448 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200449 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000450 */
451 if (interactive)
452 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
453
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000454 if (daemonized_tracer) {
455 pid_t pid = fork();
456 if (pid < 0) {
457 _exit(1);
458 }
459 if (pid) { /* parent */
460 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200461 * Wait for grandchild to attach to straced process
462 * (grandparent). Grandchild SIGKILLs us after it attached.
463 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000464 * it proceeds to exec the straced program.
465 */
466 pause();
467 _exit(0); /* paranoia */
468 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200469 /* grandchild */
470 /* We will be the tracer process. Remember our new pid: */
471 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000472 }
473
Roland McGrath02203312007-06-11 22:06:31 +0000474 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
475 tcp = tcbtab[tcbi];
476 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
477 continue;
478#ifdef LINUX
479 if (tcp->flags & TCB_CLONE_THREAD)
480 continue;
481#endif
482 /* Reinitialize the output since it may have changed. */
483 tcp->outf = outf;
484 if (newoutf(tcp) < 0)
485 exit(1);
486
487#ifdef USE_PROCFS
488 if (proc_open(tcp, 1) < 0) {
489 fprintf(stderr, "trouble opening proc file\n");
490 droptcb(tcp);
491 continue;
492 }
493#else /* !USE_PROCFS */
494# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000495 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000496 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000497 DIR *dir;
498
499 sprintf(procdir, "/proc/%d/task", tcp->pid);
500 dir = opendir(procdir);
501 if (dir != NULL) {
502 unsigned int ntid = 0, nerr = 0;
503 struct dirent *de;
504 int tid;
505 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000506 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000507 continue;
508 tid = atoi(de->d_name);
509 if (tid <= 0)
510 continue;
511 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000512 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000513 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000514 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000515 tcp = alloctcb(tid);
Wang Chao21b8db42010-08-27 17:43:16 +0800516 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000517 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000518 tcp->parent = tcbtab[tcbi];
519 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000520 if (interactive) {
521 sigprocmask(SIG_SETMASK, &empty_set, NULL);
522 if (interrupted)
523 return;
524 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
525 }
Roland McGrath02203312007-06-11 22:06:31 +0000526 }
527 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000528 ntid -= nerr;
529 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000530 perror("attach: ptrace(PTRACE_ATTACH, ...)");
531 droptcb(tcp);
532 continue;
533 }
534 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000535 fprintf(stderr, ntid > 1
536? "Process %u attached with %u threads - interrupt to quit\n"
537: "Process %u attached - interrupt to quit\n",
538 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000539 }
540 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000541 } /* if (opendir worked) */
542 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000543# endif
544 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
545 perror("attach: ptrace(PTRACE_ATTACH, ...)");
546 droptcb(tcp);
547 continue;
548 }
549 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000550
551 if (daemonized_tracer) {
552 /*
553 * It is our grandparent we trace, not a -p PID.
554 * Don't want to just detach on exit, so...
555 */
556 tcp->flags &= ~TCB_ATTACHED;
557 /*
558 * Make parent go away.
559 * Also makes grandparent's wait() unblock.
560 */
561 kill(getppid(), SIGKILL);
562 }
563
Roland McGrath02203312007-06-11 22:06:31 +0000564#endif /* !USE_PROCFS */
565 if (!qflag)
566 fprintf(stderr,
567 "Process %u attached - interrupt to quit\n",
568 tcp->pid);
569 }
570
571 if (interactive)
572 sigprocmask(SIG_SETMASK, &empty_set, NULL);
573}
574
575static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200576startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000577{
578 struct stat statbuf;
579 const char *filename;
580 char pathname[MAXPATHLEN];
581 int pid = 0;
582 struct tcb *tcp;
583
584 filename = argv[0];
585 if (strchr(filename, '/')) {
586 if (strlen(filename) > sizeof pathname - 1) {
587 errno = ENAMETOOLONG;
588 perror("strace: exec");
589 exit(1);
590 }
591 strcpy(pathname, filename);
592 }
593#ifdef USE_DEBUGGING_EXEC
594 /*
595 * Debuggers customarily check the current directory
596 * first regardless of the path but doing that gives
597 * security geeks a panic attack.
598 */
599 else if (stat(filename, &statbuf) == 0)
600 strcpy(pathname, filename);
601#endif /* USE_DEBUGGING_EXEC */
602 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000603 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000604 int m, n, len;
605
606 for (path = getenv("PATH"); path && *path; path += m) {
607 if (strchr(path, ':')) {
608 n = strchr(path, ':') - path;
609 m = n + 1;
610 }
611 else
612 m = n = strlen(path);
613 if (n == 0) {
614 if (!getcwd(pathname, MAXPATHLEN))
615 continue;
616 len = strlen(pathname);
617 }
618 else if (n > sizeof pathname - 1)
619 continue;
620 else {
621 strncpy(pathname, path, n);
622 len = n;
623 }
624 if (len && pathname[len - 1] != '/')
625 pathname[len++] = '/';
626 strcpy(pathname + len, filename);
627 if (stat(pathname, &statbuf) == 0 &&
628 /* Accept only regular files
629 with some execute bits set.
630 XXX not perfect, might still fail */
631 S_ISREG(statbuf.st_mode) &&
632 (statbuf.st_mode & 0111))
633 break;
634 }
635 }
636 if (stat(pathname, &statbuf) < 0) {
637 fprintf(stderr, "%s: %s: command not found\n",
638 progname, filename);
639 exit(1);
640 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000641 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000642 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000643 perror("strace: fork");
644 cleanup();
645 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000646 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200647 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
648 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000649 ) {
650 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000651#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200652 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000653#ifdef MIPS
654 /* Kludge for SGI, see proc_open for details. */
655 sa.sa_handler = foobar;
656 sa.sa_flags = 0;
657 sigemptyset(&sa.sa_mask);
658 sigaction(SIGINT, &sa, NULL);
659#endif /* MIPS */
660#ifndef FREEBSD
661 pause();
662#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000663 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000664#endif /* FREEBSD */
665#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200666 if (outf != stderr)
667 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000668
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000669 if (!daemonized_tracer) {
670 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
671 perror("strace: ptrace(PTRACE_TRACEME, ...)");
672 exit(1);
673 }
674 if (debug)
675 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000676 }
Roland McGrath02203312007-06-11 22:06:31 +0000677
678 if (username != NULL || geteuid() == 0) {
679 uid_t run_euid = run_uid;
680 gid_t run_egid = run_gid;
681
682 if (statbuf.st_mode & S_ISUID)
683 run_euid = statbuf.st_uid;
684 if (statbuf.st_mode & S_ISGID)
685 run_egid = statbuf.st_gid;
686
687 /*
688 * It is important to set groups before we
689 * lose privileges on setuid.
690 */
691 if (username != NULL) {
692 if (initgroups(username, run_gid) < 0) {
693 perror("initgroups");
694 exit(1);
695 }
696 if (setregid(run_gid, run_egid) < 0) {
697 perror("setregid");
698 exit(1);
699 }
700 if (setreuid(run_uid, run_euid) < 0) {
701 perror("setreuid");
702 exit(1);
703 }
704 }
705 }
706 else
707 setreuid(run_uid, run_uid);
708
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000709 if (!daemonized_tracer) {
710 /*
711 * Induce an immediate stop so that the parent
712 * will resume us with PTRACE_SYSCALL and display
713 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400714 * Unless of course we're on a no-MMU system where
715 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000716 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400717 if (!strace_vforked)
718 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000719 } else {
720 struct sigaction sv_sigchld;
721 sigaction(SIGCHLD, NULL, &sv_sigchld);
722 /*
723 * Make sure it is not SIG_IGN, otherwise wait
724 * will not block.
725 */
726 signal(SIGCHLD, SIG_DFL);
727 /*
728 * Wait for grandchild to attach to us.
729 * It kills child after that, and wait() unblocks.
730 */
731 alarm(3);
732 wait(NULL);
733 alarm(0);
734 sigaction(SIGCHLD, &sv_sigchld, NULL);
735 }
Roland McGrath02203312007-06-11 22:06:31 +0000736#endif /* !USE_PROCFS */
737
738 execv(pathname, argv);
739 perror("strace: exec");
740 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000741 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000742
743 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200744 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
745 strace_tracer_pid = getpid();
746
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000747 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000748 if (daemonized_tracer) {
749 /* We want subsequent startup_attach() to attach to it. */
750 tcp->flags |= TCB_ATTACHED;
751 }
Roland McGrath02203312007-06-11 22:06:31 +0000752#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000753 if (proc_open(tcp, 0) < 0) {
754 fprintf(stderr, "trouble opening proc file\n");
755 cleanup();
756 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000757 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000758#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000759}
760
Wang Chaob13c0de2010-11-12 17:25:19 +0800761#ifdef LINUX
762/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000763 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800764 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000765 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800766 */
767static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200768test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800769{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000770 int pid, expected_grandchild = 0, found_grandchild = 0;
771 const unsigned int test_options = PTRACE_O_TRACECLONE |
772 PTRACE_O_TRACEFORK |
773 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800774
775 if ((pid = fork()) < 0)
776 return -1;
777 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000778 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800779 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800780 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000781 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800782 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000783
784 while (1) {
785 int status, tracee_pid;
786
787 tracee_pid = wait(&status);
788 if (tracee_pid == -1) {
789 if (errno == EINTR)
790 continue;
791 else if (errno == ECHILD)
792 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200793 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000794 return -1;
795 }
796 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000797 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000798 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
799 errno != ESRCH)
800 kill(tracee_pid, SIGKILL);
801 }
802 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000803 switch (WSTOPSIG(status)) {
804 case SIGSTOP:
805 if (ptrace(PTRACE_SETOPTIONS, pid,
806 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000807 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800808 return -1;
809 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000810 break;
811 case SIGTRAP:
812 if (status >> 16 == PTRACE_EVENT_FORK) {
813 long msg = 0;
814
815 if (ptrace(PTRACE_GETEVENTMSG, pid,
816 NULL, (long) &msg) == 0)
817 expected_grandchild = msg;
818 }
819 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800820 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000821 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
822 errno != ESRCH)
823 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800824 }
825 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000826 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200827 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800828 return 0;
829}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200830
831/*
832 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
833 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
834 * and then see whether it will stop with (SIGTRAP | 0x80).
835 *
836 * Use of this option enables correct handling of user-generated SIGTRAPs,
837 * and SIGTRAPs generated by special instructions such as int3 on x86:
838 * _start: .globl _start
839 * int3
840 * movl $42, %ebx
841 * movl $1, %eax
842 * int $0x80
843 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
844 */
845static void
846test_ptrace_setoptions_for_all(void)
847{
848 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
849 int pid;
850 int it_worked = 0;
851
852 pid = fork();
853 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200854 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200855
856 if (pid == 0) {
857 pid = getpid();
858 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200859 /* Note: exits with exitcode 1 */
860 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200861 kill(pid, SIGSTOP);
862 _exit(0); /* parent should see entry into this syscall */
863 }
864
865 while (1) {
866 int status, tracee_pid;
867
868 errno = 0;
869 tracee_pid = wait(&status);
870 if (tracee_pid <= 0) {
871 if (errno == EINTR)
872 continue;
873 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200874 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200875 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200876 if (WIFEXITED(status)) {
877 if (WEXITSTATUS(status) == 0)
878 break;
879 /* PTRACE_TRACEME failed in child. This is fatal. */
880 exit(1);
881 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200882 if (!WIFSTOPPED(status)) {
883 kill(pid, SIGKILL);
884 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
885 }
886 if (WSTOPSIG(status) == SIGSTOP) {
887 /*
888 * We don't check "options aren't accepted" error.
889 * If it happens, we'll never get (SIGTRAP | 0x80),
890 * and thus will decide to not use the option.
891 * IOW: the outcome of the test will be correct.
892 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200893 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
894 if (errno != EINVAL)
895 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200896 }
897 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
898 it_worked = 1;
899 }
900 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
901 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200902 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200903 }
904 }
905
906 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200907 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200908 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200909 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200910 fprintf(stderr, "ptrace_setoptions = %#x\n",
911 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200912 return;
913 }
914
915 fprintf(stderr,
916 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
917}
Wang Chaob13c0de2010-11-12 17:25:19 +0800918#endif
919
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000920int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000921main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000923 struct tcb *tcp;
924 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000925 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926 struct sigaction sa;
927
928 static char buf[BUFSIZ];
929
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000930 progname = argv[0] ? argv[0] : "strace";
931
Denys Vlasenko75422762011-05-27 14:36:01 +0200932 strace_tracer_pid = getpid();
933
Roland McGrathee9d4352002-12-18 04:16:10 +0000934 /* Allocate the initial tcbtab. */
935 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000936 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000937 fprintf(stderr, "%s: out of memory\n", progname);
938 exit(1);
939 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000940 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000941 fprintf(stderr, "%s: out of memory\n", progname);
942 exit(1);
943 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000944 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
945 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
946
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947 outf = stderr;
948 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000949 set_sortby(DEFAULT_SORTBY);
950 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 qualify("trace=all");
952 qualify("abbrev=all");
953 qualify("verbose=all");
954 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000956 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000957#ifndef USE_PROCFS
958 "D"
959#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000960 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000961 switch (c) {
962 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000963 if (cflag == CFLAG_BOTH) {
964 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
965 progname);
966 exit(1);
967 }
968 cflag = CFLAG_ONLY_STATS;
969 break;
970 case 'C':
971 if (cflag == CFLAG_ONLY_STATS) {
972 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
973 progname);
974 exit(1);
975 }
976 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977 break;
978 case 'd':
979 debug++;
980 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000981#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000982 case 'D':
983 daemonized_tracer = 1;
984 break;
985#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000986 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000987 optF = 1;
988 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989 case 'f':
990 followfork++;
991 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992 case 'h':
993 usage(stdout, 0);
994 break;
995 case 'i':
996 iflag++;
997 break;
998 case 'q':
999 qflag++;
1000 break;
1001 case 'r':
1002 rflag++;
1003 tflag++;
1004 break;
1005 case 't':
1006 tflag++;
1007 break;
1008 case 'T':
1009 dtime++;
1010 break;
1011 case 'x':
1012 xflag++;
1013 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001014 case 'y':
1015 show_fd_path = 1;
1016 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 case 'v':
1018 qualify("abbrev=none");
1019 break;
1020 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001021 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 exit(0);
1023 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001024 case 'z':
1025 not_failing_only = 1;
1026 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 case 'a':
1028 acolumn = atoi(optarg);
1029 break;
1030 case 'e':
1031 qualify(optarg);
1032 break;
1033 case 'o':
1034 outfname = strdup(optarg);
1035 break;
1036 case 'O':
1037 set_overhead(atoi(optarg));
1038 break;
1039 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +00001040 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 fprintf(stderr, "%s: Invalid process id: %s\n",
1042 progname, optarg);
1043 break;
1044 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001045 if (pid == strace_tracer_pid) {
Wichert Akkerman54a47671999-10-17 00:57:34 +00001046 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 break;
1048 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001049 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 tcp->flags |= TCB_ATTACHED;
1051 pflag_seen++;
1052 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001053 case 'P':
1054 tracing_paths = 1;
1055 if (pathtrace_select(optarg)) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001056 fprintf(stderr, "%s : failed to select path '%s'\n", progname, optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001057 exit(1);
1058 }
1059 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 case 's':
1061 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001062 if (max_strlen < 0) {
1063 fprintf(stderr,
1064 "%s: invalid -s argument: %s\n",
1065 progname, optarg);
1066 exit(1);
1067 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 break;
1069 case 'S':
1070 set_sortby(optarg);
1071 break;
1072 case 'u':
1073 username = strdup(optarg);
1074 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001075 case 'E':
1076 if (putenv(optarg) < 0) {
1077 fprintf(stderr, "%s: out of memory\n",
1078 progname);
1079 exit(1);
1080 }
1081 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082 default:
1083 usage(stderr, 1);
1084 break;
1085 }
1086 }
1087
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001088 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001089 usage(stderr, 1);
1090
Wang Chaod322a4b2010-08-05 14:30:11 +08001091 if (pflag_seen && daemonized_tracer) {
1092 fprintf(stderr,
1093 "%s: -D and -p are mutually exclusive options\n",
1094 progname);
1095 exit(1);
1096 }
1097
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001098 if (!followfork)
1099 followfork = optF;
1100
Roland McGrathcb9def62006-04-25 07:48:03 +00001101 if (followfork > 1 && cflag) {
1102 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001103 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +00001104 progname);
1105 exit(1);
1106 }
1107
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 /* See if they want to run as another user. */
1109 if (username != NULL) {
1110 struct passwd *pent;
1111
1112 if (getuid() != 0 || geteuid() != 0) {
1113 fprintf(stderr,
1114 "%s: you must be root to use the -u option\n",
1115 progname);
1116 exit(1);
1117 }
1118 if ((pent = getpwnam(username)) == NULL) {
1119 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +00001120 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121 exit(1);
1122 }
1123 run_uid = pent->pw_uid;
1124 run_gid = pent->pw_gid;
1125 }
1126 else {
1127 run_uid = getuid();
1128 run_gid = getgid();
1129 }
1130
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001131#ifdef LINUX
1132 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001133 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001134 fprintf(stderr,
1135 "Test for options supported by PTRACE_SETOPTIONS "
1136 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001137 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001138 }
1139 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001140 fprintf(stderr, "ptrace_setoptions = %#x\n",
1141 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001142 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001143 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001144#endif
1145
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 /* Check if they want to redirect the output. */
1147 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001148 /* See if they want to pipe the output. */
1149 if (outfname[0] == '|' || outfname[0] == '!') {
1150 /*
1151 * We can't do the <outfname>.PID funny business
1152 * when using popen, so prohibit it.
1153 */
1154 if (followfork > 1) {
1155 fprintf(stderr, "\
1156%s: piping the output and -ff are mutually exclusive options\n",
1157 progname);
1158 exit(1);
1159 }
1160
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001161 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +00001162 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001163 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001164 else if (followfork <= 1 &&
1165 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 }
1168
Roland McGrath37b9a662003-11-07 02:26:54 +00001169 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +00001171 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001174 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001175
Roland McGrath54cc1c82007-11-03 23:34:11 +00001176 /* Valid states here:
1177 optind < argc pflag_seen outfname interactive
1178 1 0 0 1
1179 0 1 0 1
1180 1 0 1 0
1181 0 1 1 1
1182 */
1183
1184 /* STARTUP_CHILD must be called before the signal handlers get
1185 installed below as they are inherited into the spawned process.
1186 Also we do not need to be protected by them as during interruption
1187 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1188 if (!pflag_seen)
1189 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 sigemptyset(&empty_set);
1192 sigemptyset(&blocked_set);
1193 sa.sa_handler = SIG_IGN;
1194 sigemptyset(&sa.sa_mask);
1195 sa.sa_flags = 0;
1196 sigaction(SIGTTOU, &sa, NULL);
1197 sigaction(SIGTTIN, &sa, NULL);
1198 if (interactive) {
1199 sigaddset(&blocked_set, SIGHUP);
1200 sigaddset(&blocked_set, SIGINT);
1201 sigaddset(&blocked_set, SIGQUIT);
1202 sigaddset(&blocked_set, SIGPIPE);
1203 sigaddset(&blocked_set, SIGTERM);
1204 sa.sa_handler = interrupt;
1205#ifdef SUNOS4
1206 /* POSIX signals on sunos4.1 are a little broken. */
1207 sa.sa_flags = SA_INTERRUPT;
1208#endif /* SUNOS4 */
1209 }
1210 sigaction(SIGHUP, &sa, NULL);
1211 sigaction(SIGINT, &sa, NULL);
1212 sigaction(SIGQUIT, &sa, NULL);
1213 sigaction(SIGPIPE, &sa, NULL);
1214 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001215#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 sa.sa_handler = reaper;
1217 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001218#else
1219 /* Make sure SIGCHLD has the default action so that waitpid
1220 definitely works without losing track of children. The user
1221 should not have given us a bogus state to inherit, but he might
1222 have. Arguably we should detect SIG_IGN here and pass it on
1223 to children, but probably noone really needs that. */
1224 sa.sa_handler = SIG_DFL;
1225 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001226#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001228 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001229 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001230
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 if (trace() < 0)
1232 exit(1);
1233 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001234 fflush(NULL);
1235 if (exit_code > 0xff) {
1236 /* Child was killed by a signal, mimic that. */
1237 exit_code &= 0xff;
1238 signal(exit_code, SIG_DFL);
1239 raise(exit_code);
1240 /* Paranoia - what if this signal is not fatal?
1241 Exit with 128 + signo then. */
1242 exit_code += 128;
1243 }
1244 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245}
1246
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001247void
1248expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001249{
1250 /* Allocate some more TCBs and expand the table.
1251 We don't want to relocate the TCBs because our
1252 callers have pointers and it would be a pain.
1253 So tcbtab is a table of pointers. Since we never
1254 free the TCBs, we allocate a single chunk of many. */
1255 struct tcb **newtab = (struct tcb **)
1256 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
1257 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
1258 sizeof *newtcbs);
1259 int i;
1260 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +00001261 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
1262 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001263 cleanup();
1264 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001265 }
1266 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1267 newtab[i] = &newtcbs[i - tcbtabsize];
1268 tcbtabsize *= 2;
1269 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001270}
1271
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001273alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274{
1275 int i;
1276 struct tcb *tcp;
1277
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001278 if (nprocs == tcbtabsize)
1279 expand_tcbtab();
1280
Roland McGrathee9d4352002-12-18 04:16:10 +00001281 for (i = 0; i < tcbtabsize; i++) {
1282 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283 if ((tcp->flags & TCB_INUSE) == 0) {
1284 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001285 tcp->parent = NULL;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001286#ifdef TCB_CLONE_THREAD
Wang Chao21b8db42010-08-27 17:43:16 +08001287 tcp->nclone_threads = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001288#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289 tcp->flags = TCB_INUSE | TCB_STARTUP;
1290 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001291 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001292 tcp->stime.tv_sec = 0;
1293 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294 tcp->pfd = -1;
1295 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001296 if (command_options_parsed)
1297 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001298 return tcp;
1299 }
1300 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001301 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1302 cleanup();
1303 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304}
1305
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001306#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001308proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309{
1310 char proc[32];
1311 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001312#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001313 int i;
1314 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315 sigset_t signals;
1316 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318#ifndef HAVE_POLLABLE_PROCFS
1319 static int last_pfd;
1320#endif
1321
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001322#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001323 /* Open the process pseudo-files in /proc. */
1324 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1325 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326 perror("strace: open(\"/proc/...\", ...)");
1327 return -1;
1328 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001329 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 return -1;
1331 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001332 sprintf(proc, "/proc/%d/status", tcp->pid);
1333 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1334 perror("strace: open(\"/proc/...\", ...)");
1335 return -1;
1336 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001337 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001338 return -1;
1339 }
1340 sprintf(proc, "/proc/%d/as", tcp->pid);
1341 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1342 perror("strace: open(\"/proc/...\", ...)");
1343 return -1;
1344 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001345 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001346 return -1;
1347 }
1348#else
1349 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001350#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001351 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001352 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001353#else /* FREEBSD */
1354 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001355 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001356#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001357 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001358 perror("strace: open(\"/proc/...\", ...)");
1359 return -1;
1360 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001361 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001362 return -1;
1363 }
1364#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001365#ifdef FREEBSD
1366 sprintf(proc, "/proc/%d/regs", tcp->pid);
1367 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1368 perror("strace: open(\"/proc/.../regs\", ...)");
1369 return -1;
1370 }
1371 if (cflag) {
1372 sprintf(proc, "/proc/%d/status", tcp->pid);
1373 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1374 perror("strace: open(\"/proc/.../status\", ...)");
1375 return -1;
1376 }
1377 } else
1378 tcp->pfd_status = -1;
1379#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001380 rebuild_pollv();
1381 if (!attaching) {
1382 /*
1383 * Wait for the child to pause. Because of a race
1384 * condition we have to poll for the event.
1385 */
1386 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001387 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001388 perror("strace: PIOCSTATUS");
1389 return -1;
1390 }
1391 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001392 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001393 }
1394 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001395#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001396 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001397 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001398 perror("strace: PIOCSTOP");
1399 return -1;
1400 }
Roland McGrath553a6092002-12-16 20:40:39 +00001401#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001402#ifdef PIOCSET
1403 /* Set Run-on-Last-Close. */
1404 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001405 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 perror("PIOCSET PR_RLC");
1407 return -1;
1408 }
1409 /* Set or Reset Inherit-on-Fork. */
1410 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001411 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001412 perror("PIOC{SET,RESET} PR_FORK");
1413 return -1;
1414 }
1415#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001416#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1418 perror("PIOCSRLC");
1419 return -1;
1420 }
1421 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1422 perror("PIOC{S,R}FORK");
1423 return -1;
1424 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001425#else /* FREEBSD */
1426 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1427 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1428 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001429 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001430 }
1431 arg &= ~PF_LINGER;
1432 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001433 perror("PIOCSFL");
1434 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001435 }
1436#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001438#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001439 /* Enable all syscall entries we care about. */
1440 premptyset(&syscalls);
1441 for (i = 1; i < MAX_QUALS; ++i) {
1442 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001443 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001444 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001445 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001446 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001447 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001448#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001449 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001450#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001451#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001452 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001453#endif
1454#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001455 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001456#endif
1457#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001458 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001459#endif
1460 }
1461 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462 perror("PIOCSENTRY");
1463 return -1;
1464 }
John Hughes19e49982001-10-19 08:59:12 +00001465 /* Enable the syscall exits. */
1466 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001467 perror("PIOSEXIT");
1468 return -1;
1469 }
John Hughes19e49982001-10-19 08:59:12 +00001470 /* Enable signals we care about. */
1471 premptyset(&signals);
1472 for (i = 1; i < MAX_QUALS; ++i) {
1473 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001474 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001475 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001476 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477 perror("PIOCSTRACE");
1478 return -1;
1479 }
John Hughes19e49982001-10-19 08:59:12 +00001480 /* Enable faults we care about */
1481 premptyset(&faults);
1482 for (i = 1; i < MAX_QUALS; ++i) {
1483 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001484 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001485 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001486 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 perror("PIOCSFAULT");
1488 return -1;
1489 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001490#else /* FREEBSD */
1491 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001492 arg = S_SIG | S_SCE | S_SCX;
1493 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001494 perror("PIOCBIS");
1495 return -1;
1496 }
1497#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498 if (!attaching) {
1499#ifdef MIPS
1500 /*
1501 * The SGI PRSABORT doesn't work for pause() so
1502 * we send it a caught signal to wake it up.
1503 */
1504 kill(tcp->pid, SIGINT);
1505#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001506#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001508 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001509 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510 perror("PIOCRUN");
1511 return -1;
1512 }
Roland McGrath553a6092002-12-16 20:40:39 +00001513#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001514#endif /* !MIPS*/
1515#ifdef FREEBSD
1516 /* wake up the child if it received the SIGSTOP */
1517 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001518#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 for (;;) {
1520 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001521 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522 perror("PIOCWSTOP");
1523 return -1;
1524 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001525 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001526 tcp->flags &= ~TCB_INSYSCALL;
1527 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001528 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529 break;
1530 }
1531 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001532#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001533 arg = 0;
1534 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001535#else /* FREEBSD */
1536 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001537#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538 perror("PIOCRUN");
1539 return -1;
1540 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001541#ifdef FREEBSD
1542 /* handle the case where we "opened" the child before
1543 it did the kill -STOP */
1544 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1545 tcp->status.PR_WHAT == SIGSTOP)
1546 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001547#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001548 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001549#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001551#else /* FREEBSD */
1552 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001553 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001554 /* We are attaching to an already running process.
1555 * Try to figure out the state of the process in syscalls,
1556 * to handle the first event well.
1557 * This is done by having a look at the "wchan" property of the
1558 * process, which tells where it is stopped (if it is). */
1559 FILE * status;
1560 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001561
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001562 sprintf(proc, "/proc/%d/status", tcp->pid);
1563 status = fopen(proc, "r");
1564 if (status &&
1565 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1566 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1567 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1568 strcmp(wchan, "stopevent")) {
1569 /* The process is asleep in the middle of a syscall.
1570 Fake the syscall entry event */
1571 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1572 tcp->status.PR_WHY = PR_SYSENTRY;
1573 trace_syscall(tcp);
1574 }
1575 if (status)
1576 fclose(status);
1577 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001578 }
1579#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580#ifndef HAVE_POLLABLE_PROCFS
1581 if (proc_poll_pipe[0] != -1)
1582 proc_poller(tcp->pfd);
1583 else if (nprocs > 1) {
1584 proc_poll_open();
1585 proc_poller(last_pfd);
1586 proc_poller(tcp->pfd);
1587 }
1588 last_pfd = tcp->pfd;
1589#endif /* !HAVE_POLLABLE_PROCFS */
1590 return 0;
1591}
1592
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001593#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001595struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001596pid2tcb(int pid)
1597{
1598 int i;
1599
1600 if (pid <= 0)
1601 return NULL;
1602
1603 for (i = 0; i < tcbtabsize; i++) {
1604 struct tcb *tcp = tcbtab[i];
1605 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1606 return tcp;
1607 }
1608
1609 return NULL;
1610}
1611
1612#ifdef USE_PROCFS
1613
1614static struct tcb *
1615first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616{
1617 int i;
1618 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001619 for (i = 0; i < tcbtabsize; i++) {
1620 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621 if (tcp->flags & TCB_INUSE)
1622 return tcp;
1623 }
1624 return NULL;
1625}
1626
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001628pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629{
1630 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631
Roland McGrathca16be82003-01-10 19:55:28 +00001632 for (i = 0; i < tcbtabsize; i++) {
1633 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634 if (tcp->pfd != pfd)
1635 continue;
1636 if (tcp->flags & TCB_INUSE)
1637 return tcp;
1638 }
1639 return NULL;
1640}
1641
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001642#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643
1644void
Denys Vlasenko12014262011-05-30 14:00:14 +02001645droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646{
1647 if (tcp->pid == 0)
1648 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001649#ifdef TCB_CLONE_THREAD
1650 if (tcp->nclone_threads > 0) {
1651 /* There are other threads left in this process, but this
1652 is the one whose PID represents the whole process.
1653 We need to keep this record around as a zombie until
1654 all the threads die. */
1655 tcp->flags |= TCB_EXITING;
1656 return;
1657 }
1658#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001659 nprocs--;
1660 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001661
Roland McGrathe29341c2003-01-10 20:14:20 +00001662 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001663#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001664 if (tcp->flags & TCB_CLONE_THREAD)
1665 tcp->parent->nclone_threads--;
1666#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001667#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001668 /* Update fields like NCLONE_DETACHED, only
1669 for zombie group leader that has already reported
1670 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001671 function. The same condition as at the top of DETACH. */
1672 if ((tcp->flags & TCB_CLONE_THREAD) &&
1673 tcp->parent->nclone_threads == 0 &&
1674 (tcp->parent->flags & TCB_EXITING))
1675 droptcb(tcp->parent);
1676#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001677 tcp->parent = NULL;
1678 }
1679
1680 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 if (tcp->pfd != -1) {
1682 close(tcp->pfd);
1683 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001684#ifdef FREEBSD
1685 if (tcp->pfd_reg != -1) {
1686 close(tcp->pfd_reg);
1687 tcp->pfd_reg = -1;
1688 }
1689 if (tcp->pfd_status != -1) {
1690 close(tcp->pfd_status);
1691 tcp->pfd_status = -1;
1692 }
Roland McGrath553a6092002-12-16 20:40:39 +00001693#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001694#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001695 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696#endif
1697 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001698
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001699 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001701
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 tcp->outf = 0;
1703}
1704
Roland McGrath0a463882007-07-05 18:43:16 +00001705/* detach traced process; continue with sig
1706 Never call DETACH twice on the same process as both unattached and
1707 attached-unstopped processes give the same ESRCH. For unattached process we
1708 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709
1710static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001711detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712{
1713 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001714#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001715 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001716 struct tcb *zombie = NULL;
1717
1718 /* If the group leader is lingering only because of this other
1719 thread now dying, then detach the leader as well. */
1720 if ((tcp->flags & TCB_CLONE_THREAD) &&
1721 tcp->parent->nclone_threads == 1 &&
1722 (tcp->parent->flags & TCB_EXITING))
1723 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001724#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725
1726 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001727 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001728
1729#ifdef LINUX
1730 /*
1731 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001732 * before detaching. Arghh. We go through hoops
1733 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001735#if defined(SPARC)
1736#undef PTRACE_DETACH
1737#define PTRACE_DETACH PTRACE_SUNDETACH
1738#endif
Roland McGrath02203312007-06-11 22:06:31 +00001739 /*
1740 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1741 * expected SIGSTOP. We must catch exactly one as otherwise the
1742 * detached process would be left stopped (process state T).
1743 */
1744 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1746 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001747 }
1748 else if (errno != ESRCH) {
1749 /* Shouldn't happen. */
1750 perror("detach: ptrace(PTRACE_DETACH, ...)");
1751 }
Roland McGrath134813a2007-06-02 00:07:33 +00001752 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1753 : tcp->pid),
1754 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001755 if (errno != ESRCH)
1756 perror("detach: checking sanity");
1757 }
Roland McGrath02203312007-06-11 22:06:31 +00001758 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1759 ? tcp->parent->pid : tcp->pid),
1760 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001761 if (errno != ESRCH)
1762 perror("detach: stopping child");
1763 }
Roland McGrath02203312007-06-11 22:06:31 +00001764 else
1765 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001766 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001768#ifdef __WALL
1769 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1770 if (errno == ECHILD) /* Already gone. */
1771 break;
1772 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001773 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001774 break;
1775 }
1776#endif /* __WALL */
1777 /* No __WALL here. */
1778 if (waitpid(tcp->pid, &status, 0) < 0) {
1779 if (errno != ECHILD) {
1780 perror("detach: waiting");
1781 break;
1782 }
1783#ifdef __WCLONE
1784 /* If no processes, try clones. */
1785 if (wait4(tcp->pid, &status, __WCLONE,
1786 NULL) < 0) {
1787 if (errno != ECHILD)
1788 perror("detach: waiting");
1789 break;
1790 }
1791#endif /* __WCLONE */
1792 }
1793#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001794 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001795#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 if (!WIFSTOPPED(status)) {
1797 /* Au revoir, mon ami. */
1798 break;
1799 }
1800 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001801 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802 break;
1803 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001804 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001805 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001806 : WSTOPSIG(status));
1807 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001810 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001811#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812
1813#if defined(SUNOS4)
1814 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1815 if (sig && kill(tcp->pid, sig) < 0)
1816 perror("detach: kill");
1817 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001818 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819#endif /* SUNOS4 */
1820
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821 if (!qflag)
1822 fprintf(stderr, "Process %u detached\n", tcp->pid);
1823
1824 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001825
1826#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001827 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001828 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001829 droptcb(zombie);
1830 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001831#endif
1832
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833 return error;
1834}
1835
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001836#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001838static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839{
1840 int pid;
1841 int status;
1842
1843 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844 }
1845}
1846
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001847#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848
1849static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001850cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851{
1852 int i;
1853 struct tcb *tcp;
1854
Roland McGrathee9d4352002-12-18 04:16:10 +00001855 for (i = 0; i < tcbtabsize; i++) {
1856 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 if (!(tcp->flags & TCB_INUSE))
1858 continue;
1859 if (debug)
1860 fprintf(stderr,
1861 "cleanup: looking at pid %u\n", tcp->pid);
1862 if (tcp_last &&
1863 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001864 tprintf(" <unfinished ...>");
1865 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866 }
1867 if (tcp->flags & TCB_ATTACHED)
1868 detach(tcp, 0);
1869 else {
1870 kill(tcp->pid, SIGCONT);
1871 kill(tcp->pid, SIGTERM);
1872 }
1873 }
1874 if (cflag)
1875 call_summary(outf);
1876}
1877
1878static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001879interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880{
1881 interrupted = 1;
1882}
1883
1884#ifndef HAVE_STRERROR
1885
Roland McGrath6d2b3492002-12-30 00:51:30 +00001886#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001887extern int sys_nerr;
1888extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001889#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890
1891const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001892strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001893{
1894 static char buf[64];
1895
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001896 if (err_no < 1 || err_no >= sys_nerr) {
1897 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898 return buf;
1899 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001900 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901}
1902
1903#endif /* HAVE_STERRROR */
1904
1905#ifndef HAVE_STRSIGNAL
1906
Roland McGrath8f474e02003-01-14 07:53:33 +00001907#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001908extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001910#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1911extern char *_sys_siglist[];
1912#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001913
1914const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001915strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001916{
1917 static char buf[64];
1918
1919 if (sig < 1 || sig >= NSIG) {
1920 sprintf(buf, "Unknown signal %d", sig);
1921 return buf;
1922 }
1923#ifdef HAVE__SYS_SIGLIST
1924 return _sys_siglist[sig];
1925#else
1926 return sys_siglist[sig];
1927#endif
1928}
1929
1930#endif /* HAVE_STRSIGNAL */
1931
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001932#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001933
1934static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001935rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936{
1937 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938
Roland McGrathee9d4352002-12-18 04:16:10 +00001939 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001940 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001941 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001942 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001943 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001944 exit(1);
1945 }
1946
Roland McGrathca16be82003-01-10 19:55:28 +00001947 for (i = j = 0; i < tcbtabsize; i++) {
1948 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949 if (!(tcp->flags & TCB_INUSE))
1950 continue;
1951 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001952 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953 j++;
1954 }
1955 if (j != nprocs) {
1956 fprintf(stderr, "strace: proc miscount\n");
1957 exit(1);
1958 }
1959}
1960
1961#ifndef HAVE_POLLABLE_PROCFS
1962
1963static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001964proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 int i;
1967
1968 if (pipe(proc_poll_pipe) < 0) {
1969 perror("pipe");
1970 exit(1);
1971 }
1972 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001973 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001974 exit(1);
1975 }
1976 }
1977}
1978
1979static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001980proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981{
1982 int i;
1983 int n;
1984 struct proc_pollfd pollinfo;
1985
1986 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1987 return n;
1988 if (n != sizeof(struct proc_pollfd)) {
1989 fprintf(stderr, "panic: short read: %d\n", n);
1990 exit(1);
1991 }
1992 for (i = 0; i < nprocs; i++) {
1993 if (pollv[i].fd == pollinfo.fd)
1994 pollv[i].revents = pollinfo.revents;
1995 else
1996 pollv[i].revents = 0;
1997 }
1998 poller_pid = pollinfo.pid;
1999 return 1;
2000}
2001
2002static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002003wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004{
2005}
2006
2007static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002008proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009{
2010 struct proc_pollfd pollinfo;
2011 struct sigaction sa;
2012 sigset_t blocked_set, empty_set;
2013 int i;
2014 int n;
2015 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002016#ifdef FREEBSD
2017 struct procfs_status pfs;
2018#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019
2020 switch (fork()) {
2021 case -1:
2022 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00002023 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 case 0:
2025 break;
2026 default:
2027 return;
2028 }
2029
2030 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2031 sa.sa_flags = 0;
2032 sigemptyset(&sa.sa_mask);
2033 sigaction(SIGHUP, &sa, NULL);
2034 sigaction(SIGINT, &sa, NULL);
2035 sigaction(SIGQUIT, &sa, NULL);
2036 sigaction(SIGPIPE, &sa, NULL);
2037 sigaction(SIGTERM, &sa, NULL);
2038 sa.sa_handler = wakeup_handler;
2039 sigaction(SIGUSR1, &sa, NULL);
2040 sigemptyset(&blocked_set);
2041 sigaddset(&blocked_set, SIGUSR1);
2042 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2043 sigemptyset(&empty_set);
2044
2045 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
2046 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00002047 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048 }
2049 n = rl.rlim_cur;
2050 for (i = 0; i < n; i++) {
2051 if (i != pfd && i != proc_poll_pipe[1])
2052 close(i);
2053 }
2054
2055 pollinfo.fd = pfd;
2056 pollinfo.pid = getpid();
2057 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002058#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002059 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2060#else
2061 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2062#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002063 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002064 switch (errno) {
2065 case EINTR:
2066 continue;
2067 case EBADF:
2068 pollinfo.revents = POLLERR;
2069 break;
2070 case ENOENT:
2071 pollinfo.revents = POLLHUP;
2072 break;
2073 default:
2074 perror("proc_poller: PIOCWSTOP");
2075 }
2076 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2077 _exit(0);
2078 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002079 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002080 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2081 sigsuspend(&empty_set);
2082 }
2083}
2084
2085#endif /* !HAVE_POLLABLE_PROCFS */
2086
2087static int
2088choose_pfd()
2089{
2090 int i, j;
2091 struct tcb *tcp;
2092
2093 static int last;
2094
2095 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002096 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002097 /*
2098 * The previous process is ready to run again. We'll
2099 * let it do so if it is currently in a syscall. This
2100 * heuristic improves the readability of the trace.
2101 */
2102 tcp = pfd2tcb(pollv[last].fd);
2103 if (tcp && (tcp->flags & TCB_INSYSCALL))
2104 return pollv[last].fd;
2105 }
2106
2107 for (i = 0; i < nprocs; i++) {
2108 /* Let competing children run round robin. */
2109 j = (i + last + 1) % nprocs;
2110 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2111 tcp = pfd2tcb(pollv[j].fd);
2112 if (!tcp) {
2113 fprintf(stderr, "strace: lost proc\n");
2114 exit(1);
2115 }
2116 droptcb(tcp);
2117 return -1;
2118 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002119 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002120 last = j;
2121 return pollv[j].fd;
2122 }
2123 }
2124 fprintf(stderr, "strace: nothing ready\n");
2125 exit(1);
2126}
2127
2128static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002129trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002131#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002132 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002133#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134 struct tcb *tcp;
2135 int pfd;
2136 int what;
2137 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002138 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139
2140 for (;;) {
2141 if (interactive)
2142 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2143
2144 if (nprocs == 0)
2145 break;
2146
2147 switch (nprocs) {
2148 case 1:
2149#ifndef HAVE_POLLABLE_PROCFS
2150 if (proc_poll_pipe[0] == -1) {
2151#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002152 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 if (!tcp)
2154 continue;
2155 pfd = tcp->pfd;
2156 if (pfd == -1)
2157 continue;
2158 break;
2159#ifndef HAVE_POLLABLE_PROCFS
2160 }
2161 /* fall through ... */
2162#endif /* !HAVE_POLLABLE_PROCFS */
2163 default:
2164#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002165#ifdef POLL_HACK
2166 /* On some systems (e.g. UnixWare) we get too much ugly
2167 "unfinished..." stuff when multiple proceses are in
2168 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002169
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002170 if (in_syscall) {
2171 struct pollfd pv;
2172 tcp = in_syscall;
2173 in_syscall = NULL;
2174 pv.fd = tcp->pfd;
2175 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002176 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002177 if (interrupted)
2178 return 0;
2179 continue;
2180 }
2181 else if (what == 1 && pv.revents & POLLWANT) {
2182 goto FOUND;
2183 }
2184 }
2185#endif
2186
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 if (poll(pollv, nprocs, INFTIM) < 0) {
2188 if (interrupted)
2189 return 0;
2190 continue;
2191 }
2192#else /* !HAVE_POLLABLE_PROCFS */
2193 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2194 if (interrupted)
2195 return 0;
2196 continue;
2197 }
2198#endif /* !HAVE_POLLABLE_PROCFS */
2199 pfd = choose_pfd();
2200 if (pfd == -1)
2201 continue;
2202 break;
2203 }
2204
2205 /* Look up `pfd' in our table. */
2206 if ((tcp = pfd2tcb(pfd)) == NULL) {
2207 fprintf(stderr, "unknown pfd: %u\n", pfd);
2208 exit(1);
2209 }
John Hughesb6643082002-05-23 11:02:22 +00002210#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002211 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002212#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002213 /* Get the status of the process. */
2214 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002215#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002216 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002217#else /* FREEBSD */
2218 /* Thanks to some scheduling mystery, the first poller
2219 sometimes waits for the already processed end of fork
2220 event. Doing a non blocking poll here solves the problem. */
2221 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002222 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002223 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002224 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002225#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002226 ioctl_errno = errno;
2227#ifndef HAVE_POLLABLE_PROCFS
2228 if (proc_poll_pipe[0] != -1) {
2229 if (ioctl_result < 0)
2230 kill(poller_pid, SIGKILL);
2231 else
2232 kill(poller_pid, SIGUSR1);
2233 }
2234#endif /* !HAVE_POLLABLE_PROCFS */
2235 }
2236 if (interrupted)
2237 return 0;
2238
2239 if (interactive)
2240 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2241
2242 if (ioctl_result < 0) {
2243 /* Find out what happened if it failed. */
2244 switch (ioctl_errno) {
2245 case EINTR:
2246 case EBADF:
2247 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002248#ifdef FREEBSD
2249 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002250#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002251 case ENOENT:
2252 droptcb(tcp);
2253 continue;
2254 default:
2255 perror("PIOCWSTOP");
2256 exit(1);
2257 }
2258 }
2259
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002260#ifdef FREEBSD
2261 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2262 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002263 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002264 continue;
2265 }
Roland McGrath553a6092002-12-16 20:40:39 +00002266#endif
2267
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002268 /* clear the just started flag */
2269 tcp->flags &= ~TCB_STARTUP;
2270
2271 /* set current output file */
2272 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002273 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002274
2275 if (cflag) {
2276 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002277#ifdef FREEBSD
2278 char buf[1024];
2279 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002280
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002281 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2282 buf[len] = '\0';
2283 sscanf(buf,
2284 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2285 &stime.tv_sec, &stime.tv_usec);
2286 } else
2287 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002288#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002289 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2290 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002291#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002292 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2293 tcp->stime = stime;
2294 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002295 what = tcp->status.PR_WHAT;
2296 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002297#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002298 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002299 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2300 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002301 if (trace_syscall(tcp) < 0) {
2302 fprintf(stderr, "syscall trouble\n");
2303 exit(1);
2304 }
2305 }
2306 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002307#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002309#ifdef POLL_HACK
2310 in_syscall = tcp;
2311#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312 case PR_SYSEXIT:
2313 if (trace_syscall(tcp) < 0) {
2314 fprintf(stderr, "syscall trouble\n");
2315 exit(1);
2316 }
2317 break;
2318 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002319 if (cflag != CFLAG_ONLY_STATS
2320 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002321 printleader(tcp);
2322 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002323 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002324 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002325#ifdef PR_INFO
2326 if (tcp->status.PR_INFO.si_signo == what) {
2327 printleader(tcp);
2328 tprintf(" siginfo=");
2329 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002330 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002331 }
2332#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002333 }
2334 break;
2335 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002336 if (cflag != CFLAGS_ONLY_STATS
2337 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002338 printleader(tcp);
2339 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002340 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341 }
2342 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002343#ifdef FREEBSD
2344 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002345 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002346#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002348 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002349 exit(1);
2350 break;
2351 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002352 /* Remember current print column before continuing. */
2353 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002354 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002355#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002356 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002357#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002358 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002359#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002360 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002361 perror("PIOCRUN");
2362 exit(1);
2363 }
2364 }
2365 return 0;
2366}
2367
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002368#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002369
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002370#ifdef TCB_GROUP_EXITING
2371/* Handle an exit detach or death signal that is taking all the
2372 related clone threads with it. This is called in three circumstances:
2373 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2374 SIG == 0 Continuing TCP will perform an exit_group syscall.
2375 SIG == other Continuing TCP with SIG will kill the process.
2376*/
2377static int
2378handle_group_exit(struct tcb *tcp, int sig)
2379{
2380 /* We need to locate our records of all the clone threads
2381 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002382 struct tcb *leader = NULL;
2383
2384 if (tcp->flags & TCB_CLONE_THREAD)
2385 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002386
2387 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002388 if (leader != NULL && leader != tcp
2389 && !(leader->flags & TCB_GROUP_EXITING)
2390 && !(tcp->flags & TCB_STARTUP)
2391 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002392 fprintf(stderr,
2393 "PANIC: handle_group_exit: %d leader %d\n",
2394 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002395 }
2396 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002397 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002398 }
2399 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002400 /* Mark that we are taking the process down. */
2401 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002402 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002403 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002404 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002405 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002406 } else {
2407 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2408 cleanup();
2409 return -1;
2410 }
2411 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002412 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002413 if (leader != tcp)
2414 droptcb(tcp);
2415 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002416 /* The leader will report to us as parent now,
2417 and then we'll get to the SIG==-1 case. */
2418 return 0;
2419 }
2420 }
2421
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002422 return 0;
2423}
2424#endif
2425
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002426#ifdef LINUX
2427static int
2428handle_ptrace_event(int status, struct tcb *tcp)
2429{
2430 if (status >> 16 == PTRACE_EVENT_VFORK ||
2431 status >> 16 == PTRACE_EVENT_CLONE ||
2432 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002433 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002434
2435 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2436 if (errno != ESRCH) {
2437 fprintf(stderr, "\
2438%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2439 progname);
2440 cleanup();
2441 exit(1);
2442 }
2443 return -1;
2444 }
2445 return handle_new_child(tcp, childpid, 0);
2446 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002447 if (status >> 16 == PTRACE_EVENT_EXEC) {
2448 if (debug)
2449 fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
2450 return 0;
2451 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002452 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2453 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002454 return 1;
2455}
2456#endif
2457
Roland McGratheb9e2e82009-06-02 16:49:22 -07002458static int
2459trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002460{
2461 int pid;
2462 int wait_errno;
2463 int status;
2464 struct tcb *tcp;
2465#ifdef LINUX
2466 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002467#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002468 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002469#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002470#endif /* LINUX */
2471
Roland McGratheb9e2e82009-06-02 16:49:22 -07002472 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002473 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002474 return 0;
2475 if (interactive)
2476 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002477#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002478#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002479 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002480 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002481 /* this kernel does not support __WALL */
2482 wait4_options &= ~__WALL;
2483 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002484 pid = wait4(-1, &status, wait4_options,
2485 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002486 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002487 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002488 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002489 pid = wait4(-1, &status, __WCLONE,
2490 cflag ? &ru : NULL);
2491 if (pid == -1) {
2492 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002493 "failed: %s\n", strerror(errno));
2494 }
2495 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002496#else
2497 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2498#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002499#endif /* LINUX */
2500#ifdef SUNOS4
2501 pid = wait(&status);
2502#endif /* SUNOS4 */
2503 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002504 if (interactive)
2505 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002506
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002507 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002508 switch (wait_errno) {
2509 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002510 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002511 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002512 /*
2513 * We would like to verify this case
2514 * but sometimes a race in Solbourne's
2515 * version of SunOS sometimes reports
2516 * ECHILD before sending us SIGCHILD.
2517 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002518 return 0;
2519 default:
2520 errno = wait_errno;
2521 perror("strace: wait");
2522 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002523 }
2524 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002525 if (pid == popen_pid) {
2526 if (WIFEXITED(status) || WIFSIGNALED(status))
2527 popen_pid = -1;
2528 continue;
2529 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002530 if (debug)
2531 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2532
2533 /* Look up `pid' in our table. */
2534 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002535#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002536 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002537 /* This is needed to go with the CLONE_PTRACE
2538 changes in process.c/util.c: we might see
2539 the child's initial trap before we see the
2540 parent return from the clone syscall.
2541 Leave the child suspended until the parent
2542 returns from its system call. Only then
2543 will we have the association of parent and
2544 child so that we know how to do clearbpt
2545 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002546 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002547 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002548 if (!qflag)
2549 fprintf(stderr, "\
2550Process %d attached (waiting for parent)\n",
2551 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002552 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002553 else
2554 /* This can happen if a clone call used
2555 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002556#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002557 {
2558 fprintf(stderr, "unknown pid: %u\n", pid);
2559 if (WIFSTOPPED(status))
2560 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2561 exit(1);
2562 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002563 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002564 /* set current output file */
2565 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002566 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002567 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002568#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002569 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2570 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002571#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002573
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002574 if (tcp->flags & TCB_SUSPENDED) {
2575 /*
2576 * Apparently, doing any ptrace() call on a stopped
2577 * process, provokes the kernel to report the process
2578 * status again on a subsequent wait(), even if the
2579 * process has not been actually restarted.
2580 * Since we have inspected the arguments of suspended
2581 * processes we end up here testing for this case.
2582 */
2583 continue;
2584 }
2585 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002586 if (pid == strace_child)
2587 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002588 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002589 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2590 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002591 tprintf("+++ killed by %s %s+++",
2592 signame(WTERMSIG(status)),
2593#ifdef WCOREDUMP
2594 WCOREDUMP(status) ? "(core dumped) " :
2595#endif
2596 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002597 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002598 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002599#ifdef TCB_GROUP_EXITING
2600 handle_group_exit(tcp, -1);
2601#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002602 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002603#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002604 continue;
2605 }
2606 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002607 if (pid == strace_child)
2608 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002609 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002610 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2611 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002612#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002613 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002614 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002615#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002616 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002617 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002618 "PANIC: attached pid %u exited with %d\n",
2619 pid, WEXITSTATUS(status));
2620 }
Roland McGrath0a396902003-06-10 03:05:53 +00002621 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002622 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002623 tprintf(" <unfinished ... exit status %d>\n",
2624 WEXITSTATUS(status));
2625 tcp_last = NULL;
2626 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002627#ifdef TCB_GROUP_EXITING
2628 handle_group_exit(tcp, -1);
2629#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002630 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002631#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002632 continue;
2633 }
2634 if (!WIFSTOPPED(status)) {
2635 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2636 droptcb(tcp);
2637 continue;
2638 }
2639 if (debug)
2640 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002641 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002642
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002643 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002644 if (handle_ptrace_event(status, tcp) != 1)
2645 goto tracing;
2646 }
2647
Roland McGrath02203312007-06-11 22:06:31 +00002648 /*
2649 * Interestingly, the process may stop
2650 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002651 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002652 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002653 * A no-MMU vforked child won't send up a signal,
2654 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002655 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002656 if ((tcp->flags & TCB_STARTUP) &&
2657 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002658 /*
2659 * This flag is there to keep us in sync.
2660 * Next time this process stops it should
2661 * really be entering a system call.
2662 */
2663 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002664 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002665 /*
2666 * One example is a breakpoint inherited from
2667 * parent through fork ().
2668 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002669 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2670 droptcb(tcp);
2671 cleanup();
2672 return -1;
2673 }
2674 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002675#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002676 /* If options were not set for this tracee yet */
2677 if (tcp->parent == NULL) {
2678 if (ptrace_setoptions) {
2679 if (debug)
2680 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2681 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2682 if (errno != ESRCH) {
2683 /* Should never happen, really */
2684 perror_msg_and_die("PTRACE_SETOPTIONS");
2685 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002686 }
2687 }
2688 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002689#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002690 goto tracing;
2691 }
2692
Denys Vlasenko75422762011-05-27 14:36:01 +02002693 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694 if (WSTOPSIG(status) == SIGSTOP &&
2695 (tcp->flags & TCB_SIGTRAPPED)) {
2696 /*
2697 * Trapped attempt to block SIGTRAP
2698 * Hope we are back in control now.
2699 */
2700 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002701 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002702 cleanup();
2703 return -1;
2704 }
2705 continue;
2706 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002707 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002708 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002709 siginfo_t si;
2710#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002711 long pc = 0;
2712 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002713
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002714 upeek(tcp, PT_CR_IPSR, &psr);
2715 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002716
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002717# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002718 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002719# define PC_FORMAT_STR " @ %lx"
2720# define PC_FORMAT_ARG pc
2721#else
2722# define PC_FORMAT_STR "%s"
2723# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002724#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002725 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002726 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2727 tprintf("--- ");
2728 printsiginfo(&si, verbose(tcp));
2729 tprintf(" (%s)" PC_FORMAT_STR " ---",
2730 strsignal(WSTOPSIG(status)),
2731 PC_FORMAT_ARG);
2732 } else
2733 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2734 strsignal(WSTOPSIG(status)),
2735 signame(WSTOPSIG(status)),
2736 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002737 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002738 }
Roland McGrath05690952004-10-20 01:00:27 +00002739 if (((tcp->flags & TCB_ATTACHED) ||
2740 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002741 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002742#ifdef TCB_GROUP_EXITING
2743 handle_group_exit(tcp, WSTOPSIG(status));
2744#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002745 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002746#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002747 continue;
2748 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002749 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002750 cleanup();
2751 return -1;
2752 }
2753 tcp->flags &= ~TCB_SUSPENDED;
2754 continue;
2755 }
Roland McGrath02203312007-06-11 22:06:31 +00002756 /* we handled the STATUS, we are permitted to interrupt now. */
2757 if (interrupted)
2758 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002759 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2760 /* ptrace() failed in trace_syscall() with ESRCH.
2761 * Likely a result of process disappearing mid-flight.
2762 * Observed case: exit_group() terminating
2763 * all processes in thread group. In this case, threads
2764 * "disappear" in an unpredictable moment without any
2765 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002766 */
2767 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002768 if (tcp_last) {
2769 /* Do we have dangling line "syscall(param, param"?
2770 * Finish the line then. We cannot
2771 */
2772 tcp_last->flags |= TCB_REPRINT;
2773 tprintf(" <unfinished ...>");
2774 printtrailer();
2775 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002776 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002777 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002778 ptrace(PTRACE_KILL,
2779 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002780 droptcb(tcp);
2781 }
2782 continue;
2783 }
2784 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002785#ifdef TCB_GROUP_EXITING
2786 if (tcp->flags & TCB_GROUP_EXITING) {
2787 if (handle_group_exit(tcp, 0) < 0)
2788 return -1;
2789 continue;
2790 }
2791#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002792 if (tcp->flags & TCB_ATTACHED)
2793 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002794 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002795 cleanup();
2796 return -1;
2797 }
2798 continue;
2799 }
2800 if (tcp->flags & TCB_SUSPENDED) {
2801 if (!qflag)
2802 fprintf(stderr, "Process %u suspended\n", pid);
2803 continue;
2804 }
2805 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002806 /* Remember current print column before continuing. */
2807 tcp->curcol = curcol;
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 }
2813 return 0;
2814}
2815
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002816#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002817
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002818#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002819
2820void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002821tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002822{
2823 va_list args;
2824
Andreas Schwabe5355de2009-10-27 16:56:43 +01002825 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002826 if (outf) {
2827 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002828 if (n < 0) {
2829 if (outf != stderr)
2830 perror(outfname == NULL
2831 ? "<writing to pipe>" : outfname);
2832 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002833 curcol += n;
2834 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002835 va_end(args);
2836 return;
2837}
2838
2839void
Denys Vlasenko12014262011-05-30 14:00:14 +02002840printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002841{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002842 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002843 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002844 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002845 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002846 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002847 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002848 tprintf("= ? <unavailable>\n");
2849 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002850 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002851 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002852 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002853 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002854 }
2855 curcol = 0;
2856 if ((followfork == 1 || pflag_seen > 1) && outfname)
2857 tprintf("%-5d ", tcp->pid);
2858 else if (nprocs > 1 && !outfname)
2859 tprintf("[pid %5u] ", tcp->pid);
2860 if (tflag) {
2861 char str[sizeof("HH:MM:SS")];
2862 struct timeval tv, dtv;
2863 static struct timeval otv;
2864
2865 gettimeofday(&tv, NULL);
2866 if (rflag) {
2867 if (otv.tv_sec == 0)
2868 otv = tv;
2869 tv_sub(&dtv, &tv, &otv);
2870 tprintf("%6ld.%06ld ",
2871 (long) dtv.tv_sec, (long) dtv.tv_usec);
2872 otv = tv;
2873 }
2874 else if (tflag > 2) {
2875 tprintf("%ld.%06ld ",
2876 (long) tv.tv_sec, (long) tv.tv_usec);
2877 }
2878 else {
2879 time_t local = tv.tv_sec;
2880 strftime(str, sizeof(str), "%T", localtime(&local));
2881 if (tflag > 1)
2882 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2883 else
2884 tprintf("%s ", str);
2885 }
2886 }
2887 if (iflag)
2888 printcall(tcp);
2889}
2890
2891void
Denys Vlasenko12014262011-05-30 14:00:14 +02002892tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002893{
2894 if (curcol < col)
2895 tprintf("%*s", col - curcol, "");
2896}
2897
2898void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002899printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002900{
2901 tprintf("\n");
2902 tcp_last = NULL;
2903}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002904
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002905#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002906
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002907int
2908mp_ioctl(int fd, int cmd, void *arg, int size)
2909{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002910 struct iovec iov[2];
2911 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002912
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002913 iov[0].iov_base = &cmd;
2914 iov[0].iov_len = sizeof cmd;
2915 if (arg) {
2916 ++n;
2917 iov[1].iov_base = arg;
2918 iov[1].iov_len = size;
2919 }
Roland McGrath553a6092002-12-16 20:40:39 +00002920
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002921 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002922}
2923
2924#endif