blob: 4129a8a00f23deae421e9ebf01e1b482768659a1 [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>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010048#include <sys/utsname.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020051# if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000053# else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020058# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000059# endif
Roland McGrath134813a2007-06-02 00:07:33 +000060
Denys Vlasenko84703742012-02-25 02:38:52 +010061#if defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000062# include <asm/ptrace_offsets.h>
63#endif
64
Denys Vlasenko96d5a762008-12-29 19:13:27 +000065extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000066extern int optind;
67extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000068
Roland McGrath41c48222008-07-18 00:25:10 +000069int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020070unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020071/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020072static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000073int dtime = 0, xflag = 0, qflag = 0;
74cflag_t cflag = CFLAG_NONE;
Denys Vlasenkofd883382012-03-09 13:03:41 +010075static int iflag = 0, rflag = 0, tflag = 0;
76static int print_pid_pfx = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010077
78/* -I n */
79enum {
80 INTR_NOT_SET = 0,
81 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
82 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
83 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
84 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
85 NUM_INTR_OPTS
86};
87static int opt_intr;
88/* We play with signal mask only if this mode is active: */
89#define interactive (opt_intr == INTR_WHILE_WAIT)
90
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100105#ifdef USE_SEIZE
106static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
107# define use_seize (post_attach_sigstop == 0)
108#else
109# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
110# define use_seize 0
111#endif
112
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000113/* Sometimes we want to print only succeeding syscalls. */
114int not_failing_only = 0;
115
Grant Edwards8a082772011-04-07 20:25:40 +0000116/* Show path associated with fd arguments */
117int show_fd_path = 0;
118
119/* are we filtering traces based on paths? */
120int tracing_paths = 0;
121
Dmitry V. Levina6809652008-11-10 17:14:58 +0000122static int exit_code = 0;
123static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200124static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700125
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static uid_t run_uid;
128static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200131static int acolumn = DEFAULT_ACOLUMN;
132static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000133static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200134static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100135struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100136static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200137static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200138static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200139static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100141static char *os_release; /* from uname() */
142
Denys Vlasenko4c196382012-01-04 15:11:09 +0100143static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100144static int trace(void);
145static void cleanup(void);
146static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147static sigset_t empty_set, blocked_set;
148
149#ifdef HAVE_SIG_ATOMIC_T
150static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100151#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100153#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200156usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157{
158 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100159usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
160 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100161 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100162 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100163 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200165-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100166-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100168-F -- attempt to follow vforks\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100170-I interruptible\n\
171 1: no signals are blocked\n\
172 2: fatal signals are blocked while decoding syscall (default)\n\
173 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
174 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
175 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176-q -- suppress messages about attaching, detaching, etc.\n\
177-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100178-T -- print time spent in each syscall\n\
179-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000181-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100182-h -- print help message\n\
183-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-a column -- alignment COLUMN for printing syscall results (default %d)\n\
185-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
186 options: trace, abbrev, verbose, raw, signal, read, or write\n\
187-o file -- send trace output to FILE instead of stderr\n\
188-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
189-p pid -- trace process with process id PID, may be repeated\n\
190-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
191-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
192-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000193-E var=val -- put var=val in the environment for command\n\
194-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000195-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000196" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000197-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000198 */
199, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 exit(exitval);
201}
202
Denys Vlasenko75422762011-05-27 14:36:01 +0200203static void die(void) __attribute__ ((noreturn));
204static void die(void)
205{
206 if (strace_tracer_pid == getpid()) {
207 cflag = 0;
208 cleanup();
209 }
210 exit(1);
211}
212
213static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200214{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100215 char *msg;
216
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000217 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100218
219 /* We want to print entire message with single fprintf to ensure
220 * message integrity if stderr is shared with other programs.
221 * Thus we use vasprintf + single fprintf.
222 */
223 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100224 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100225 if (err_no)
226 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
227 else
228 fprintf(stderr, "%s: %s\n", progname, msg);
229 free(msg);
230 } else {
231 /* malloc in vasprintf failed, try it without malloc */
232 fprintf(stderr, "%s: ", progname);
233 vfprintf(stderr, fmt, p);
234 if (err_no)
235 fprintf(stderr, ": %s\n", strerror(err_no));
236 else
237 putc('\n', stderr);
238 }
239 /* We don't switch stderr to buffered, thus fprintf(stderr)
240 * always flushes its output and this is not necessary: */
241 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200242}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200243
Denys Vlasenko75422762011-05-27 14:36:01 +0200244void error_msg(const char *fmt, ...)
245{
246 va_list p;
247 va_start(p, fmt);
248 verror_msg(0, fmt, p);
249 va_end(p);
250}
251
252void error_msg_and_die(const char *fmt, ...)
253{
254 va_list p;
255 va_start(p, fmt);
256 verror_msg(0, fmt, p);
257 die();
258}
259
260void perror_msg(const char *fmt, ...)
261{
262 va_list p;
263 va_start(p, fmt);
264 verror_msg(errno, fmt, p);
265 va_end(p);
266}
267
268void perror_msg_and_die(const char *fmt, ...)
269{
270 va_list p;
271 va_start(p, fmt);
272 verror_msg(errno, fmt, p);
273 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200274}
275
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200276void die_out_of_memory(void)
277{
278 static bool recursed = 0;
279 if (recursed)
280 exit(1);
281 recursed = 1;
282 error_msg_and_die("Out of memory");
283}
284
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400285/* Glue for systems without a MMU that cannot provide fork() */
286#ifdef HAVE_FORK
287# define strace_vforked 0
288#else
289# define strace_vforked 1
290# define fork() vfork()
291#endif
292
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100293#ifdef USE_SEIZE
294static int
295ptrace_attach_or_seize(int pid)
296{
297 int r;
298 if (!use_seize)
299 return ptrace(PTRACE_ATTACH, pid, 0, 0);
300 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
301 if (r)
302 return r;
303 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
304 return r;
305}
306#else
307# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
308#endif
309
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200310static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000311set_cloexec_flag(int fd)
312{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200313 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000314
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200315 flags = fcntl(fd, F_GETFD);
316 if (flags < 0) {
317 /* Can happen only if fd is bad.
318 * Should never happen: if it does, we have a bug
319 * in the caller. Therefore we just abort
320 * instead of propagating the error.
321 */
322 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000323 }
324
325 newflags = flags | FD_CLOEXEC;
326 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200327 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000328
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200329 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330}
331
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100332static void kill_save_errno(pid_t pid, int sig)
333{
334 int saved_errno = errno;
335
336 (void) kill(pid, sig);
337 errno = saved_errno;
338}
339
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100340void
341tprintf(const char *fmt, ...)
342{
343 va_list args;
344
345 va_start(args, fmt);
346 if (outf) {
347 int n = vfprintf(outf, fmt, args);
348 if (n < 0) {
349 if (outf != stderr)
350 perror(outfname == NULL
351 ? "<writing to pipe>" : outfname);
352 } else
353 curcol += n;
354 }
355 va_end(args);
356}
357
358void
359tprints(const char *str)
360{
361 if (outf) {
362 int n = fputs(str, outf);
363 if (n >= 0) {
364 curcol += strlen(str);
365 return;
366 }
367 if (outf != stderr)
368 perror(outfname == NULL
369 ? "<writing to pipe>" : outfname);
370 }
371}
372
373void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100374line_ended(void)
375{
376 curcol = 0;
377 fflush(outf);
378 if (!printing_tcp)
379 return;
380 printing_tcp->curcol = 0;
381 printing_tcp = NULL;
382}
383
384void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100385printleader(struct tcb *tcp)
386{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100387 /* If -ff, "previous tcb we printed" is always the same as current,
388 * because we have per-tcb output files.
389 */
390 if (followfork >= 2)
391 printing_tcp = tcp;
392
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100393 if (printing_tcp) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100394 outf = printing_tcp->outf;
395 curcol = printing_tcp->curcol;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100396 if (printing_tcp->ptrace_errno) {
397 if (printing_tcp->flags & TCB_INSYSCALL) {
398 tprints(" <unavailable>) ");
399 tabto();
400 }
401 tprints("= ? <unavailable>\n");
402 printing_tcp->ptrace_errno = 0;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100403 printing_tcp->curcol = 0;
404 }
405 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
406 /*
407 * case 1: we have a shared log (i.e. not -ff), and last line
408 * wasn't finished (same or different tcb, doesn't matter).
409 * case 2: split log, we are the same tcb, but our last line
410 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
411 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100412 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100413 printing_tcp->flags |= TCB_REPRINT;
414 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100415 }
416 }
417
418 printing_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100419 outf = tcp->outf;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100420 curcol = 0;
421
422 if (print_pid_pfx)
423 tprintf("%-5d ", tcp->pid);
424 else if (nprocs > 1 && !outfname)
425 tprintf("[pid %5u] ", tcp->pid);
426
427 if (tflag) {
428 char str[sizeof("HH:MM:SS")];
429 struct timeval tv, dtv;
430 static struct timeval otv;
431
432 gettimeofday(&tv, NULL);
433 if (rflag) {
434 if (otv.tv_sec == 0)
435 otv = tv;
436 tv_sub(&dtv, &tv, &otv);
437 tprintf("%6ld.%06ld ",
438 (long) dtv.tv_sec, (long) dtv.tv_usec);
439 otv = tv;
440 }
441 else if (tflag > 2) {
442 tprintf("%ld.%06ld ",
443 (long) tv.tv_sec, (long) tv.tv_usec);
444 }
445 else {
446 time_t local = tv.tv_sec;
447 strftime(str, sizeof(str), "%T", localtime(&local));
448 if (tflag > 1)
449 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
450 else
451 tprintf("%s ", str);
452 }
453 }
454 if (iflag)
455 printcall(tcp);
456}
457
458void
459tabto(void)
460{
461 if (curcol < acolumn)
462 tprints(acolumn_spaces + curcol);
463}
464
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000465/*
466 * When strace is setuid executable, we have to swap uids
467 * before and after filesystem and process management operations.
468 */
469static void
470swap_uid(void)
471{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000472 int euid = geteuid(), uid = getuid();
473
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200474 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200475 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000476 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000477}
478
Roland McGrath4bfa6262007-07-05 20:03:16 +0000479#if _LFS64_LARGEFILE
480# define fopen_for_output fopen64
481#else
482# define fopen_for_output fopen
483#endif
484
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000485static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200486strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000487{
488 FILE *fp;
489
490 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200491 fp = fopen_for_output(path, "w");
492 if (!fp)
493 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000494 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200495 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000496 return fp;
497}
498
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200499static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000500
501#ifndef _PATH_BSHELL
502# define _PATH_BSHELL "/bin/sh"
503#endif
504
505/*
506 * We cannot use standard popen(3) here because we have to distinguish
507 * popen child process from other processes we trace, and standard popen(3)
508 * does not export its child's pid.
509 */
510static FILE *
511strace_popen(const char *command)
512{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200513 FILE *fp;
514 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000515
516 swap_uid();
517 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200518 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000519
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200520 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000521
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200522 popen_pid = vfork();
523 if (popen_pid == -1)
524 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000525
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200526 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000527 /* child */
528 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200529 if (fds[0] != 0) {
530 if (dup2(fds[0], 0))
531 perror_msg_and_die("dup2");
532 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000533 }
534 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200535 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000536 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200537
538 /* parent */
539 close(fds[0]);
540 swap_uid();
541 fp = fdopen(fds[1], "w");
542 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200543 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200544 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000545}
546
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200547static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000548newoutf(struct tcb *tcp)
549{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100550 if (outfname && followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000551 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000552 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200553 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000554 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000555}
556
Denys Vlasenko558e5122012-03-12 23:32:16 +0100557static void
558process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100559{
560 while (*opt) {
561 /*
562 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
563 * pidof uses space as delim, pgrep uses newline. :(
564 */
565 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100566 char *delim = opt + strcspn(opt, ", \n\t");
567 char c = *delim;
568
569 *delim = '\0';
570 pid = atoi(opt); /* TODO: stricter parsing of the number? */
571 if (pid <= 0) {
572 error_msg("Invalid process id: '%s'", opt);
573 *delim = c;
574 return;
575 }
576 if (pid == strace_tracer_pid) {
577 error_msg("I'm sorry, I can't let you do that, Dave.");
578 *delim = c;
579 return;
580 }
581 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100582 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100583 if (c == '\0')
584 break;
585 opt = delim + 1;
586 }
587}
588
Roland McGrath02203312007-06-11 22:06:31 +0000589static void
590startup_attach(void)
591{
592 int tcbi;
593 struct tcb *tcp;
594
595 /*
596 * Block user interruptions as we would leave the traced
597 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200598 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200599 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000600 */
601 if (interactive)
602 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
603
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000604 if (daemonized_tracer) {
605 pid_t pid = fork();
606 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200607 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000608 }
609 if (pid) { /* parent */
610 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200611 * Wait for grandchild to attach to straced process
612 * (grandparent). Grandchild SIGKILLs us after it attached.
613 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000614 * it proceeds to exec the straced program.
615 */
616 pause();
617 _exit(0); /* paranoia */
618 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200619 /* grandchild */
620 /* We will be the tracer process. Remember our new pid: */
621 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000622 }
623
Roland McGrath02203312007-06-11 22:06:31 +0000624 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
625 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200626
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100627 if (!(tcp->flags & TCB_INUSE))
628 continue;
629
Denys Vlasenkod116a732011-09-05 14:01:33 +0200630 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100631 if (tcp->flags & TCB_ATTACHED)
632 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200633
634 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000635 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200636 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000637
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000638 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000639 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000640 DIR *dir;
641
642 sprintf(procdir, "/proc/%d/task", tcp->pid);
643 dir = opendir(procdir);
644 if (dir != NULL) {
645 unsigned int ntid = 0, nerr = 0;
646 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200647
Roland McGrath02203312007-06-11 22:06:31 +0000648 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200649 struct tcb *cur_tcp;
650 int tid;
651
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000652 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000653 continue;
654 tid = atoi(de->d_name);
655 if (tid <= 0)
656 continue;
657 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100658 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000659 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200660 if (debug)
661 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200662 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200663 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200664 if (debug)
665 fprintf(stderr, "attach to pid %d succeeded\n", tid);
666 cur_tcp = tcp;
667 if (tid != tcp->pid)
668 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100669 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000670 }
671 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200672 if (interactive) {
673 sigprocmask(SIG_SETMASK, &empty_set, NULL);
674 if (interrupted)
675 goto ret;
676 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
677 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000678 ntid -= nerr;
679 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000680 perror("attach: ptrace(PTRACE_ATTACH, ...)");
681 droptcb(tcp);
682 continue;
683 }
684 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000685 fprintf(stderr, ntid > 1
686? "Process %u attached with %u threads - interrupt to quit\n"
687: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200688 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000689 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100690 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200691 /* -p PID, we failed to attach to PID itself
692 * but did attach to some of its sibling threads.
693 * Drop PID's tcp.
694 */
695 droptcb(tcp);
696 }
Roland McGrath02203312007-06-11 22:06:31 +0000697 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000698 } /* if (opendir worked) */
699 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100700 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000701 perror("attach: ptrace(PTRACE_ATTACH, ...)");
702 droptcb(tcp);
703 continue;
704 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100705 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200706 if (debug)
707 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708
709 if (daemonized_tracer) {
710 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000711 * Make parent go away.
712 * Also makes grandparent's wait() unblock.
713 */
714 kill(getppid(), SIGKILL);
715 }
716
Roland McGrath02203312007-06-11 22:06:31 +0000717 if (!qflag)
718 fprintf(stderr,
719 "Process %u attached - interrupt to quit\n",
720 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200721 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000722
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200723 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000724 if (interactive)
725 sigprocmask(SIG_SETMASK, &empty_set, NULL);
726}
727
728static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200729startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000730{
731 struct stat statbuf;
732 const char *filename;
733 char pathname[MAXPATHLEN];
734 int pid = 0;
735 struct tcb *tcp;
736
737 filename = argv[0];
738 if (strchr(filename, '/')) {
739 if (strlen(filename) > sizeof pathname - 1) {
740 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200741 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000742 }
743 strcpy(pathname, filename);
744 }
745#ifdef USE_DEBUGGING_EXEC
746 /*
747 * Debuggers customarily check the current directory
748 * first regardless of the path but doing that gives
749 * security geeks a panic attack.
750 */
751 else if (stat(filename, &statbuf) == 0)
752 strcpy(pathname, filename);
753#endif /* USE_DEBUGGING_EXEC */
754 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000755 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000756 int m, n, len;
757
758 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100759 const char *colon = strchr(path, ':');
760 if (colon) {
761 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000762 m = n + 1;
763 }
764 else
765 m = n = strlen(path);
766 if (n == 0) {
767 if (!getcwd(pathname, MAXPATHLEN))
768 continue;
769 len = strlen(pathname);
770 }
771 else if (n > sizeof pathname - 1)
772 continue;
773 else {
774 strncpy(pathname, path, n);
775 len = n;
776 }
777 if (len && pathname[len - 1] != '/')
778 pathname[len++] = '/';
779 strcpy(pathname + len, filename);
780 if (stat(pathname, &statbuf) == 0 &&
781 /* Accept only regular files
782 with some execute bits set.
783 XXX not perfect, might still fail */
784 S_ISREG(statbuf.st_mode) &&
785 (statbuf.st_mode & 0111))
786 break;
787 }
788 }
789 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200790 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000791 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000792 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000793 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200794 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000795 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200796 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
797 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000798 ) {
799 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200800 if (outf != stderr)
801 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100802 if (!daemonized_tracer && !use_seize) {
803 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200804 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000805 }
Roland McGrath02203312007-06-11 22:06:31 +0000806 }
Roland McGrath02203312007-06-11 22:06:31 +0000807
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200808 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000809 uid_t run_euid = run_uid;
810 gid_t run_egid = run_gid;
811
812 if (statbuf.st_mode & S_ISUID)
813 run_euid = statbuf.st_uid;
814 if (statbuf.st_mode & S_ISGID)
815 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000816 /*
817 * It is important to set groups before we
818 * lose privileges on setuid.
819 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200820 if (initgroups(username, run_gid) < 0) {
821 perror_msg_and_die("initgroups");
822 }
823 if (setregid(run_gid, run_egid) < 0) {
824 perror_msg_and_die("setregid");
825 }
826 if (setreuid(run_uid, run_euid) < 0) {
827 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000828 }
829 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200830 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000831 setreuid(run_uid, run_uid);
832
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000833 if (!daemonized_tracer) {
834 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200835 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000836 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200837 * the immediately following execve syscall.
838 * Can't do this on NOMMU systems, we are after
839 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000840 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400841 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200842 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000843 } else {
844 struct sigaction sv_sigchld;
845 sigaction(SIGCHLD, NULL, &sv_sigchld);
846 /*
847 * Make sure it is not SIG_IGN, otherwise wait
848 * will not block.
849 */
850 signal(SIGCHLD, SIG_DFL);
851 /*
852 * Wait for grandchild to attach to us.
853 * It kills child after that, and wait() unblocks.
854 */
855 alarm(3);
856 wait(NULL);
857 alarm(0);
858 sigaction(SIGCHLD, &sv_sigchld, NULL);
859 }
Roland McGrath02203312007-06-11 22:06:31 +0000860
861 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200862 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000863 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000864
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200865 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200866
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200867 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100868 if (!use_seize) {
869 /* child did PTRACE_TRACEME, nothing to do in parent */
870 } else {
871 if (!strace_vforked) {
872 /* Wait until child stopped itself */
873 int status;
874 while (waitpid(pid, &status, WSTOPPED) < 0) {
875 if (errno == EINTR)
876 continue;
877 perror_msg_and_die("waitpid");
878 }
879 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100880 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100881 perror_msg_and_die("Unexpected wait status %x", status);
882 }
883 }
884 /* Else: vforked case, we have no way to sync.
885 * Just attach to it as soon as possible.
886 * This means that we may miss a few first syscalls...
887 */
888
889 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100890 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100891 perror_msg_and_die("Can't attach to %d", pid);
892 }
893 if (!strace_vforked)
894 kill(pid, SIGCONT);
895 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200896 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200897 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100898 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200899 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100900 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200901 }
902 else {
903 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
904 strace_tracer_pid = getpid();
905 /* The tracee is our parent: */
906 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100907 alloctcb(pid);
908 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000909 }
Roland McGrath02203312007-06-11 22:06:31 +0000910}
911
Wang Chaob13c0de2010-11-12 17:25:19 +0800912/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000913 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800914 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000915 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800916 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000917static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200918test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800919{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000920 int pid, expected_grandchild = 0, found_grandchild = 0;
921 const unsigned int test_options = PTRACE_O_TRACECLONE |
922 PTRACE_O_TRACEFORK |
923 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800924
Denys Vlasenko5d645812011-08-20 12:48:18 +0200925 pid = fork();
926 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000927 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200928 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000929 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100930 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000931 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
932 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100933 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000934 if (fork() < 0)
935 perror_msg_and_die("fork");
936 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800937 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000938
939 while (1) {
940 int status, tracee_pid;
941
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000942 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000943 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000944 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000945 if (errno == EINTR)
946 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100947 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000948 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000949 kill_save_errno(pid, SIGKILL);
950 perror_msg_and_die("%s: unexpected wait result %d",
951 __func__, tracee_pid);
952 }
953 if (WIFEXITED(status)) {
954 if (WEXITSTATUS(status)) {
955 if (tracee_pid != pid)
956 kill_save_errno(pid, SIGKILL);
957 error_msg_and_die("%s: unexpected exit status %u",
958 __func__, WEXITSTATUS(status));
959 }
960 continue;
961 }
962 if (WIFSIGNALED(status)) {
963 if (tracee_pid != pid)
964 kill_save_errno(pid, SIGKILL);
965 error_msg_and_die("%s: unexpected signal %u",
966 __func__, WTERMSIG(status));
967 }
968 if (!WIFSTOPPED(status)) {
969 if (tracee_pid != pid)
970 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100971 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000972 error_msg_and_die("%s: unexpected wait status %x",
973 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000974 }
975 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000976 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000977 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
978 kill_save_errno(tracee_pid, SIGKILL);
979 kill_save_errno(pid, SIGKILL);
980 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800981 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000982 continue;
983 }
984 switch (WSTOPSIG(status)) {
985 case SIGSTOP:
986 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
987 && errno != EINVAL && errno != EIO)
988 perror_msg("PTRACE_SETOPTIONS");
989 break;
990 case SIGTRAP:
991 if (status >> 16 == PTRACE_EVENT_FORK) {
992 long msg = 0;
993
994 if (ptrace(PTRACE_GETEVENTMSG, pid,
995 NULL, (long) &msg) == 0)
996 expected_grandchild = msg;
997 }
998 break;
999 }
1000 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1001 kill_save_errno(pid, SIGKILL);
1002 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001003 }
1004 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001005 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001006 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001007 if (debug)
1008 fprintf(stderr, "ptrace_setoptions = %#x\n",
1009 ptrace_setoptions);
1010 return;
1011 }
1012 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1013 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001014}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001015
1016/*
1017 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1018 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1019 * and then see whether it will stop with (SIGTRAP | 0x80).
1020 *
1021 * Use of this option enables correct handling of user-generated SIGTRAPs,
1022 * and SIGTRAPs generated by special instructions such as int3 on x86:
1023 * _start: .globl _start
1024 * int3
1025 * movl $42, %ebx
1026 * movl $1, %eax
1027 * int $0x80
1028 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1029 */
1030static void
1031test_ptrace_setoptions_for_all(void)
1032{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001033 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1034 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001035 int pid;
1036 int it_worked = 0;
1037
1038 pid = fork();
1039 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001040 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001041
1042 if (pid == 0) {
1043 pid = getpid();
1044 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001045 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001046 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1047 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001048 kill(pid, SIGSTOP);
1049 _exit(0); /* parent should see entry into this syscall */
1050 }
1051
1052 while (1) {
1053 int status, tracee_pid;
1054
1055 errno = 0;
1056 tracee_pid = wait(&status);
1057 if (tracee_pid <= 0) {
1058 if (errno == EINTR)
1059 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001060 kill_save_errno(pid, SIGKILL);
1061 perror_msg_and_die("%s: unexpected wait result %d",
1062 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001063 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001064 if (WIFEXITED(status)) {
1065 if (WEXITSTATUS(status) == 0)
1066 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001067 error_msg_and_die("%s: unexpected exit status %u",
1068 __func__, WEXITSTATUS(status));
1069 }
1070 if (WIFSIGNALED(status)) {
1071 error_msg_and_die("%s: unexpected signal %u",
1072 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001073 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001074 if (!WIFSTOPPED(status)) {
1075 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001076 error_msg_and_die("%s: unexpected wait status %x",
1077 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001078 }
1079 if (WSTOPSIG(status) == SIGSTOP) {
1080 /*
1081 * We don't check "options aren't accepted" error.
1082 * If it happens, we'll never get (SIGTRAP | 0x80),
1083 * and thus will decide to not use the option.
1084 * IOW: the outcome of the test will be correct.
1085 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001086 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1087 && errno != EINVAL && errno != EIO)
1088 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001089 }
1090 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1091 it_worked = 1;
1092 }
1093 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001094 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001095 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001096 }
1097 }
1098
1099 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001100 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001101 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001102 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001103 fprintf(stderr, "ptrace_setoptions = %#x\n",
1104 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001105 return;
1106 }
1107
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001108 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1109 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001110}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001111
1112# ifdef USE_SEIZE
1113static void
1114test_ptrace_seize(void)
1115{
1116 int pid;
1117
1118 pid = fork();
1119 if (pid < 0)
1120 perror_msg_and_die("fork");
1121
1122 if (pid == 0) {
1123 pause();
1124 _exit(0);
1125 }
1126
1127 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1128 * attaching tracee continues to run unless a trap condition occurs.
1129 * PTRACE_SEIZE doesn't affect signal or group stop state.
1130 */
1131 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1132 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1133 } else if (debug) {
1134 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1135 }
1136
1137 kill(pid, SIGKILL);
1138
1139 while (1) {
1140 int status, tracee_pid;
1141
1142 errno = 0;
1143 tracee_pid = waitpid(pid, &status, 0);
1144 if (tracee_pid <= 0) {
1145 if (errno == EINTR)
1146 continue;
1147 perror_msg_and_die("%s: unexpected wait result %d",
1148 __func__, tracee_pid);
1149 }
1150 if (WIFSIGNALED(status)) {
1151 return;
1152 }
1153 error_msg_and_die("%s: unexpected wait status %x",
1154 __func__, status);
1155 }
1156}
1157# else /* !USE_SEIZE */
1158# define test_ptrace_seize() ((void)0)
1159# endif
1160
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001161static void
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001162get_os_release(void)
1163{
1164 struct utsname u;
1165 if (uname(&u) < 0)
1166 perror_msg_and_die("uname");
1167 os_release = strdup(u.release);
1168 if (!os_release)
1169 die_out_of_memory();
1170}
1171
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001172/*
1173 * Initialization part of main() was eating much stack (~0.5k),
1174 * which was unused after init.
1175 * We can reuse it if we move init code into a separate function.
1176 *
1177 * Don't want main() to inline us and defeat the reason
1178 * we have a separate function.
1179 */
1180static void __attribute__ ((noinline))
1181init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001183 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001184 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001185 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186 struct sigaction sa;
1187
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001188 progname = argv[0] ? argv[0] : "strace";
1189
Denys Vlasenko75422762011-05-27 14:36:01 +02001190 strace_tracer_pid = getpid();
1191
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001192 get_os_release();
1193
Roland McGrathee9d4352002-12-18 04:16:10 +00001194 /* Allocate the initial tcbtab. */
1195 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001196 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001197 if (!tcbtab)
1198 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001199 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001200 if (!tcp)
1201 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001202 for (c = 0; c < tcbtabsize; c++)
1203 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001204
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001206 set_sortby(DEFAULT_SORTBY);
1207 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 qualify("trace=all");
1209 qualify("abbrev=all");
1210 qualify("verbose=all");
1211 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001213 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001214 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001215 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 switch (c) {
1217 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001218 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001219 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001220 }
1221 cflag = CFLAG_ONLY_STATS;
1222 break;
1223 case 'C':
1224 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001225 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001226 }
1227 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228 break;
1229 case 'd':
1230 debug++;
1231 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001232 case 'D':
1233 daemonized_tracer = 1;
1234 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001235 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001236 optF = 1;
1237 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238 case 'f':
1239 followfork++;
1240 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 case 'h':
1242 usage(stdout, 0);
1243 break;
1244 case 'i':
1245 iflag++;
1246 break;
1247 case 'q':
1248 qflag++;
1249 break;
1250 case 'r':
1251 rflag++;
1252 tflag++;
1253 break;
1254 case 't':
1255 tflag++;
1256 break;
1257 case 'T':
1258 dtime++;
1259 break;
1260 case 'x':
1261 xflag++;
1262 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001263 case 'y':
1264 show_fd_path = 1;
1265 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 case 'v':
1267 qualify("abbrev=none");
1268 break;
1269 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001270 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271 exit(0);
1272 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001273 case 'z':
1274 not_failing_only = 1;
1275 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 case 'a':
1277 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001278 if (acolumn < 0)
1279 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280 break;
1281 case 'e':
1282 qualify(optarg);
1283 break;
1284 case 'o':
1285 outfname = strdup(optarg);
1286 break;
1287 case 'O':
1288 set_overhead(atoi(optarg));
1289 break;
1290 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001291 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001293 case 'P':
1294 tracing_paths = 1;
1295 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001296 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001297 }
1298 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299 case 's':
1300 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001301 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001302 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001303 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 break;
1305 case 'S':
1306 set_sortby(optarg);
1307 break;
1308 case 'u':
1309 username = strdup(optarg);
1310 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001311 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001312 if (putenv(optarg) < 0)
1313 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001314 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001315 case 'I':
1316 opt_intr = atoi(optarg);
1317 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1318 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1319 }
1320 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001321 default:
1322 usage(stderr, 1);
1323 break;
1324 }
1325 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001326 argv += optind;
1327 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328
Denys Vlasenko102ec492011-08-25 01:27:59 +02001329 acolumn_spaces = malloc(acolumn + 1);
1330 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001331 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001332 memset(acolumn_spaces, ' ', acolumn);
1333 acolumn_spaces[acolumn] = '\0';
1334
Denys Vlasenko837399a2012-01-24 11:37:03 +01001335 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001336 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001337 usage(stderr, 1);
1338
Denys Vlasenkofd883382012-03-09 13:03:41 +01001339 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001340 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001341 }
1342
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001343 if (!followfork)
1344 followfork = optF;
1345
Roland McGrathcb9def62006-04-25 07:48:03 +00001346 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001347 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001348 }
1349
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350 /* See if they want to run as another user. */
1351 if (username != NULL) {
1352 struct passwd *pent;
1353
1354 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001355 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001357 pent = getpwnam(username);
1358 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001359 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 }
1361 run_uid = pent->pw_uid;
1362 run_gid = pent->pw_gid;
1363 }
1364 else {
1365 run_uid = getuid();
1366 run_gid = getgid();
1367 }
1368
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001369 if (followfork)
1370 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001371 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001372 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001373
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374 /* Check if they want to redirect the output. */
1375 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001376 /* See if they want to pipe the output. */
1377 if (outfname[0] == '|' || outfname[0] == '!') {
1378 /*
1379 * We can't do the <outfname>.PID funny business
1380 * when using popen, so prohibit it.
1381 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001382 if (followfork > 1)
1383 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1384 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001385 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001386 else if (followfork <= 1)
1387 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001388 } else {
1389 /* -ff without -o FILE is the same as single -f */
1390 if (followfork > 1)
1391 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392 }
1393
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001394 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001395 char *buf = malloc(BUFSIZ);
1396 if (!buf)
1397 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001399 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001400 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001401 if (!opt_intr)
1402 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001403 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001404 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001405 if (!opt_intr)
1406 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001407
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001408 /* argv[0] -pPID -oFILE Default interactive setting
1409 * yes 0 0 INTR_WHILE_WAIT
1410 * no 1 0 INTR_WHILE_WAIT
1411 * yes 0 1 INTR_NEVER
1412 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001413 */
1414
1415 /* STARTUP_CHILD must be called before the signal handlers get
1416 installed below as they are inherited into the spawned process.
1417 Also we do not need to be protected by them as during interruption
1418 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001419 if (argv[0])
1420 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 sigemptyset(&empty_set);
1423 sigemptyset(&blocked_set);
1424 sa.sa_handler = SIG_IGN;
1425 sigemptyset(&sa.sa_mask);
1426 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001427 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1428 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1429 if (opt_intr != INTR_ANYWHERE) {
1430 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1431 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1432 /*
1433 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1434 * fatal signals are blocked while syscall stop is processed,
1435 * and acted on in between, when waiting for new syscall stops.
1436 * In non-interactive mode, signals are ignored.
1437 */
1438 if (opt_intr == INTR_WHILE_WAIT) {
1439 sigaddset(&blocked_set, SIGHUP);
1440 sigaddset(&blocked_set, SIGINT);
1441 sigaddset(&blocked_set, SIGQUIT);
1442 sigaddset(&blocked_set, SIGPIPE);
1443 sigaddset(&blocked_set, SIGTERM);
1444 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001445 }
1446 /* SIG_IGN, or set handler for these */
1447 sigaction(SIGHUP, &sa, NULL);
1448 sigaction(SIGINT, &sa, NULL);
1449 sigaction(SIGQUIT, &sa, NULL);
1450 sigaction(SIGPIPE, &sa, NULL);
1451 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001452 }
Roland McGrath553a6092002-12-16 20:40:39 +00001453 /* Make sure SIGCHLD has the default action so that waitpid
1454 definitely works without losing track of children. The user
1455 should not have given us a bogus state to inherit, but he might
1456 have. Arguably we should detect SIG_IGN here and pass it on
1457 to children, but probably noone really needs that. */
1458 sa.sa_handler = SIG_DFL;
1459 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460
Denys Vlasenkofd883382012-03-09 13:03:41 +01001461 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001462 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001463
Denys Vlasenkofd883382012-03-09 13:03:41 +01001464 /* Do we want pids printed in our -o OUTFILE?
1465 * -ff: no (every pid has its own file); or
1466 * -f: yes (there can be more pids in the future); or
1467 * -p PID1,PID2: yes (there are already more than one pid)
1468 */
1469 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470}
1471
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001472static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001473expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001474{
1475 /* Allocate some more TCBs and expand the table.
1476 We don't want to relocate the TCBs because our
1477 callers have pointers and it would be a pain.
1478 So tcbtab is a table of pointers. Since we never
1479 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001480 int i = tcbtabsize;
1481 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1482 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001483 if (!newtab || !newtcbs)
1484 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001485 tcbtabsize *= 2;
1486 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001487 while (i < tcbtabsize)
1488 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001489}
1490
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001492alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493{
1494 int i;
1495 struct tcb *tcp;
1496
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001497 if (nprocs == tcbtabsize)
1498 expand_tcbtab();
1499
Roland McGrathee9d4352002-12-18 04:16:10 +00001500 for (i = 0; i < tcbtabsize; i++) {
1501 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001503 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001505 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001506 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001507#if SUPPORTED_PERSONALITIES > 1
1508 tcp->currpers = current_personality;
1509#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001511 if (debug)
1512 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001513 if (command_options_parsed)
1514 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 return tcp;
1516 }
1517 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001518 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519}
1520
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001521static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001522pid2tcb(int pid)
1523{
1524 int i;
1525
1526 if (pid <= 0)
1527 return NULL;
1528
1529 for (i = 0; i < tcbtabsize; i++) {
1530 struct tcb *tcp = tcbtab[i];
1531 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1532 return tcp;
1533 }
1534
1535 return NULL;
1536}
1537
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538void
Denys Vlasenko12014262011-05-30 14:00:14 +02001539droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540{
1541 if (tcp->pid == 0)
1542 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001543
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001545 if (debug)
1546 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001547
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001548 if (printing_tcp == tcp)
1549 printing_tcp = NULL;
1550
1551 if (outfname && followfork >= 2 && tcp->outf) {
1552 if (tcp->curcol != 0)
1553 fprintf(tcp->outf, " <detached>\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554 fclose(tcp->outf);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001555 } else if (tcp->outf) {
1556 fflush(tcp->outf);
1557 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001558
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001559 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001560}
1561
Roland McGrath0a463882007-07-05 18:43:16 +00001562/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001563 * Never call DETACH twice on the same process as both unattached and
1564 * attached-unstopped processes give the same ESRCH. For unattached process we
1565 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1566 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001568detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001570 int error;
1571 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572
1573 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001574 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001576 /*
1577 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001578 * before detaching. Arghh. We go through hoops
1579 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001581#if defined(SPARC)
1582#undef PTRACE_DETACH
1583#define PTRACE_DETACH PTRACE_SUNDETACH
1584#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001585
1586 sigstop_expected = 0;
1587 if (tcp->flags & TCB_ATTACHED) {
1588 /*
1589 * We attached but possibly didn't see the expected SIGSTOP.
1590 * We must catch exactly one as otherwise the detached process
1591 * would be left stopped (process state T).
1592 */
1593 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1594 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1595 if (error == 0) {
1596 /* On a clear day, you can see forever. */
1597 }
1598 else if (errno != ESRCH) {
1599 /* Shouldn't happen. */
1600 perror("detach: ptrace(PTRACE_DETACH, ...)");
1601 }
1602 else if (my_tkill(tcp->pid, 0) < 0) {
1603 if (errno != ESRCH)
1604 perror("detach: checking sanity");
1605 }
1606 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1607 if (errno != ESRCH)
1608 perror("detach: stopping child");
1609 }
1610 else
1611 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001612 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001613
1614 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001616#ifdef __WALL
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001617 if (waitpid(tcp->pid, &status, __WALL) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001618 if (errno == ECHILD) /* Already gone. */
1619 break;
1620 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001621 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001622 break;
1623 }
1624#endif /* __WALL */
1625 /* No __WALL here. */
1626 if (waitpid(tcp->pid, &status, 0) < 0) {
1627 if (errno != ECHILD) {
1628 perror("detach: waiting");
1629 break;
1630 }
1631#ifdef __WCLONE
1632 /* If no processes, try clones. */
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001633 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001634 if (errno != ECHILD)
1635 perror("detach: waiting");
1636 break;
1637 }
1638#endif /* __WCLONE */
1639 }
1640#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001641 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001642#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643 if (!WIFSTOPPED(status)) {
1644 /* Au revoir, mon ami. */
1645 break;
1646 }
1647 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001648 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649 break;
1650 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001651 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001652 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001653 : WSTOPSIG(status));
1654 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001657 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001659 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660 fprintf(stderr, "Process %u detached\n", tcp->pid);
1661
1662 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001663
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664 return error;
1665}
1666
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001668cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669{
1670 int i;
1671 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001672 int fatal_sig;
1673
1674 /* 'interrupted' is a volatile object, fetch it only once */
1675 fatal_sig = interrupted;
1676 if (!fatal_sig)
1677 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678
Roland McGrathee9d4352002-12-18 04:16:10 +00001679 for (i = 0; i < tcbtabsize; i++) {
1680 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 if (!(tcp->flags & TCB_INUSE))
1682 continue;
1683 if (debug)
1684 fprintf(stderr,
1685 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001686 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001688 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001690 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 }
1692 if (cflag)
1693 call_summary(outf);
1694}
1695
1696static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001697interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001699 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700}
1701
1702#ifndef HAVE_STRERROR
1703
Roland McGrath6d2b3492002-12-30 00:51:30 +00001704#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705extern int sys_nerr;
1706extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001707#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708
1709const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001710strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001712 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001714 if (err_no < 1 || err_no >= sys_nerr) {
1715 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716 return buf;
1717 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001718 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719}
1720
1721#endif /* HAVE_STERRROR */
1722
1723#ifndef HAVE_STRSIGNAL
1724
Roland McGrath8f474e02003-01-14 07:53:33 +00001725#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001726extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001728#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1729extern char *_sys_siglist[];
1730#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731
1732const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001733strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001735 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736
1737 if (sig < 1 || sig >= NSIG) {
1738 sprintf(buf, "Unknown signal %d", sig);
1739 return buf;
1740 }
1741#ifdef HAVE__SYS_SIGLIST
1742 return _sys_siglist[sig];
1743#else
1744 return sys_siglist[sig];
1745#endif
1746}
1747
1748#endif /* HAVE_STRSIGNAL */
1749
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001751trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001754 struct rusage *rup = cflag ? &ru : NULL;
1755# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001756 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001757# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
Roland McGratheb9e2e82009-06-02 16:49:22 -07001759 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001760 int pid;
1761 int wait_errno;
1762 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001763 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001764 struct tcb *tcp;
1765 unsigned event;
1766
Denys Vlasenko222713a2009-03-17 14:29:59 +00001767 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001768 return 0;
1769 if (interactive)
1770 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001771# ifdef __WALL
1772 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001773 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001774 /* this kernel does not support __WALL */
1775 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001776 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001777 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001778 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001779 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001780 pid = wait4(-1, &status, __WCLONE, rup);
1781 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001782 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001783 }
1784 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001785# else
1786 pid = wait4(-1, &status, 0, rup);
1787# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001789 if (interactive)
1790 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001792 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001793 switch (wait_errno) {
1794 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001796 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 /*
1798 * We would like to verify this case
1799 * but sometimes a race in Solbourne's
1800 * version of SunOS sometimes reports
1801 * ECHILD before sending us SIGCHILD.
1802 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001803 return 0;
1804 default:
1805 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001806 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001807 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 }
1809 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001810 if (pid == popen_pid) {
1811 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001812 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001813 continue;
1814 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001815
1816 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001817 if (debug) {
1818 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001819 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001820 static const char *const event_names[] = {
1821 [PTRACE_EVENT_CLONE] = "CLONE",
1822 [PTRACE_EVENT_FORK] = "FORK",
1823 [PTRACE_EVENT_VFORK] = "VFORK",
1824 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1825 [PTRACE_EVENT_EXEC] = "EXEC",
1826 [PTRACE_EVENT_EXIT] = "EXIT",
1827 };
1828 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001829 if (event < ARRAY_SIZE(event_names))
1830 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001831 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001832 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001833 e = buf;
1834 }
1835 fprintf(stderr, " PTRACE_EVENT_%s", e);
1836 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001837 strcpy(buf, "???");
1838 if (WIFSIGNALED(status))
1839#ifdef WCOREDUMP
1840 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1841 WCOREDUMP(status) ? "core," : "",
1842 signame(WTERMSIG(status)));
1843#else
1844 sprintf(buf, "WIFSIGNALED,sig=%s",
1845 signame(WTERMSIG(status)));
1846#endif
1847 if (WIFEXITED(status))
1848 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1849 if (WIFSTOPPED(status))
1850 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001851#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001852 if (WIFCONTINUED(status))
1853 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001854#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001855 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1856 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001858 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001859 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001860
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001861 /* Under Linux, execve changes pid to thread leader's pid,
1862 * and we see this changed pid on EVENT_EXEC and later,
1863 * execve sysexit. Leader "disappears" without exit
1864 * notification. Let user know that, drop leader's tcb,
1865 * and fix up pid in execve thread's tcb.
1866 * Effectively, execve thread's tcb replaces leader's tcb.
1867 *
1868 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1869 * on exit syscall) in multithreaded programs exactly
1870 * in order to handle this case.
1871 *
1872 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1873 * On 2.6 and earlier, it can return garbage.
1874 */
1875 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1876 long old_pid = 0;
1877 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1878 && old_pid > 0
1879 && old_pid != pid
1880 ) {
1881 struct tcb *execve_thread = pid2tcb(old_pid);
1882 if (tcp) {
1883 outf = tcp->outf;
1884 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001885 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001886 if (execve_thread->curcol != 0) {
1887 /*
1888 * One case we are here is -ff:
1889 * try "strace -oLOG -ff test/threaded_execve"
1890 */
1891 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1892 execve_thread->curcol = 0;
1893 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001894 /* swap output FILEs (needed for -ff) */
1895 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001896 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001897 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001898 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001899 }
1900 droptcb(tcp);
1901 }
1902 tcp = execve_thread;
1903 if (tcp) {
1904 tcp->pid = pid;
1905 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001906 if (!cflag) {
1907 printleader(tcp);
1908 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1909 line_ended();
1910 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001911 }
1912 }
1913 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001914
Denys Vlasenko5d645812011-08-20 12:48:18 +02001915 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001916 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001917 /* This is needed to go with the CLONE_PTRACE
1918 changes in process.c/util.c: we might see
1919 the child's initial trap before we see the
1920 parent return from the clone syscall.
1921 Leave the child suspended until the parent
1922 returns from its system call. Only then
1923 will we have the association of parent and
1924 child so that we know how to do clearbpt
1925 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001926 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001927 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001928 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001929 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001930 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001931 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001932 else
1933 /* This can happen if a clone call used
1934 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001935 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001936 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001937 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001938 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001939 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001941
1942 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001943 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001944 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001945
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001946 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001947 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1948 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001950
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001951 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001952 if (pid == strace_child)
1953 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001954 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1956 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001957#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001958 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001959 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001960 WCOREDUMP(status) ? "(core dumped) " : "");
1961#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001962 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001963 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001964#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001965 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 }
1967 droptcb(tcp);
1968 continue;
1969 }
1970 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001971 if (pid == strace_child)
1972 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001973 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1974 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001975 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001976 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001977 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001978 droptcb(tcp);
1979 continue;
1980 }
1981 if (!WIFSTOPPED(status)) {
1982 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1983 droptcb(tcp);
1984 continue;
1985 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001987 /* Is this the very first time we see this tracee stopped? */
1988 if (tcp->flags & TCB_STARTUP) {
1989 if (debug)
1990 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001991 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001992 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001993 /*
1994 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001995 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001996 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001997 if (clearbpt(tcp) < 0) {
1998 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001999 droptcb(tcp);
2000 cleanup();
2001 return -1;
2002 }
2003 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002004 if (ptrace_setoptions) {
2005 if (debug)
2006 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2007 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2008 if (errno != ESRCH) {
2009 /* Should never happen, really */
2010 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002011 }
2012 }
2013 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002014 }
2015
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002016 sig = WSTOPSIG(status);
2017
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002018 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002019 /* Ptrace event */
2020#ifdef USE_SEIZE
2021 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002022 /*
2023 * PTRACE_INTERRUPT-stop or group-stop.
2024 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2025 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002026 if (sig == SIGSTOP
2027 || sig == SIGTSTP
2028 || sig == SIGTTIN
2029 || sig == SIGTTOU
2030 ) {
2031 stopped = 1;
2032 goto show_stopsig;
2033 }
2034 }
2035#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002036 goto restart_tracee_with_sig_0;
2037 }
2038
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002039 /* Is this post-attach SIGSTOP?
2040 * Interestingly, the process may stop
2041 * with STOPSIG equal to some other signal
2042 * than SIGSTOP if we happend to attach
2043 * just before the process takes a signal.
2044 */
2045 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2046 if (debug)
2047 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2048 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002049 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002050 }
2051
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002052 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002053 siginfo_t si;
2054
2055 /* Nonzero (true) if tracee is stopped by signal
2056 * (as opposed to "tracee received signal").
2057 */
2058 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002059#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002060 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002061#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002062 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002063 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002064#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002065 long pc = 0;
2066 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002067
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002068 upeek(tcp, PT_CR_IPSR, &psr);
2069 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002070
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002071# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002072 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002073# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002074# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002075#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002076# define PC_FORMAT_STR ""
2077# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002078#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002080 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002081 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002082 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002083 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002084 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002085 PC_FORMAT_ARG);
2086 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002087 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002088 strsignal(sig),
2089 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002090 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002091 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002093
2094 if (!stopped)
2095 /* It's signal-delivery-stop. Inject the signal */
2096 goto restart_tracee;
2097
2098 /* It's group-stop */
2099#ifdef USE_SEIZE
2100 if (use_seize) {
2101 /*
2102 * This ends ptrace-stop, but does *not* end group-stop.
2103 * This makes stopping signals work properly on straced process
2104 * (that is, process really stops. It used to continue to run).
2105 */
2106 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2107 cleanup();
2108 return -1;
2109 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002110 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002111 continue;
2112 }
2113 /* We don't have PTRACE_LISTEN support... */
2114#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002115 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002117
2118 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002119 if (interrupted)
2120 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002121
2122 /* This should be syscall entry or exit.
2123 * (Or it still can be that pesky post-execve SIGTRAP!)
2124 * Handle it.
2125 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002126 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2127 /* ptrace() failed in trace_syscall() with ESRCH.
2128 * Likely a result of process disappearing mid-flight.
2129 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002130 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002131 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002132 * We used to detach(tcp) here, but since we no longer
2133 * implement "detach before death" policy/hack,
2134 * we can let this process to report its death to us
2135 * normally, via WIFEXITED or WIFSIGNALED wait status.
2136 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002137 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 continue;
2139 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002140 restart_tracee_with_sig_0:
2141 sig = 0;
2142 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002143 /* Remember current print column before continuing. */
2144 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002145 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 cleanup();
2147 return -1;
2148 }
2149 }
2150 return 0;
2151}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002152
2153int
2154main(int argc, char *argv[])
2155{
2156 init(argc, argv);
2157
2158 /* Run main tracing loop */
2159 if (trace() < 0)
2160 return 1;
2161
2162 cleanup();
2163 fflush(NULL);
2164 if (exit_code > 0xff) {
2165 /* Avoid potential core file clobbering. */
2166 struct rlimit rlim = {0, 0};
2167 setrlimit(RLIMIT_CORE, &rlim);
2168
2169 /* Child was killed by a signal, mimic that. */
2170 exit_code &= 0xff;
2171 signal(exit_code, SIG_DFL);
2172 raise(exit_code);
2173 /* Paranoia - what if this signal is not fatal?
2174 Exit with 128 + signo then. */
2175 exit_code += 128;
2176 }
2177
2178 return exit_code;
2179}