blob: 2c5c1b4fcb8d743c7a9217ec9a8f22077ec6d2c0 [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
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020035#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <sys/param.h>
37#include <fcntl.h>
38#include <sys/resource.h>
39#include <sys/wait.h>
40#include <sys/stat.h>
41#include <pwd.h>
42#include <grp.h>
Roland McGrath70b08532004-04-09 00:25:21 +000043#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010044#include <sys/utsname.h>
Denys Vlasenko84703742012-02-25 02:38:52 +010045#if defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000046# include <asm/ptrace_offsets.h>
47#endif
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010048/* In some libc, these aren't declared. Do it ourself: */
Denys Vlasenko96d5a762008-12-29 19:13:27 +000049extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000050extern int optind;
51extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000052
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010053
54#if defined __NR_tkill
55# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
56#else
57 /* kill() may choose arbitrarily the target task of the process group
58 while we later wait on a that specific TID. PID process waits become
59 TID task specific waits for a process under ptrace(2). */
60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61# define my_tkill(tid, sig) kill((tid), (sig))
62#endif
63
64#undef KERNEL_VERSION
65#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
66
67cflag_t cflag = CFLAG_NONE;
68unsigned int followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020069unsigned int ptrace_setoptions = 0;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010070unsigned int xflag = 0;
71bool debug_flag = 0;
72bool Tflag = 0;
73bool qflag = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020074/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020075static unsigned int syscall_trap_sig = SIGTRAP;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010076static unsigned int tflag = 0;
77static bool iflag = 0;
78static bool rflag = 0;
79static bool print_pid_pfx = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010080
81/* -I n */
82enum {
83 INTR_NOT_SET = 0,
84 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
85 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
86 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
87 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
88 NUM_INTR_OPTS
89};
90static int opt_intr;
91/* We play with signal mask only if this mode is active: */
92#define interactive (opt_intr == INTR_WHILE_WAIT)
93
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000094/*
95 * daemonized_tracer supports -D option.
96 * With this option, strace forks twice.
97 * Unlike normal case, with -D *grandparent* process exec's,
98 * becoming a traced process. Child exits (this prevents traced process
99 * from having children it doesn't expect to have), and grandchild
100 * attaches to grandparent similarly to strace -p PID.
101 * This allows for more transparent interaction in cases
102 * when process and its parent are communicating via signals,
103 * wait() etc. Without -D, strace process gets lodged in between,
104 * disrupting parent<->child link.
105 */
106static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100108#ifdef USE_SEIZE
109static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
110# define use_seize (post_attach_sigstop == 0)
111#else
112# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
113# define use_seize 0
114#endif
115
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000116/* Sometimes we want to print only succeeding syscalls. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100117bool not_failing_only = 0;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000118
Grant Edwards8a082772011-04-07 20:25:40 +0000119/* Show path associated with fd arguments */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100120bool show_fd_path = 0;
Grant Edwards8a082772011-04-07 20:25:40 +0000121
122/* are we filtering traces based on paths? */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100123bool tracing_paths = 0;
Grant Edwards8a082772011-04-07 20:25:40 +0000124
Dmitry V. Levina6809652008-11-10 17:14:58 +0000125static int exit_code = 0;
126static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200127static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700128
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000129static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200130static uid_t run_uid;
131static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100133unsigned int max_strlen = DEFAULT_STRLEN;
134static unsigned int acolumn = DEFAULT_ACOLUMN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200135static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000136static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200137static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100138struct tcb *printing_tcp = NULL;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100139static unsigned int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200140static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200141static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200142static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100144static char *os_release; /* from uname() */
145
Denys Vlasenko4c196382012-01-04 15:11:09 +0100146static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100147static int trace(void);
148static void cleanup(void);
149static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150static sigset_t empty_set, blocked_set;
151
152#ifdef HAVE_SIG_ATOMIC_T
153static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100154#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100156#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200159usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000160{
161 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100162usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
163 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100164 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100165 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100166 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200168-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100169-d -- enable debug output to stderr\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100170-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000171-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100172-F -- attempt to follow vforks (deprecated, use -f)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000173-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100174-I interruptible\n\
175 1: no signals are blocked\n\
176 2: fatal signals are blocked while decoding syscall (default)\n\
177 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
178 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
179 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180-q -- suppress messages about attaching, detaching, etc.\n\
181-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100182-T -- print time spent in each syscall\n\
183-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000185-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100186-h -- print help message\n\
187-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188-a column -- alignment COLUMN for printing syscall results (default %d)\n\
189-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
190 options: trace, abbrev, verbose, raw, signal, read, or write\n\
191-o file -- send trace output to FILE instead of stderr\n\
192-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
193-p pid -- trace process with process id PID, may be repeated\n\
194-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
195-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
196-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000197-E var=val -- put var=val in the environment for command\n\
198-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000199-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000200" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000201-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000202 */
203, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204 exit(exitval);
205}
206
Denys Vlasenko75422762011-05-27 14:36:01 +0200207static void die(void) __attribute__ ((noreturn));
208static void die(void)
209{
210 if (strace_tracer_pid == getpid()) {
211 cflag = 0;
212 cleanup();
213 }
214 exit(1);
215}
216
217static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200218{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100219 char *msg;
220
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000221 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100222
223 /* We want to print entire message with single fprintf to ensure
224 * message integrity if stderr is shared with other programs.
225 * Thus we use vasprintf + single fprintf.
226 */
227 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100228 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100229 if (err_no)
230 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
231 else
232 fprintf(stderr, "%s: %s\n", progname, msg);
233 free(msg);
234 } else {
235 /* malloc in vasprintf failed, try it without malloc */
236 fprintf(stderr, "%s: ", progname);
237 vfprintf(stderr, fmt, p);
238 if (err_no)
239 fprintf(stderr, ": %s\n", strerror(err_no));
240 else
241 putc('\n', stderr);
242 }
243 /* We don't switch stderr to buffered, thus fprintf(stderr)
244 * always flushes its output and this is not necessary: */
245 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200246}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200247
Denys Vlasenko75422762011-05-27 14:36:01 +0200248void error_msg(const char *fmt, ...)
249{
250 va_list p;
251 va_start(p, fmt);
252 verror_msg(0, fmt, p);
253 va_end(p);
254}
255
256void error_msg_and_die(const char *fmt, ...)
257{
258 va_list p;
259 va_start(p, fmt);
260 verror_msg(0, fmt, p);
261 die();
262}
263
264void perror_msg(const char *fmt, ...)
265{
266 va_list p;
267 va_start(p, fmt);
268 verror_msg(errno, fmt, p);
269 va_end(p);
270}
271
272void perror_msg_and_die(const char *fmt, ...)
273{
274 va_list p;
275 va_start(p, fmt);
276 verror_msg(errno, fmt, p);
277 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200278}
279
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200280void die_out_of_memory(void)
281{
282 static bool recursed = 0;
283 if (recursed)
284 exit(1);
285 recursed = 1;
286 error_msg_and_die("Out of memory");
287}
288
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400289/* Glue for systems without a MMU that cannot provide fork() */
290#ifdef HAVE_FORK
291# define strace_vforked 0
292#else
293# define strace_vforked 1
294# define fork() vfork()
295#endif
296
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100297#ifdef USE_SEIZE
298static int
299ptrace_attach_or_seize(int pid)
300{
301 int r;
302 if (!use_seize)
303 return ptrace(PTRACE_ATTACH, pid, 0, 0);
304 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
305 if (r)
306 return r;
307 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
308 return r;
309}
310#else
311# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
312#endif
313
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200314static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000315set_cloexec_flag(int fd)
316{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200317 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000318
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200319 flags = fcntl(fd, F_GETFD);
320 if (flags < 0) {
321 /* Can happen only if fd is bad.
322 * Should never happen: if it does, we have a bug
323 * in the caller. Therefore we just abort
324 * instead of propagating the error.
325 */
326 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000327 }
328
329 newflags = flags | FD_CLOEXEC;
330 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200331 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000332
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200333 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000334}
335
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100336static void kill_save_errno(pid_t pid, int sig)
337{
338 int saved_errno = errno;
339
340 (void) kill(pid, sig);
341 errno = saved_errno;
342}
343
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100344void
345tprintf(const char *fmt, ...)
346{
347 va_list args;
348
349 va_start(args, fmt);
350 if (outf) {
351 int n = vfprintf(outf, fmt, args);
352 if (n < 0) {
353 if (outf != stderr)
354 perror(outfname == NULL
355 ? "<writing to pipe>" : outfname);
356 } else
357 curcol += n;
358 }
359 va_end(args);
360}
361
362void
363tprints(const char *str)
364{
365 if (outf) {
366 int n = fputs(str, outf);
367 if (n >= 0) {
368 curcol += strlen(str);
369 return;
370 }
371 if (outf != stderr)
372 perror(outfname == NULL
373 ? "<writing to pipe>" : outfname);
374 }
375}
376
377void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100378line_ended(void)
379{
380 curcol = 0;
381 fflush(outf);
382 if (!printing_tcp)
383 return;
384 printing_tcp->curcol = 0;
385 printing_tcp = NULL;
386}
387
388void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100389printleader(struct tcb *tcp)
390{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100391 /* If -ff, "previous tcb we printed" is always the same as current,
392 * because we have per-tcb output files.
393 */
394 if (followfork >= 2)
395 printing_tcp = tcp;
396
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100397 if (printing_tcp) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100398 outf = printing_tcp->outf;
399 curcol = printing_tcp->curcol;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100400 if (printing_tcp->ptrace_errno) {
401 if (printing_tcp->flags & TCB_INSYSCALL) {
402 tprints(" <unavailable>) ");
403 tabto();
404 }
405 tprints("= ? <unavailable>\n");
406 printing_tcp->ptrace_errno = 0;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100407 printing_tcp->curcol = 0;
408 }
409 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
410 /*
411 * case 1: we have a shared log (i.e. not -ff), and last line
412 * wasn't finished (same or different tcb, doesn't matter).
413 * case 2: split log, we are the same tcb, but our last line
414 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
415 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100416 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100417 printing_tcp->flags |= TCB_REPRINT;
418 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100419 }
420 }
421
422 printing_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100423 outf = tcp->outf;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100424 curcol = 0;
425
426 if (print_pid_pfx)
427 tprintf("%-5d ", tcp->pid);
428 else if (nprocs > 1 && !outfname)
429 tprintf("[pid %5u] ", tcp->pid);
430
431 if (tflag) {
432 char str[sizeof("HH:MM:SS")];
433 struct timeval tv, dtv;
434 static struct timeval otv;
435
436 gettimeofday(&tv, NULL);
437 if (rflag) {
438 if (otv.tv_sec == 0)
439 otv = tv;
440 tv_sub(&dtv, &tv, &otv);
441 tprintf("%6ld.%06ld ",
442 (long) dtv.tv_sec, (long) dtv.tv_usec);
443 otv = tv;
444 }
445 else if (tflag > 2) {
446 tprintf("%ld.%06ld ",
447 (long) tv.tv_sec, (long) tv.tv_usec);
448 }
449 else {
450 time_t local = tv.tv_sec;
451 strftime(str, sizeof(str), "%T", localtime(&local));
452 if (tflag > 1)
453 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
454 else
455 tprintf("%s ", str);
456 }
457 }
458 if (iflag)
459 printcall(tcp);
460}
461
462void
463tabto(void)
464{
465 if (curcol < acolumn)
466 tprints(acolumn_spaces + curcol);
467}
468
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000469/*
470 * When strace is setuid executable, we have to swap uids
471 * before and after filesystem and process management operations.
472 */
473static void
474swap_uid(void)
475{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000476 int euid = geteuid(), uid = getuid();
477
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200478 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200479 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000480 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000481}
482
Roland McGrath4bfa6262007-07-05 20:03:16 +0000483#if _LFS64_LARGEFILE
484# define fopen_for_output fopen64
485#else
486# define fopen_for_output fopen
487#endif
488
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000489static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200490strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000491{
492 FILE *fp;
493
494 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200495 fp = fopen_for_output(path, "w");
496 if (!fp)
497 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000498 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200499 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000500 return fp;
501}
502
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200503static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000504
505#ifndef _PATH_BSHELL
506# define _PATH_BSHELL "/bin/sh"
507#endif
508
509/*
510 * We cannot use standard popen(3) here because we have to distinguish
511 * popen child process from other processes we trace, and standard popen(3)
512 * does not export its child's pid.
513 */
514static FILE *
515strace_popen(const char *command)
516{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200517 FILE *fp;
518 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000519
520 swap_uid();
521 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200522 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000523
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200524 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000525
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200526 popen_pid = vfork();
527 if (popen_pid == -1)
528 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000529
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200530 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000531 /* child */
532 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200533 if (fds[0] != 0) {
534 if (dup2(fds[0], 0))
535 perror_msg_and_die("dup2");
536 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000537 }
538 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200539 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000540 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200541
542 /* parent */
543 close(fds[0]);
544 swap_uid();
545 fp = fdopen(fds[1], "w");
546 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200547 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200548 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000549}
550
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200551static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000552newoutf(struct tcb *tcp)
553{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100554 if (outfname && followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000555 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000556 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200557 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000558 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000559}
560
Denys Vlasenko558e5122012-03-12 23:32:16 +0100561static void
562process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100563{
564 while (*opt) {
565 /*
566 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
567 * pidof uses space as delim, pgrep uses newline. :(
568 */
569 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100570 char *delim = opt + strcspn(opt, ", \n\t");
571 char c = *delim;
572
573 *delim = '\0';
574 pid = atoi(opt); /* TODO: stricter parsing of the number? */
575 if (pid <= 0) {
576 error_msg("Invalid process id: '%s'", opt);
577 *delim = c;
578 return;
579 }
580 if (pid == strace_tracer_pid) {
581 error_msg("I'm sorry, I can't let you do that, Dave.");
582 *delim = c;
583 return;
584 }
585 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100586 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100587 if (c == '\0')
588 break;
589 opt = delim + 1;
590 }
591}
592
Roland McGrath02203312007-06-11 22:06:31 +0000593static void
594startup_attach(void)
595{
596 int tcbi;
597 struct tcb *tcp;
598
599 /*
600 * Block user interruptions as we would leave the traced
601 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200602 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200603 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000604 */
605 if (interactive)
606 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
607
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000608 if (daemonized_tracer) {
609 pid_t pid = fork();
610 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200611 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000612 }
613 if (pid) { /* parent */
614 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200615 * Wait for grandchild to attach to straced process
616 * (grandparent). Grandchild SIGKILLs us after it attached.
617 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000618 * it proceeds to exec the straced program.
619 */
620 pause();
621 _exit(0); /* paranoia */
622 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200623 /* grandchild */
624 /* We will be the tracer process. Remember our new pid: */
625 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000626 }
627
Roland McGrath02203312007-06-11 22:06:31 +0000628 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
629 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200630
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100631 if (!(tcp->flags & TCB_INUSE))
632 continue;
633
Denys Vlasenkod116a732011-09-05 14:01:33 +0200634 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100635 if (tcp->flags & TCB_ATTACHED)
636 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200637
638 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000639 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200640 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000641
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000642 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000643 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000644 DIR *dir;
645
646 sprintf(procdir, "/proc/%d/task", tcp->pid);
647 dir = opendir(procdir);
648 if (dir != NULL) {
649 unsigned int ntid = 0, nerr = 0;
650 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200651
Roland McGrath02203312007-06-11 22:06:31 +0000652 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200653 struct tcb *cur_tcp;
654 int tid;
655
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000656 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000657 continue;
658 tid = atoi(de->d_name);
659 if (tid <= 0)
660 continue;
661 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100662 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000663 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100664 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200665 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200666 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200667 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100668 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200669 fprintf(stderr, "attach to pid %d succeeded\n", tid);
670 cur_tcp = tcp;
671 if (tid != tcp->pid)
672 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100673 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000674 }
675 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200676 if (interactive) {
677 sigprocmask(SIG_SETMASK, &empty_set, NULL);
678 if (interrupted)
679 goto ret;
680 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
681 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000682 ntid -= nerr;
683 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000684 perror("attach: ptrace(PTRACE_ATTACH, ...)");
685 droptcb(tcp);
686 continue;
687 }
688 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000689 fprintf(stderr, ntid > 1
690? "Process %u attached with %u threads - interrupt to quit\n"
691: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200692 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000693 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100694 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200695 /* -p PID, we failed to attach to PID itself
696 * but did attach to some of its sibling threads.
697 * Drop PID's tcp.
698 */
699 droptcb(tcp);
700 }
Roland McGrath02203312007-06-11 22:06:31 +0000701 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000702 } /* if (opendir worked) */
703 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100704 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000705 perror("attach: ptrace(PTRACE_ATTACH, ...)");
706 droptcb(tcp);
707 continue;
708 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100709 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100710 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200711 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000712
713 if (daemonized_tracer) {
714 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000715 * Make parent go away.
716 * Also makes grandparent's wait() unblock.
717 */
718 kill(getppid(), SIGKILL);
719 }
720
Roland McGrath02203312007-06-11 22:06:31 +0000721 if (!qflag)
722 fprintf(stderr,
723 "Process %u attached - interrupt to quit\n",
724 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200725 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000726
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200727 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000728 if (interactive)
729 sigprocmask(SIG_SETMASK, &empty_set, NULL);
730}
731
732static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200733startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000734{
735 struct stat statbuf;
736 const char *filename;
737 char pathname[MAXPATHLEN];
738 int pid = 0;
739 struct tcb *tcp;
740
741 filename = argv[0];
742 if (strchr(filename, '/')) {
743 if (strlen(filename) > sizeof pathname - 1) {
744 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200745 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000746 }
747 strcpy(pathname, filename);
748 }
749#ifdef USE_DEBUGGING_EXEC
750 /*
751 * Debuggers customarily check the current directory
752 * first regardless of the path but doing that gives
753 * security geeks a panic attack.
754 */
755 else if (stat(filename, &statbuf) == 0)
756 strcpy(pathname, filename);
757#endif /* USE_DEBUGGING_EXEC */
758 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000759 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000760 int m, n, len;
761
762 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100763 const char *colon = strchr(path, ':');
764 if (colon) {
765 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000766 m = n + 1;
767 }
768 else
769 m = n = strlen(path);
770 if (n == 0) {
771 if (!getcwd(pathname, MAXPATHLEN))
772 continue;
773 len = strlen(pathname);
774 }
775 else if (n > sizeof pathname - 1)
776 continue;
777 else {
778 strncpy(pathname, path, n);
779 len = n;
780 }
781 if (len && pathname[len - 1] != '/')
782 pathname[len++] = '/';
783 strcpy(pathname + len, filename);
784 if (stat(pathname, &statbuf) == 0 &&
785 /* Accept only regular files
786 with some execute bits set.
787 XXX not perfect, might still fail */
788 S_ISREG(statbuf.st_mode) &&
789 (statbuf.st_mode & 0111))
790 break;
791 }
792 }
793 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200794 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000795 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000796 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000797 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200798 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000799 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200800 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
801 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000802 ) {
803 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200804 if (outf != stderr)
805 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100806 if (!daemonized_tracer && !use_seize) {
807 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200808 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000809 }
Roland McGrath02203312007-06-11 22:06:31 +0000810 }
Roland McGrath02203312007-06-11 22:06:31 +0000811
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200812 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000813 uid_t run_euid = run_uid;
814 gid_t run_egid = run_gid;
815
816 if (statbuf.st_mode & S_ISUID)
817 run_euid = statbuf.st_uid;
818 if (statbuf.st_mode & S_ISGID)
819 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000820 /*
821 * It is important to set groups before we
822 * lose privileges on setuid.
823 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200824 if (initgroups(username, run_gid) < 0) {
825 perror_msg_and_die("initgroups");
826 }
827 if (setregid(run_gid, run_egid) < 0) {
828 perror_msg_and_die("setregid");
829 }
830 if (setreuid(run_uid, run_euid) < 0) {
831 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000832 }
833 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200834 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000835 setreuid(run_uid, run_uid);
836
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000837 if (!daemonized_tracer) {
838 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200839 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000840 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200841 * the immediately following execve syscall.
842 * Can't do this on NOMMU systems, we are after
843 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000844 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400845 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200846 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000847 } else {
848 struct sigaction sv_sigchld;
849 sigaction(SIGCHLD, NULL, &sv_sigchld);
850 /*
851 * Make sure it is not SIG_IGN, otherwise wait
852 * will not block.
853 */
854 signal(SIGCHLD, SIG_DFL);
855 /*
856 * Wait for grandchild to attach to us.
857 * It kills child after that, and wait() unblocks.
858 */
859 alarm(3);
860 wait(NULL);
861 alarm(0);
862 sigaction(SIGCHLD, &sv_sigchld, NULL);
863 }
Roland McGrath02203312007-06-11 22:06:31 +0000864
865 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200866 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000867 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000868
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200869 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200870
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200871 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100872 if (!use_seize) {
873 /* child did PTRACE_TRACEME, nothing to do in parent */
874 } else {
875 if (!strace_vforked) {
876 /* Wait until child stopped itself */
877 int status;
878 while (waitpid(pid, &status, WSTOPPED) < 0) {
879 if (errno == EINTR)
880 continue;
881 perror_msg_and_die("waitpid");
882 }
883 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100884 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100885 perror_msg_and_die("Unexpected wait status %x", status);
886 }
887 }
888 /* Else: vforked case, we have no way to sync.
889 * Just attach to it as soon as possible.
890 * This means that we may miss a few first syscalls...
891 */
892
893 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100894 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100895 perror_msg_and_die("Can't attach to %d", pid);
896 }
897 if (!strace_vforked)
898 kill(pid, SIGCONT);
899 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200900 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200901 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100902 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200903 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100904 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200905 }
906 else {
907 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
908 strace_tracer_pid = getpid();
909 /* The tracee is our parent: */
910 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100911 alloctcb(pid);
912 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000913 }
Roland McGrath02203312007-06-11 22:06:31 +0000914}
915
Wang Chaob13c0de2010-11-12 17:25:19 +0800916/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000917 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800918 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000919 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800920 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000921static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200922test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800923{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000924 int pid, expected_grandchild = 0, found_grandchild = 0;
925 const unsigned int test_options = PTRACE_O_TRACECLONE |
926 PTRACE_O_TRACEFORK |
927 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800928
Denys Vlasenko5d645812011-08-20 12:48:18 +0200929 pid = fork();
930 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000931 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200932 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000933 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100934 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000935 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
936 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100937 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000938 if (fork() < 0)
939 perror_msg_and_die("fork");
940 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800941 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000942
943 while (1) {
944 int status, tracee_pid;
945
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000946 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000947 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000948 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000949 if (errno == EINTR)
950 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100951 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000952 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000953 kill_save_errno(pid, SIGKILL);
954 perror_msg_and_die("%s: unexpected wait result %d",
955 __func__, tracee_pid);
956 }
957 if (WIFEXITED(status)) {
958 if (WEXITSTATUS(status)) {
959 if (tracee_pid != pid)
960 kill_save_errno(pid, SIGKILL);
961 error_msg_and_die("%s: unexpected exit status %u",
962 __func__, WEXITSTATUS(status));
963 }
964 continue;
965 }
966 if (WIFSIGNALED(status)) {
967 if (tracee_pid != pid)
968 kill_save_errno(pid, SIGKILL);
969 error_msg_and_die("%s: unexpected signal %u",
970 __func__, WTERMSIG(status));
971 }
972 if (!WIFSTOPPED(status)) {
973 if (tracee_pid != pid)
974 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100975 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000976 error_msg_and_die("%s: unexpected wait status %x",
977 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000978 }
979 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000980 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000981 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
982 kill_save_errno(tracee_pid, SIGKILL);
983 kill_save_errno(pid, SIGKILL);
984 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800985 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000986 continue;
987 }
988 switch (WSTOPSIG(status)) {
989 case SIGSTOP:
990 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
991 && errno != EINVAL && errno != EIO)
992 perror_msg("PTRACE_SETOPTIONS");
993 break;
994 case SIGTRAP:
995 if (status >> 16 == PTRACE_EVENT_FORK) {
996 long msg = 0;
997
998 if (ptrace(PTRACE_GETEVENTMSG, pid,
999 NULL, (long) &msg) == 0)
1000 expected_grandchild = msg;
1001 }
1002 break;
1003 }
1004 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1005 kill_save_errno(pid, SIGKILL);
1006 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001007 }
1008 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001009 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001010 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001011 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001012 fprintf(stderr, "ptrace_setoptions = %#x\n",
1013 ptrace_setoptions);
1014 return;
1015 }
1016 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1017 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001018}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001019
1020/*
1021 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1022 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1023 * and then see whether it will stop with (SIGTRAP | 0x80).
1024 *
1025 * Use of this option enables correct handling of user-generated SIGTRAPs,
1026 * and SIGTRAPs generated by special instructions such as int3 on x86:
1027 * _start: .globl _start
1028 * int3
1029 * movl $42, %ebx
1030 * movl $1, %eax
1031 * int $0x80
1032 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1033 */
1034static void
1035test_ptrace_setoptions_for_all(void)
1036{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001037 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1038 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001039 int pid;
1040 int it_worked = 0;
1041
1042 pid = fork();
1043 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001044 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001045
1046 if (pid == 0) {
1047 pid = getpid();
1048 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001049 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001050 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1051 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001052 kill(pid, SIGSTOP);
1053 _exit(0); /* parent should see entry into this syscall */
1054 }
1055
1056 while (1) {
1057 int status, tracee_pid;
1058
1059 errno = 0;
1060 tracee_pid = wait(&status);
1061 if (tracee_pid <= 0) {
1062 if (errno == EINTR)
1063 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001064 kill_save_errno(pid, SIGKILL);
1065 perror_msg_and_die("%s: unexpected wait result %d",
1066 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001067 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001068 if (WIFEXITED(status)) {
1069 if (WEXITSTATUS(status) == 0)
1070 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001071 error_msg_and_die("%s: unexpected exit status %u",
1072 __func__, WEXITSTATUS(status));
1073 }
1074 if (WIFSIGNALED(status)) {
1075 error_msg_and_die("%s: unexpected signal %u",
1076 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001077 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001078 if (!WIFSTOPPED(status)) {
1079 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001080 error_msg_and_die("%s: unexpected wait status %x",
1081 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001082 }
1083 if (WSTOPSIG(status) == SIGSTOP) {
1084 /*
1085 * We don't check "options aren't accepted" error.
1086 * If it happens, we'll never get (SIGTRAP | 0x80),
1087 * and thus will decide to not use the option.
1088 * IOW: the outcome of the test will be correct.
1089 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001090 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1091 && errno != EINVAL && errno != EIO)
1092 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001093 }
1094 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1095 it_worked = 1;
1096 }
1097 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001098 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001099 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001100 }
1101 }
1102
1103 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001104 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001105 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001106 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001107 fprintf(stderr, "ptrace_setoptions = %#x\n",
1108 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001109 return;
1110 }
1111
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001112 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1113 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001114}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001115
1116# ifdef USE_SEIZE
1117static void
1118test_ptrace_seize(void)
1119{
1120 int pid;
1121
1122 pid = fork();
1123 if (pid < 0)
1124 perror_msg_and_die("fork");
1125
1126 if (pid == 0) {
1127 pause();
1128 _exit(0);
1129 }
1130
1131 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1132 * attaching tracee continues to run unless a trap condition occurs.
1133 * PTRACE_SEIZE doesn't affect signal or group stop state.
1134 */
1135 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1136 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001137 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001138 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1139 }
1140
1141 kill(pid, SIGKILL);
1142
1143 while (1) {
1144 int status, tracee_pid;
1145
1146 errno = 0;
1147 tracee_pid = waitpid(pid, &status, 0);
1148 if (tracee_pid <= 0) {
1149 if (errno == EINTR)
1150 continue;
1151 perror_msg_and_die("%s: unexpected wait result %d",
1152 __func__, tracee_pid);
1153 }
1154 if (WIFSIGNALED(status)) {
1155 return;
1156 }
1157 error_msg_and_die("%s: unexpected wait status %x",
1158 __func__, status);
1159 }
1160}
1161# else /* !USE_SEIZE */
1162# define test_ptrace_seize() ((void)0)
1163# endif
1164
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001165static void
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001166get_os_release(void)
1167{
1168 struct utsname u;
1169 if (uname(&u) < 0)
1170 perror_msg_and_die("uname");
1171 os_release = strdup(u.release);
1172 if (!os_release)
1173 die_out_of_memory();
1174}
1175
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001176/*
1177 * Initialization part of main() was eating much stack (~0.5k),
1178 * which was unused after init.
1179 * We can reuse it if we move init code into a separate function.
1180 *
1181 * Don't want main() to inline us and defeat the reason
1182 * we have a separate function.
1183 */
1184static void __attribute__ ((noinline))
1185init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001188 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001189 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 struct sigaction sa;
1191
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001192 progname = argv[0] ? argv[0] : "strace";
1193
Denys Vlasenko75422762011-05-27 14:36:01 +02001194 strace_tracer_pid = getpid();
1195
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001196 get_os_release();
1197
Roland McGrathee9d4352002-12-18 04:16:10 +00001198 /* Allocate the initial tcbtab. */
1199 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001200 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001201 if (!tcbtab)
1202 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001203 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001204 if (!tcp)
1205 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001206 for (c = 0; c < tcbtabsize; c++)
1207 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001208
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001210 set_sortby(DEFAULT_SORTBY);
1211 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 qualify("trace=all");
1213 qualify("abbrev=all");
1214 qualify("verbose=all");
1215 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001217 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001218 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001219 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220 switch (c) {
1221 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001222 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001223 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001224 }
1225 cflag = CFLAG_ONLY_STATS;
1226 break;
1227 case 'C':
1228 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001229 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001230 }
1231 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232 break;
1233 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001234 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001235 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001236 case 'D':
1237 daemonized_tracer = 1;
1238 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001239 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001240 optF = 1;
1241 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 case 'f':
1243 followfork++;
1244 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 case 'h':
1246 usage(stdout, 0);
1247 break;
1248 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001249 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250 break;
1251 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001252 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 break;
1254 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001255 rflag = 1;
1256 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257 case 't':
1258 tflag++;
1259 break;
1260 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001261 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 break;
1263 case 'x':
1264 xflag++;
1265 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001266 case 'y':
1267 show_fd_path = 1;
1268 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269 case 'v':
1270 qualify("abbrev=none");
1271 break;
1272 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001273 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 exit(0);
1275 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001276 case 'z':
1277 not_failing_only = 1;
1278 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279 case 'a':
1280 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001281 if (acolumn < 0)
1282 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283 break;
1284 case 'e':
1285 qualify(optarg);
1286 break;
1287 case 'o':
1288 outfname = strdup(optarg);
1289 break;
1290 case 'O':
1291 set_overhead(atoi(optarg));
1292 break;
1293 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001294 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001296 case 'P':
1297 tracing_paths = 1;
1298 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001299 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001300 }
1301 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 case 's':
1303 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001304 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001305 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001306 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307 break;
1308 case 'S':
1309 set_sortby(optarg);
1310 break;
1311 case 'u':
1312 username = strdup(optarg);
1313 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001314 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001315 if (putenv(optarg) < 0)
1316 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001317 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001318 case 'I':
1319 opt_intr = atoi(optarg);
1320 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1321 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1322 }
1323 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001324 default:
1325 usage(stderr, 1);
1326 break;
1327 }
1328 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001329 argv += optind;
1330 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331
Denys Vlasenko102ec492011-08-25 01:27:59 +02001332 acolumn_spaces = malloc(acolumn + 1);
1333 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001334 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001335 memset(acolumn_spaces, ' ', acolumn);
1336 acolumn_spaces[acolumn] = '\0';
1337
Denys Vlasenko837399a2012-01-24 11:37:03 +01001338 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001339 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001340 usage(stderr, 1);
1341
Denys Vlasenkofd883382012-03-09 13:03:41 +01001342 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001343 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001344 }
1345
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001346 if (!followfork)
1347 followfork = optF;
1348
Roland McGrathcb9def62006-04-25 07:48:03 +00001349 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001350 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001351 }
1352
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353 /* See if they want to run as another user. */
1354 if (username != NULL) {
1355 struct passwd *pent;
1356
1357 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001358 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001359 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001360 pent = getpwnam(username);
1361 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001362 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 }
1364 run_uid = pent->pw_uid;
1365 run_gid = pent->pw_gid;
1366 }
1367 else {
1368 run_uid = getuid();
1369 run_gid = getgid();
1370 }
1371
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001372 if (followfork)
1373 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001374 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001375 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001376
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377 /* Check if they want to redirect the output. */
1378 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001379 /* See if they want to pipe the output. */
1380 if (outfname[0] == '|' || outfname[0] == '!') {
1381 /*
1382 * We can't do the <outfname>.PID funny business
1383 * when using popen, so prohibit it.
1384 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001385 if (followfork > 1)
1386 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1387 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001388 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001389 else if (followfork <= 1)
1390 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001391 } else {
1392 /* -ff without -o FILE is the same as single -f */
1393 if (followfork > 1)
1394 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001395 }
1396
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001397 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001398 char *buf = malloc(BUFSIZ);
1399 if (!buf)
1400 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001401 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001402 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001403 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001404 if (!opt_intr)
1405 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001407 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001408 if (!opt_intr)
1409 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001410
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001411 /* argv[0] -pPID -oFILE Default interactive setting
1412 * yes 0 0 INTR_WHILE_WAIT
1413 * no 1 0 INTR_WHILE_WAIT
1414 * yes 0 1 INTR_NEVER
1415 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001416 */
1417
1418 /* STARTUP_CHILD must be called before the signal handlers get
1419 installed below as they are inherited into the spawned process.
1420 Also we do not need to be protected by them as during interruption
1421 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001422 if (argv[0])
1423 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001425 sigemptyset(&empty_set);
1426 sigemptyset(&blocked_set);
1427 sa.sa_handler = SIG_IGN;
1428 sigemptyset(&sa.sa_mask);
1429 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001430 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1431 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1432 if (opt_intr != INTR_ANYWHERE) {
1433 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1434 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1435 /*
1436 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1437 * fatal signals are blocked while syscall stop is processed,
1438 * and acted on in between, when waiting for new syscall stops.
1439 * In non-interactive mode, signals are ignored.
1440 */
1441 if (opt_intr == INTR_WHILE_WAIT) {
1442 sigaddset(&blocked_set, SIGHUP);
1443 sigaddset(&blocked_set, SIGINT);
1444 sigaddset(&blocked_set, SIGQUIT);
1445 sigaddset(&blocked_set, SIGPIPE);
1446 sigaddset(&blocked_set, SIGTERM);
1447 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001448 }
1449 /* SIG_IGN, or set handler for these */
1450 sigaction(SIGHUP, &sa, NULL);
1451 sigaction(SIGINT, &sa, NULL);
1452 sigaction(SIGQUIT, &sa, NULL);
1453 sigaction(SIGPIPE, &sa, NULL);
1454 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455 }
Roland McGrath553a6092002-12-16 20:40:39 +00001456 /* Make sure SIGCHLD has the default action so that waitpid
1457 definitely works without losing track of children. The user
1458 should not have given us a bogus state to inherit, but he might
1459 have. Arguably we should detect SIG_IGN here and pass it on
1460 to children, but probably noone really needs that. */
1461 sa.sa_handler = SIG_DFL;
1462 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001463
Denys Vlasenkofd883382012-03-09 13:03:41 +01001464 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001465 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001466
Denys Vlasenkofd883382012-03-09 13:03:41 +01001467 /* Do we want pids printed in our -o OUTFILE?
1468 * -ff: no (every pid has its own file); or
1469 * -f: yes (there can be more pids in the future); or
1470 * -p PID1,PID2: yes (there are already more than one pid)
1471 */
1472 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473}
1474
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001475static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001476expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001477{
1478 /* Allocate some more TCBs and expand the table.
1479 We don't want to relocate the TCBs because our
1480 callers have pointers and it would be a pain.
1481 So tcbtab is a table of pointers. Since we never
1482 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001483 int i = tcbtabsize;
1484 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1485 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001486 if (!newtab || !newtcbs)
1487 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001488 tcbtabsize *= 2;
1489 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001490 while (i < tcbtabsize)
1491 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001492}
1493
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001495alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001496{
1497 int i;
1498 struct tcb *tcp;
1499
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001500 if (nprocs == tcbtabsize)
1501 expand_tcbtab();
1502
Roland McGrathee9d4352002-12-18 04:16:10 +00001503 for (i = 0; i < tcbtabsize; i++) {
1504 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001506 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001508 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001510#if SUPPORTED_PERSONALITIES > 1
1511 tcp->currpers = current_personality;
1512#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 nprocs++;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001514 if (debug_flag)
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001515 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001516 if (command_options_parsed)
1517 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518 return tcp;
1519 }
1520 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001521 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522}
1523
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001524static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001525pid2tcb(int pid)
1526{
1527 int i;
1528
1529 if (pid <= 0)
1530 return NULL;
1531
1532 for (i = 0; i < tcbtabsize; i++) {
1533 struct tcb *tcp = tcbtab[i];
1534 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1535 return tcp;
1536 }
1537
1538 return NULL;
1539}
1540
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541void
Denys Vlasenko12014262011-05-30 14:00:14 +02001542droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543{
1544 if (tcp->pid == 0)
1545 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001546
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 nprocs--;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001548 if (debug_flag)
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001549 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001550
Denys Vlasenko3e084ac2012-03-15 13:39:05 +01001551 if (tcp->outf) {
1552 if (outfname && followfork >= 2) {
1553 if (tcp->curcol != 0)
1554 fprintf(tcp->outf, " <detached ...>\n");
1555 fclose(tcp->outf);
1556 if (outf == tcp->outf)
1557 outf = NULL;
1558 } else {
1559 if (printing_tcp == tcp && tcp->curcol != 0)
1560 fprintf(tcp->outf, " <detached ...>\n");
1561 fflush(tcp->outf);
1562 }
1563 }
1564
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001565 if (printing_tcp == tcp)
1566 printing_tcp = NULL;
1567
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001568 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569}
1570
Roland McGrath0a463882007-07-05 18:43:16 +00001571/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001572 * Never call DETACH twice on the same process as both unattached and
1573 * attached-unstopped processes give the same ESRCH. For unattached process we
1574 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1575 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001576static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001577detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001579 int error;
1580 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581
1582 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001583 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001584
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585 /*
1586 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001587 * before detaching. Arghh. We go through hoops
1588 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001590#if defined(SPARC)
1591#undef PTRACE_DETACH
1592#define PTRACE_DETACH PTRACE_SUNDETACH
1593#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001594
Denys Vlasenko3e084ac2012-03-15 13:39:05 +01001595 error = 0;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001596 sigstop_expected = 0;
1597 if (tcp->flags & TCB_ATTACHED) {
1598 /*
1599 * We attached but possibly didn't see the expected SIGSTOP.
1600 * We must catch exactly one as otherwise the detached process
1601 * would be left stopped (process state T).
1602 */
1603 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1604 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1605 if (error == 0) {
1606 /* On a clear day, you can see forever. */
1607 }
1608 else if (errno != ESRCH) {
1609 /* Shouldn't happen. */
1610 perror("detach: ptrace(PTRACE_DETACH, ...)");
1611 }
1612 else if (my_tkill(tcp->pid, 0) < 0) {
1613 if (errno != ESRCH)
1614 perror("detach: checking sanity");
1615 }
1616 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1617 if (errno != ESRCH)
1618 perror("detach: stopping child");
1619 }
1620 else
1621 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001622 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001623
1624 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001626#ifdef __WALL
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001627 if (waitpid(tcp->pid, &status, __WALL) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001628 if (errno == ECHILD) /* Already gone. */
1629 break;
1630 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001631 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001632 break;
1633 }
1634#endif /* __WALL */
1635 /* No __WALL here. */
1636 if (waitpid(tcp->pid, &status, 0) < 0) {
1637 if (errno != ECHILD) {
1638 perror("detach: waiting");
1639 break;
1640 }
1641#ifdef __WCLONE
1642 /* If no processes, try clones. */
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001643 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001644 if (errno != ECHILD)
1645 perror("detach: waiting");
1646 break;
1647 }
1648#endif /* __WCLONE */
1649 }
1650#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001651 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001652#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653 if (!WIFSTOPPED(status)) {
1654 /* Au revoir, mon ami. */
1655 break;
1656 }
1657 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001658 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001659 break;
1660 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001661 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001662 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001663 : WSTOPSIG(status));
1664 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001667 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001669 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670 fprintf(stderr, "Process %u detached\n", tcp->pid);
1671
1672 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001673
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 return error;
1675}
1676
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001678cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001679{
1680 int i;
1681 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001682 int fatal_sig;
1683
1684 /* 'interrupted' is a volatile object, fetch it only once */
1685 fatal_sig = interrupted;
1686 if (!fatal_sig)
1687 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688
Roland McGrathee9d4352002-12-18 04:16:10 +00001689 for (i = 0; i < tcbtabsize; i++) {
1690 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 if (!(tcp->flags & TCB_INUSE))
1692 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001693 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694 fprintf(stderr,
1695 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001696 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001698 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001700 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701 }
1702 if (cflag)
1703 call_summary(outf);
1704}
1705
1706static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001707interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001709 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710}
1711
1712#ifndef HAVE_STRERROR
1713
Roland McGrath6d2b3492002-12-30 00:51:30 +00001714#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715extern int sys_nerr;
1716extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001717#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718
1719const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001720strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001721{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001722 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001724 if (err_no < 1 || err_no >= sys_nerr) {
1725 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001726 return buf;
1727 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001728 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729}
1730
1731#endif /* HAVE_STERRROR */
1732
1733#ifndef HAVE_STRSIGNAL
1734
Roland McGrath8f474e02003-01-14 07:53:33 +00001735#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001736extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001738#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1739extern char *_sys_siglist[];
1740#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001741
1742const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001743strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001745 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746
1747 if (sig < 1 || sig >= NSIG) {
1748 sprintf(buf, "Unknown signal %d", sig);
1749 return buf;
1750 }
1751#ifdef HAVE__SYS_SIGLIST
1752 return _sys_siglist[sig];
1753#else
1754 return sys_siglist[sig];
1755#endif
1756}
1757
1758#endif /* HAVE_STRSIGNAL */
1759
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001761trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001764 struct rusage *rup = cflag ? &ru : NULL;
1765# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001766 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001767# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768
Roland McGratheb9e2e82009-06-02 16:49:22 -07001769 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001770 int pid;
1771 int wait_errno;
1772 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001773 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001774 struct tcb *tcp;
1775 unsigned event;
1776
Denys Vlasenko222713a2009-03-17 14:29:59 +00001777 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001778 return 0;
1779 if (interactive)
1780 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001781# ifdef __WALL
1782 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001783 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001784 /* this kernel does not support __WALL */
1785 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001786 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001787 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001788 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001789 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001790 pid = wait4(-1, &status, __WCLONE, rup);
1791 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001792 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001793 }
1794 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001795# else
1796 pid = wait4(-1, &status, 0, rup);
1797# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001799 if (interactive)
1800 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001802 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001803 switch (wait_errno) {
1804 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001806 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807 /*
1808 * We would like to verify this case
1809 * but sometimes a race in Solbourne's
1810 * version of SunOS sometimes reports
1811 * ECHILD before sending us SIGCHILD.
1812 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001813 return 0;
1814 default:
1815 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001816 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001817 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818 }
1819 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001820 if (pid == popen_pid) {
1821 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001822 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001823 continue;
1824 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001825
1826 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001827 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001828 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001829 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001830 strcpy(buf, "???");
1831 if (WIFSIGNALED(status))
1832#ifdef WCOREDUMP
1833 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1834 WCOREDUMP(status) ? "core," : "",
1835 signame(WTERMSIG(status)));
1836#else
1837 sprintf(buf, "WIFSIGNALED,sig=%s",
1838 signame(WTERMSIG(status)));
1839#endif
1840 if (WIFEXITED(status))
1841 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1842 if (WIFSTOPPED(status))
1843 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001844#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001845 if (WIFCONTINUED(status))
1846 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001847#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001848 evbuf[0] = '\0';
1849 if (event != 0) {
1850 static const char *const event_names[] = {
1851 [PTRACE_EVENT_CLONE] = "CLONE",
1852 [PTRACE_EVENT_FORK] = "FORK",
1853 [PTRACE_EVENT_VFORK] = "VFORK",
1854 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1855 [PTRACE_EVENT_EXEC] = "EXEC",
1856 [PTRACE_EVENT_EXIT] = "EXIT",
1857 };
1858 const char *e;
1859 if (event < ARRAY_SIZE(event_names))
1860 e = event_names[event];
1861 else {
1862 sprintf(buf, "?? (%u)", event);
1863 e = buf;
1864 }
1865 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1866 }
1867 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001868 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001870 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001871 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001872
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001873 /* Under Linux, execve changes pid to thread leader's pid,
1874 * and we see this changed pid on EVENT_EXEC and later,
1875 * execve sysexit. Leader "disappears" without exit
1876 * notification. Let user know that, drop leader's tcb,
1877 * and fix up pid in execve thread's tcb.
1878 * Effectively, execve thread's tcb replaces leader's tcb.
1879 *
1880 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1881 * on exit syscall) in multithreaded programs exactly
1882 * in order to handle this case.
1883 *
1884 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1885 * On 2.6 and earlier, it can return garbage.
1886 */
1887 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1888 long old_pid = 0;
1889 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1890 && old_pid > 0
1891 && old_pid != pid
1892 ) {
1893 struct tcb *execve_thread = pid2tcb(old_pid);
1894 if (tcp) {
1895 outf = tcp->outf;
1896 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001897 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001898 if (execve_thread->curcol != 0) {
1899 /*
1900 * One case we are here is -ff:
1901 * try "strace -oLOG -ff test/threaded_execve"
1902 */
1903 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1904 execve_thread->curcol = 0;
1905 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001906 /* swap output FILEs (needed for -ff) */
1907 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001908 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001909 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001910 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001911 }
1912 droptcb(tcp);
1913 }
1914 tcp = execve_thread;
1915 if (tcp) {
1916 tcp->pid = pid;
1917 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001918 if (!cflag) {
1919 printleader(tcp);
1920 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1921 line_ended();
1922 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001923 }
1924 }
1925 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001926
Denys Vlasenko5d645812011-08-20 12:48:18 +02001927 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001928 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001929 /* This is needed to go with the CLONE_PTRACE
1930 changes in process.c/util.c: we might see
1931 the child's initial trap before we see the
1932 parent return from the clone syscall.
1933 Leave the child suspended until the parent
1934 returns from its system call. Only then
1935 will we have the association of parent and
1936 child so that we know how to do clearbpt
1937 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001938 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001939 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001940 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001941 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001942 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001943 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001944 else
1945 /* This can happen if a clone call used
1946 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001947 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001948 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001949 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001950 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001951 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001953
1954 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001955 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001956 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001957
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001958 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1960 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001962
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001963 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001964 if (pid == strace_child)
1965 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001966 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001967 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1968 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001969#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001970 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001971 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001972 WCOREDUMP(status) ? "(core dumped) " : "");
1973#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001974 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001975 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001976#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001977 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001978 }
1979 droptcb(tcp);
1980 continue;
1981 }
1982 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001983 if (pid == strace_child)
1984 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001985 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1986 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001987 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001988 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001989 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001990 droptcb(tcp);
1991 continue;
1992 }
1993 if (!WIFSTOPPED(status)) {
1994 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1995 droptcb(tcp);
1996 continue;
1997 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001999 /* Is this the very first time we see this tracee stopped? */
2000 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002001 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002002 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002003 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002005 /*
2006 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002007 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002008 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002009 if (clearbpt(tcp) < 0) {
2010 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011 droptcb(tcp);
2012 cleanup();
2013 return -1;
2014 }
2015 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002016 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002017 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002018 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2019 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2020 if (errno != ESRCH) {
2021 /* Should never happen, really */
2022 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002023 }
2024 }
2025 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002026 }
2027
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002028 sig = WSTOPSIG(status);
2029
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002030 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002031 /* Ptrace event */
2032#ifdef USE_SEIZE
2033 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002034 /*
2035 * PTRACE_INTERRUPT-stop or group-stop.
2036 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2037 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002038 if (sig == SIGSTOP
2039 || sig == SIGTSTP
2040 || sig == SIGTTIN
2041 || sig == SIGTTOU
2042 ) {
2043 stopped = 1;
2044 goto show_stopsig;
2045 }
2046 }
2047#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002048 goto restart_tracee_with_sig_0;
2049 }
2050
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002051 /* Is this post-attach SIGSTOP?
2052 * Interestingly, the process may stop
2053 * with STOPSIG equal to some other signal
2054 * than SIGSTOP if we happend to attach
2055 * just before the process takes a signal.
2056 */
2057 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002058 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002059 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2060 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002061 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062 }
2063
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002064 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002065 siginfo_t si;
2066
2067 /* Nonzero (true) if tracee is stopped by signal
2068 * (as opposed to "tracee received signal").
2069 */
2070 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002071#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002072 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002073#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002074 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002075 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002076#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002077 long pc = 0;
2078 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002079
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002080 upeek(tcp, PT_CR_IPSR, &psr);
2081 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002082
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002083# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002084 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002085# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002086# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002087#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002088# define PC_FORMAT_STR ""
2089# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002090#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002092 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002093 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002094 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002095 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002096 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002097 PC_FORMAT_ARG);
2098 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002099 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002100 strsignal(sig),
2101 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002102 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002103 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002104 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002105
2106 if (!stopped)
2107 /* It's signal-delivery-stop. Inject the signal */
2108 goto restart_tracee;
2109
2110 /* It's group-stop */
2111#ifdef USE_SEIZE
2112 if (use_seize) {
2113 /*
2114 * This ends ptrace-stop, but does *not* end group-stop.
2115 * This makes stopping signals work properly on straced process
2116 * (that is, process really stops. It used to continue to run).
2117 */
2118 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2119 cleanup();
2120 return -1;
2121 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002122 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002123 continue;
2124 }
2125 /* We don't have PTRACE_LISTEN support... */
2126#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002127 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002129
2130 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002131 if (interrupted)
2132 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002133
2134 /* This should be syscall entry or exit.
2135 * (Or it still can be that pesky post-execve SIGTRAP!)
2136 * Handle it.
2137 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002138 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2139 /* ptrace() failed in trace_syscall() with ESRCH.
2140 * Likely a result of process disappearing mid-flight.
2141 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002142 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002143 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002144 * We used to detach(tcp) here, but since we no longer
2145 * implement "detach before death" policy/hack,
2146 * we can let this process to report its death to us
2147 * normally, via WIFEXITED or WIFSIGNALED wait status.
2148 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002149 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002150 continue;
2151 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002152 restart_tracee_with_sig_0:
2153 sig = 0;
2154 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002155 /* Remember current print column before continuing. */
2156 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002157 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002158 cleanup();
2159 return -1;
2160 }
2161 }
2162 return 0;
2163}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002164
2165int
2166main(int argc, char *argv[])
2167{
2168 init(argc, argv);
2169
2170 /* Run main tracing loop */
2171 if (trace() < 0)
2172 return 1;
2173
2174 cleanup();
2175 fflush(NULL);
2176 if (exit_code > 0xff) {
2177 /* Avoid potential core file clobbering. */
2178 struct rlimit rlim = {0, 0};
2179 setrlimit(RLIMIT_CORE, &rlim);
2180
2181 /* Child was killed by a signal, mimic that. */
2182 exit_code &= 0xff;
2183 signal(exit_code, SIG_DFL);
2184 raise(exit_code);
2185 /* Paranoia - what if this signal is not fatal?
2186 Exit with 128 + signo then. */
2187 exit_code += 128;
2188 }
2189
2190 return exit_code;
2191}