blob: f452254e13ecf65e5ddd869c94cb162680ec5ce1 [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
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100125static bool detach_on_execve = 0;
126static bool skip_startup_execve = 0;
127
Dmitry V. Levina6809652008-11-10 17:14:58 +0000128static int exit_code = 0;
129static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200130static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700131
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000132static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200133static uid_t run_uid;
134static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100136unsigned int max_strlen = DEFAULT_STRLEN;
137static unsigned int acolumn = DEFAULT_ACOLUMN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200138static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000139static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200140static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100141struct tcb *printing_tcp = NULL;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100142static unsigned int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200143static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200144static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200145static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +0100147static unsigned os_release; /* generated from uname()'s u.release */
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100148
Denys Vlasenko4c196382012-01-04 15:11:09 +0100149static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100150static int trace(void);
151static void cleanup(void);
152static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153static sigset_t empty_set, blocked_set;
154
155#ifdef HAVE_SIG_ATOMIC_T
156static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100157#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100159#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000160
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100161#ifndef HAVE_STRERROR
162
163#if !HAVE_DECL_SYS_ERRLIST
164extern int sys_nerr;
165extern char *sys_errlist[];
166#endif /* HAVE_DECL_SYS_ERRLIST */
167
168const char *
169strerror(int err_no)
170{
171 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
172
173 if (err_no < 1 || err_no >= sys_nerr) {
174 sprintf(buf, "Unknown error %d", err_no);
175 return buf;
176 }
177 return sys_errlist[err_no];
178}
179
180#endif /* HAVE_STERRROR */
181
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200183usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184{
185 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100186usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
187 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100188 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100189 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100190 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000191-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200192-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100193-d -- enable debug output to stderr\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100194-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100196-F -- attempt to follow vforks (deprecated, use -f)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100198-I interruptible\n\
199 1: no signals are blocked\n\
200 2: fatal signals are blocked while decoding syscall (default)\n\
201 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
202 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
203 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204-q -- suppress messages about attaching, detaching, etc.\n\
205-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100206-T -- print time spent in each syscall\n\
207-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000208-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000209-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100210-h -- print help message\n\
211-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000212-a column -- alignment COLUMN for printing syscall results (default %d)\n\
213-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
214 options: trace, abbrev, verbose, raw, signal, read, or write\n\
215-o file -- send trace output to FILE instead of stderr\n\
216-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
217-p pid -- trace process with process id PID, may be repeated\n\
218-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
219-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
220-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000221-E var=val -- put var=val in the environment for command\n\
222-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000223-P path -- trace accesses to path\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100224"
225/* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000226-z -- print only succeeding syscalls\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100227 */
228/* experimental, don't document it yet (option letter may change in the future!)
229-b -- detach on successful execve\n\
230 */
Roland McGrathde6e5332003-01-24 04:31:23 +0000231, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232 exit(exitval);
233}
234
Denys Vlasenko75422762011-05-27 14:36:01 +0200235static void die(void) __attribute__ ((noreturn));
236static void die(void)
237{
238 if (strace_tracer_pid == getpid()) {
239 cflag = 0;
240 cleanup();
241 }
242 exit(1);
243}
244
245static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200246{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100247 char *msg;
248
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000249 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100250
251 /* We want to print entire message with single fprintf to ensure
252 * message integrity if stderr is shared with other programs.
253 * Thus we use vasprintf + single fprintf.
254 */
255 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100256 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100257 if (err_no)
258 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
259 else
260 fprintf(stderr, "%s: %s\n", progname, msg);
261 free(msg);
262 } else {
263 /* malloc in vasprintf failed, try it without malloc */
264 fprintf(stderr, "%s: ", progname);
265 vfprintf(stderr, fmt, p);
266 if (err_no)
267 fprintf(stderr, ": %s\n", strerror(err_no));
268 else
269 putc('\n', stderr);
270 }
271 /* We don't switch stderr to buffered, thus fprintf(stderr)
272 * always flushes its output and this is not necessary: */
273 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200274}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200275
Denys Vlasenko75422762011-05-27 14:36:01 +0200276void error_msg(const char *fmt, ...)
277{
278 va_list p;
279 va_start(p, fmt);
280 verror_msg(0, fmt, p);
281 va_end(p);
282}
283
284void error_msg_and_die(const char *fmt, ...)
285{
286 va_list p;
287 va_start(p, fmt);
288 verror_msg(0, fmt, p);
289 die();
290}
291
292void perror_msg(const char *fmt, ...)
293{
294 va_list p;
295 va_start(p, fmt);
296 verror_msg(errno, fmt, p);
297 va_end(p);
298}
299
300void perror_msg_and_die(const char *fmt, ...)
301{
302 va_list p;
303 va_start(p, fmt);
304 verror_msg(errno, fmt, p);
305 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200306}
307
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200308void die_out_of_memory(void)
309{
310 static bool recursed = 0;
311 if (recursed)
312 exit(1);
313 recursed = 1;
314 error_msg_and_die("Out of memory");
315}
316
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400317/* Glue for systems without a MMU that cannot provide fork() */
318#ifdef HAVE_FORK
319# define strace_vforked 0
320#else
321# define strace_vforked 1
322# define fork() vfork()
323#endif
324
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100325#ifdef USE_SEIZE
326static int
327ptrace_attach_or_seize(int pid)
328{
329 int r;
330 if (!use_seize)
331 return ptrace(PTRACE_ATTACH, pid, 0, 0);
332 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
333 if (r)
334 return r;
335 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
336 return r;
337}
338#else
339# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
340#endif
341
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200342static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343set_cloexec_flag(int fd)
344{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200345 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000346
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200347 flags = fcntl(fd, F_GETFD);
348 if (flags < 0) {
349 /* Can happen only if fd is bad.
350 * Should never happen: if it does, we have a bug
351 * in the caller. Therefore we just abort
352 * instead of propagating the error.
353 */
354 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000355 }
356
357 newflags = flags | FD_CLOEXEC;
358 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200359 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200361 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362}
363
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100364static void kill_save_errno(pid_t pid, int sig)
365{
366 int saved_errno = errno;
367
368 (void) kill(pid, sig);
369 errno = saved_errno;
370}
371
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100372void
373tprintf(const char *fmt, ...)
374{
375 va_list args;
376
377 va_start(args, fmt);
378 if (outf) {
379 int n = vfprintf(outf, fmt, args);
380 if (n < 0) {
381 if (outf != stderr)
382 perror(outfname == NULL
383 ? "<writing to pipe>" : outfname);
384 } else
385 curcol += n;
386 }
387 va_end(args);
388}
389
390void
391tprints(const char *str)
392{
393 if (outf) {
394 int n = fputs(str, outf);
395 if (n >= 0) {
396 curcol += strlen(str);
397 return;
398 }
399 if (outf != stderr)
400 perror(outfname == NULL
401 ? "<writing to pipe>" : outfname);
402 }
403}
404
405void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100406line_ended(void)
407{
408 curcol = 0;
409 fflush(outf);
410 if (!printing_tcp)
411 return;
412 printing_tcp->curcol = 0;
413 printing_tcp = NULL;
414}
415
416void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100417printleader(struct tcb *tcp)
418{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100419 /* If -ff, "previous tcb we printed" is always the same as current,
420 * because we have per-tcb output files.
421 */
422 if (followfork >= 2)
423 printing_tcp = tcp;
424
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100425 if (printing_tcp) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100426 outf = printing_tcp->outf;
427 curcol = printing_tcp->curcol;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100428 if (printing_tcp->ptrace_errno) {
429 if (printing_tcp->flags & TCB_INSYSCALL) {
430 tprints(" <unavailable>) ");
431 tabto();
432 }
433 tprints("= ? <unavailable>\n");
434 printing_tcp->ptrace_errno = 0;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100435 printing_tcp->curcol = 0;
436 }
437 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
438 /*
439 * case 1: we have a shared log (i.e. not -ff), and last line
440 * wasn't finished (same or different tcb, doesn't matter).
441 * case 2: split log, we are the same tcb, but our last line
442 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
443 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100444 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100445 printing_tcp->flags |= TCB_REPRINT;
446 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100447 }
448 }
449
450 printing_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100451 outf = tcp->outf;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100452 curcol = 0;
453
454 if (print_pid_pfx)
455 tprintf("%-5d ", tcp->pid);
456 else if (nprocs > 1 && !outfname)
457 tprintf("[pid %5u] ", tcp->pid);
458
459 if (tflag) {
460 char str[sizeof("HH:MM:SS")];
461 struct timeval tv, dtv;
462 static struct timeval otv;
463
464 gettimeofday(&tv, NULL);
465 if (rflag) {
466 if (otv.tv_sec == 0)
467 otv = tv;
468 tv_sub(&dtv, &tv, &otv);
469 tprintf("%6ld.%06ld ",
470 (long) dtv.tv_sec, (long) dtv.tv_usec);
471 otv = tv;
472 }
473 else if (tflag > 2) {
474 tprintf("%ld.%06ld ",
475 (long) tv.tv_sec, (long) tv.tv_usec);
476 }
477 else {
478 time_t local = tv.tv_sec;
479 strftime(str, sizeof(str), "%T", localtime(&local));
480 if (tflag > 1)
481 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
482 else
483 tprintf("%s ", str);
484 }
485 }
486 if (iflag)
487 printcall(tcp);
488}
489
490void
491tabto(void)
492{
493 if (curcol < acolumn)
494 tprints(acolumn_spaces + curcol);
495}
496
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000497/*
498 * When strace is setuid executable, we have to swap uids
499 * before and after filesystem and process management operations.
500 */
501static void
502swap_uid(void)
503{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000504 int euid = geteuid(), uid = getuid();
505
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200506 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200507 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000508 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000509}
510
Roland McGrath4bfa6262007-07-05 20:03:16 +0000511#if _LFS64_LARGEFILE
512# define fopen_for_output fopen64
513#else
514# define fopen_for_output fopen
515#endif
516
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000517static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200518strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000519{
520 FILE *fp;
521
522 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200523 fp = fopen_for_output(path, "w");
524 if (!fp)
525 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000526 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200527 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000528 return fp;
529}
530
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200531static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000532
533#ifndef _PATH_BSHELL
534# define _PATH_BSHELL "/bin/sh"
535#endif
536
537/*
538 * We cannot use standard popen(3) here because we have to distinguish
539 * popen child process from other processes we trace, and standard popen(3)
540 * does not export its child's pid.
541 */
542static FILE *
543strace_popen(const char *command)
544{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200545 FILE *fp;
546 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000547
548 swap_uid();
549 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200550 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000551
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200552 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000553
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200554 popen_pid = vfork();
555 if (popen_pid == -1)
556 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000557
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200558 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000559 /* child */
560 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200561 if (fds[0] != 0) {
562 if (dup2(fds[0], 0))
563 perror_msg_and_die("dup2");
564 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000565 }
566 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200567 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000568 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200569
570 /* parent */
571 close(fds[0]);
572 swap_uid();
573 fp = fdopen(fds[1], "w");
574 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200575 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200576 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000577}
578
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200579static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000580newoutf(struct tcb *tcp)
581{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100582 if (outfname && followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000583 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000584 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200585 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000586 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000587}
588
Denys Vlasenko558e5122012-03-12 23:32:16 +0100589static void
590process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100591{
592 while (*opt) {
593 /*
594 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
595 * pidof uses space as delim, pgrep uses newline. :(
596 */
597 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100598 char *delim = opt + strcspn(opt, ", \n\t");
599 char c = *delim;
600
601 *delim = '\0';
602 pid = atoi(opt); /* TODO: stricter parsing of the number? */
603 if (pid <= 0) {
604 error_msg("Invalid process id: '%s'", opt);
605 *delim = c;
606 return;
607 }
608 if (pid == strace_tracer_pid) {
609 error_msg("I'm sorry, I can't let you do that, Dave.");
610 *delim = c;
611 return;
612 }
613 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100614 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100615 if (c == '\0')
616 break;
617 opt = delim + 1;
618 }
619}
620
Roland McGrath02203312007-06-11 22:06:31 +0000621static void
622startup_attach(void)
623{
624 int tcbi;
625 struct tcb *tcp;
626
627 /*
628 * Block user interruptions as we would leave the traced
629 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200630 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200631 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000632 */
633 if (interactive)
634 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
635
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000636 if (daemonized_tracer) {
637 pid_t pid = fork();
638 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200639 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000640 }
641 if (pid) { /* parent */
642 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200643 * Wait for grandchild to attach to straced process
644 * (grandparent). Grandchild SIGKILLs us after it attached.
645 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000646 * it proceeds to exec the straced program.
647 */
648 pause();
649 _exit(0); /* paranoia */
650 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200651 /* grandchild */
652 /* We will be the tracer process. Remember our new pid: */
653 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000654 }
655
Roland McGrath02203312007-06-11 22:06:31 +0000656 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
657 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200658
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100659 if (!(tcp->flags & TCB_INUSE))
660 continue;
661
Denys Vlasenkod116a732011-09-05 14:01:33 +0200662 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100663 if (tcp->flags & TCB_ATTACHED)
664 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200665
666 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000667 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200668 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000669
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000670 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000671 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000672 DIR *dir;
673
674 sprintf(procdir, "/proc/%d/task", tcp->pid);
675 dir = opendir(procdir);
676 if (dir != NULL) {
677 unsigned int ntid = 0, nerr = 0;
678 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200679
Roland McGrath02203312007-06-11 22:06:31 +0000680 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200681 struct tcb *cur_tcp;
682 int tid;
683
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000684 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000685 continue;
686 tid = atoi(de->d_name);
687 if (tid <= 0)
688 continue;
689 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100690 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000691 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100692 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200693 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200694 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200695 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100696 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200697 fprintf(stderr, "attach to pid %d succeeded\n", tid);
698 cur_tcp = tcp;
699 if (tid != tcp->pid)
700 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100701 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000702 }
703 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200704 if (interactive) {
705 sigprocmask(SIG_SETMASK, &empty_set, NULL);
706 if (interrupted)
707 goto ret;
708 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
709 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000710 ntid -= nerr;
711 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000712 perror("attach: ptrace(PTRACE_ATTACH, ...)");
713 droptcb(tcp);
714 continue;
715 }
716 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000717 fprintf(stderr, ntid > 1
718? "Process %u attached with %u threads - interrupt to quit\n"
719: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200720 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000721 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100722 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200723 /* -p PID, we failed to attach to PID itself
724 * but did attach to some of its sibling threads.
725 * Drop PID's tcp.
726 */
727 droptcb(tcp);
728 }
Roland McGrath02203312007-06-11 22:06:31 +0000729 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000730 } /* if (opendir worked) */
731 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100732 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000733 perror("attach: ptrace(PTRACE_ATTACH, ...)");
734 droptcb(tcp);
735 continue;
736 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100737 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100738 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200739 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000740
741 if (daemonized_tracer) {
742 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000743 * Make parent go away.
744 * Also makes grandparent's wait() unblock.
745 */
746 kill(getppid(), SIGKILL);
747 }
748
Roland McGrath02203312007-06-11 22:06:31 +0000749 if (!qflag)
750 fprintf(stderr,
751 "Process %u attached - interrupt to quit\n",
752 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200753 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000754
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200755 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000756 if (interactive)
757 sigprocmask(SIG_SETMASK, &empty_set, NULL);
758}
759
760static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200761startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000762{
763 struct stat statbuf;
764 const char *filename;
765 char pathname[MAXPATHLEN];
766 int pid = 0;
767 struct tcb *tcp;
768
769 filename = argv[0];
770 if (strchr(filename, '/')) {
771 if (strlen(filename) > sizeof pathname - 1) {
772 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200773 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000774 }
775 strcpy(pathname, filename);
776 }
777#ifdef USE_DEBUGGING_EXEC
778 /*
779 * Debuggers customarily check the current directory
780 * first regardless of the path but doing that gives
781 * security geeks a panic attack.
782 */
783 else if (stat(filename, &statbuf) == 0)
784 strcpy(pathname, filename);
785#endif /* USE_DEBUGGING_EXEC */
786 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000787 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000788 int m, n, len;
789
790 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100791 const char *colon = strchr(path, ':');
792 if (colon) {
793 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000794 m = n + 1;
795 }
796 else
797 m = n = strlen(path);
798 if (n == 0) {
799 if (!getcwd(pathname, MAXPATHLEN))
800 continue;
801 len = strlen(pathname);
802 }
803 else if (n > sizeof pathname - 1)
804 continue;
805 else {
806 strncpy(pathname, path, n);
807 len = n;
808 }
809 if (len && pathname[len - 1] != '/')
810 pathname[len++] = '/';
811 strcpy(pathname + len, filename);
812 if (stat(pathname, &statbuf) == 0 &&
813 /* Accept only regular files
814 with some execute bits set.
815 XXX not perfect, might still fail */
816 S_ISREG(statbuf.st_mode) &&
817 (statbuf.st_mode & 0111))
818 break;
819 }
820 }
821 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200822 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000823 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000824 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000825 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200826 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000827 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200828 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
829 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000830 ) {
831 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200832 if (outf != stderr)
833 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100834 if (!daemonized_tracer && !use_seize) {
835 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200836 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000837 }
Roland McGrath02203312007-06-11 22:06:31 +0000838 }
Roland McGrath02203312007-06-11 22:06:31 +0000839
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200840 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000841 uid_t run_euid = run_uid;
842 gid_t run_egid = run_gid;
843
844 if (statbuf.st_mode & S_ISUID)
845 run_euid = statbuf.st_uid;
846 if (statbuf.st_mode & S_ISGID)
847 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000848 /*
849 * It is important to set groups before we
850 * lose privileges on setuid.
851 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200852 if (initgroups(username, run_gid) < 0) {
853 perror_msg_and_die("initgroups");
854 }
855 if (setregid(run_gid, run_egid) < 0) {
856 perror_msg_and_die("setregid");
857 }
858 if (setreuid(run_uid, run_euid) < 0) {
859 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000860 }
861 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200862 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000863 setreuid(run_uid, run_uid);
864
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000865 if (!daemonized_tracer) {
866 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200867 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000868 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200869 * the immediately following execve syscall.
870 * Can't do this on NOMMU systems, we are after
871 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000872 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400873 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200874 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000875 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000876 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +0100877 /* we depend on SIGCHLD set to SIG_DFL by init code */
878 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000879 wait(NULL);
880 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000881 }
Roland McGrath02203312007-06-11 22:06:31 +0000882
883 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200884 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000885 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000886
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200887 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200888
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200889 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100890 if (!use_seize) {
891 /* child did PTRACE_TRACEME, nothing to do in parent */
892 } else {
893 if (!strace_vforked) {
894 /* Wait until child stopped itself */
895 int status;
896 while (waitpid(pid, &status, WSTOPPED) < 0) {
897 if (errno == EINTR)
898 continue;
899 perror_msg_and_die("waitpid");
900 }
901 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100902 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100903 perror_msg_and_die("Unexpected wait status %x", status);
904 }
905 }
906 /* Else: vforked case, we have no way to sync.
907 * Just attach to it as soon as possible.
908 * This means that we may miss a few first syscalls...
909 */
910
911 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100912 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100913 perror_msg_and_die("Can't attach to %d", pid);
914 }
915 if (!strace_vforked)
916 kill(pid, SIGCONT);
917 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200918 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200919 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100920 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200921 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100922 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200923 }
924 else {
925 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
926 strace_tracer_pid = getpid();
927 /* The tracee is our parent: */
928 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100929 alloctcb(pid);
930 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000931 }
Roland McGrath02203312007-06-11 22:06:31 +0000932}
933
Wang Chaob13c0de2010-11-12 17:25:19 +0800934/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000935 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800936 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000937 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800938 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000939static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200940test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800941{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000942 int pid, expected_grandchild = 0, found_grandchild = 0;
943 const unsigned int test_options = PTRACE_O_TRACECLONE |
944 PTRACE_O_TRACEFORK |
945 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800946
Denys Vlasenko5d645812011-08-20 12:48:18 +0200947 pid = fork();
948 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000949 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200950 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000951 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100952 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000953 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
954 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100955 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000956 if (fork() < 0)
957 perror_msg_and_die("fork");
958 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800959 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000960
961 while (1) {
962 int status, tracee_pid;
963
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000964 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000965 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000966 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000967 if (errno == EINTR)
968 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100969 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000970 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000971 kill_save_errno(pid, SIGKILL);
972 perror_msg_and_die("%s: unexpected wait result %d",
973 __func__, tracee_pid);
974 }
975 if (WIFEXITED(status)) {
976 if (WEXITSTATUS(status)) {
977 if (tracee_pid != pid)
978 kill_save_errno(pid, SIGKILL);
979 error_msg_and_die("%s: unexpected exit status %u",
980 __func__, WEXITSTATUS(status));
981 }
982 continue;
983 }
984 if (WIFSIGNALED(status)) {
985 if (tracee_pid != pid)
986 kill_save_errno(pid, SIGKILL);
987 error_msg_and_die("%s: unexpected signal %u",
988 __func__, WTERMSIG(status));
989 }
990 if (!WIFSTOPPED(status)) {
991 if (tracee_pid != pid)
992 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100993 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000994 error_msg_and_die("%s: unexpected wait status %x",
995 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000996 }
997 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000998 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000999 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1000 kill_save_errno(tracee_pid, SIGKILL);
1001 kill_save_errno(pid, SIGKILL);
1002 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001003 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001004 continue;
1005 }
1006 switch (WSTOPSIG(status)) {
1007 case SIGSTOP:
1008 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1009 && errno != EINVAL && errno != EIO)
1010 perror_msg("PTRACE_SETOPTIONS");
1011 break;
1012 case SIGTRAP:
1013 if (status >> 16 == PTRACE_EVENT_FORK) {
1014 long msg = 0;
1015
1016 if (ptrace(PTRACE_GETEVENTMSG, pid,
1017 NULL, (long) &msg) == 0)
1018 expected_grandchild = msg;
1019 }
1020 break;
1021 }
1022 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1023 kill_save_errno(pid, SIGKILL);
1024 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001025 }
1026 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001027 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001028 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001029 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001030 fprintf(stderr, "ptrace_setoptions = %#x\n",
1031 ptrace_setoptions);
1032 return;
1033 }
1034 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1035 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001036}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001037
1038/*
1039 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1040 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1041 * and then see whether it will stop with (SIGTRAP | 0x80).
1042 *
1043 * Use of this option enables correct handling of user-generated SIGTRAPs,
1044 * and SIGTRAPs generated by special instructions such as int3 on x86:
1045 * _start: .globl _start
1046 * int3
1047 * movl $42, %ebx
1048 * movl $1, %eax
1049 * int $0x80
1050 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1051 */
1052static void
1053test_ptrace_setoptions_for_all(void)
1054{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001055 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1056 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001057 int pid;
1058 int it_worked = 0;
1059
1060 pid = fork();
1061 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001062 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001063
1064 if (pid == 0) {
1065 pid = getpid();
1066 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001067 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001068 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1069 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001070 kill(pid, SIGSTOP);
1071 _exit(0); /* parent should see entry into this syscall */
1072 }
1073
1074 while (1) {
1075 int status, tracee_pid;
1076
1077 errno = 0;
1078 tracee_pid = wait(&status);
1079 if (tracee_pid <= 0) {
1080 if (errno == EINTR)
1081 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001082 kill_save_errno(pid, SIGKILL);
1083 perror_msg_and_die("%s: unexpected wait result %d",
1084 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001085 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001086 if (WIFEXITED(status)) {
1087 if (WEXITSTATUS(status) == 0)
1088 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001089 error_msg_and_die("%s: unexpected exit status %u",
1090 __func__, WEXITSTATUS(status));
1091 }
1092 if (WIFSIGNALED(status)) {
1093 error_msg_and_die("%s: unexpected signal %u",
1094 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001095 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001096 if (!WIFSTOPPED(status)) {
1097 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001098 error_msg_and_die("%s: unexpected wait status %x",
1099 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001100 }
1101 if (WSTOPSIG(status) == SIGSTOP) {
1102 /*
1103 * We don't check "options aren't accepted" error.
1104 * If it happens, we'll never get (SIGTRAP | 0x80),
1105 * and thus will decide to not use the option.
1106 * IOW: the outcome of the test will be correct.
1107 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001108 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1109 && errno != EINVAL && errno != EIO)
1110 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001111 }
1112 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1113 it_worked = 1;
1114 }
1115 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001116 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001117 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001118 }
1119 }
1120
1121 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001122 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001123 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001124 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001125 fprintf(stderr, "ptrace_setoptions = %#x\n",
1126 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001127 return;
1128 }
1129
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001130 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1131 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001132}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001133
1134# ifdef USE_SEIZE
1135static void
1136test_ptrace_seize(void)
1137{
1138 int pid;
1139
1140 pid = fork();
1141 if (pid < 0)
1142 perror_msg_and_die("fork");
1143
1144 if (pid == 0) {
1145 pause();
1146 _exit(0);
1147 }
1148
1149 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1150 * attaching tracee continues to run unless a trap condition occurs.
1151 * PTRACE_SEIZE doesn't affect signal or group stop state.
1152 */
1153 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1154 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001155 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001156 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1157 }
1158
1159 kill(pid, SIGKILL);
1160
1161 while (1) {
1162 int status, tracee_pid;
1163
1164 errno = 0;
1165 tracee_pid = waitpid(pid, &status, 0);
1166 if (tracee_pid <= 0) {
1167 if (errno == EINTR)
1168 continue;
1169 perror_msg_and_die("%s: unexpected wait result %d",
1170 __func__, tracee_pid);
1171 }
1172 if (WIFSIGNALED(status)) {
1173 return;
1174 }
1175 error_msg_and_die("%s: unexpected wait status %x",
1176 __func__, status);
1177 }
1178}
1179# else /* !USE_SEIZE */
1180# define test_ptrace_seize() ((void)0)
1181# endif
1182
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001183static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001184get_os_release(void)
1185{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001186 unsigned rel;
1187 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001188 struct utsname u;
1189 if (uname(&u) < 0)
1190 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001191 /* u.release has this form: "3.2.9[-some-garbage]" */
1192 rel = 0;
1193 p = u.release;
1194 for (;;) {
1195 if (!(*p >= '0' && *p <= '9'))
1196 error_msg_and_die("Bad OS release string: '%s'", u.release);
1197 /* Note: this open-codes KERNEL_VERSION(): */
1198 rel = (rel << 8) | atoi(p);
1199 if (rel >= KERNEL_VERSION(1,0,0))
1200 break;
1201 while (*p >= '0' && *p <= '9')
1202 p++;
1203 if (*p != '.')
1204 error_msg_and_die("Bad OS release string: '%s'", u.release);
1205 p++;
1206 }
1207 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001208}
1209
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001210/*
1211 * Initialization part of main() was eating much stack (~0.5k),
1212 * which was unused after init.
1213 * We can reuse it if we move init code into a separate function.
1214 *
1215 * Don't want main() to inline us and defeat the reason
1216 * we have a separate function.
1217 */
1218static void __attribute__ ((noinline))
1219init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001222 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001223 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 struct sigaction sa;
1225
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001226 progname = argv[0] ? argv[0] : "strace";
1227
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001228 /* Make sure SIGCHLD has the default action so that waitpid
1229 definitely works without losing track of children. The user
1230 should not have given us a bogus state to inherit, but he might
1231 have. Arguably we should detect SIG_IGN here and pass it on
1232 to children, but probably noone really needs that. */
1233 signal(SIGCHLD, SIG_DFL);
1234
Denys Vlasenko75422762011-05-27 14:36:01 +02001235 strace_tracer_pid = getpid();
1236
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001237 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001238
Roland McGrathee9d4352002-12-18 04:16:10 +00001239 /* Allocate the initial tcbtab. */
1240 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001241 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001242 if (!tcbtab)
1243 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001244 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001245 if (!tcp)
1246 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001247 for (c = 0; c < tcbtabsize; c++)
1248 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001249
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001251 set_sortby(DEFAULT_SORTBY);
1252 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 qualify("trace=all");
1254 qualify("abbrev=all");
1255 qualify("verbose=all");
1256 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001258 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001259 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001260 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001262 case 'b':
1263 detach_on_execve = 1;
1264 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001266 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001267 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001268 }
1269 cflag = CFLAG_ONLY_STATS;
1270 break;
1271 case 'C':
1272 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001273 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001274 }
1275 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 break;
1277 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001278 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001280 case 'D':
1281 daemonized_tracer = 1;
1282 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001283 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001284 optF = 1;
1285 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001286 case 'f':
1287 followfork++;
1288 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289 case 'h':
1290 usage(stdout, 0);
1291 break;
1292 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001293 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294 break;
1295 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001296 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001297 break;
1298 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001299 rflag = 1;
1300 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001301 case 't':
1302 tflag++;
1303 break;
1304 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001305 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306 break;
1307 case 'x':
1308 xflag++;
1309 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001310 case 'y':
1311 show_fd_path = 1;
1312 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 case 'v':
1314 qualify("abbrev=none");
1315 break;
1316 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001317 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318 exit(0);
1319 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001320 case 'z':
1321 not_failing_only = 1;
1322 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323 case 'a':
1324 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001325 if (acolumn < 0)
1326 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001327 break;
1328 case 'e':
1329 qualify(optarg);
1330 break;
1331 case 'o':
1332 outfname = strdup(optarg);
1333 break;
1334 case 'O':
1335 set_overhead(atoi(optarg));
1336 break;
1337 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001338 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001340 case 'P':
1341 tracing_paths = 1;
1342 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001343 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001344 }
1345 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346 case 's':
1347 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001348 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001349 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001350 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001351 break;
1352 case 'S':
1353 set_sortby(optarg);
1354 break;
1355 case 'u':
1356 username = strdup(optarg);
1357 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001358 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001359 if (putenv(optarg) < 0)
1360 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001361 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001362 case 'I':
1363 opt_intr = atoi(optarg);
1364 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1365 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1366 }
1367 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001368 default:
1369 usage(stderr, 1);
1370 break;
1371 }
1372 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001373 argv += optind;
1374 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375
Denys Vlasenko102ec492011-08-25 01:27:59 +02001376 acolumn_spaces = malloc(acolumn + 1);
1377 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001378 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001379 memset(acolumn_spaces, ' ', acolumn);
1380 acolumn_spaces[acolumn] = '\0';
1381
Denys Vlasenko837399a2012-01-24 11:37:03 +01001382 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001383 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001384 usage(stderr, 1);
1385
Denys Vlasenkofd883382012-03-09 13:03:41 +01001386 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001387 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001388 }
1389
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001390 if (!followfork)
1391 followfork = optF;
1392
Roland McGrathcb9def62006-04-25 07:48:03 +00001393 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001394 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001395 }
1396
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001397 /* See if they want to run as another user. */
1398 if (username != NULL) {
1399 struct passwd *pent;
1400
1401 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001402 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001403 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001404 pent = getpwnam(username);
1405 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001406 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407 }
1408 run_uid = pent->pw_uid;
1409 run_gid = pent->pw_gid;
1410 }
1411 else {
1412 run_uid = getuid();
1413 run_gid = getgid();
1414 }
1415
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001416 if (followfork)
1417 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001418 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001419 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001420
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421 /* Check if they want to redirect the output. */
1422 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001423 /* See if they want to pipe the output. */
1424 if (outfname[0] == '|' || outfname[0] == '!') {
1425 /*
1426 * We can't do the <outfname>.PID funny business
1427 * when using popen, so prohibit it.
1428 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001429 if (followfork > 1)
1430 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1431 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001432 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001433 else if (followfork <= 1)
1434 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001435 } else {
1436 /* -ff without -o FILE is the same as single -f */
1437 if (followfork > 1)
1438 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439 }
1440
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001441 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001442 char *buf = malloc(BUFSIZ);
1443 if (!buf)
1444 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001446 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001447 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001448 if (!opt_intr)
1449 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001451 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001452 if (!opt_intr)
1453 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001454
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001455 /* argv[0] -pPID -oFILE Default interactive setting
1456 * yes 0 0 INTR_WHILE_WAIT
1457 * no 1 0 INTR_WHILE_WAIT
1458 * yes 0 1 INTR_NEVER
1459 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001460 */
1461
1462 /* STARTUP_CHILD must be called before the signal handlers get
1463 installed below as they are inherited into the spawned process.
1464 Also we do not need to be protected by them as during interruption
1465 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001466 if (argv[0]) {
1467 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001468 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001469 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 sigemptyset(&empty_set);
1472 sigemptyset(&blocked_set);
1473 sa.sa_handler = SIG_IGN;
1474 sigemptyset(&sa.sa_mask);
1475 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001476 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1477 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1478 if (opt_intr != INTR_ANYWHERE) {
1479 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1480 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1481 /*
1482 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1483 * fatal signals are blocked while syscall stop is processed,
1484 * and acted on in between, when waiting for new syscall stops.
1485 * In non-interactive mode, signals are ignored.
1486 */
1487 if (opt_intr == INTR_WHILE_WAIT) {
1488 sigaddset(&blocked_set, SIGHUP);
1489 sigaddset(&blocked_set, SIGINT);
1490 sigaddset(&blocked_set, SIGQUIT);
1491 sigaddset(&blocked_set, SIGPIPE);
1492 sigaddset(&blocked_set, SIGTERM);
1493 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001494 }
1495 /* SIG_IGN, or set handler for these */
1496 sigaction(SIGHUP, &sa, NULL);
1497 sigaction(SIGINT, &sa, NULL);
1498 sigaction(SIGQUIT, &sa, NULL);
1499 sigaction(SIGPIPE, &sa, NULL);
1500 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001502 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001503 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001504
Denys Vlasenkofd883382012-03-09 13:03:41 +01001505 /* Do we want pids printed in our -o OUTFILE?
1506 * -ff: no (every pid has its own file); or
1507 * -f: yes (there can be more pids in the future); or
1508 * -p PID1,PID2: yes (there are already more than one pid)
1509 */
1510 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001511}
1512
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001513static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001514expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001515{
1516 /* Allocate some more TCBs and expand the table.
1517 We don't want to relocate the TCBs because our
1518 callers have pointers and it would be a pain.
1519 So tcbtab is a table of pointers. Since we never
1520 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001521 int i = tcbtabsize;
1522 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1523 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001524 if (!newtab || !newtcbs)
1525 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001526 tcbtabsize *= 2;
1527 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001528 while (i < tcbtabsize)
1529 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001530}
1531
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001533alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534{
1535 int i;
1536 struct tcb *tcp;
1537
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001538 if (nprocs == tcbtabsize)
1539 expand_tcbtab();
1540
Roland McGrathee9d4352002-12-18 04:16:10 +00001541 for (i = 0; i < tcbtabsize; i++) {
1542 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001544 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001546 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001548#if SUPPORTED_PERSONALITIES > 1
1549 tcp->currpers = current_personality;
1550#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551 nprocs++;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001552 if (debug_flag)
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001553 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001554 if (command_options_parsed)
1555 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556 return tcp;
1557 }
1558 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001559 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001560}
1561
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001562static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001563pid2tcb(int pid)
1564{
1565 int i;
1566
1567 if (pid <= 0)
1568 return NULL;
1569
1570 for (i = 0; i < tcbtabsize; i++) {
1571 struct tcb *tcp = tcbtab[i];
1572 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1573 return tcp;
1574 }
1575
1576 return NULL;
1577}
1578
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579void
Denys Vlasenko12014262011-05-30 14:00:14 +02001580droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581{
1582 if (tcp->pid == 0)
1583 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001584
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585 nprocs--;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001586 if (debug_flag)
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001587 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001588
Denys Vlasenko3e084ac2012-03-15 13:39:05 +01001589 if (tcp->outf) {
1590 if (outfname && followfork >= 2) {
1591 if (tcp->curcol != 0)
1592 fprintf(tcp->outf, " <detached ...>\n");
1593 fclose(tcp->outf);
1594 if (outf == tcp->outf)
1595 outf = NULL;
1596 } else {
1597 if (printing_tcp == tcp && tcp->curcol != 0)
1598 fprintf(tcp->outf, " <detached ...>\n");
1599 fflush(tcp->outf);
1600 }
1601 }
1602
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001603 if (printing_tcp == tcp)
1604 printing_tcp = NULL;
1605
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001606 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607}
1608
Roland McGrath0a463882007-07-05 18:43:16 +00001609/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001610 * Never call DETACH twice on the same process as both unattached and
1611 * attached-unstopped processes give the same ESRCH. For unattached process we
1612 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1613 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001615detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001617 int error;
1618 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619
1620 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001621 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623 /*
1624 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001625 * before detaching. Arghh. We go through hoops
1626 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001628#if defined(SPARC)
1629#undef PTRACE_DETACH
1630#define PTRACE_DETACH PTRACE_SUNDETACH
1631#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001632
Denys Vlasenko3e084ac2012-03-15 13:39:05 +01001633 error = 0;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001634 sigstop_expected = 0;
1635 if (tcp->flags & TCB_ATTACHED) {
1636 /*
1637 * We attached but possibly didn't see the expected SIGSTOP.
1638 * We must catch exactly one as otherwise the detached process
1639 * would be left stopped (process state T).
1640 */
1641 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1642 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1643 if (error == 0) {
1644 /* On a clear day, you can see forever. */
1645 }
1646 else if (errno != ESRCH) {
1647 /* Shouldn't happen. */
1648 perror("detach: ptrace(PTRACE_DETACH, ...)");
1649 }
1650 else if (my_tkill(tcp->pid, 0) < 0) {
1651 if (errno != ESRCH)
1652 perror("detach: checking sanity");
1653 }
1654 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1655 if (errno != ESRCH)
1656 perror("detach: stopping child");
1657 }
1658 else
1659 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001660 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001661
1662 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001664#ifdef __WALL
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001665 if (waitpid(tcp->pid, &status, __WALL) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001666 if (errno == ECHILD) /* Already gone. */
1667 break;
1668 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001669 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001670 break;
1671 }
1672#endif /* __WALL */
1673 /* No __WALL here. */
1674 if (waitpid(tcp->pid, &status, 0) < 0) {
1675 if (errno != ECHILD) {
1676 perror("detach: waiting");
1677 break;
1678 }
1679#ifdef __WCLONE
1680 /* If no processes, try clones. */
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001681 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001682 if (errno != ECHILD)
1683 perror("detach: waiting");
1684 break;
1685 }
1686#endif /* __WCLONE */
1687 }
1688#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001689 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001690#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 if (!WIFSTOPPED(status)) {
1692 /* Au revoir, mon ami. */
1693 break;
1694 }
1695 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001696 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 break;
1698 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001699 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001700 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001701 : WSTOPSIG(status));
1702 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001704 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001705 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001707 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708 fprintf(stderr, "Process %u detached\n", tcp->pid);
1709
1710 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001711
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 return error;
1713}
1714
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001716cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717{
1718 int i;
1719 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001720 int fatal_sig;
1721
1722 /* 'interrupted' is a volatile object, fetch it only once */
1723 fatal_sig = interrupted;
1724 if (!fatal_sig)
1725 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001726
Roland McGrathee9d4352002-12-18 04:16:10 +00001727 for (i = 0; i < tcbtabsize; i++) {
1728 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729 if (!(tcp->flags & TCB_INUSE))
1730 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001731 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 fprintf(stderr,
1733 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001734 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001736 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001738 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 }
1740 if (cflag)
1741 call_summary(outf);
1742}
1743
1744static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001745interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001747 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748}
1749
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001751trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001754 struct rusage *rup = cflag ? &ru : NULL;
1755# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001756 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001757# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
Roland McGratheb9e2e82009-06-02 16:49:22 -07001759 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001760 int pid;
1761 int wait_errno;
1762 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001763 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001764 struct tcb *tcp;
1765 unsigned event;
1766
Denys Vlasenko222713a2009-03-17 14:29:59 +00001767 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001768 return 0;
1769 if (interactive)
1770 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001771# ifdef __WALL
1772 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001773 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001774 /* this kernel does not support __WALL */
1775 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001776 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001777 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001778 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001779 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001780 pid = wait4(-1, &status, __WCLONE, rup);
1781 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001782 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001783 }
1784 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001785# else
1786 pid = wait4(-1, &status, 0, rup);
1787# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001789 if (interactive)
1790 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001792 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001793 switch (wait_errno) {
1794 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001796 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 /*
1798 * We would like to verify this case
1799 * but sometimes a race in Solbourne's
1800 * version of SunOS sometimes reports
1801 * ECHILD before sending us SIGCHILD.
1802 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001803 return 0;
1804 default:
1805 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001806 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001807 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 }
1809 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001810 if (pid == popen_pid) {
1811 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001812 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001813 continue;
1814 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001815
1816 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001817 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001818 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001819 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001820 strcpy(buf, "???");
1821 if (WIFSIGNALED(status))
1822#ifdef WCOREDUMP
1823 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1824 WCOREDUMP(status) ? "core," : "",
1825 signame(WTERMSIG(status)));
1826#else
1827 sprintf(buf, "WIFSIGNALED,sig=%s",
1828 signame(WTERMSIG(status)));
1829#endif
1830 if (WIFEXITED(status))
1831 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1832 if (WIFSTOPPED(status))
1833 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001834#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001835 if (WIFCONTINUED(status))
1836 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001837#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001838 evbuf[0] = '\0';
1839 if (event != 0) {
1840 static const char *const event_names[] = {
1841 [PTRACE_EVENT_CLONE] = "CLONE",
1842 [PTRACE_EVENT_FORK] = "FORK",
1843 [PTRACE_EVENT_VFORK] = "VFORK",
1844 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1845 [PTRACE_EVENT_EXEC] = "EXEC",
1846 [PTRACE_EVENT_EXIT] = "EXIT",
1847 };
1848 const char *e;
1849 if (event < ARRAY_SIZE(event_names))
1850 e = event_names[event];
1851 else {
1852 sprintf(buf, "?? (%u)", event);
1853 e = buf;
1854 }
1855 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1856 }
1857 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001858 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001860 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001861 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001862
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001863 /* Under Linux, execve changes pid to thread leader's pid,
1864 * and we see this changed pid on EVENT_EXEC and later,
1865 * execve sysexit. Leader "disappears" without exit
1866 * notification. Let user know that, drop leader's tcb,
1867 * and fix up pid in execve thread's tcb.
1868 * Effectively, execve thread's tcb replaces leader's tcb.
1869 *
1870 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1871 * on exit syscall) in multithreaded programs exactly
1872 * in order to handle this case.
1873 *
1874 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1875 * On 2.6 and earlier, it can return garbage.
1876 */
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001877 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001878 long old_pid = 0;
1879 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1880 && old_pid > 0
1881 && old_pid != pid
1882 ) {
1883 struct tcb *execve_thread = pid2tcb(old_pid);
1884 if (tcp) {
1885 outf = tcp->outf;
1886 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001887 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001888 if (execve_thread->curcol != 0) {
1889 /*
1890 * One case we are here is -ff:
1891 * try "strace -oLOG -ff test/threaded_execve"
1892 */
1893 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1894 execve_thread->curcol = 0;
1895 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001896 /* swap output FILEs (needed for -ff) */
1897 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001898 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001899 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001900 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001901 }
1902 droptcb(tcp);
1903 }
1904 tcp = execve_thread;
1905 if (tcp) {
1906 tcp->pid = pid;
1907 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001908 if (!cflag) {
1909 printleader(tcp);
1910 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1911 line_ended();
1912 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001913 }
1914 }
1915 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001916
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001917 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1918 if (!skip_startup_execve)
1919 detach(tcp);
1920 /* This was initial execve for "strace PROG". Skip. */
1921 skip_startup_execve = 0;
1922 }
1923
Denys Vlasenko5d645812011-08-20 12:48:18 +02001924 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001925 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001926 /* This is needed to go with the CLONE_PTRACE
1927 changes in process.c/util.c: we might see
1928 the child's initial trap before we see the
1929 parent return from the clone syscall.
1930 Leave the child suspended until the parent
1931 returns from its system call. Only then
1932 will we have the association of parent and
1933 child so that we know how to do clearbpt
1934 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001935 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001936 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001937 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001938 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001939 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001940 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001941 else
1942 /* This can happen if a clone call used
1943 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001944 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001945 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001946 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001947 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001948 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001950
1951 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001952 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001953 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001954
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001955 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001956 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1957 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001958 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001959
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001961 if (pid == strace_child)
1962 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001963 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001964 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1965 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001966#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001967 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001968 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001969 WCOREDUMP(status) ? "(core dumped) " : "");
1970#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001971 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001972 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001973#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001974 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 }
1976 droptcb(tcp);
1977 continue;
1978 }
1979 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001980 if (pid == strace_child)
1981 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001982 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1983 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001984 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001985 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001986 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001987 droptcb(tcp);
1988 continue;
1989 }
1990 if (!WIFSTOPPED(status)) {
1991 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1992 droptcb(tcp);
1993 continue;
1994 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001996 /* Is this the very first time we see this tracee stopped? */
1997 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001998 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001999 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002002 /*
2003 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002004 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002005 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002006 if (clearbpt(tcp) < 0) {
2007 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002008 droptcb(tcp);
2009 cleanup();
2010 return -1;
2011 }
2012 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002013 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002014 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002015 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2016 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2017 if (errno != ESRCH) {
2018 /* Should never happen, really */
2019 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002020 }
2021 }
2022 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002023 }
2024
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002025 sig = WSTOPSIG(status);
2026
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002027 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002028 /* Ptrace event */
2029#ifdef USE_SEIZE
2030 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002031 /*
2032 * PTRACE_INTERRUPT-stop or group-stop.
2033 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2034 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002035 if (sig == SIGSTOP
2036 || sig == SIGTSTP
2037 || sig == SIGTTIN
2038 || sig == SIGTTOU
2039 ) {
2040 stopped = 1;
2041 goto show_stopsig;
2042 }
2043 }
2044#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002045 goto restart_tracee_with_sig_0;
2046 }
2047
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002048 /* Is this post-attach SIGSTOP?
2049 * Interestingly, the process may stop
2050 * with STOPSIG equal to some other signal
2051 * than SIGSTOP if we happend to attach
2052 * just before the process takes a signal.
2053 */
2054 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002055 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002056 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2057 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002058 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059 }
2060
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002061 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002062 siginfo_t si;
2063
2064 /* Nonzero (true) if tracee is stopped by signal
2065 * (as opposed to "tracee received signal").
2066 */
2067 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002068#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002069 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002070#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002071 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002072 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002073#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002074 long pc = 0;
2075 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002076
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002077 upeek(tcp, PT_CR_IPSR, &psr);
2078 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002079
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002080# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002081 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002082# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002083# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002084#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002085# define PC_FORMAT_STR ""
2086# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002087#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002088 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002089 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002090 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002091 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002092 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002093 PC_FORMAT_ARG);
2094 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002095 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002096 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002097 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002098 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002100
2101 if (!stopped)
2102 /* It's signal-delivery-stop. Inject the signal */
2103 goto restart_tracee;
2104
2105 /* It's group-stop */
2106#ifdef USE_SEIZE
2107 if (use_seize) {
2108 /*
2109 * This ends ptrace-stop, but does *not* end group-stop.
2110 * This makes stopping signals work properly on straced process
2111 * (that is, process really stops. It used to continue to run).
2112 */
2113 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2114 cleanup();
2115 return -1;
2116 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002117 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002118 continue;
2119 }
2120 /* We don't have PTRACE_LISTEN support... */
2121#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002122 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002123 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002124
2125 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002126 if (interrupted)
2127 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002128
2129 /* This should be syscall entry or exit.
2130 * (Or it still can be that pesky post-execve SIGTRAP!)
2131 * Handle it.
2132 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002133 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2134 /* ptrace() failed in trace_syscall() with ESRCH.
2135 * Likely a result of process disappearing mid-flight.
2136 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002137 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002138 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002139 * We used to detach(tcp) here, but since we no longer
2140 * implement "detach before death" policy/hack,
2141 * we can let this process to report its death to us
2142 * normally, via WIFEXITED or WIFSIGNALED wait status.
2143 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002144 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002145 continue;
2146 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002147 restart_tracee_with_sig_0:
2148 sig = 0;
2149 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002150 /* Remember current print column before continuing. */
2151 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002152 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 cleanup();
2154 return -1;
2155 }
2156 }
2157 return 0;
2158}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002159
2160int
2161main(int argc, char *argv[])
2162{
2163 init(argc, argv);
2164
2165 /* Run main tracing loop */
2166 if (trace() < 0)
2167 return 1;
2168
2169 cleanup();
2170 fflush(NULL);
2171 if (exit_code > 0xff) {
2172 /* Avoid potential core file clobbering. */
2173 struct rlimit rlim = {0, 0};
2174 setrlimit(RLIMIT_CORE, &rlim);
2175
2176 /* Child was killed by a signal, mimic that. */
2177 exit_code &= 0xff;
2178 signal(exit_code, SIG_DFL);
2179 raise(exit_code);
2180 /* Paranoia - what if this signal is not fatal?
2181 Exit with 128 + signo then. */
2182 exit_code += 128;
2183 }
2184
2185 return exit_code;
2186}