blob: dda340465a7b415909edb650086be62b03404f8d [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 {
876 struct sigaction sv_sigchld;
877 sigaction(SIGCHLD, NULL, &sv_sigchld);
878 /*
879 * Make sure it is not SIG_IGN, otherwise wait
880 * will not block.
881 */
882 signal(SIGCHLD, SIG_DFL);
883 /*
884 * Wait for grandchild to attach to us.
885 * It kills child after that, and wait() unblocks.
886 */
887 alarm(3);
888 wait(NULL);
889 alarm(0);
890 sigaction(SIGCHLD, &sv_sigchld, NULL);
891 }
Roland McGrath02203312007-06-11 22:06:31 +0000892
893 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200894 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000895 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000896
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200897 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200898
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200899 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100900 if (!use_seize) {
901 /* child did PTRACE_TRACEME, nothing to do in parent */
902 } else {
903 if (!strace_vforked) {
904 /* Wait until child stopped itself */
905 int status;
906 while (waitpid(pid, &status, WSTOPPED) < 0) {
907 if (errno == EINTR)
908 continue;
909 perror_msg_and_die("waitpid");
910 }
911 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
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("Unexpected wait status %x", status);
914 }
915 }
916 /* Else: vforked case, we have no way to sync.
917 * Just attach to it as soon as possible.
918 * This means that we may miss a few first syscalls...
919 */
920
921 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100922 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100923 perror_msg_and_die("Can't attach to %d", pid);
924 }
925 if (!strace_vforked)
926 kill(pid, SIGCONT);
927 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200928 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200929 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100930 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200931 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100932 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200933 }
934 else {
935 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
936 strace_tracer_pid = getpid();
937 /* The tracee is our parent: */
938 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100939 alloctcb(pid);
940 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000941 }
Roland McGrath02203312007-06-11 22:06:31 +0000942}
943
Wang Chaob13c0de2010-11-12 17:25:19 +0800944/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000945 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800946 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000947 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800948 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000949static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200950test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800951{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000952 int pid, expected_grandchild = 0, found_grandchild = 0;
953 const unsigned int test_options = PTRACE_O_TRACECLONE |
954 PTRACE_O_TRACEFORK |
955 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800956
Denys Vlasenko5d645812011-08-20 12:48:18 +0200957 pid = fork();
958 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000959 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200960 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000961 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100962 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000963 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
964 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100965 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000966 if (fork() < 0)
967 perror_msg_and_die("fork");
968 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800969 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000970
971 while (1) {
972 int status, tracee_pid;
973
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000974 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000975 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000976 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000977 if (errno == EINTR)
978 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100979 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000980 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000981 kill_save_errno(pid, SIGKILL);
982 perror_msg_and_die("%s: unexpected wait result %d",
983 __func__, tracee_pid);
984 }
985 if (WIFEXITED(status)) {
986 if (WEXITSTATUS(status)) {
987 if (tracee_pid != pid)
988 kill_save_errno(pid, SIGKILL);
989 error_msg_and_die("%s: unexpected exit status %u",
990 __func__, WEXITSTATUS(status));
991 }
992 continue;
993 }
994 if (WIFSIGNALED(status)) {
995 if (tracee_pid != pid)
996 kill_save_errno(pid, SIGKILL);
997 error_msg_and_die("%s: unexpected signal %u",
998 __func__, WTERMSIG(status));
999 }
1000 if (!WIFSTOPPED(status)) {
1001 if (tracee_pid != pid)
1002 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001003 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001004 error_msg_and_die("%s: unexpected wait status %x",
1005 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001006 }
1007 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001008 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001009 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1010 kill_save_errno(tracee_pid, SIGKILL);
1011 kill_save_errno(pid, SIGKILL);
1012 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001013 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001014 continue;
1015 }
1016 switch (WSTOPSIG(status)) {
1017 case SIGSTOP:
1018 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1019 && errno != EINVAL && errno != EIO)
1020 perror_msg("PTRACE_SETOPTIONS");
1021 break;
1022 case SIGTRAP:
1023 if (status >> 16 == PTRACE_EVENT_FORK) {
1024 long msg = 0;
1025
1026 if (ptrace(PTRACE_GETEVENTMSG, pid,
1027 NULL, (long) &msg) == 0)
1028 expected_grandchild = msg;
1029 }
1030 break;
1031 }
1032 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1033 kill_save_errno(pid, SIGKILL);
1034 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001035 }
1036 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001037 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001038 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001039 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001040 fprintf(stderr, "ptrace_setoptions = %#x\n",
1041 ptrace_setoptions);
1042 return;
1043 }
1044 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1045 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001046}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001047
1048/*
1049 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1050 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1051 * and then see whether it will stop with (SIGTRAP | 0x80).
1052 *
1053 * Use of this option enables correct handling of user-generated SIGTRAPs,
1054 * and SIGTRAPs generated by special instructions such as int3 on x86:
1055 * _start: .globl _start
1056 * int3
1057 * movl $42, %ebx
1058 * movl $1, %eax
1059 * int $0x80
1060 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1061 */
1062static void
1063test_ptrace_setoptions_for_all(void)
1064{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001065 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1066 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001067 int pid;
1068 int it_worked = 0;
1069
1070 pid = fork();
1071 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001072 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001073
1074 if (pid == 0) {
1075 pid = getpid();
1076 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001077 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001078 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1079 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001080 kill(pid, SIGSTOP);
1081 _exit(0); /* parent should see entry into this syscall */
1082 }
1083
1084 while (1) {
1085 int status, tracee_pid;
1086
1087 errno = 0;
1088 tracee_pid = wait(&status);
1089 if (tracee_pid <= 0) {
1090 if (errno == EINTR)
1091 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001092 kill_save_errno(pid, SIGKILL);
1093 perror_msg_and_die("%s: unexpected wait result %d",
1094 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001095 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001096 if (WIFEXITED(status)) {
1097 if (WEXITSTATUS(status) == 0)
1098 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001099 error_msg_and_die("%s: unexpected exit status %u",
1100 __func__, WEXITSTATUS(status));
1101 }
1102 if (WIFSIGNALED(status)) {
1103 error_msg_and_die("%s: unexpected signal %u",
1104 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001105 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001106 if (!WIFSTOPPED(status)) {
1107 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001108 error_msg_and_die("%s: unexpected wait status %x",
1109 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001110 }
1111 if (WSTOPSIG(status) == SIGSTOP) {
1112 /*
1113 * We don't check "options aren't accepted" error.
1114 * If it happens, we'll never get (SIGTRAP | 0x80),
1115 * and thus will decide to not use the option.
1116 * IOW: the outcome of the test will be correct.
1117 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001118 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1119 && errno != EINVAL && errno != EIO)
1120 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001121 }
1122 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1123 it_worked = 1;
1124 }
1125 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001126 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001127 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001128 }
1129 }
1130
1131 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001132 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001133 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001134 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001135 fprintf(stderr, "ptrace_setoptions = %#x\n",
1136 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001137 return;
1138 }
1139
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001140 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1141 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001142}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001143
1144# ifdef USE_SEIZE
1145static void
1146test_ptrace_seize(void)
1147{
1148 int pid;
1149
1150 pid = fork();
1151 if (pid < 0)
1152 perror_msg_and_die("fork");
1153
1154 if (pid == 0) {
1155 pause();
1156 _exit(0);
1157 }
1158
1159 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1160 * attaching tracee continues to run unless a trap condition occurs.
1161 * PTRACE_SEIZE doesn't affect signal or group stop state.
1162 */
1163 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1164 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001165 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001166 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1167 }
1168
1169 kill(pid, SIGKILL);
1170
1171 while (1) {
1172 int status, tracee_pid;
1173
1174 errno = 0;
1175 tracee_pid = waitpid(pid, &status, 0);
1176 if (tracee_pid <= 0) {
1177 if (errno == EINTR)
1178 continue;
1179 perror_msg_and_die("%s: unexpected wait result %d",
1180 __func__, tracee_pid);
1181 }
1182 if (WIFSIGNALED(status)) {
1183 return;
1184 }
1185 error_msg_and_die("%s: unexpected wait status %x",
1186 __func__, status);
1187 }
1188}
1189# else /* !USE_SEIZE */
1190# define test_ptrace_seize() ((void)0)
1191# endif
1192
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001193static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001194get_os_release(void)
1195{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001196 unsigned rel;
1197 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001198 struct utsname u;
1199 if (uname(&u) < 0)
1200 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001201 /* u.release has this form: "3.2.9[-some-garbage]" */
1202 rel = 0;
1203 p = u.release;
1204 for (;;) {
1205 if (!(*p >= '0' && *p <= '9'))
1206 error_msg_and_die("Bad OS release string: '%s'", u.release);
1207 /* Note: this open-codes KERNEL_VERSION(): */
1208 rel = (rel << 8) | atoi(p);
1209 if (rel >= KERNEL_VERSION(1,0,0))
1210 break;
1211 while (*p >= '0' && *p <= '9')
1212 p++;
1213 if (*p != '.')
1214 error_msg_and_die("Bad OS release string: '%s'", u.release);
1215 p++;
1216 }
1217 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001218}
1219
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001220/*
1221 * Initialization part of main() was eating much stack (~0.5k),
1222 * which was unused after init.
1223 * We can reuse it if we move init code into a separate function.
1224 *
1225 * Don't want main() to inline us and defeat the reason
1226 * we have a separate function.
1227 */
1228static void __attribute__ ((noinline))
1229init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001232 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001233 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234 struct sigaction sa;
1235
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001236 progname = argv[0] ? argv[0] : "strace";
1237
Denys Vlasenko75422762011-05-27 14:36:01 +02001238 strace_tracer_pid = getpid();
1239
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001240 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001241
Roland McGrathee9d4352002-12-18 04:16:10 +00001242 /* Allocate the initial tcbtab. */
1243 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001244 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001245 if (!tcbtab)
1246 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001247 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001248 if (!tcp)
1249 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001250 for (c = 0; c < tcbtabsize; c++)
1251 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001252
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001254 set_sortby(DEFAULT_SORTBY);
1255 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001256 qualify("trace=all");
1257 qualify("abbrev=all");
1258 qualify("verbose=all");
1259 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001261 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001262 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001263 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001265 case 'b':
1266 detach_on_execve = 1;
1267 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001269 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001270 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001271 }
1272 cflag = CFLAG_ONLY_STATS;
1273 break;
1274 case 'C':
1275 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001276 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001277 }
1278 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279 break;
1280 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001281 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001282 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001283 case 'D':
1284 daemonized_tracer = 1;
1285 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001286 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001287 optF = 1;
1288 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289 case 'f':
1290 followfork++;
1291 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 case 'h':
1293 usage(stdout, 0);
1294 break;
1295 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001296 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001297 break;
1298 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001299 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001300 break;
1301 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001302 rflag = 1;
1303 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 case 't':
1305 tflag++;
1306 break;
1307 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001308 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309 break;
1310 case 'x':
1311 xflag++;
1312 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001313 case 'y':
1314 show_fd_path = 1;
1315 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316 case 'v':
1317 qualify("abbrev=none");
1318 break;
1319 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001320 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001321 exit(0);
1322 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001323 case 'z':
1324 not_failing_only = 1;
1325 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326 case 'a':
1327 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001328 if (acolumn < 0)
1329 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 break;
1331 case 'e':
1332 qualify(optarg);
1333 break;
1334 case 'o':
1335 outfname = strdup(optarg);
1336 break;
1337 case 'O':
1338 set_overhead(atoi(optarg));
1339 break;
1340 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001341 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001343 case 'P':
1344 tracing_paths = 1;
1345 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001346 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001347 }
1348 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001349 case 's':
1350 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001351 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001352 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001353 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354 break;
1355 case 'S':
1356 set_sortby(optarg);
1357 break;
1358 case 'u':
1359 username = strdup(optarg);
1360 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001361 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001362 if (putenv(optarg) < 0)
1363 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001364 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001365 case 'I':
1366 opt_intr = atoi(optarg);
1367 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1368 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1369 }
1370 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001371 default:
1372 usage(stderr, 1);
1373 break;
1374 }
1375 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001376 argv += optind;
1377 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378
Denys Vlasenko102ec492011-08-25 01:27:59 +02001379 acolumn_spaces = malloc(acolumn + 1);
1380 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001381 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001382 memset(acolumn_spaces, ' ', acolumn);
1383 acolumn_spaces[acolumn] = '\0';
1384
Denys Vlasenko837399a2012-01-24 11:37:03 +01001385 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001386 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001387 usage(stderr, 1);
1388
Denys Vlasenkofd883382012-03-09 13:03:41 +01001389 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001390 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001391 }
1392
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001393 if (!followfork)
1394 followfork = optF;
1395
Roland McGrathcb9def62006-04-25 07:48:03 +00001396 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001397 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001398 }
1399
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001400 /* See if they want to run as another user. */
1401 if (username != NULL) {
1402 struct passwd *pent;
1403
1404 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001405 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001407 pent = getpwnam(username);
1408 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001409 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410 }
1411 run_uid = pent->pw_uid;
1412 run_gid = pent->pw_gid;
1413 }
1414 else {
1415 run_uid = getuid();
1416 run_gid = getgid();
1417 }
1418
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001419 if (followfork)
1420 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001421 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001422 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001423
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424 /* Check if they want to redirect the output. */
1425 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001426 /* See if they want to pipe the output. */
1427 if (outfname[0] == '|' || outfname[0] == '!') {
1428 /*
1429 * We can't do the <outfname>.PID funny business
1430 * when using popen, so prohibit it.
1431 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001432 if (followfork > 1)
1433 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1434 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001435 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001436 else if (followfork <= 1)
1437 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001438 } else {
1439 /* -ff without -o FILE is the same as single -f */
1440 if (followfork > 1)
1441 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 }
1443
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001444 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001445 char *buf = malloc(BUFSIZ);
1446 if (!buf)
1447 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001449 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001450 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001451 if (!opt_intr)
1452 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001453 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001454 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001455 if (!opt_intr)
1456 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001457
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001458 /* argv[0] -pPID -oFILE Default interactive setting
1459 * yes 0 0 INTR_WHILE_WAIT
1460 * no 1 0 INTR_WHILE_WAIT
1461 * yes 0 1 INTR_NEVER
1462 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001463 */
1464
1465 /* STARTUP_CHILD must be called before the signal handlers get
1466 installed below as they are inherited into the spawned process.
1467 Also we do not need to be protected by them as during interruption
1468 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001469 if (argv[0]) {
1470 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001471 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001472 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001474 sigemptyset(&empty_set);
1475 sigemptyset(&blocked_set);
1476 sa.sa_handler = SIG_IGN;
1477 sigemptyset(&sa.sa_mask);
1478 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001479 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1480 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1481 if (opt_intr != INTR_ANYWHERE) {
1482 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1483 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1484 /*
1485 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1486 * fatal signals are blocked while syscall stop is processed,
1487 * and acted on in between, when waiting for new syscall stops.
1488 * In non-interactive mode, signals are ignored.
1489 */
1490 if (opt_intr == INTR_WHILE_WAIT) {
1491 sigaddset(&blocked_set, SIGHUP);
1492 sigaddset(&blocked_set, SIGINT);
1493 sigaddset(&blocked_set, SIGQUIT);
1494 sigaddset(&blocked_set, SIGPIPE);
1495 sigaddset(&blocked_set, SIGTERM);
1496 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001497 }
1498 /* SIG_IGN, or set handler for these */
1499 sigaction(SIGHUP, &sa, NULL);
1500 sigaction(SIGINT, &sa, NULL);
1501 sigaction(SIGQUIT, &sa, NULL);
1502 sigaction(SIGPIPE, &sa, NULL);
1503 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 }
Roland McGrath553a6092002-12-16 20:40:39 +00001505 /* Make sure SIGCHLD has the default action so that waitpid
1506 definitely works without losing track of children. The user
1507 should not have given us a bogus state to inherit, but he might
1508 have. Arguably we should detect SIG_IGN here and pass it on
1509 to children, but probably noone really needs that. */
1510 sa.sa_handler = SIG_DFL;
1511 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512
Denys Vlasenkofd883382012-03-09 13:03:41 +01001513 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001514 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001515
Denys Vlasenkofd883382012-03-09 13:03:41 +01001516 /* Do we want pids printed in our -o OUTFILE?
1517 * -ff: no (every pid has its own file); or
1518 * -f: yes (there can be more pids in the future); or
1519 * -p PID1,PID2: yes (there are already more than one pid)
1520 */
1521 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522}
1523
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001524static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001525expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001526{
1527 /* Allocate some more TCBs and expand the table.
1528 We don't want to relocate the TCBs because our
1529 callers have pointers and it would be a pain.
1530 So tcbtab is a table of pointers. Since we never
1531 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001532 int i = tcbtabsize;
1533 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1534 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001535 if (!newtab || !newtcbs)
1536 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001537 tcbtabsize *= 2;
1538 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001539 while (i < tcbtabsize)
1540 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001541}
1542
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001544alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545{
1546 int i;
1547 struct tcb *tcp;
1548
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001549 if (nprocs == tcbtabsize)
1550 expand_tcbtab();
1551
Roland McGrathee9d4352002-12-18 04:16:10 +00001552 for (i = 0; i < tcbtabsize; i++) {
1553 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001555 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001557 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001558 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001559#if SUPPORTED_PERSONALITIES > 1
1560 tcp->currpers = current_personality;
1561#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562 nprocs++;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001563 if (debug_flag)
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001564 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001565 if (command_options_parsed)
1566 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567 return tcp;
1568 }
1569 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001570 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001571}
1572
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001573static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001574pid2tcb(int pid)
1575{
1576 int i;
1577
1578 if (pid <= 0)
1579 return NULL;
1580
1581 for (i = 0; i < tcbtabsize; i++) {
1582 struct tcb *tcp = tcbtab[i];
1583 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1584 return tcp;
1585 }
1586
1587 return NULL;
1588}
1589
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590void
Denys Vlasenko12014262011-05-30 14:00:14 +02001591droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592{
1593 if (tcp->pid == 0)
1594 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001595
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596 nprocs--;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001597 if (debug_flag)
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001598 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001599
Denys Vlasenko3e084ac2012-03-15 13:39:05 +01001600 if (tcp->outf) {
1601 if (outfname && followfork >= 2) {
1602 if (tcp->curcol != 0)
1603 fprintf(tcp->outf, " <detached ...>\n");
1604 fclose(tcp->outf);
1605 if (outf == tcp->outf)
1606 outf = NULL;
1607 } else {
1608 if (printing_tcp == tcp && tcp->curcol != 0)
1609 fprintf(tcp->outf, " <detached ...>\n");
1610 fflush(tcp->outf);
1611 }
1612 }
1613
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001614 if (printing_tcp == tcp)
1615 printing_tcp = NULL;
1616
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001617 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618}
1619
Roland McGrath0a463882007-07-05 18:43:16 +00001620/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001621 * Never call DETACH twice on the same process as both unattached and
1622 * attached-unstopped processes give the same ESRCH. For unattached process we
1623 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1624 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001626detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001628 int error;
1629 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630
1631 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001632 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634 /*
1635 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001636 * before detaching. Arghh. We go through hoops
1637 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001639#if defined(SPARC)
1640#undef PTRACE_DETACH
1641#define PTRACE_DETACH PTRACE_SUNDETACH
1642#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001643
Denys Vlasenko3e084ac2012-03-15 13:39:05 +01001644 error = 0;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001645 sigstop_expected = 0;
1646 if (tcp->flags & TCB_ATTACHED) {
1647 /*
1648 * We attached but possibly didn't see the expected SIGSTOP.
1649 * We must catch exactly one as otherwise the detached process
1650 * would be left stopped (process state T).
1651 */
1652 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1653 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1654 if (error == 0) {
1655 /* On a clear day, you can see forever. */
1656 }
1657 else if (errno != ESRCH) {
1658 /* Shouldn't happen. */
1659 perror("detach: ptrace(PTRACE_DETACH, ...)");
1660 }
1661 else if (my_tkill(tcp->pid, 0) < 0) {
1662 if (errno != ESRCH)
1663 perror("detach: checking sanity");
1664 }
1665 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1666 if (errno != ESRCH)
1667 perror("detach: stopping child");
1668 }
1669 else
1670 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001671 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001672
1673 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001675#ifdef __WALL
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001676 if (waitpid(tcp->pid, &status, __WALL) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001677 if (errno == ECHILD) /* Already gone. */
1678 break;
1679 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001680 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001681 break;
1682 }
1683#endif /* __WALL */
1684 /* No __WALL here. */
1685 if (waitpid(tcp->pid, &status, 0) < 0) {
1686 if (errno != ECHILD) {
1687 perror("detach: waiting");
1688 break;
1689 }
1690#ifdef __WCLONE
1691 /* If no processes, try clones. */
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001692 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001693 if (errno != ECHILD)
1694 perror("detach: waiting");
1695 break;
1696 }
1697#endif /* __WCLONE */
1698 }
1699#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001700 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001701#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 if (!WIFSTOPPED(status)) {
1703 /* Au revoir, mon ami. */
1704 break;
1705 }
1706 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001707 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708 break;
1709 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001710 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001711 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001712 : WSTOPSIG(status));
1713 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001716 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001718 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719 fprintf(stderr, "Process %u detached\n", tcp->pid);
1720
1721 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001722
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723 return error;
1724}
1725
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001726static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001727cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001728{
1729 int i;
1730 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001731 int fatal_sig;
1732
1733 /* 'interrupted' is a volatile object, fetch it only once */
1734 fatal_sig = interrupted;
1735 if (!fatal_sig)
1736 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737
Roland McGrathee9d4352002-12-18 04:16:10 +00001738 for (i = 0; i < tcbtabsize; i++) {
1739 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001740 if (!(tcp->flags & TCB_INUSE))
1741 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001742 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743 fprintf(stderr,
1744 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001745 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001747 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001749 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750 }
1751 if (cflag)
1752 call_summary(outf);
1753}
1754
1755static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001756interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001758 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759}
1760
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001762trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001764 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001765 struct rusage *rup = cflag ? &ru : NULL;
1766# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001767 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001768# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769
Roland McGratheb9e2e82009-06-02 16:49:22 -07001770 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001771 int pid;
1772 int wait_errno;
1773 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001774 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001775 struct tcb *tcp;
1776 unsigned event;
1777
Denys Vlasenko222713a2009-03-17 14:29:59 +00001778 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001779 return 0;
1780 if (interactive)
1781 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001782# ifdef __WALL
1783 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001784 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001785 /* this kernel does not support __WALL */
1786 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001787 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001788 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001789 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001790 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001791 pid = wait4(-1, &status, __WCLONE, rup);
1792 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001793 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001794 }
1795 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001796# else
1797 pid = wait4(-1, &status, 0, rup);
1798# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001800 if (interactive)
1801 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001803 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001804 switch (wait_errno) {
1805 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001807 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 /*
1809 * We would like to verify this case
1810 * but sometimes a race in Solbourne's
1811 * version of SunOS sometimes reports
1812 * ECHILD before sending us SIGCHILD.
1813 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001814 return 0;
1815 default:
1816 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001817 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001818 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819 }
1820 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001821 if (pid == popen_pid) {
1822 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001823 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001824 continue;
1825 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001826
1827 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001828 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001829 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001830 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001831 strcpy(buf, "???");
1832 if (WIFSIGNALED(status))
1833#ifdef WCOREDUMP
1834 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1835 WCOREDUMP(status) ? "core," : "",
1836 signame(WTERMSIG(status)));
1837#else
1838 sprintf(buf, "WIFSIGNALED,sig=%s",
1839 signame(WTERMSIG(status)));
1840#endif
1841 if (WIFEXITED(status))
1842 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1843 if (WIFSTOPPED(status))
1844 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001845#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001846 if (WIFCONTINUED(status))
1847 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001848#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001849 evbuf[0] = '\0';
1850 if (event != 0) {
1851 static const char *const event_names[] = {
1852 [PTRACE_EVENT_CLONE] = "CLONE",
1853 [PTRACE_EVENT_FORK] = "FORK",
1854 [PTRACE_EVENT_VFORK] = "VFORK",
1855 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1856 [PTRACE_EVENT_EXEC] = "EXEC",
1857 [PTRACE_EVENT_EXIT] = "EXIT",
1858 };
1859 const char *e;
1860 if (event < ARRAY_SIZE(event_names))
1861 e = event_names[event];
1862 else {
1863 sprintf(buf, "?? (%u)", event);
1864 e = buf;
1865 }
1866 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1867 }
1868 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001869 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001871 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001872 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001873
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001874 /* Under Linux, execve changes pid to thread leader's pid,
1875 * and we see this changed pid on EVENT_EXEC and later,
1876 * execve sysexit. Leader "disappears" without exit
1877 * notification. Let user know that, drop leader's tcb,
1878 * and fix up pid in execve thread's tcb.
1879 * Effectively, execve thread's tcb replaces leader's tcb.
1880 *
1881 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1882 * on exit syscall) in multithreaded programs exactly
1883 * in order to handle this case.
1884 *
1885 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1886 * On 2.6 and earlier, it can return garbage.
1887 */
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001888 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001889 long old_pid = 0;
1890 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1891 && old_pid > 0
1892 && old_pid != pid
1893 ) {
1894 struct tcb *execve_thread = pid2tcb(old_pid);
1895 if (tcp) {
1896 outf = tcp->outf;
1897 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001898 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001899 if (execve_thread->curcol != 0) {
1900 /*
1901 * One case we are here is -ff:
1902 * try "strace -oLOG -ff test/threaded_execve"
1903 */
1904 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1905 execve_thread->curcol = 0;
1906 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001907 /* swap output FILEs (needed for -ff) */
1908 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001909 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001910 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001911 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001912 }
1913 droptcb(tcp);
1914 }
1915 tcp = execve_thread;
1916 if (tcp) {
1917 tcp->pid = pid;
1918 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001919 if (!cflag) {
1920 printleader(tcp);
1921 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1922 line_ended();
1923 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001924 }
1925 }
1926 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001927
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001928 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1929 if (!skip_startup_execve)
1930 detach(tcp);
1931 /* This was initial execve for "strace PROG". Skip. */
1932 skip_startup_execve = 0;
1933 }
1934
Denys Vlasenko5d645812011-08-20 12:48:18 +02001935 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001936 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001937 /* This is needed to go with the CLONE_PTRACE
1938 changes in process.c/util.c: we might see
1939 the child's initial trap before we see the
1940 parent return from the clone syscall.
1941 Leave the child suspended until the parent
1942 returns from its system call. Only then
1943 will we have the association of parent and
1944 child so that we know how to do clearbpt
1945 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001946 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001947 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001948 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001949 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001950 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001951 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001952 else
1953 /* This can happen if a clone call used
1954 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001955 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001956 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001957 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001958 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001959 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001961
1962 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001963 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001964 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001965
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001966 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001967 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1968 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001970
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001972 if (pid == strace_child)
1973 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001974 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1976 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001977#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001978 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001979 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001980 WCOREDUMP(status) ? "(core dumped) " : "");
1981#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001982 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001983 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001984#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001985 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986 }
1987 droptcb(tcp);
1988 continue;
1989 }
1990 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001991 if (pid == strace_child)
1992 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001993 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1994 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001995 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001996 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001997 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 droptcb(tcp);
1999 continue;
2000 }
2001 if (!WIFSTOPPED(status)) {
2002 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2003 droptcb(tcp);
2004 continue;
2005 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002006
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002007 /* Is this the very first time we see this tracee stopped? */
2008 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002009 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002010 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002013 /*
2014 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002015 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002016 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002017 if (clearbpt(tcp) < 0) {
2018 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019 droptcb(tcp);
2020 cleanup();
2021 return -1;
2022 }
2023 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002024 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002025 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002026 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2027 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2028 if (errno != ESRCH) {
2029 /* Should never happen, really */
2030 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002031 }
2032 }
2033 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002034 }
2035
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002036 sig = WSTOPSIG(status);
2037
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002038 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002039 /* Ptrace event */
2040#ifdef USE_SEIZE
2041 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002042 /*
2043 * PTRACE_INTERRUPT-stop or group-stop.
2044 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2045 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002046 if (sig == SIGSTOP
2047 || sig == SIGTSTP
2048 || sig == SIGTTIN
2049 || sig == SIGTTOU
2050 ) {
2051 stopped = 1;
2052 goto show_stopsig;
2053 }
2054 }
2055#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002056 goto restart_tracee_with_sig_0;
2057 }
2058
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002059 /* Is this post-attach SIGSTOP?
2060 * Interestingly, the process may stop
2061 * with STOPSIG equal to some other signal
2062 * than SIGSTOP if we happend to attach
2063 * just before the process takes a signal.
2064 */
2065 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002066 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002067 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2068 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002069 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 }
2071
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002072 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002073 siginfo_t si;
2074
2075 /* Nonzero (true) if tracee is stopped by signal
2076 * (as opposed to "tracee received signal").
2077 */
2078 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002079#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002080 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002081#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002082 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002083 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002084#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002085 long pc = 0;
2086 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002087
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002088 upeek(tcp, PT_CR_IPSR, &psr);
2089 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002090
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002091# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002092 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002093# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002094# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002095#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002096# define PC_FORMAT_STR ""
2097# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002098#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002100 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002101 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002102 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002103 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002104 PC_FORMAT_ARG);
2105 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002106 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002107 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002108 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002109 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002111
2112 if (!stopped)
2113 /* It's signal-delivery-stop. Inject the signal */
2114 goto restart_tracee;
2115
2116 /* It's group-stop */
2117#ifdef USE_SEIZE
2118 if (use_seize) {
2119 /*
2120 * This ends ptrace-stop, but does *not* end group-stop.
2121 * This makes stopping signals work properly on straced process
2122 * (that is, process really stops. It used to continue to run).
2123 */
2124 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2125 cleanup();
2126 return -1;
2127 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002128 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002129 continue;
2130 }
2131 /* We don't have PTRACE_LISTEN support... */
2132#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002133 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002135
2136 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002137 if (interrupted)
2138 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002139
2140 /* This should be syscall entry or exit.
2141 * (Or it still can be that pesky post-execve SIGTRAP!)
2142 * Handle it.
2143 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002144 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2145 /* ptrace() failed in trace_syscall() with ESRCH.
2146 * Likely a result of process disappearing mid-flight.
2147 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002148 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002149 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002150 * We used to detach(tcp) here, but since we no longer
2151 * implement "detach before death" policy/hack,
2152 * we can let this process to report its death to us
2153 * normally, via WIFEXITED or WIFSIGNALED wait status.
2154 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002155 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002156 continue;
2157 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002158 restart_tracee_with_sig_0:
2159 sig = 0;
2160 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002161 /* Remember current print column before continuing. */
2162 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002163 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002164 cleanup();
2165 return -1;
2166 }
2167 }
2168 return 0;
2169}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002170
2171int
2172main(int argc, char *argv[])
2173{
2174 init(argc, argv);
2175
2176 /* Run main tracing loop */
2177 if (trace() < 0)
2178 return 1;
2179
2180 cleanup();
2181 fflush(NULL);
2182 if (exit_code > 0xff) {
2183 /* Avoid potential core file clobbering. */
2184 struct rlimit rlim = {0, 0};
2185 setrlimit(RLIMIT_CORE, &rlim);
2186
2187 /* Child was killed by a signal, mimic that. */
2188 exit_code &= 0xff;
2189 signal(exit_code, SIG_DFL);
2190 raise(exit_code);
2191 /* Paranoia - what if this signal is not fatal?
2192 Exit with 128 + signo then. */
2193 exit_code += 128;
2194 }
2195
2196 return exit_code;
2197}