blob: c211ac73ad1a2ea18cd84cdc1af7b09dbca93732 [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.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000029 */
30
31#include "defs.h"
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020032#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000033#include <sys/param.h>
34#include <fcntl.h>
35#include <sys/resource.h>
36#include <sys/wait.h>
37#include <sys/stat.h>
38#include <pwd.h>
39#include <grp.h>
Roland McGrath70b08532004-04-09 00:25:21 +000040#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010041#include <sys/utsname.h>
Denys Vlasenko84703742012-02-25 02:38:52 +010042#if defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000043# include <asm/ptrace_offsets.h>
44#endif
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010045/* In some libc, these aren't declared. Do it ourself: */
Denys Vlasenko96d5a762008-12-29 19:13:27 +000046extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000047extern int optind;
48extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000049
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010050
51#if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
53#else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
58# define my_tkill(tid, sig) kill((tid), (sig))
59#endif
60
61#undef KERNEL_VERSION
62#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
63
64cflag_t cflag = CFLAG_NONE;
65unsigned int followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020066unsigned int ptrace_setoptions = 0;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010067unsigned int xflag = 0;
68bool debug_flag = 0;
69bool Tflag = 0;
70bool qflag = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020071/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020072static unsigned int syscall_trap_sig = SIGTRAP;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010073static unsigned int tflag = 0;
74static bool iflag = 0;
75static bool rflag = 0;
76static bool print_pid_pfx = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010077
78/* -I n */
79enum {
80 INTR_NOT_SET = 0,
81 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
82 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
83 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
84 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
85 NUM_INTR_OPTS
86};
87static int opt_intr;
88/* We play with signal mask only if this mode is active: */
89#define interactive (opt_intr == INTR_WHILE_WAIT)
90
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100105#ifdef USE_SEIZE
106static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
107# define use_seize (post_attach_sigstop == 0)
108#else
109# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
110# define use_seize 0
111#endif
112
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000113/* Sometimes we want to print only succeeding syscalls. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100114bool not_failing_only = 0;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000115
Grant Edwards8a082772011-04-07 20:25:40 +0000116/* Show path associated with fd arguments */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100117bool show_fd_path = 0;
Grant Edwards8a082772011-04-07 20:25:40 +0000118
119/* are we filtering traces based on paths? */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100120bool tracing_paths = 0;
Grant Edwards8a082772011-04-07 20:25:40 +0000121
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100122static bool detach_on_execve = 0;
123static bool skip_startup_execve = 0;
124
Dmitry V. Levina6809652008-11-10 17:14:58 +0000125static int exit_code = 0;
126static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200127static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700128
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000129static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200130static uid_t run_uid;
131static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100133unsigned int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000134static int acolumn = DEFAULT_ACOLUMN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200135static char *acolumn_spaces;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100136
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000137static char *outfname = NULL;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100138/* If -ff, points to stderr. Else, it's our common output log */
139static FILE *shared_log;
140
Denys Vlasenko000b6012012-01-28 01:25:03 +0100141struct tcb *printing_tcp = NULL;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100142static struct tcb *current_tcp;
143
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200144static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200145static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200146static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +0100148static unsigned os_release; /* generated from uname()'s u.release */
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100149
Denys Vlasenko4c196382012-01-04 15:11:09 +0100150static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100151static int trace(void);
152static void cleanup(void);
153static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154static sigset_t empty_set, blocked_set;
155
156#ifdef HAVE_SIG_ATOMIC_T
157static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100158#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100160#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100162#ifndef HAVE_STRERROR
163
164#if !HAVE_DECL_SYS_ERRLIST
165extern int sys_nerr;
166extern char *sys_errlist[];
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +0100167#endif
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100168
169const char *
170strerror(int err_no)
171{
172 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
173
174 if (err_no < 1 || err_no >= sys_nerr) {
175 sprintf(buf, "Unknown error %d", err_no);
176 return buf;
177 }
178 return sys_errlist[err_no];
179}
180
181#endif /* HAVE_STERRROR */
182
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200184usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185{
186 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100187usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
188 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100189 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100190 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100191 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000192-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200193-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100194-d -- enable debug output to stderr\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100195-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000196-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100197-F -- attempt to follow vforks (deprecated, use -f)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100199-I interruptible\n\
200 1: no signals are blocked\n\
201 2: fatal signals are blocked while decoding syscall (default)\n\
202 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
203 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
204 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205-q -- suppress messages about attaching, detaching, etc.\n\
206-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100207-T -- print time spent in each syscall\n\
208-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000210-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100211-h -- print help message\n\
212-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213-a column -- alignment COLUMN for printing syscall results (default %d)\n\
214-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
215 options: trace, abbrev, verbose, raw, signal, read, or write\n\
216-o file -- send trace output to FILE instead of stderr\n\
217-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
218-p pid -- trace process with process id PID, may be repeated\n\
219-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
220-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
221-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000222-E var=val -- put var=val in the environment for command\n\
223-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000224-P path -- trace accesses to path\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100225"
226/* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000227-z -- print only succeeding syscalls\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100228 */
229/* experimental, don't document it yet (option letter may change in the future!)
230-b -- detach on successful execve\n\
231 */
Roland McGrathde6e5332003-01-24 04:31:23 +0000232, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233 exit(exitval);
234}
235
Denys Vlasenko75422762011-05-27 14:36:01 +0200236static void die(void) __attribute__ ((noreturn));
237static void die(void)
238{
239 if (strace_tracer_pid == getpid()) {
240 cflag = 0;
241 cleanup();
242 }
243 exit(1);
244}
245
246static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200247{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100248 char *msg;
249
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000250 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100251
252 /* We want to print entire message with single fprintf to ensure
253 * message integrity if stderr is shared with other programs.
254 * Thus we use vasprintf + single fprintf.
255 */
256 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100257 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100258 if (err_no)
259 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
260 else
261 fprintf(stderr, "%s: %s\n", progname, msg);
262 free(msg);
263 } else {
264 /* malloc in vasprintf failed, try it without malloc */
265 fprintf(stderr, "%s: ", progname);
266 vfprintf(stderr, fmt, p);
267 if (err_no)
268 fprintf(stderr, ": %s\n", strerror(err_no));
269 else
270 putc('\n', stderr);
271 }
272 /* We don't switch stderr to buffered, thus fprintf(stderr)
273 * always flushes its output and this is not necessary: */
274 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200275}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200276
Denys Vlasenko75422762011-05-27 14:36:01 +0200277void error_msg(const char *fmt, ...)
278{
279 va_list p;
280 va_start(p, fmt);
281 verror_msg(0, fmt, p);
282 va_end(p);
283}
284
285void error_msg_and_die(const char *fmt, ...)
286{
287 va_list p;
288 va_start(p, fmt);
289 verror_msg(0, fmt, p);
290 die();
291}
292
293void perror_msg(const char *fmt, ...)
294{
295 va_list p;
296 va_start(p, fmt);
297 verror_msg(errno, fmt, p);
298 va_end(p);
299}
300
301void perror_msg_and_die(const char *fmt, ...)
302{
303 va_list p;
304 va_start(p, fmt);
305 verror_msg(errno, fmt, p);
306 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200307}
308
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200309void die_out_of_memory(void)
310{
311 static bool recursed = 0;
312 if (recursed)
313 exit(1);
314 recursed = 1;
315 error_msg_and_die("Out of memory");
316}
317
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000318static void
319error_opt_arg(int opt, const char *arg)
320{
321 error_msg_and_die("Invalid -%c argument: '%s'", opt, arg);
322}
323
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400324/* Glue for systems without a MMU that cannot provide fork() */
325#ifdef HAVE_FORK
326# define strace_vforked 0
327#else
328# define strace_vforked 1
329# define fork() vfork()
330#endif
331
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100332#ifdef USE_SEIZE
333static int
334ptrace_attach_or_seize(int pid)
335{
336 int r;
337 if (!use_seize)
338 return ptrace(PTRACE_ATTACH, pid, 0, 0);
339 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
340 if (r)
341 return r;
342 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
343 return r;
344}
345#else
346# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
347#endif
348
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100349/*
350 * Used when we want to unblock stopped traced process.
351 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
352 * Returns 0 on success or if error was ESRCH
353 * (presumably process was killed while we talk to it).
354 * Otherwise prints error message and returns -1.
355 */
356static int
357ptrace_restart(int op, struct tcb *tcp, int sig)
358{
359 int err;
360 const char *msg;
361
362 errno = 0;
363 ptrace(op, tcp->pid, (void *) 0, (long) sig);
364 err = errno;
Denys Vlasenko23506752012-03-21 10:32:49 +0100365 if (!err)
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100366 return 0;
367
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100368 msg = "SYSCALL";
369 if (op == PTRACE_CONT)
370 msg = "CONT";
371 if (op == PTRACE_DETACH)
372 msg = "DETACH";
373#ifdef PTRACE_LISTEN
374 if (op == PTRACE_LISTEN)
375 msg = "LISTEN";
376#endif
Denys Vlasenko23506752012-03-21 10:32:49 +0100377 /*
378 * Why curcol != 0? Otherwise sometimes we get this:
379 *
380 * 10252 kill(10253, SIGKILL) = 0
381 * <ptrace(SYSCALL,10252):No such process>10253 ...next decode...
382 *
383 * 10252 died after we retrieved syscall exit data,
384 * but before we tried to restart it. Log looks ugly.
385 */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100386 if (current_tcp && current_tcp->curcol != 0) {
Denys Vlasenko23506752012-03-21 10:32:49 +0100387 tprintf(" <ptrace(%s):%s>\n", msg, strerror(err));
388 line_ended();
389 }
390 if (err == ESRCH)
391 return 0;
392 errno = err;
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100393 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
394 return -1;
395}
396
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200397static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000398set_cloexec_flag(int fd)
399{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200400 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000401
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200402 flags = fcntl(fd, F_GETFD);
403 if (flags < 0) {
404 /* Can happen only if fd is bad.
405 * Should never happen: if it does, we have a bug
406 * in the caller. Therefore we just abort
407 * instead of propagating the error.
408 */
409 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000410 }
411
412 newflags = flags | FD_CLOEXEC;
413 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200414 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000415
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200416 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000417}
418
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100419static void kill_save_errno(pid_t pid, int sig)
420{
421 int saved_errno = errno;
422
423 (void) kill(pid, sig);
424 errno = saved_errno;
425}
426
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100427/*
428 * When strace is setuid executable, we have to swap uids
429 * before and after filesystem and process management operations.
430 */
431static void
432swap_uid(void)
433{
434 int euid = geteuid(), uid = getuid();
435
436 if (euid != uid && setreuid(euid, uid) < 0) {
437 perror_msg_and_die("setreuid");
438 }
439}
440
441#if _LFS64_LARGEFILE
442# define fopen_for_output fopen64
443#else
444# define fopen_for_output fopen
445#endif
446
447static FILE *
448strace_fopen(const char *path)
449{
450 FILE *fp;
451
452 swap_uid();
453 fp = fopen_for_output(path, "w");
454 if (!fp)
455 perror_msg_and_die("Can't fopen '%s'", path);
456 swap_uid();
457 set_cloexec_flag(fileno(fp));
458 return fp;
459}
460
461static int popen_pid = 0;
462
463#ifndef _PATH_BSHELL
464# define _PATH_BSHELL "/bin/sh"
465#endif
466
467/*
468 * We cannot use standard popen(3) here because we have to distinguish
469 * popen child process from other processes we trace, and standard popen(3)
470 * does not export its child's pid.
471 */
472static FILE *
473strace_popen(const char *command)
474{
475 FILE *fp;
476 int fds[2];
477
478 swap_uid();
479 if (pipe(fds) < 0)
480 perror_msg_and_die("pipe");
481
482 set_cloexec_flag(fds[1]); /* never fails */
483
484 popen_pid = vfork();
485 if (popen_pid == -1)
486 perror_msg_and_die("vfork");
487
488 if (popen_pid == 0) {
489 /* child */
490 close(fds[1]);
491 if (fds[0] != 0) {
492 if (dup2(fds[0], 0))
493 perror_msg_and_die("dup2");
494 close(fds[0]);
495 }
496 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
497 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
498 }
499
500 /* parent */
501 close(fds[0]);
502 swap_uid();
503 fp = fdopen(fds[1], "w");
504 if (!fp)
505 die_out_of_memory();
506 return fp;
507}
508
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100509void
510tprintf(const char *fmt, ...)
511{
512 va_list args;
513
514 va_start(args, fmt);
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100515 if (current_tcp) {
516 int n = vfprintf(current_tcp->outf, fmt, args);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100517 if (n < 0) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100518 if (current_tcp->outf != stderr)
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100519 perror(outfname == NULL
520 ? "<writing to pipe>" : outfname);
521 } else
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100522 current_tcp->curcol += n;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100523 }
524 va_end(args);
525}
526
527void
528tprints(const char *str)
529{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100530 if (current_tcp) {
531 int n = fputs(str, current_tcp->outf);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100532 if (n >= 0) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100533 current_tcp->curcol += strlen(str);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100534 return;
535 }
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100536 if (current_tcp->outf != stderr)
537 perror(!outfname ? "<writing to pipe>" : outfname);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100538 }
539}
540
541void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100542line_ended(void)
543{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100544 if (current_tcp) {
545 current_tcp->curcol = 0;
546 fflush(current_tcp->outf);
547 }
548 if (printing_tcp) {
549 printing_tcp->curcol = 0;
550 printing_tcp = NULL;
551 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100552}
553
554void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100555printleader(struct tcb *tcp)
556{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100557 /* If -ff, "previous tcb we printed" is always the same as current,
558 * because we have per-tcb output files.
559 */
560 if (followfork >= 2)
561 printing_tcp = tcp;
562
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100563 if (printing_tcp) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100564 current_tcp = printing_tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100565 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
566 /*
567 * case 1: we have a shared log (i.e. not -ff), and last line
568 * wasn't finished (same or different tcb, doesn't matter).
569 * case 2: split log, we are the same tcb, but our last line
570 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
571 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100572 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100573 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100574 }
575 }
576
577 printing_tcp = tcp;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100578 current_tcp = tcp;
579 current_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100580
581 if (print_pid_pfx)
582 tprintf("%-5d ", tcp->pid);
583 else if (nprocs > 1 && !outfname)
584 tprintf("[pid %5u] ", tcp->pid);
585
586 if (tflag) {
587 char str[sizeof("HH:MM:SS")];
588 struct timeval tv, dtv;
589 static struct timeval otv;
590
591 gettimeofday(&tv, NULL);
592 if (rflag) {
593 if (otv.tv_sec == 0)
594 otv = tv;
595 tv_sub(&dtv, &tv, &otv);
596 tprintf("%6ld.%06ld ",
597 (long) dtv.tv_sec, (long) dtv.tv_usec);
598 otv = tv;
599 }
600 else if (tflag > 2) {
601 tprintf("%ld.%06ld ",
602 (long) tv.tv_sec, (long) tv.tv_usec);
603 }
604 else {
605 time_t local = tv.tv_sec;
606 strftime(str, sizeof(str), "%T", localtime(&local));
607 if (tflag > 1)
608 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
609 else
610 tprintf("%s ", str);
611 }
612 }
613 if (iflag)
614 printcall(tcp);
615}
616
617void
618tabto(void)
619{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100620 if (current_tcp->curcol < acolumn)
621 tprints(acolumn_spaces + current_tcp->curcol);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100622}
623
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100624/* Should be only called directly *after successful attach* to a tracee.
625 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
626 * may create bogus empty FILE.<nonexistant_pid>, and then die.
627 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200628static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000629newoutf(struct tcb *tcp)
630{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100631 tcp->outf = shared_log; /* if not -ff mode, the same file is for all */
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100632 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000633 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000634 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200635 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000636 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000637}
638
Denys Vlasenko558e5122012-03-12 23:32:16 +0100639static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100640expand_tcbtab(void)
641{
642 /* Allocate some more TCBs and expand the table.
643 We don't want to relocate the TCBs because our
644 callers have pointers and it would be a pain.
645 So tcbtab is a table of pointers. Since we never
646 free the TCBs, we allocate a single chunk of many. */
647 int i = tcbtabsize;
648 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
649 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
650 if (!newtab || !newtcbs)
651 die_out_of_memory();
652 tcbtabsize *= 2;
653 tcbtab = newtab;
654 while (i < tcbtabsize)
655 tcbtab[i++] = newtcbs++;
656}
657
658static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100659alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100660{
661 int i;
662 struct tcb *tcp;
663
664 if (nprocs == tcbtabsize)
665 expand_tcbtab();
666
667 for (i = 0; i < tcbtabsize; i++) {
668 tcp = tcbtab[i];
669 if ((tcp->flags & TCB_INUSE) == 0) {
670 memset(tcp, 0, sizeof(*tcp));
671 tcp->pid = pid;
672 tcp->flags = TCB_INUSE;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100673#if SUPPORTED_PERSONALITIES > 1
674 tcp->currpers = current_personality;
675#endif
676 nprocs++;
677 if (debug_flag)
678 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100679 return tcp;
680 }
681 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100682 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100683}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100684
685static void
686droptcb(struct tcb *tcp)
687{
688 if (tcp->pid == 0)
689 return;
690
691 nprocs--;
692 if (debug_flag)
693 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
694
695 if (tcp->outf) {
Denys Vlasenko8511f2a2012-03-22 09:35:51 +0100696 if (followfork >= 2) {
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100697 if (tcp->curcol != 0)
698 fprintf(tcp->outf, " <detached ...>\n");
699 fclose(tcp->outf);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100700 } else {
701 if (printing_tcp == tcp && tcp->curcol != 0)
702 fprintf(tcp->outf, " <detached ...>\n");
703 fflush(tcp->outf);
704 }
705 }
706
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100707 if (current_tcp == tcp)
708 current_tcp = NULL;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100709 if (printing_tcp == tcp)
710 printing_tcp = NULL;
711
712 memset(tcp, 0, sizeof(*tcp));
713}
714
715/* detach traced process; continue with sig
716 * Never call DETACH twice on the same process as both unattached and
717 * attached-unstopped processes give the same ESRCH. For unattached process we
718 * would SIGSTOP it and wait for its SIGSTOP notification forever.
719 */
720static int
721detach(struct tcb *tcp)
722{
723 int error;
724 int status, sigstop_expected;
725
726 if (tcp->flags & TCB_BPTSET)
727 clearbpt(tcp);
728
729 /*
730 * Linux wrongly insists the child be stopped
731 * before detaching. Arghh. We go through hoops
732 * to make a clean break of things.
733 */
734#if defined(SPARC)
735#undef PTRACE_DETACH
736#define PTRACE_DETACH PTRACE_SUNDETACH
737#endif
738
739 error = 0;
740 sigstop_expected = 0;
741 if (tcp->flags & TCB_ATTACHED) {
742 /*
743 * We attached but possibly didn't see the expected SIGSTOP.
744 * We must catch exactly one as otherwise the detached process
745 * would be left stopped (process state T).
746 */
747 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
748 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
749 if (error == 0) {
750 /* On a clear day, you can see forever. */
751 }
752 else if (errno != ESRCH) {
753 /* Shouldn't happen. */
754 perror("detach: ptrace(PTRACE_DETACH, ...)");
755 }
756 else if (my_tkill(tcp->pid, 0) < 0) {
757 if (errno != ESRCH)
758 perror("detach: checking sanity");
759 }
760 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
761 if (errno != ESRCH)
762 perror("detach: stopping child");
763 }
764 else
765 sigstop_expected = 1;
766 }
767
768 if (sigstop_expected) {
769 for (;;) {
770#ifdef __WALL
771 if (waitpid(tcp->pid, &status, __WALL) < 0) {
772 if (errno == ECHILD) /* Already gone. */
773 break;
774 if (errno != EINVAL) {
775 perror("detach: waiting");
776 break;
777 }
778#endif /* __WALL */
779 /* No __WALL here. */
780 if (waitpid(tcp->pid, &status, 0) < 0) {
781 if (errno != ECHILD) {
782 perror("detach: waiting");
783 break;
784 }
785#ifdef __WCLONE
786 /* If no processes, try clones. */
787 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
788 if (errno != ECHILD)
789 perror("detach: waiting");
790 break;
791 }
792#endif /* __WCLONE */
793 }
794#ifdef __WALL
795 }
796#endif
797 if (!WIFSTOPPED(status)) {
798 /* Au revoir, mon ami. */
799 break;
800 }
801 if (WSTOPSIG(status) == SIGSTOP) {
802 ptrace_restart(PTRACE_DETACH, tcp, 0);
803 break;
804 }
805 error = ptrace_restart(PTRACE_CONT, tcp,
806 WSTOPSIG(status) == syscall_trap_sig ? 0
807 : WSTOPSIG(status));
808 if (error < 0)
809 break;
810 }
811 }
812
813 if (!qflag && (tcp->flags & TCB_ATTACHED))
814 fprintf(stderr, "Process %u detached\n", tcp->pid);
815
816 droptcb(tcp);
817
818 return error;
819}
820
821static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100822process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100823{
824 while (*opt) {
825 /*
826 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
827 * pidof uses space as delim, pgrep uses newline. :(
828 */
829 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100830 char *delim = opt + strcspn(opt, ", \n\t");
831 char c = *delim;
832
833 *delim = '\0';
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000834 pid = string_to_uint(opt);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100835 if (pid <= 0) {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000836 error_msg_and_die("Invalid process id: '%s'", opt);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100837 *delim = c;
838 return;
839 }
840 if (pid == strace_tracer_pid) {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000841 error_msg_and_die("I'm sorry, I can't let you do that, Dave.");
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100842 *delim = c;
843 return;
844 }
845 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100846 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100847 if (c == '\0')
848 break;
849 opt = delim + 1;
850 }
851}
852
Roland McGrath02203312007-06-11 22:06:31 +0000853static void
854startup_attach(void)
855{
856 int tcbi;
857 struct tcb *tcp;
858
859 /*
860 * Block user interruptions as we would leave the traced
861 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200862 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200863 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000864 */
865 if (interactive)
866 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
867
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000868 if (daemonized_tracer) {
869 pid_t pid = fork();
870 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200871 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000872 }
873 if (pid) { /* parent */
874 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200875 * Wait for grandchild to attach to straced process
876 * (grandparent). Grandchild SIGKILLs us after it attached.
877 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000878 * it proceeds to exec the straced program.
879 */
880 pause();
881 _exit(0); /* paranoia */
882 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200883 /* grandchild */
884 /* We will be the tracer process. Remember our new pid: */
885 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000886 }
887
Roland McGrath02203312007-06-11 22:06:31 +0000888 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
889 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200890
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100891 if (!(tcp->flags & TCB_INUSE))
892 continue;
893
Denys Vlasenkod116a732011-09-05 14:01:33 +0200894 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100895 if (tcp->flags & TCB_ATTACHED)
896 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200897
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000898 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000899 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000900 DIR *dir;
901
902 sprintf(procdir, "/proc/%d/task", tcp->pid);
903 dir = opendir(procdir);
904 if (dir != NULL) {
905 unsigned int ntid = 0, nerr = 0;
906 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200907
Roland McGrath02203312007-06-11 22:06:31 +0000908 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200909 struct tcb *cur_tcp;
910 int tid;
911
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000912 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000913 continue;
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000914 /* we trust /proc filesystem */
Roland McGrath02203312007-06-11 22:06:31 +0000915 tid = atoi(de->d_name);
916 if (tid <= 0)
917 continue;
918 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100919 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000920 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100921 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200922 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200923 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200924 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100925 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200926 fprintf(stderr, "attach to pid %d succeeded\n", tid);
927 cur_tcp = tcp;
928 if (tid != tcp->pid)
929 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100930 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100931 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000932 }
933 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200934 if (interactive) {
935 sigprocmask(SIG_SETMASK, &empty_set, NULL);
936 if (interrupted)
937 goto ret;
938 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
939 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000940 ntid -= nerr;
941 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000942 perror("attach: ptrace(PTRACE_ATTACH, ...)");
943 droptcb(tcp);
944 continue;
945 }
946 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000947 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100948? "Process %u attached with %u threads\n"
949: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200950 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000951 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100952 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200953 /* -p PID, we failed to attach to PID itself
954 * but did attach to some of its sibling threads.
955 * Drop PID's tcp.
956 */
957 droptcb(tcp);
958 }
Roland McGrath02203312007-06-11 22:06:31 +0000959 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000960 } /* if (opendir worked) */
961 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100962 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000963 perror("attach: ptrace(PTRACE_ATTACH, ...)");
964 droptcb(tcp);
965 continue;
966 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100967 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100968 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100969 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200970 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000971
972 if (daemonized_tracer) {
973 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000974 * Make parent go away.
975 * Also makes grandparent's wait() unblock.
976 */
977 kill(getppid(), SIGKILL);
978 }
979
Roland McGrath02203312007-06-11 22:06:31 +0000980 if (!qflag)
981 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100982 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000983 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200984 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000985
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200986 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000987 if (interactive)
988 sigprocmask(SIG_SETMASK, &empty_set, NULL);
989}
990
991static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200992startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000993{
994 struct stat statbuf;
995 const char *filename;
996 char pathname[MAXPATHLEN];
997 int pid = 0;
998 struct tcb *tcp;
999
1000 filename = argv[0];
1001 if (strchr(filename, '/')) {
1002 if (strlen(filename) > sizeof pathname - 1) {
1003 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001004 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001005 }
1006 strcpy(pathname, filename);
1007 }
1008#ifdef USE_DEBUGGING_EXEC
1009 /*
1010 * Debuggers customarily check the current directory
1011 * first regardless of the path but doing that gives
1012 * security geeks a panic attack.
1013 */
1014 else if (stat(filename, &statbuf) == 0)
1015 strcpy(pathname, filename);
1016#endif /* USE_DEBUGGING_EXEC */
1017 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +00001018 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +00001019 int m, n, len;
1020
1021 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +01001022 const char *colon = strchr(path, ':');
1023 if (colon) {
1024 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +00001025 m = n + 1;
1026 }
1027 else
1028 m = n = strlen(path);
1029 if (n == 0) {
1030 if (!getcwd(pathname, MAXPATHLEN))
1031 continue;
1032 len = strlen(pathname);
1033 }
1034 else if (n > sizeof pathname - 1)
1035 continue;
1036 else {
1037 strncpy(pathname, path, n);
1038 len = n;
1039 }
1040 if (len && pathname[len - 1] != '/')
1041 pathname[len++] = '/';
1042 strcpy(pathname + len, filename);
1043 if (stat(pathname, &statbuf) == 0 &&
1044 /* Accept only regular files
1045 with some execute bits set.
1046 XXX not perfect, might still fail */
1047 S_ISREG(statbuf.st_mode) &&
1048 (statbuf.st_mode & 0111))
1049 break;
1050 }
1051 }
1052 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001053 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001054 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001055 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001056 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001057 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001058 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001059 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1060 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001061 ) {
1062 pid = getpid();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001063 if (shared_log != stderr)
1064 close(fileno(shared_log));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001065 if (!daemonized_tracer && !use_seize) {
1066 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001067 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001068 }
Roland McGrath02203312007-06-11 22:06:31 +00001069 }
Roland McGrath02203312007-06-11 22:06:31 +00001070
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001071 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001072 uid_t run_euid = run_uid;
1073 gid_t run_egid = run_gid;
1074
1075 if (statbuf.st_mode & S_ISUID)
1076 run_euid = statbuf.st_uid;
1077 if (statbuf.st_mode & S_ISGID)
1078 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001079 /*
1080 * It is important to set groups before we
1081 * lose privileges on setuid.
1082 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001083 if (initgroups(username, run_gid) < 0) {
1084 perror_msg_and_die("initgroups");
1085 }
1086 if (setregid(run_gid, run_egid) < 0) {
1087 perror_msg_and_die("setregid");
1088 }
1089 if (setreuid(run_uid, run_euid) < 0) {
1090 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001091 }
1092 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001093 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001094 setreuid(run_uid, run_uid);
1095
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001096 if (!daemonized_tracer) {
1097 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001098 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001099 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001100 * the immediately following execve syscall.
1101 * Can't do this on NOMMU systems, we are after
1102 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001103 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001104 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001105 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001106 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001107 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001108 /* we depend on SIGCHLD set to SIG_DFL by init code */
1109 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001110 wait(NULL);
1111 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001112 }
Roland McGrath02203312007-06-11 22:06:31 +00001113
1114 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001115 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001116 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001117
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001118 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001119
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001120 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001121 if (!use_seize) {
1122 /* child did PTRACE_TRACEME, nothing to do in parent */
1123 } else {
1124 if (!strace_vforked) {
1125 /* Wait until child stopped itself */
1126 int status;
1127 while (waitpid(pid, &status, WSTOPPED) < 0) {
1128 if (errno == EINTR)
1129 continue;
1130 perror_msg_and_die("waitpid");
1131 }
1132 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001133 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001134 perror_msg_and_die("Unexpected wait status %x", status);
1135 }
1136 }
1137 /* Else: vforked case, we have no way to sync.
1138 * Just attach to it as soon as possible.
1139 * This means that we may miss a few first syscalls...
1140 */
1141
1142 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001143 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001144 perror_msg_and_die("Can't attach to %d", pid);
1145 }
1146 if (!strace_vforked)
1147 kill(pid, SIGCONT);
1148 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001149 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001150 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001151 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001152 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001153 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001154 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001155 }
1156 else {
1157 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1158 strace_tracer_pid = getpid();
1159 /* The tracee is our parent: */
1160 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001161 alloctcb(pid);
1162 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001163 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001164 }
Roland McGrath02203312007-06-11 22:06:31 +00001165}
1166
Wang Chaob13c0de2010-11-12 17:25:19 +08001167/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001168 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001169 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001170 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001171 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001172static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001173test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001174{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001175 int pid, expected_grandchild = 0, found_grandchild = 0;
1176 const unsigned int test_options = PTRACE_O_TRACECLONE |
1177 PTRACE_O_TRACEFORK |
1178 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001179
Denys Vlasenko5d645812011-08-20 12:48:18 +02001180 pid = fork();
1181 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001182 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001183 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001184 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001185 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001186 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1187 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001188 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001189 if (fork() < 0)
1190 perror_msg_and_die("fork");
1191 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001192 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001193
1194 while (1) {
1195 int status, tracee_pid;
1196
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001197 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001198 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001199 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001200 if (errno == EINTR)
1201 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001202 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001203 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001204 kill_save_errno(pid, SIGKILL);
1205 perror_msg_and_die("%s: unexpected wait result %d",
1206 __func__, tracee_pid);
1207 }
1208 if (WIFEXITED(status)) {
1209 if (WEXITSTATUS(status)) {
1210 if (tracee_pid != pid)
1211 kill_save_errno(pid, SIGKILL);
1212 error_msg_and_die("%s: unexpected exit status %u",
1213 __func__, WEXITSTATUS(status));
1214 }
1215 continue;
1216 }
1217 if (WIFSIGNALED(status)) {
1218 if (tracee_pid != pid)
1219 kill_save_errno(pid, SIGKILL);
1220 error_msg_and_die("%s: unexpected signal %u",
1221 __func__, WTERMSIG(status));
1222 }
1223 if (!WIFSTOPPED(status)) {
1224 if (tracee_pid != pid)
1225 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001226 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001227 error_msg_and_die("%s: unexpected wait status %x",
1228 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001229 }
1230 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001231 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001232 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1233 kill_save_errno(tracee_pid, SIGKILL);
1234 kill_save_errno(pid, SIGKILL);
1235 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001236 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001237 continue;
1238 }
1239 switch (WSTOPSIG(status)) {
1240 case SIGSTOP:
1241 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1242 && errno != EINVAL && errno != EIO)
1243 perror_msg("PTRACE_SETOPTIONS");
1244 break;
1245 case SIGTRAP:
1246 if (status >> 16 == PTRACE_EVENT_FORK) {
1247 long msg = 0;
1248
1249 if (ptrace(PTRACE_GETEVENTMSG, pid,
1250 NULL, (long) &msg) == 0)
1251 expected_grandchild = msg;
1252 }
1253 break;
1254 }
1255 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1256 kill_save_errno(pid, SIGKILL);
1257 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001258 }
1259 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001260 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001261 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001262 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001263 fprintf(stderr, "ptrace_setoptions = %#x\n",
1264 ptrace_setoptions);
1265 return;
1266 }
1267 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1268 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001269}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001270
1271/*
1272 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1273 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1274 * and then see whether it will stop with (SIGTRAP | 0x80).
1275 *
1276 * Use of this option enables correct handling of user-generated SIGTRAPs,
1277 * and SIGTRAPs generated by special instructions such as int3 on x86:
1278 * _start: .globl _start
1279 * int3
1280 * movl $42, %ebx
1281 * movl $1, %eax
1282 * int $0x80
1283 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1284 */
1285static void
1286test_ptrace_setoptions_for_all(void)
1287{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001288 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1289 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001290 int pid;
1291 int it_worked = 0;
1292
1293 pid = fork();
1294 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001295 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001296
1297 if (pid == 0) {
1298 pid = getpid();
1299 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001300 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001301 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1302 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001303 kill(pid, SIGSTOP);
1304 _exit(0); /* parent should see entry into this syscall */
1305 }
1306
1307 while (1) {
1308 int status, tracee_pid;
1309
1310 errno = 0;
1311 tracee_pid = wait(&status);
1312 if (tracee_pid <= 0) {
1313 if (errno == EINTR)
1314 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001315 kill_save_errno(pid, SIGKILL);
1316 perror_msg_and_die("%s: unexpected wait result %d",
1317 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001318 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001319 if (WIFEXITED(status)) {
1320 if (WEXITSTATUS(status) == 0)
1321 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001322 error_msg_and_die("%s: unexpected exit status %u",
1323 __func__, WEXITSTATUS(status));
1324 }
1325 if (WIFSIGNALED(status)) {
1326 error_msg_and_die("%s: unexpected signal %u",
1327 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001328 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001329 if (!WIFSTOPPED(status)) {
1330 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001331 error_msg_and_die("%s: unexpected wait status %x",
1332 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001333 }
1334 if (WSTOPSIG(status) == SIGSTOP) {
1335 /*
1336 * We don't check "options aren't accepted" error.
1337 * If it happens, we'll never get (SIGTRAP | 0x80),
1338 * and thus will decide to not use the option.
1339 * IOW: the outcome of the test will be correct.
1340 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001341 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1342 && errno != EINVAL && errno != EIO)
1343 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001344 }
1345 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1346 it_worked = 1;
1347 }
1348 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001349 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001350 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001351 }
1352 }
1353
1354 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001355 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001356 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001357 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001358 fprintf(stderr, "ptrace_setoptions = %#x\n",
1359 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001360 return;
1361 }
1362
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001363 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1364 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001365}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001366
1367# ifdef USE_SEIZE
1368static void
1369test_ptrace_seize(void)
1370{
1371 int pid;
1372
1373 pid = fork();
1374 if (pid < 0)
1375 perror_msg_and_die("fork");
1376
1377 if (pid == 0) {
1378 pause();
1379 _exit(0);
1380 }
1381
1382 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1383 * attaching tracee continues to run unless a trap condition occurs.
1384 * PTRACE_SEIZE doesn't affect signal or group stop state.
1385 */
1386 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1387 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001388 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001389 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1390 }
1391
1392 kill(pid, SIGKILL);
1393
1394 while (1) {
1395 int status, tracee_pid;
1396
1397 errno = 0;
1398 tracee_pid = waitpid(pid, &status, 0);
1399 if (tracee_pid <= 0) {
1400 if (errno == EINTR)
1401 continue;
1402 perror_msg_and_die("%s: unexpected wait result %d",
1403 __func__, tracee_pid);
1404 }
1405 if (WIFSIGNALED(status)) {
1406 return;
1407 }
1408 error_msg_and_die("%s: unexpected wait status %x",
1409 __func__, status);
1410 }
1411}
1412# else /* !USE_SEIZE */
1413# define test_ptrace_seize() ((void)0)
1414# endif
1415
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001416static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001417get_os_release(void)
1418{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001419 unsigned rel;
1420 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001421 struct utsname u;
1422 if (uname(&u) < 0)
1423 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001424 /* u.release has this form: "3.2.9[-some-garbage]" */
1425 rel = 0;
1426 p = u.release;
1427 for (;;) {
1428 if (!(*p >= '0' && *p <= '9'))
1429 error_msg_and_die("Bad OS release string: '%s'", u.release);
1430 /* Note: this open-codes KERNEL_VERSION(): */
1431 rel = (rel << 8) | atoi(p);
1432 if (rel >= KERNEL_VERSION(1,0,0))
1433 break;
1434 while (*p >= '0' && *p <= '9')
1435 p++;
1436 if (*p != '.')
1437 error_msg_and_die("Bad OS release string: '%s'", u.release);
1438 p++;
1439 }
1440 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001441}
1442
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001443/*
1444 * Initialization part of main() was eating much stack (~0.5k),
1445 * which was unused after init.
1446 * We can reuse it if we move init code into a separate function.
1447 *
1448 * Don't want main() to inline us and defeat the reason
1449 * we have a separate function.
1450 */
1451static void __attribute__ ((noinline))
1452init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001453{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454 struct tcb *tcp;
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001455 int c, i;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001456 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457 struct sigaction sa;
1458
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001459 progname = argv[0] ? argv[0] : "strace";
1460
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001461 /* Make sure SIGCHLD has the default action so that waitpid
1462 definitely works without losing track of children. The user
1463 should not have given us a bogus state to inherit, but he might
1464 have. Arguably we should detect SIG_IGN here and pass it on
1465 to children, but probably noone really needs that. */
1466 signal(SIGCHLD, SIG_DFL);
1467
Denys Vlasenko75422762011-05-27 14:36:01 +02001468 strace_tracer_pid = getpid();
1469
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001470 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001471
Roland McGrathee9d4352002-12-18 04:16:10 +00001472 /* Allocate the initial tcbtab. */
1473 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001474 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001475 if (!tcbtab)
1476 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001477 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001478 if (!tcp)
1479 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001480 for (c = 0; c < tcbtabsize; c++)
1481 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001482
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001483 shared_log = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001484 set_sortby(DEFAULT_SORTBY);
1485 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001486 qualify("trace=all");
1487 qualify("abbrev=all");
1488 qualify("verbose=all");
1489 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001491 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001492 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001493 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001495 case 'b':
1496 detach_on_execve = 1;
1497 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001499 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001500 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001501 }
1502 cflag = CFLAG_ONLY_STATS;
1503 break;
1504 case 'C':
1505 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001506 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001507 }
1508 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 break;
1510 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001511 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001513 case 'D':
1514 daemonized_tracer = 1;
1515 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001516 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001517 optF = 1;
1518 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 case 'f':
1520 followfork++;
1521 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522 case 'h':
1523 usage(stdout, 0);
1524 break;
1525 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001526 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527 break;
1528 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001529 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530 break;
1531 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001532 rflag = 1;
1533 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534 case 't':
1535 tflag++;
1536 break;
1537 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001538 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539 break;
1540 case 'x':
1541 xflag++;
1542 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001543 case 'y':
1544 show_fd_path = 1;
1545 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546 case 'v':
1547 qualify("abbrev=none");
1548 break;
1549 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001550 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551 exit(0);
1552 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001553 case 'z':
1554 not_failing_only = 1;
1555 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556 case 'a':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001557 acolumn = string_to_uint(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001558 if (acolumn < 0)
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001559 error_opt_arg(c, optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001560 break;
1561 case 'e':
1562 qualify(optarg);
1563 break;
1564 case 'o':
1565 outfname = strdup(optarg);
1566 break;
1567 case 'O':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001568 i = string_to_uint(optarg);
1569 if (i < 0)
1570 error_opt_arg(c, optarg);
1571 set_overhead(i);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572 break;
1573 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001574 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001576 case 'P':
1577 tracing_paths = 1;
1578 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001579 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001580 }
1581 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 case 's':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001583 i = string_to_uint(optarg);
1584 if (i < 0)
1585 error_opt_arg(c, optarg);
1586 max_strlen = i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587 break;
1588 case 'S':
1589 set_sortby(optarg);
1590 break;
1591 case 'u':
1592 username = strdup(optarg);
1593 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001594 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001595 if (putenv(optarg) < 0)
1596 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001597 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001598 case 'I':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001599 opt_intr = string_to_uint(optarg);
1600 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS)
1601 error_opt_arg(c, optarg);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001602 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603 default:
1604 usage(stderr, 1);
1605 break;
1606 }
1607 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001608 argv += optind;
1609 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610
Denys Vlasenko102ec492011-08-25 01:27:59 +02001611 acolumn_spaces = malloc(acolumn + 1);
1612 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001613 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001614 memset(acolumn_spaces, ' ', acolumn);
1615 acolumn_spaces[acolumn] = '\0';
1616
Denys Vlasenko837399a2012-01-24 11:37:03 +01001617 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001618 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001619 usage(stderr, 1);
1620
Denys Vlasenkofd883382012-03-09 13:03:41 +01001621 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001622 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001623 }
1624
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001625 if (!followfork)
1626 followfork = optF;
1627
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001628 if (followfork >= 2 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001629 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001630 }
1631
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632 /* See if they want to run as another user. */
1633 if (username != NULL) {
1634 struct passwd *pent;
1635
1636 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001637 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001639 pent = getpwnam(username);
1640 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001641 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 }
1643 run_uid = pent->pw_uid;
1644 run_gid = pent->pw_gid;
1645 }
1646 else {
1647 run_uid = getuid();
1648 run_gid = getgid();
1649 }
1650
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001651 if (followfork)
1652 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001653 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001654 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001655
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656 /* Check if they want to redirect the output. */
1657 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001658 /* See if they want to pipe the output. */
1659 if (outfname[0] == '|' || outfname[0] == '!') {
1660 /*
1661 * We can't do the <outfname>.PID funny business
1662 * when using popen, so prohibit it.
1663 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001664 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001665 error_msg_and_die("Piping the output and -ff are mutually exclusive");
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001666 shared_log = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001667 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001668 else if (followfork < 2)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001669 shared_log = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001670 } else {
1671 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001672 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001673 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 }
1675
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001676 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001677 char *buf = malloc(BUFSIZ);
1678 if (!buf)
1679 die_out_of_memory();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001680 setvbuf(shared_log, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001681 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001682 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001683 if (!opt_intr)
1684 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001686 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001687 if (!opt_intr)
1688 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001689
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001690 /* argv[0] -pPID -oFILE Default interactive setting
1691 * yes 0 0 INTR_WHILE_WAIT
1692 * no 1 0 INTR_WHILE_WAIT
1693 * yes 0 1 INTR_NEVER
1694 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001695 */
1696
1697 /* STARTUP_CHILD must be called before the signal handlers get
1698 installed below as they are inherited into the spawned process.
1699 Also we do not need to be protected by them as during interruption
1700 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001701 if (argv[0]) {
1702 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001703 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001704 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706 sigemptyset(&empty_set);
1707 sigemptyset(&blocked_set);
1708 sa.sa_handler = SIG_IGN;
1709 sigemptyset(&sa.sa_mask);
1710 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001711 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1712 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1713 if (opt_intr != INTR_ANYWHERE) {
1714 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1715 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1716 /*
1717 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1718 * fatal signals are blocked while syscall stop is processed,
1719 * and acted on in between, when waiting for new syscall stops.
1720 * In non-interactive mode, signals are ignored.
1721 */
1722 if (opt_intr == INTR_WHILE_WAIT) {
1723 sigaddset(&blocked_set, SIGHUP);
1724 sigaddset(&blocked_set, SIGINT);
1725 sigaddset(&blocked_set, SIGQUIT);
1726 sigaddset(&blocked_set, SIGPIPE);
1727 sigaddset(&blocked_set, SIGTERM);
1728 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001729 }
1730 /* SIG_IGN, or set handler for these */
1731 sigaction(SIGHUP, &sa, NULL);
1732 sigaction(SIGINT, &sa, NULL);
1733 sigaction(SIGQUIT, &sa, NULL);
1734 sigaction(SIGPIPE, &sa, NULL);
1735 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001737 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001738 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001739
Denys Vlasenkofd883382012-03-09 13:03:41 +01001740 /* Do we want pids printed in our -o OUTFILE?
1741 * -ff: no (every pid has its own file); or
1742 * -f: yes (there can be more pids in the future); or
1743 * -p PID1,PID2: yes (there are already more than one pid)
1744 */
1745 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746}
1747
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001748static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001749pid2tcb(int pid)
1750{
1751 int i;
1752
1753 if (pid <= 0)
1754 return NULL;
1755
1756 for (i = 0; i < tcbtabsize; i++) {
1757 struct tcb *tcp = tcbtab[i];
1758 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1759 return tcp;
1760 }
1761
1762 return NULL;
1763}
1764
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001766cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767{
1768 int i;
1769 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001770 int fatal_sig;
1771
1772 /* 'interrupted' is a volatile object, fetch it only once */
1773 fatal_sig = interrupted;
1774 if (!fatal_sig)
1775 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776
Roland McGrathee9d4352002-12-18 04:16:10 +00001777 for (i = 0; i < tcbtabsize; i++) {
1778 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779 if (!(tcp->flags & TCB_INUSE))
1780 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001781 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782 fprintf(stderr,
1783 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001784 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001786 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001788 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789 }
1790 if (cflag)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001791 call_summary(shared_log);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792}
1793
1794static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001795interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001797 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798}
1799
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001801trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001804 struct rusage *rup = cflag ? &ru : NULL;
1805# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001806 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001807# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808
Roland McGratheb9e2e82009-06-02 16:49:22 -07001809 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001810 int pid;
1811 int wait_errno;
1812 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001813 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001814 struct tcb *tcp;
1815 unsigned event;
1816
Denys Vlasenko222713a2009-03-17 14:29:59 +00001817 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001818 return 0;
1819 if (interactive)
1820 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001821# ifdef __WALL
1822 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001823 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001824 /* this kernel does not support __WALL */
1825 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001826 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001827 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001828 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001829 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001830 pid = wait4(-1, &status, __WCLONE, rup);
1831 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001832 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001833 }
1834 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001835# else
1836 pid = wait4(-1, &status, 0, rup);
1837# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001839 if (interactive)
1840 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001842 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001843 switch (wait_errno) {
1844 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001846 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847 /*
1848 * We would like to verify this case
1849 * but sometimes a race in Solbourne's
1850 * version of SunOS sometimes reports
1851 * ECHILD before sending us SIGCHILD.
1852 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001853 return 0;
1854 default:
1855 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001856 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001857 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001858 }
1859 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001860 if (pid == popen_pid) {
1861 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001862 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001863 continue;
1864 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001865
1866 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001867 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001868 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001869 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001870 strcpy(buf, "???");
1871 if (WIFSIGNALED(status))
1872#ifdef WCOREDUMP
1873 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1874 WCOREDUMP(status) ? "core," : "",
1875 signame(WTERMSIG(status)));
1876#else
1877 sprintf(buf, "WIFSIGNALED,sig=%s",
1878 signame(WTERMSIG(status)));
1879#endif
1880 if (WIFEXITED(status))
1881 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1882 if (WIFSTOPPED(status))
1883 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001884#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001885 if (WIFCONTINUED(status))
1886 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001887#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001888 evbuf[0] = '\0';
1889 if (event != 0) {
1890 static const char *const event_names[] = {
1891 [PTRACE_EVENT_CLONE] = "CLONE",
1892 [PTRACE_EVENT_FORK] = "FORK",
1893 [PTRACE_EVENT_VFORK] = "VFORK",
1894 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1895 [PTRACE_EVENT_EXEC] = "EXEC",
1896 [PTRACE_EVENT_EXIT] = "EXIT",
1897 };
1898 const char *e;
1899 if (event < ARRAY_SIZE(event_names))
1900 e = event_names[event];
1901 else {
1902 sprintf(buf, "?? (%u)", event);
1903 e = buf;
1904 }
1905 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1906 }
1907 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001908 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001910 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001911 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001912
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001913 if (!tcp) {
Roland McGrath41c48222008-07-18 00:25:10 +00001914 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001915 /* This is needed to go with the CLONE_PTRACE
1916 changes in process.c/util.c: we might see
1917 the child's initial trap before we see the
1918 parent return from the clone syscall.
1919 Leave the child suspended until the parent
1920 returns from its system call. Only then
1921 will we have the association of parent and
1922 child so that we know how to do clearbpt
1923 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001924 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001925 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001926 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001927 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001928 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001929 pid);
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001930 } else {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001931 /* This can happen if a clone call used
1932 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001933 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001934 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001935 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001936 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001938
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001939 /* Under Linux, execve changes pid to thread leader's pid,
1940 * and we see this changed pid on EVENT_EXEC and later,
1941 * execve sysexit. Leader "disappears" without exit
1942 * notification. Let user know that, drop leader's tcb,
1943 * and fix up pid in execve thread's tcb.
1944 * Effectively, execve thread's tcb replaces leader's tcb.
1945 *
1946 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1947 * on exit syscall) in multithreaded programs exactly
1948 * in order to handle this case.
1949 *
1950 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1951 * On 2.6 and earlier, it can return garbage.
1952 */
1953 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001954 FILE *fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001955 struct tcb *execve_thread;
1956 long old_pid = 0;
1957
1958 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0)
1959 goto dont_switch_tcbs;
1960 if (old_pid <= 0 || old_pid == pid)
1961 goto dont_switch_tcbs;
1962 execve_thread = pid2tcb(old_pid);
1963 /* It should be !NULL, but I feel paranoid */
1964 if (!execve_thread)
1965 goto dont_switch_tcbs;
1966
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001967 if (execve_thread->curcol != 0) {
1968 /*
1969 * One case we are here is -ff:
1970 * try "strace -oLOG -ff test/threaded_execve"
1971 */
1972 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001973 /*execve_thread->curcol = 0; - no need, see code below */
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001974 }
1975 /* Swap output FILEs (needed for -ff) */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001976 fp = execve_thread->outf;
1977 execve_thread->outf = tcp->outf;
1978 tcp->outf = fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001979 /* And their column positions */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001980 execve_thread->curcol = tcp->curcol;
1981 tcp->curcol = 0;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001982 /* Drop leader, but close execve'd thread outfile (if -ff) */
1983 droptcb(tcp);
1984 /* Switch to the thread, reusing leader's outfile and pid */
1985 tcp = execve_thread;
1986 tcp->pid = pid;
1987 if (cflag != CFLAG_ONLY_STATS) {
1988 printleader(tcp);
1989 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1990 line_ended();
1991 tcp->flags |= TCB_REPRINT;
1992 }
1993 }
1994 dont_switch_tcbs:
1995
1996 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1997 if (!skip_startup_execve)
1998 detach(tcp);
1999 /* This was initial execve for "strace PROG". Skip. */
2000 skip_startup_execve = 0;
2001 }
2002
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002003 /* Set current output file */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01002004 current_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002005
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002006 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002007 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2008 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002010
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002012 if (pid == strace_child)
2013 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002014 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2016 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002017#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002018 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002019 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002020 WCOREDUMP(status) ? "(core dumped) " : "");
2021#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002022 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002023 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002024#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002025 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002026 }
2027 droptcb(tcp);
2028 continue;
2029 }
2030 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002031 if (pid == strace_child)
2032 exit_code = WEXITSTATUS(status);
Denys Vlasenkob5e09082012-03-21 14:27:40 +01002033 if (cflag != CFLAG_ONLY_STATS) {
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002034 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002035 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002036 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002037 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038 droptcb(tcp);
2039 continue;
2040 }
2041 if (!WIFSTOPPED(status)) {
2042 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2043 droptcb(tcp);
2044 continue;
2045 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002046
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002047 /* Is this the very first time we see this tracee stopped? */
2048 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002049 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002050 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002051 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002053 /*
2054 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002055 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002056 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002057 if (clearbpt(tcp) < 0) {
2058 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059 droptcb(tcp);
2060 cleanup();
2061 return -1;
2062 }
2063 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002064 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002065 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002066 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2067 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2068 if (errno != ESRCH) {
2069 /* Should never happen, really */
2070 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002071 }
2072 }
2073 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002074 }
2075
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002076 sig = WSTOPSIG(status);
2077
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002078 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002079 /* Ptrace event */
2080#ifdef USE_SEIZE
2081 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002082 /*
2083 * PTRACE_INTERRUPT-stop or group-stop.
2084 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2085 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002086 if (sig == SIGSTOP
2087 || sig == SIGTSTP
2088 || sig == SIGTTIN
2089 || sig == SIGTTOU
2090 ) {
2091 stopped = 1;
2092 goto show_stopsig;
2093 }
2094 }
2095#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002096 goto restart_tracee_with_sig_0;
2097 }
2098
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002099 /* Is this post-attach SIGSTOP?
2100 * Interestingly, the process may stop
2101 * with STOPSIG equal to some other signal
2102 * than SIGSTOP if we happend to attach
2103 * just before the process takes a signal.
2104 */
2105 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002106 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002107 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2108 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002109 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 }
2111
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002112 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002113 siginfo_t si;
2114
2115 /* Nonzero (true) if tracee is stopped by signal
2116 * (as opposed to "tracee received signal").
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002117 * TODO: shouldn't we check for errno == EINVAL too?
2118 * We can get ESRCH instead, you know...
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002119 */
2120 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002121#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002122 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002123#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002124 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002125 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002126#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002127 long pc = 0;
2128 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002129
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002130 upeek(tcp, PT_CR_IPSR, &psr);
2131 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002132
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002133# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002134 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002135# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002136# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002137#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002138# define PC_FORMAT_STR ""
2139# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002140#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002142 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002143 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002144 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002145 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002146 PC_FORMAT_ARG);
2147 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002148 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002149 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002150 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002151 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002152 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002153
2154 if (!stopped)
2155 /* It's signal-delivery-stop. Inject the signal */
2156 goto restart_tracee;
2157
2158 /* It's group-stop */
2159#ifdef USE_SEIZE
2160 if (use_seize) {
2161 /*
2162 * This ends ptrace-stop, but does *not* end group-stop.
2163 * This makes stopping signals work properly on straced process
2164 * (that is, process really stops. It used to continue to run).
2165 */
2166 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2167 cleanup();
2168 return -1;
2169 }
2170 continue;
2171 }
2172 /* We don't have PTRACE_LISTEN support... */
2173#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002174 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002175 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002176
2177 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002178 if (interrupted)
2179 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002180
2181 /* This should be syscall entry or exit.
2182 * (Or it still can be that pesky post-execve SIGTRAP!)
2183 * Handle it.
2184 */
Denys Vlasenko23506752012-03-21 10:32:49 +01002185 if (trace_syscall(tcp) < 0) {
2186 /* ptrace() failed in trace_syscall().
Roland McGratheb9e2e82009-06-02 16:49:22 -07002187 * Likely a result of process disappearing mid-flight.
Denys Vlasenko23506752012-03-21 10:32:49 +01002188 * Observed case: exit_group() or SIGKILL terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002189 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002190 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002191 * We used to detach(tcp) here, but since we no longer
2192 * implement "detach before death" policy/hack,
2193 * we can let this process to report its death to us
2194 * normally, via WIFEXITED or WIFSIGNALED wait status.
2195 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 continue;
2197 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002198 restart_tracee_with_sig_0:
2199 sig = 0;
2200 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002201 /* Remember current print column before continuing. */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002202 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 cleanup();
2204 return -1;
2205 }
2206 }
2207 return 0;
2208}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002209
2210int
2211main(int argc, char *argv[])
2212{
2213 init(argc, argv);
2214
2215 /* Run main tracing loop */
2216 if (trace() < 0)
2217 return 1;
2218
2219 cleanup();
2220 fflush(NULL);
2221 if (exit_code > 0xff) {
2222 /* Avoid potential core file clobbering. */
2223 struct rlimit rlim = {0, 0};
2224 setrlimit(RLIMIT_CORE, &rlim);
2225
2226 /* Child was killed by a signal, mimic that. */
2227 exit_code &= 0xff;
2228 signal(exit_code, SIG_DFL);
2229 raise(exit_code);
2230 /* Paranoia - what if this signal is not fatal?
2231 Exit with 128 + signo then. */
2232 exit_code += 128;
2233 }
2234
2235 return exit_code;
2236}