blob: ac7e67203878153ca86a42d01e18c40b69cc4c4b [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;
134static unsigned 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
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400318/* Glue for systems without a MMU that cannot provide fork() */
319#ifdef HAVE_FORK
320# define strace_vforked 0
321#else
322# define strace_vforked 1
323# define fork() vfork()
324#endif
325
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100326#ifdef USE_SEIZE
327static int
328ptrace_attach_or_seize(int pid)
329{
330 int r;
331 if (!use_seize)
332 return ptrace(PTRACE_ATTACH, pid, 0, 0);
333 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
334 if (r)
335 return r;
336 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
337 return r;
338}
339#else
340# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
341#endif
342
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100343/*
344 * Used when we want to unblock stopped traced process.
345 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
346 * Returns 0 on success or if error was ESRCH
347 * (presumably process was killed while we talk to it).
348 * Otherwise prints error message and returns -1.
349 */
350static int
351ptrace_restart(int op, struct tcb *tcp, int sig)
352{
353 int err;
354 const char *msg;
355
356 errno = 0;
357 ptrace(op, tcp->pid, (void *) 0, (long) sig);
358 err = errno;
Denys Vlasenko23506752012-03-21 10:32:49 +0100359 if (!err)
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100360 return 0;
361
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100362 msg = "SYSCALL";
363 if (op == PTRACE_CONT)
364 msg = "CONT";
365 if (op == PTRACE_DETACH)
366 msg = "DETACH";
367#ifdef PTRACE_LISTEN
368 if (op == PTRACE_LISTEN)
369 msg = "LISTEN";
370#endif
Denys Vlasenko23506752012-03-21 10:32:49 +0100371 /*
372 * Why curcol != 0? Otherwise sometimes we get this:
373 *
374 * 10252 kill(10253, SIGKILL) = 0
375 * <ptrace(SYSCALL,10252):No such process>10253 ...next decode...
376 *
377 * 10252 died after we retrieved syscall exit data,
378 * but before we tried to restart it. Log looks ugly.
379 */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100380 if (current_tcp && current_tcp->curcol != 0) {
Denys Vlasenko23506752012-03-21 10:32:49 +0100381 tprintf(" <ptrace(%s):%s>\n", msg, strerror(err));
382 line_ended();
383 }
384 if (err == ESRCH)
385 return 0;
386 errno = err;
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100387 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
388 return -1;
389}
390
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200391static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000392set_cloexec_flag(int fd)
393{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200394 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000395
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200396 flags = fcntl(fd, F_GETFD);
397 if (flags < 0) {
398 /* Can happen only if fd is bad.
399 * Should never happen: if it does, we have a bug
400 * in the caller. Therefore we just abort
401 * instead of propagating the error.
402 */
403 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000404 }
405
406 newflags = flags | FD_CLOEXEC;
407 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200408 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000409
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200410 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000411}
412
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100413static void kill_save_errno(pid_t pid, int sig)
414{
415 int saved_errno = errno;
416
417 (void) kill(pid, sig);
418 errno = saved_errno;
419}
420
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100421/*
422 * When strace is setuid executable, we have to swap uids
423 * before and after filesystem and process management operations.
424 */
425static void
426swap_uid(void)
427{
428 int euid = geteuid(), uid = getuid();
429
430 if (euid != uid && setreuid(euid, uid) < 0) {
431 perror_msg_and_die("setreuid");
432 }
433}
434
435#if _LFS64_LARGEFILE
436# define fopen_for_output fopen64
437#else
438# define fopen_for_output fopen
439#endif
440
441static FILE *
442strace_fopen(const char *path)
443{
444 FILE *fp;
445
446 swap_uid();
447 fp = fopen_for_output(path, "w");
448 if (!fp)
449 perror_msg_and_die("Can't fopen '%s'", path);
450 swap_uid();
451 set_cloexec_flag(fileno(fp));
452 return fp;
453}
454
455static int popen_pid = 0;
456
457#ifndef _PATH_BSHELL
458# define _PATH_BSHELL "/bin/sh"
459#endif
460
461/*
462 * We cannot use standard popen(3) here because we have to distinguish
463 * popen child process from other processes we trace, and standard popen(3)
464 * does not export its child's pid.
465 */
466static FILE *
467strace_popen(const char *command)
468{
469 FILE *fp;
470 int fds[2];
471
472 swap_uid();
473 if (pipe(fds) < 0)
474 perror_msg_and_die("pipe");
475
476 set_cloexec_flag(fds[1]); /* never fails */
477
478 popen_pid = vfork();
479 if (popen_pid == -1)
480 perror_msg_and_die("vfork");
481
482 if (popen_pid == 0) {
483 /* child */
484 close(fds[1]);
485 if (fds[0] != 0) {
486 if (dup2(fds[0], 0))
487 perror_msg_and_die("dup2");
488 close(fds[0]);
489 }
490 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
491 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
492 }
493
494 /* parent */
495 close(fds[0]);
496 swap_uid();
497 fp = fdopen(fds[1], "w");
498 if (!fp)
499 die_out_of_memory();
500 return fp;
501}
502
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100503void
504tprintf(const char *fmt, ...)
505{
506 va_list args;
507
508 va_start(args, fmt);
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100509 if (current_tcp) {
510 int n = vfprintf(current_tcp->outf, fmt, args);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100511 if (n < 0) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100512 if (current_tcp->outf != stderr)
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100513 perror(outfname == NULL
514 ? "<writing to pipe>" : outfname);
515 } else
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100516 current_tcp->curcol += n;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100517 }
518 va_end(args);
519}
520
521void
522tprints(const char *str)
523{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100524 if (current_tcp) {
525 int n = fputs(str, current_tcp->outf);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100526 if (n >= 0) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100527 current_tcp->curcol += strlen(str);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100528 return;
529 }
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100530 if (current_tcp->outf != stderr)
531 perror(!outfname ? "<writing to pipe>" : outfname);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100532 }
533}
534
535void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100536line_ended(void)
537{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100538 if (current_tcp) {
539 current_tcp->curcol = 0;
540 fflush(current_tcp->outf);
541 }
542 if (printing_tcp) {
543 printing_tcp->curcol = 0;
544 printing_tcp = NULL;
545 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100546}
547
548void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100549printleader(struct tcb *tcp)
550{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100551 /* If -ff, "previous tcb we printed" is always the same as current,
552 * because we have per-tcb output files.
553 */
554 if (followfork >= 2)
555 printing_tcp = tcp;
556
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100557 if (printing_tcp) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100558 current_tcp = printing_tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100559 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
560 /*
561 * case 1: we have a shared log (i.e. not -ff), and last line
562 * wasn't finished (same or different tcb, doesn't matter).
563 * case 2: split log, we are the same tcb, but our last line
564 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
565 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100566 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100567 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100568 }
569 }
570
571 printing_tcp = tcp;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100572 current_tcp = tcp;
573 current_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100574
575 if (print_pid_pfx)
576 tprintf("%-5d ", tcp->pid);
577 else if (nprocs > 1 && !outfname)
578 tprintf("[pid %5u] ", tcp->pid);
579
580 if (tflag) {
581 char str[sizeof("HH:MM:SS")];
582 struct timeval tv, dtv;
583 static struct timeval otv;
584
585 gettimeofday(&tv, NULL);
586 if (rflag) {
587 if (otv.tv_sec == 0)
588 otv = tv;
589 tv_sub(&dtv, &tv, &otv);
590 tprintf("%6ld.%06ld ",
591 (long) dtv.tv_sec, (long) dtv.tv_usec);
592 otv = tv;
593 }
594 else if (tflag > 2) {
595 tprintf("%ld.%06ld ",
596 (long) tv.tv_sec, (long) tv.tv_usec);
597 }
598 else {
599 time_t local = tv.tv_sec;
600 strftime(str, sizeof(str), "%T", localtime(&local));
601 if (tflag > 1)
602 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
603 else
604 tprintf("%s ", str);
605 }
606 }
607 if (iflag)
608 printcall(tcp);
609}
610
611void
612tabto(void)
613{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100614 if (current_tcp->curcol < acolumn)
615 tprints(acolumn_spaces + current_tcp->curcol);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100616}
617
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100618/* Should be only called directly *after successful attach* to a tracee.
619 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
620 * may create bogus empty FILE.<nonexistant_pid>, and then die.
621 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200622static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000623newoutf(struct tcb *tcp)
624{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100625 tcp->outf = shared_log; /* if not -ff mode, the same file is for all */
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100626 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000627 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000628 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200629 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000630 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000631}
632
Denys Vlasenko558e5122012-03-12 23:32:16 +0100633static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100634expand_tcbtab(void)
635{
636 /* Allocate some more TCBs and expand the table.
637 We don't want to relocate the TCBs because our
638 callers have pointers and it would be a pain.
639 So tcbtab is a table of pointers. Since we never
640 free the TCBs, we allocate a single chunk of many. */
641 int i = tcbtabsize;
642 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
643 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
644 if (!newtab || !newtcbs)
645 die_out_of_memory();
646 tcbtabsize *= 2;
647 tcbtab = newtab;
648 while (i < tcbtabsize)
649 tcbtab[i++] = newtcbs++;
650}
651
652static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100653alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100654{
655 int i;
656 struct tcb *tcp;
657
658 if (nprocs == tcbtabsize)
659 expand_tcbtab();
660
661 for (i = 0; i < tcbtabsize; i++) {
662 tcp = tcbtab[i];
663 if ((tcp->flags & TCB_INUSE) == 0) {
664 memset(tcp, 0, sizeof(*tcp));
665 tcp->pid = pid;
666 tcp->flags = TCB_INUSE;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100667#if SUPPORTED_PERSONALITIES > 1
668 tcp->currpers = current_personality;
669#endif
670 nprocs++;
671 if (debug_flag)
672 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100673 return tcp;
674 }
675 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100676 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100677}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100678
679static void
680droptcb(struct tcb *tcp)
681{
682 if (tcp->pid == 0)
683 return;
684
685 nprocs--;
686 if (debug_flag)
687 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
688
689 if (tcp->outf) {
Denys Vlasenko8511f2a2012-03-22 09:35:51 +0100690 if (followfork >= 2) {
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100691 if (tcp->curcol != 0)
692 fprintf(tcp->outf, " <detached ...>\n");
693 fclose(tcp->outf);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100694 } else {
695 if (printing_tcp == tcp && tcp->curcol != 0)
696 fprintf(tcp->outf, " <detached ...>\n");
697 fflush(tcp->outf);
698 }
699 }
700
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100701 if (current_tcp == tcp)
702 current_tcp = NULL;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100703 if (printing_tcp == tcp)
704 printing_tcp = NULL;
705
706 memset(tcp, 0, sizeof(*tcp));
707}
708
709/* detach traced process; continue with sig
710 * Never call DETACH twice on the same process as both unattached and
711 * attached-unstopped processes give the same ESRCH. For unattached process we
712 * would SIGSTOP it and wait for its SIGSTOP notification forever.
713 */
714static int
715detach(struct tcb *tcp)
716{
717 int error;
718 int status, sigstop_expected;
719
720 if (tcp->flags & TCB_BPTSET)
721 clearbpt(tcp);
722
723 /*
724 * Linux wrongly insists the child be stopped
725 * before detaching. Arghh. We go through hoops
726 * to make a clean break of things.
727 */
728#if defined(SPARC)
729#undef PTRACE_DETACH
730#define PTRACE_DETACH PTRACE_SUNDETACH
731#endif
732
733 error = 0;
734 sigstop_expected = 0;
735 if (tcp->flags & TCB_ATTACHED) {
736 /*
737 * We attached but possibly didn't see the expected SIGSTOP.
738 * We must catch exactly one as otherwise the detached process
739 * would be left stopped (process state T).
740 */
741 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
742 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
743 if (error == 0) {
744 /* On a clear day, you can see forever. */
745 }
746 else if (errno != ESRCH) {
747 /* Shouldn't happen. */
748 perror("detach: ptrace(PTRACE_DETACH, ...)");
749 }
750 else if (my_tkill(tcp->pid, 0) < 0) {
751 if (errno != ESRCH)
752 perror("detach: checking sanity");
753 }
754 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
755 if (errno != ESRCH)
756 perror("detach: stopping child");
757 }
758 else
759 sigstop_expected = 1;
760 }
761
762 if (sigstop_expected) {
763 for (;;) {
764#ifdef __WALL
765 if (waitpid(tcp->pid, &status, __WALL) < 0) {
766 if (errno == ECHILD) /* Already gone. */
767 break;
768 if (errno != EINVAL) {
769 perror("detach: waiting");
770 break;
771 }
772#endif /* __WALL */
773 /* No __WALL here. */
774 if (waitpid(tcp->pid, &status, 0) < 0) {
775 if (errno != ECHILD) {
776 perror("detach: waiting");
777 break;
778 }
779#ifdef __WCLONE
780 /* If no processes, try clones. */
781 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
782 if (errno != ECHILD)
783 perror("detach: waiting");
784 break;
785 }
786#endif /* __WCLONE */
787 }
788#ifdef __WALL
789 }
790#endif
791 if (!WIFSTOPPED(status)) {
792 /* Au revoir, mon ami. */
793 break;
794 }
795 if (WSTOPSIG(status) == SIGSTOP) {
796 ptrace_restart(PTRACE_DETACH, tcp, 0);
797 break;
798 }
799 error = ptrace_restart(PTRACE_CONT, tcp,
800 WSTOPSIG(status) == syscall_trap_sig ? 0
801 : WSTOPSIG(status));
802 if (error < 0)
803 break;
804 }
805 }
806
807 if (!qflag && (tcp->flags & TCB_ATTACHED))
808 fprintf(stderr, "Process %u detached\n", tcp->pid);
809
810 droptcb(tcp);
811
812 return error;
813}
814
815static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100816process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100817{
818 while (*opt) {
819 /*
820 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
821 * pidof uses space as delim, pgrep uses newline. :(
822 */
823 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100824 char *delim = opt + strcspn(opt, ", \n\t");
825 char c = *delim;
826
827 *delim = '\0';
828 pid = atoi(opt); /* TODO: stricter parsing of the number? */
829 if (pid <= 0) {
830 error_msg("Invalid process id: '%s'", opt);
831 *delim = c;
832 return;
833 }
834 if (pid == strace_tracer_pid) {
835 error_msg("I'm sorry, I can't let you do that, Dave.");
836 *delim = c;
837 return;
838 }
839 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100840 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100841 if (c == '\0')
842 break;
843 opt = delim + 1;
844 }
845}
846
Roland McGrath02203312007-06-11 22:06:31 +0000847static void
848startup_attach(void)
849{
850 int tcbi;
851 struct tcb *tcp;
852
853 /*
854 * Block user interruptions as we would leave the traced
855 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200856 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200857 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000858 */
859 if (interactive)
860 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
861
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000862 if (daemonized_tracer) {
863 pid_t pid = fork();
864 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200865 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000866 }
867 if (pid) { /* parent */
868 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200869 * Wait for grandchild to attach to straced process
870 * (grandparent). Grandchild SIGKILLs us after it attached.
871 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000872 * it proceeds to exec the straced program.
873 */
874 pause();
875 _exit(0); /* paranoia */
876 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200877 /* grandchild */
878 /* We will be the tracer process. Remember our new pid: */
879 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000880 }
881
Roland McGrath02203312007-06-11 22:06:31 +0000882 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
883 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200884
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100885 if (!(tcp->flags & TCB_INUSE))
886 continue;
887
Denys Vlasenkod116a732011-09-05 14:01:33 +0200888 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100889 if (tcp->flags & TCB_ATTACHED)
890 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200891
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000892 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000893 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000894 DIR *dir;
895
896 sprintf(procdir, "/proc/%d/task", tcp->pid);
897 dir = opendir(procdir);
898 if (dir != NULL) {
899 unsigned int ntid = 0, nerr = 0;
900 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200901
Roland McGrath02203312007-06-11 22:06:31 +0000902 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200903 struct tcb *cur_tcp;
904 int tid;
905
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000906 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000907 continue;
908 tid = atoi(de->d_name);
909 if (tid <= 0)
910 continue;
911 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100912 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000913 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100914 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200915 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200916 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200917 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100918 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200919 fprintf(stderr, "attach to pid %d succeeded\n", tid);
920 cur_tcp = tcp;
921 if (tid != tcp->pid)
922 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100923 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100924 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000925 }
926 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200927 if (interactive) {
928 sigprocmask(SIG_SETMASK, &empty_set, NULL);
929 if (interrupted)
930 goto ret;
931 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
932 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000933 ntid -= nerr;
934 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000935 perror("attach: ptrace(PTRACE_ATTACH, ...)");
936 droptcb(tcp);
937 continue;
938 }
939 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000940 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100941? "Process %u attached with %u threads\n"
942: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200943 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000944 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100945 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200946 /* -p PID, we failed to attach to PID itself
947 * but did attach to some of its sibling threads.
948 * Drop PID's tcp.
949 */
950 droptcb(tcp);
951 }
Roland McGrath02203312007-06-11 22:06:31 +0000952 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000953 } /* if (opendir worked) */
954 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100955 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000956 perror("attach: ptrace(PTRACE_ATTACH, ...)");
957 droptcb(tcp);
958 continue;
959 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100960 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100961 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100962 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200963 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000964
965 if (daemonized_tracer) {
966 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000967 * Make parent go away.
968 * Also makes grandparent's wait() unblock.
969 */
970 kill(getppid(), SIGKILL);
971 }
972
Roland McGrath02203312007-06-11 22:06:31 +0000973 if (!qflag)
974 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100975 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000976 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200977 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000978
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200979 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000980 if (interactive)
981 sigprocmask(SIG_SETMASK, &empty_set, NULL);
982}
983
984static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200985startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000986{
987 struct stat statbuf;
988 const char *filename;
989 char pathname[MAXPATHLEN];
990 int pid = 0;
991 struct tcb *tcp;
992
993 filename = argv[0];
994 if (strchr(filename, '/')) {
995 if (strlen(filename) > sizeof pathname - 1) {
996 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200997 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000998 }
999 strcpy(pathname, filename);
1000 }
1001#ifdef USE_DEBUGGING_EXEC
1002 /*
1003 * Debuggers customarily check the current directory
1004 * first regardless of the path but doing that gives
1005 * security geeks a panic attack.
1006 */
1007 else if (stat(filename, &statbuf) == 0)
1008 strcpy(pathname, filename);
1009#endif /* USE_DEBUGGING_EXEC */
1010 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +00001011 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +00001012 int m, n, len;
1013
1014 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +01001015 const char *colon = strchr(path, ':');
1016 if (colon) {
1017 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +00001018 m = n + 1;
1019 }
1020 else
1021 m = n = strlen(path);
1022 if (n == 0) {
1023 if (!getcwd(pathname, MAXPATHLEN))
1024 continue;
1025 len = strlen(pathname);
1026 }
1027 else if (n > sizeof pathname - 1)
1028 continue;
1029 else {
1030 strncpy(pathname, path, n);
1031 len = n;
1032 }
1033 if (len && pathname[len - 1] != '/')
1034 pathname[len++] = '/';
1035 strcpy(pathname + len, filename);
1036 if (stat(pathname, &statbuf) == 0 &&
1037 /* Accept only regular files
1038 with some execute bits set.
1039 XXX not perfect, might still fail */
1040 S_ISREG(statbuf.st_mode) &&
1041 (statbuf.st_mode & 0111))
1042 break;
1043 }
1044 }
1045 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001046 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001047 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001048 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001049 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001050 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001051 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001052 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1053 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001054 ) {
1055 pid = getpid();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001056 if (shared_log != stderr)
1057 close(fileno(shared_log));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001058 if (!daemonized_tracer && !use_seize) {
1059 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001060 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001061 }
Roland McGrath02203312007-06-11 22:06:31 +00001062 }
Roland McGrath02203312007-06-11 22:06:31 +00001063
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001064 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001065 uid_t run_euid = run_uid;
1066 gid_t run_egid = run_gid;
1067
1068 if (statbuf.st_mode & S_ISUID)
1069 run_euid = statbuf.st_uid;
1070 if (statbuf.st_mode & S_ISGID)
1071 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001072 /*
1073 * It is important to set groups before we
1074 * lose privileges on setuid.
1075 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001076 if (initgroups(username, run_gid) < 0) {
1077 perror_msg_and_die("initgroups");
1078 }
1079 if (setregid(run_gid, run_egid) < 0) {
1080 perror_msg_and_die("setregid");
1081 }
1082 if (setreuid(run_uid, run_euid) < 0) {
1083 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001084 }
1085 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001086 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001087 setreuid(run_uid, run_uid);
1088
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001089 if (!daemonized_tracer) {
1090 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001091 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001092 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001093 * the immediately following execve syscall.
1094 * Can't do this on NOMMU systems, we are after
1095 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001096 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001097 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001098 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001099 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001100 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001101 /* we depend on SIGCHLD set to SIG_DFL by init code */
1102 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001103 wait(NULL);
1104 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001105 }
Roland McGrath02203312007-06-11 22:06:31 +00001106
1107 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001108 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001109 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001110
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001111 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001112
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001113 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001114 if (!use_seize) {
1115 /* child did PTRACE_TRACEME, nothing to do in parent */
1116 } else {
1117 if (!strace_vforked) {
1118 /* Wait until child stopped itself */
1119 int status;
1120 while (waitpid(pid, &status, WSTOPPED) < 0) {
1121 if (errno == EINTR)
1122 continue;
1123 perror_msg_and_die("waitpid");
1124 }
1125 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001126 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001127 perror_msg_and_die("Unexpected wait status %x", status);
1128 }
1129 }
1130 /* Else: vforked case, we have no way to sync.
1131 * Just attach to it as soon as possible.
1132 * This means that we may miss a few first syscalls...
1133 */
1134
1135 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001136 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001137 perror_msg_and_die("Can't attach to %d", pid);
1138 }
1139 if (!strace_vforked)
1140 kill(pid, SIGCONT);
1141 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001142 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001143 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001144 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001145 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001146 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001147 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001148 }
1149 else {
1150 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1151 strace_tracer_pid = getpid();
1152 /* The tracee is our parent: */
1153 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001154 alloctcb(pid);
1155 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001156 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001157 }
Roland McGrath02203312007-06-11 22:06:31 +00001158}
1159
Wang Chaob13c0de2010-11-12 17:25:19 +08001160/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001161 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001162 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001163 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001164 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001165static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001166test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001167{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001168 int pid, expected_grandchild = 0, found_grandchild = 0;
1169 const unsigned int test_options = PTRACE_O_TRACECLONE |
1170 PTRACE_O_TRACEFORK |
1171 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001172
Denys Vlasenko5d645812011-08-20 12:48:18 +02001173 pid = fork();
1174 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001175 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001176 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001177 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001178 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001179 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1180 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001181 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001182 if (fork() < 0)
1183 perror_msg_and_die("fork");
1184 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001185 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001186
1187 while (1) {
1188 int status, tracee_pid;
1189
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001190 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001191 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001192 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001193 if (errno == EINTR)
1194 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001195 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001196 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001197 kill_save_errno(pid, SIGKILL);
1198 perror_msg_and_die("%s: unexpected wait result %d",
1199 __func__, tracee_pid);
1200 }
1201 if (WIFEXITED(status)) {
1202 if (WEXITSTATUS(status)) {
1203 if (tracee_pid != pid)
1204 kill_save_errno(pid, SIGKILL);
1205 error_msg_and_die("%s: unexpected exit status %u",
1206 __func__, WEXITSTATUS(status));
1207 }
1208 continue;
1209 }
1210 if (WIFSIGNALED(status)) {
1211 if (tracee_pid != pid)
1212 kill_save_errno(pid, SIGKILL);
1213 error_msg_and_die("%s: unexpected signal %u",
1214 __func__, WTERMSIG(status));
1215 }
1216 if (!WIFSTOPPED(status)) {
1217 if (tracee_pid != pid)
1218 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001219 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001220 error_msg_and_die("%s: unexpected wait status %x",
1221 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001222 }
1223 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001224 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001225 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1226 kill_save_errno(tracee_pid, SIGKILL);
1227 kill_save_errno(pid, SIGKILL);
1228 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001229 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001230 continue;
1231 }
1232 switch (WSTOPSIG(status)) {
1233 case SIGSTOP:
1234 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1235 && errno != EINVAL && errno != EIO)
1236 perror_msg("PTRACE_SETOPTIONS");
1237 break;
1238 case SIGTRAP:
1239 if (status >> 16 == PTRACE_EVENT_FORK) {
1240 long msg = 0;
1241
1242 if (ptrace(PTRACE_GETEVENTMSG, pid,
1243 NULL, (long) &msg) == 0)
1244 expected_grandchild = msg;
1245 }
1246 break;
1247 }
1248 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1249 kill_save_errno(pid, SIGKILL);
1250 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001251 }
1252 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001253 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001254 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001255 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001256 fprintf(stderr, "ptrace_setoptions = %#x\n",
1257 ptrace_setoptions);
1258 return;
1259 }
1260 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1261 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001262}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001263
1264/*
1265 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1266 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1267 * and then see whether it will stop with (SIGTRAP | 0x80).
1268 *
1269 * Use of this option enables correct handling of user-generated SIGTRAPs,
1270 * and SIGTRAPs generated by special instructions such as int3 on x86:
1271 * _start: .globl _start
1272 * int3
1273 * movl $42, %ebx
1274 * movl $1, %eax
1275 * int $0x80
1276 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1277 */
1278static void
1279test_ptrace_setoptions_for_all(void)
1280{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001281 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1282 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001283 int pid;
1284 int it_worked = 0;
1285
1286 pid = fork();
1287 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001288 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001289
1290 if (pid == 0) {
1291 pid = getpid();
1292 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001293 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001294 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1295 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001296 kill(pid, SIGSTOP);
1297 _exit(0); /* parent should see entry into this syscall */
1298 }
1299
1300 while (1) {
1301 int status, tracee_pid;
1302
1303 errno = 0;
1304 tracee_pid = wait(&status);
1305 if (tracee_pid <= 0) {
1306 if (errno == EINTR)
1307 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001308 kill_save_errno(pid, SIGKILL);
1309 perror_msg_and_die("%s: unexpected wait result %d",
1310 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001311 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001312 if (WIFEXITED(status)) {
1313 if (WEXITSTATUS(status) == 0)
1314 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001315 error_msg_and_die("%s: unexpected exit status %u",
1316 __func__, WEXITSTATUS(status));
1317 }
1318 if (WIFSIGNALED(status)) {
1319 error_msg_and_die("%s: unexpected signal %u",
1320 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001321 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001322 if (!WIFSTOPPED(status)) {
1323 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001324 error_msg_and_die("%s: unexpected wait status %x",
1325 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001326 }
1327 if (WSTOPSIG(status) == SIGSTOP) {
1328 /*
1329 * We don't check "options aren't accepted" error.
1330 * If it happens, we'll never get (SIGTRAP | 0x80),
1331 * and thus will decide to not use the option.
1332 * IOW: the outcome of the test will be correct.
1333 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001334 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1335 && errno != EINVAL && errno != EIO)
1336 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001337 }
1338 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1339 it_worked = 1;
1340 }
1341 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001342 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001343 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001344 }
1345 }
1346
1347 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001348 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001349 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001350 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001351 fprintf(stderr, "ptrace_setoptions = %#x\n",
1352 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001353 return;
1354 }
1355
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001356 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1357 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001358}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001359
1360# ifdef USE_SEIZE
1361static void
1362test_ptrace_seize(void)
1363{
1364 int pid;
1365
1366 pid = fork();
1367 if (pid < 0)
1368 perror_msg_and_die("fork");
1369
1370 if (pid == 0) {
1371 pause();
1372 _exit(0);
1373 }
1374
1375 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1376 * attaching tracee continues to run unless a trap condition occurs.
1377 * PTRACE_SEIZE doesn't affect signal or group stop state.
1378 */
1379 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1380 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001381 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001382 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1383 }
1384
1385 kill(pid, SIGKILL);
1386
1387 while (1) {
1388 int status, tracee_pid;
1389
1390 errno = 0;
1391 tracee_pid = waitpid(pid, &status, 0);
1392 if (tracee_pid <= 0) {
1393 if (errno == EINTR)
1394 continue;
1395 perror_msg_and_die("%s: unexpected wait result %d",
1396 __func__, tracee_pid);
1397 }
1398 if (WIFSIGNALED(status)) {
1399 return;
1400 }
1401 error_msg_and_die("%s: unexpected wait status %x",
1402 __func__, status);
1403 }
1404}
1405# else /* !USE_SEIZE */
1406# define test_ptrace_seize() ((void)0)
1407# endif
1408
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001409static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001410get_os_release(void)
1411{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001412 unsigned rel;
1413 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001414 struct utsname u;
1415 if (uname(&u) < 0)
1416 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001417 /* u.release has this form: "3.2.9[-some-garbage]" */
1418 rel = 0;
1419 p = u.release;
1420 for (;;) {
1421 if (!(*p >= '0' && *p <= '9'))
1422 error_msg_and_die("Bad OS release string: '%s'", u.release);
1423 /* Note: this open-codes KERNEL_VERSION(): */
1424 rel = (rel << 8) | atoi(p);
1425 if (rel >= KERNEL_VERSION(1,0,0))
1426 break;
1427 while (*p >= '0' && *p <= '9')
1428 p++;
1429 if (*p != '.')
1430 error_msg_and_die("Bad OS release string: '%s'", u.release);
1431 p++;
1432 }
1433 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001434}
1435
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001436/*
1437 * Initialization part of main() was eating much stack (~0.5k),
1438 * which was unused after init.
1439 * We can reuse it if we move init code into a separate function.
1440 *
1441 * Don't want main() to inline us and defeat the reason
1442 * we have a separate function.
1443 */
1444static void __attribute__ ((noinline))
1445init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001448 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001449 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450 struct sigaction sa;
1451
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001452 progname = argv[0] ? argv[0] : "strace";
1453
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001454 /* Make sure SIGCHLD has the default action so that waitpid
1455 definitely works without losing track of children. The user
1456 should not have given us a bogus state to inherit, but he might
1457 have. Arguably we should detect SIG_IGN here and pass it on
1458 to children, but probably noone really needs that. */
1459 signal(SIGCHLD, SIG_DFL);
1460
Denys Vlasenko75422762011-05-27 14:36:01 +02001461 strace_tracer_pid = getpid();
1462
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001463 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001464
Roland McGrathee9d4352002-12-18 04:16:10 +00001465 /* Allocate the initial tcbtab. */
1466 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001467 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001468 if (!tcbtab)
1469 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001470 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001471 if (!tcp)
1472 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001473 for (c = 0; c < tcbtabsize; c++)
1474 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001475
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001476 shared_log = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001477 set_sortby(DEFAULT_SORTBY);
1478 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479 qualify("trace=all");
1480 qualify("abbrev=all");
1481 qualify("verbose=all");
1482 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001484 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001485 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001486 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001488 case 'b':
1489 detach_on_execve = 1;
1490 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001492 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001493 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001494 }
1495 cflag = CFLAG_ONLY_STATS;
1496 break;
1497 case 'C':
1498 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001499 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001500 }
1501 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 break;
1503 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001504 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001506 case 'D':
1507 daemonized_tracer = 1;
1508 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001509 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001510 optF = 1;
1511 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 case 'f':
1513 followfork++;
1514 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 case 'h':
1516 usage(stdout, 0);
1517 break;
1518 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001519 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001520 break;
1521 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001522 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 break;
1524 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001525 rflag = 1;
1526 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527 case 't':
1528 tflag++;
1529 break;
1530 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001531 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532 break;
1533 case 'x':
1534 xflag++;
1535 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001536 case 'y':
1537 show_fd_path = 1;
1538 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539 case 'v':
1540 qualify("abbrev=none");
1541 break;
1542 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001543 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544 exit(0);
1545 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001546 case 'z':
1547 not_failing_only = 1;
1548 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001549 case 'a':
1550 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001551 if (acolumn < 0)
1552 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553 break;
1554 case 'e':
1555 qualify(optarg);
1556 break;
1557 case 'o':
1558 outfname = strdup(optarg);
1559 break;
1560 case 'O':
1561 set_overhead(atoi(optarg));
1562 break;
1563 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001564 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001566 case 'P':
1567 tracing_paths = 1;
1568 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001569 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001570 }
1571 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572 case 's':
1573 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001574 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001575 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001576 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577 break;
1578 case 'S':
1579 set_sortby(optarg);
1580 break;
1581 case 'u':
1582 username = strdup(optarg);
1583 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001584 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001585 if (putenv(optarg) < 0)
1586 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001587 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001588 case 'I':
1589 opt_intr = atoi(optarg);
1590 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1591 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1592 }
1593 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594 default:
1595 usage(stderr, 1);
1596 break;
1597 }
1598 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001599 argv += optind;
1600 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601
Denys Vlasenko102ec492011-08-25 01:27:59 +02001602 acolumn_spaces = malloc(acolumn + 1);
1603 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001604 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001605 memset(acolumn_spaces, ' ', acolumn);
1606 acolumn_spaces[acolumn] = '\0';
1607
Denys Vlasenko837399a2012-01-24 11:37:03 +01001608 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001609 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001610 usage(stderr, 1);
1611
Denys Vlasenkofd883382012-03-09 13:03:41 +01001612 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001613 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001614 }
1615
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001616 if (!followfork)
1617 followfork = optF;
1618
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001619 if (followfork >= 2 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001620 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001621 }
1622
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623 /* See if they want to run as another user. */
1624 if (username != NULL) {
1625 struct passwd *pent;
1626
1627 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001628 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001630 pent = getpwnam(username);
1631 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001632 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633 }
1634 run_uid = pent->pw_uid;
1635 run_gid = pent->pw_gid;
1636 }
1637 else {
1638 run_uid = getuid();
1639 run_gid = getgid();
1640 }
1641
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001642 if (followfork)
1643 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001644 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001645 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001646
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647 /* Check if they want to redirect the output. */
1648 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001649 /* See if they want to pipe the output. */
1650 if (outfname[0] == '|' || outfname[0] == '!') {
1651 /*
1652 * We can't do the <outfname>.PID funny business
1653 * when using popen, so prohibit it.
1654 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001655 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001656 error_msg_and_die("Piping the output and -ff are mutually exclusive");
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001657 shared_log = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001658 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001659 else if (followfork < 2)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001660 shared_log = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001661 } else {
1662 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001663 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001664 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665 }
1666
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001667 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001668 char *buf = malloc(BUFSIZ);
1669 if (!buf)
1670 die_out_of_memory();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001671 setvbuf(shared_log, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001672 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001673 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001674 if (!opt_intr)
1675 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001676 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001677 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001678 if (!opt_intr)
1679 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001680
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001681 /* argv[0] -pPID -oFILE Default interactive setting
1682 * yes 0 0 INTR_WHILE_WAIT
1683 * no 1 0 INTR_WHILE_WAIT
1684 * yes 0 1 INTR_NEVER
1685 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001686 */
1687
1688 /* STARTUP_CHILD must be called before the signal handlers get
1689 installed below as they are inherited into the spawned process.
1690 Also we do not need to be protected by them as during interruption
1691 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001692 if (argv[0]) {
1693 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001694 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001695 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 sigemptyset(&empty_set);
1698 sigemptyset(&blocked_set);
1699 sa.sa_handler = SIG_IGN;
1700 sigemptyset(&sa.sa_mask);
1701 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001702 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1703 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1704 if (opt_intr != INTR_ANYWHERE) {
1705 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1706 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1707 /*
1708 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1709 * fatal signals are blocked while syscall stop is processed,
1710 * and acted on in between, when waiting for new syscall stops.
1711 * In non-interactive mode, signals are ignored.
1712 */
1713 if (opt_intr == INTR_WHILE_WAIT) {
1714 sigaddset(&blocked_set, SIGHUP);
1715 sigaddset(&blocked_set, SIGINT);
1716 sigaddset(&blocked_set, SIGQUIT);
1717 sigaddset(&blocked_set, SIGPIPE);
1718 sigaddset(&blocked_set, SIGTERM);
1719 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001720 }
1721 /* SIG_IGN, or set handler for these */
1722 sigaction(SIGHUP, &sa, NULL);
1723 sigaction(SIGINT, &sa, NULL);
1724 sigaction(SIGQUIT, &sa, NULL);
1725 sigaction(SIGPIPE, &sa, NULL);
1726 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001728 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001729 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001730
Denys Vlasenkofd883382012-03-09 13:03:41 +01001731 /* Do we want pids printed in our -o OUTFILE?
1732 * -ff: no (every pid has its own file); or
1733 * -f: yes (there can be more pids in the future); or
1734 * -p PID1,PID2: yes (there are already more than one pid)
1735 */
1736 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737}
1738
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001739static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001740pid2tcb(int pid)
1741{
1742 int i;
1743
1744 if (pid <= 0)
1745 return NULL;
1746
1747 for (i = 0; i < tcbtabsize; i++) {
1748 struct tcb *tcp = tcbtab[i];
1749 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1750 return tcp;
1751 }
1752
1753 return NULL;
1754}
1755
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001757cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758{
1759 int i;
1760 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001761 int fatal_sig;
1762
1763 /* 'interrupted' is a volatile object, fetch it only once */
1764 fatal_sig = interrupted;
1765 if (!fatal_sig)
1766 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767
Roland McGrathee9d4352002-12-18 04:16:10 +00001768 for (i = 0; i < tcbtabsize; i++) {
1769 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770 if (!(tcp->flags & TCB_INUSE))
1771 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001772 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773 fprintf(stderr,
1774 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001775 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001777 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001779 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780 }
1781 if (cflag)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001782 call_summary(shared_log);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783}
1784
1785static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001786interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001788 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789}
1790
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001792trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001795 struct rusage *rup = cflag ? &ru : NULL;
1796# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001797 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001798# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799
Roland McGratheb9e2e82009-06-02 16:49:22 -07001800 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001801 int pid;
1802 int wait_errno;
1803 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001804 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001805 struct tcb *tcp;
1806 unsigned event;
1807
Denys Vlasenko222713a2009-03-17 14:29:59 +00001808 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001809 return 0;
1810 if (interactive)
1811 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001812# ifdef __WALL
1813 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001814 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001815 /* this kernel does not support __WALL */
1816 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001817 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001818 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001819 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001820 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001821 pid = wait4(-1, &status, __WCLONE, rup);
1822 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001823 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001824 }
1825 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001826# else
1827 pid = wait4(-1, &status, 0, rup);
1828# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001830 if (interactive)
1831 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001832
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001833 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001834 switch (wait_errno) {
1835 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001836 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001837 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838 /*
1839 * We would like to verify this case
1840 * but sometimes a race in Solbourne's
1841 * version of SunOS sometimes reports
1842 * ECHILD before sending us SIGCHILD.
1843 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001844 return 0;
1845 default:
1846 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001847 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001848 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849 }
1850 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001851 if (pid == popen_pid) {
1852 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001853 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001854 continue;
1855 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001856
1857 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001858 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001859 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001860 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001861 strcpy(buf, "???");
1862 if (WIFSIGNALED(status))
1863#ifdef WCOREDUMP
1864 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1865 WCOREDUMP(status) ? "core," : "",
1866 signame(WTERMSIG(status)));
1867#else
1868 sprintf(buf, "WIFSIGNALED,sig=%s",
1869 signame(WTERMSIG(status)));
1870#endif
1871 if (WIFEXITED(status))
1872 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1873 if (WIFSTOPPED(status))
1874 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001875#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001876 if (WIFCONTINUED(status))
1877 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001878#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001879 evbuf[0] = '\0';
1880 if (event != 0) {
1881 static const char *const event_names[] = {
1882 [PTRACE_EVENT_CLONE] = "CLONE",
1883 [PTRACE_EVENT_FORK] = "FORK",
1884 [PTRACE_EVENT_VFORK] = "VFORK",
1885 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1886 [PTRACE_EVENT_EXEC] = "EXEC",
1887 [PTRACE_EVENT_EXIT] = "EXIT",
1888 };
1889 const char *e;
1890 if (event < ARRAY_SIZE(event_names))
1891 e = event_names[event];
1892 else {
1893 sprintf(buf, "?? (%u)", event);
1894 e = buf;
1895 }
1896 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1897 }
1898 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001899 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001900
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001901 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001902 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001903
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001904 if (!tcp) {
Roland McGrath41c48222008-07-18 00:25:10 +00001905 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001906 /* This is needed to go with the CLONE_PTRACE
1907 changes in process.c/util.c: we might see
1908 the child's initial trap before we see the
1909 parent return from the clone syscall.
1910 Leave the child suspended until the parent
1911 returns from its system call. Only then
1912 will we have the association of parent and
1913 child so that we know how to do clearbpt
1914 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001915 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001916 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001917 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001918 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001919 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001920 pid);
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001921 } else {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001922 /* This can happen if a clone call used
1923 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001924 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001925 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001926 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001927 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001928 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001929
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001930 /* Under Linux, execve changes pid to thread leader's pid,
1931 * and we see this changed pid on EVENT_EXEC and later,
1932 * execve sysexit. Leader "disappears" without exit
1933 * notification. Let user know that, drop leader's tcb,
1934 * and fix up pid in execve thread's tcb.
1935 * Effectively, execve thread's tcb replaces leader's tcb.
1936 *
1937 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1938 * on exit syscall) in multithreaded programs exactly
1939 * in order to handle this case.
1940 *
1941 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1942 * On 2.6 and earlier, it can return garbage.
1943 */
1944 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001945 FILE *fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001946 struct tcb *execve_thread;
1947 long old_pid = 0;
1948
1949 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0)
1950 goto dont_switch_tcbs;
1951 if (old_pid <= 0 || old_pid == pid)
1952 goto dont_switch_tcbs;
1953 execve_thread = pid2tcb(old_pid);
1954 /* It should be !NULL, but I feel paranoid */
1955 if (!execve_thread)
1956 goto dont_switch_tcbs;
1957
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001958 if (execve_thread->curcol != 0) {
1959 /*
1960 * One case we are here is -ff:
1961 * try "strace -oLOG -ff test/threaded_execve"
1962 */
1963 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001964 /*execve_thread->curcol = 0; - no need, see code below */
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001965 }
1966 /* Swap output FILEs (needed for -ff) */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001967 fp = execve_thread->outf;
1968 execve_thread->outf = tcp->outf;
1969 tcp->outf = fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001970 /* And their column positions */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001971 execve_thread->curcol = tcp->curcol;
1972 tcp->curcol = 0;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001973 /* Drop leader, but close execve'd thread outfile (if -ff) */
1974 droptcb(tcp);
1975 /* Switch to the thread, reusing leader's outfile and pid */
1976 tcp = execve_thread;
1977 tcp->pid = pid;
1978 if (cflag != CFLAG_ONLY_STATS) {
1979 printleader(tcp);
1980 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1981 line_ended();
1982 tcp->flags |= TCB_REPRINT;
1983 }
1984 }
1985 dont_switch_tcbs:
1986
1987 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1988 if (!skip_startup_execve)
1989 detach(tcp);
1990 /* This was initial execve for "strace PROG". Skip. */
1991 skip_startup_execve = 0;
1992 }
1993
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001994 /* Set current output file */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001995 current_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001996
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001997 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1999 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002001
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002002 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002003 if (pid == strace_child)
2004 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002005 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002006 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2007 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002008#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002009 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002010 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002011 WCOREDUMP(status) ? "(core dumped) " : "");
2012#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002013 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002014 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002015#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002016 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017 }
2018 droptcb(tcp);
2019 continue;
2020 }
2021 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002022 if (pid == strace_child)
2023 exit_code = WEXITSTATUS(status);
Denys Vlasenkob5e09082012-03-21 14:27:40 +01002024 if (cflag != CFLAG_ONLY_STATS) {
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002025 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002026 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002027 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002028 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029 droptcb(tcp);
2030 continue;
2031 }
2032 if (!WIFSTOPPED(status)) {
2033 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2034 droptcb(tcp);
2035 continue;
2036 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002037
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002038 /* Is this the very first time we see this tracee stopped? */
2039 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002040 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002041 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002043 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002044 /*
2045 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002046 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002047 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002048 if (clearbpt(tcp) < 0) {
2049 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002050 droptcb(tcp);
2051 cleanup();
2052 return -1;
2053 }
2054 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002055 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002056 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002057 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2058 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2059 if (errno != ESRCH) {
2060 /* Should never happen, really */
2061 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002062 }
2063 }
2064 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002065 }
2066
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002067 sig = WSTOPSIG(status);
2068
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002069 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002070 /* Ptrace event */
2071#ifdef USE_SEIZE
2072 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002073 /*
2074 * PTRACE_INTERRUPT-stop or group-stop.
2075 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2076 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002077 if (sig == SIGSTOP
2078 || sig == SIGTSTP
2079 || sig == SIGTTIN
2080 || sig == SIGTTOU
2081 ) {
2082 stopped = 1;
2083 goto show_stopsig;
2084 }
2085 }
2086#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002087 goto restart_tracee_with_sig_0;
2088 }
2089
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002090 /* Is this post-attach SIGSTOP?
2091 * Interestingly, the process may stop
2092 * with STOPSIG equal to some other signal
2093 * than SIGSTOP if we happend to attach
2094 * just before the process takes a signal.
2095 */
2096 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002097 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002098 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2099 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002100 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 }
2102
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002103 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002104 siginfo_t si;
2105
2106 /* Nonzero (true) if tracee is stopped by signal
2107 * (as opposed to "tracee received signal").
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002108 * TODO: shouldn't we check for errno == EINVAL too?
2109 * We can get ESRCH instead, you know...
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002110 */
2111 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002112#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002113 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002114#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002115 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002116 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002117#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002118 long pc = 0;
2119 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002120
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002121 upeek(tcp, PT_CR_IPSR, &psr);
2122 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002123
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002124# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002125 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002126# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002127# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002128#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002129# define PC_FORMAT_STR ""
2130# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002131#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002132 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002133 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002134 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002135 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002136 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002137 PC_FORMAT_ARG);
2138 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002139 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002140 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002141 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002142 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002143 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002144
2145 if (!stopped)
2146 /* It's signal-delivery-stop. Inject the signal */
2147 goto restart_tracee;
2148
2149 /* It's group-stop */
2150#ifdef USE_SEIZE
2151 if (use_seize) {
2152 /*
2153 * This ends ptrace-stop, but does *not* end group-stop.
2154 * This makes stopping signals work properly on straced process
2155 * (that is, process really stops. It used to continue to run).
2156 */
2157 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2158 cleanup();
2159 return -1;
2160 }
2161 continue;
2162 }
2163 /* We don't have PTRACE_LISTEN support... */
2164#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002165 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002166 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002167
2168 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002169 if (interrupted)
2170 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002171
2172 /* This should be syscall entry or exit.
2173 * (Or it still can be that pesky post-execve SIGTRAP!)
2174 * Handle it.
2175 */
Denys Vlasenko23506752012-03-21 10:32:49 +01002176 if (trace_syscall(tcp) < 0) {
2177 /* ptrace() failed in trace_syscall().
Roland McGratheb9e2e82009-06-02 16:49:22 -07002178 * Likely a result of process disappearing mid-flight.
Denys Vlasenko23506752012-03-21 10:32:49 +01002179 * Observed case: exit_group() or SIGKILL terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002180 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002181 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002182 * We used to detach(tcp) here, but since we no longer
2183 * implement "detach before death" policy/hack,
2184 * we can let this process to report its death to us
2185 * normally, via WIFEXITED or WIFSIGNALED wait status.
2186 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 continue;
2188 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002189 restart_tracee_with_sig_0:
2190 sig = 0;
2191 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002192 /* Remember current print column before continuing. */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002193 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002194 cleanup();
2195 return -1;
2196 }
2197 }
2198 return 0;
2199}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002200
2201int
2202main(int argc, char *argv[])
2203{
2204 init(argc, argv);
2205
2206 /* Run main tracing loop */
2207 if (trace() < 0)
2208 return 1;
2209
2210 cleanup();
2211 fflush(NULL);
2212 if (exit_code > 0xff) {
2213 /* Avoid potential core file clobbering. */
2214 struct rlimit rlim = {0, 0};
2215 setrlimit(RLIMIT_CORE, &rlim);
2216
2217 /* Child was killed by a signal, mimic that. */
2218 exit_code &= 0xff;
2219 signal(exit_code, SIG_DFL);
2220 raise(exit_code);
2221 /* Paranoia - what if this signal is not fatal?
2222 Exit with 128 + signo then. */
2223 exit_code += 128;
2224 }
2225
2226 return exit_code;
2227}