blob: ad29bb40003bfe9355032820ed0d16235da7f4bc [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;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000136static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200137static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100138struct tcb *printing_tcp = NULL;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100139static unsigned int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200140static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200141static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200142static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +0100144static unsigned os_release; /* generated from uname()'s u.release */
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100145
Denys Vlasenko4c196382012-01-04 15:11:09 +0100146static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100147static int trace(void);
148static void cleanup(void);
149static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150static sigset_t empty_set, blocked_set;
151
152#ifdef HAVE_SIG_ATOMIC_T
153static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100154#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100156#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100158#ifndef HAVE_STRERROR
159
160#if !HAVE_DECL_SYS_ERRLIST
161extern int sys_nerr;
162extern char *sys_errlist[];
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +0100163#endif
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100164
165const char *
166strerror(int err_no)
167{
168 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
169
170 if (err_no < 1 || err_no >= sys_nerr) {
171 sprintf(buf, "Unknown error %d", err_no);
172 return buf;
173 }
174 return sys_errlist[err_no];
175}
176
177#endif /* HAVE_STERRROR */
178
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000179static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200180usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181{
182 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100183usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
184 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100185 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100186 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100187 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200189-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100190-d -- enable debug output to stderr\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100191-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000192-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100193-F -- attempt to follow vforks (deprecated, use -f)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100195-I interruptible\n\
196 1: no signals are blocked\n\
197 2: fatal signals are blocked while decoding syscall (default)\n\
198 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
199 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
200 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201-q -- suppress messages about attaching, detaching, etc.\n\
202-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100203-T -- print time spent in each syscall\n\
204-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000206-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100207-h -- print help message\n\
208-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209-a column -- alignment COLUMN for printing syscall results (default %d)\n\
210-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
211 options: trace, abbrev, verbose, raw, signal, read, or write\n\
212-o file -- send trace output to FILE instead of stderr\n\
213-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
214-p pid -- trace process with process id PID, may be repeated\n\
215-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
216-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
217-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000218-E var=val -- put var=val in the environment for command\n\
219-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000220-P path -- trace accesses to path\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100221"
222/* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000223-z -- print only succeeding syscalls\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100224 */
225/* experimental, don't document it yet (option letter may change in the future!)
226-b -- detach on successful execve\n\
227 */
Roland McGrathde6e5332003-01-24 04:31:23 +0000228, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229 exit(exitval);
230}
231
Denys Vlasenko75422762011-05-27 14:36:01 +0200232static void die(void) __attribute__ ((noreturn));
233static void die(void)
234{
235 if (strace_tracer_pid == getpid()) {
236 cflag = 0;
237 cleanup();
238 }
239 exit(1);
240}
241
242static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200243{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100244 char *msg;
245
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000246 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100247
248 /* We want to print entire message with single fprintf to ensure
249 * message integrity if stderr is shared with other programs.
250 * Thus we use vasprintf + single fprintf.
251 */
252 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100253 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100254 if (err_no)
255 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
256 else
257 fprintf(stderr, "%s: %s\n", progname, msg);
258 free(msg);
259 } else {
260 /* malloc in vasprintf failed, try it without malloc */
261 fprintf(stderr, "%s: ", progname);
262 vfprintf(stderr, fmt, p);
263 if (err_no)
264 fprintf(stderr, ": %s\n", strerror(err_no));
265 else
266 putc('\n', stderr);
267 }
268 /* We don't switch stderr to buffered, thus fprintf(stderr)
269 * always flushes its output and this is not necessary: */
270 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200271}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200272
Denys Vlasenko75422762011-05-27 14:36:01 +0200273void error_msg(const char *fmt, ...)
274{
275 va_list p;
276 va_start(p, fmt);
277 verror_msg(0, fmt, p);
278 va_end(p);
279}
280
281void error_msg_and_die(const char *fmt, ...)
282{
283 va_list p;
284 va_start(p, fmt);
285 verror_msg(0, fmt, p);
286 die();
287}
288
289void perror_msg(const char *fmt, ...)
290{
291 va_list p;
292 va_start(p, fmt);
293 verror_msg(errno, fmt, p);
294 va_end(p);
295}
296
297void perror_msg_and_die(const char *fmt, ...)
298{
299 va_list p;
300 va_start(p, fmt);
301 verror_msg(errno, fmt, p);
302 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200303}
304
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200305void die_out_of_memory(void)
306{
307 static bool recursed = 0;
308 if (recursed)
309 exit(1);
310 recursed = 1;
311 error_msg_and_die("Out of memory");
312}
313
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400314/* Glue for systems without a MMU that cannot provide fork() */
315#ifdef HAVE_FORK
316# define strace_vforked 0
317#else
318# define strace_vforked 1
319# define fork() vfork()
320#endif
321
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100322#ifdef USE_SEIZE
323static int
324ptrace_attach_or_seize(int pid)
325{
326 int r;
327 if (!use_seize)
328 return ptrace(PTRACE_ATTACH, pid, 0, 0);
329 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
330 if (r)
331 return r;
332 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
333 return r;
334}
335#else
336# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
337#endif
338
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100339/*
340 * Used when we want to unblock stopped traced process.
341 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
342 * Returns 0 on success or if error was ESRCH
343 * (presumably process was killed while we talk to it).
344 * Otherwise prints error message and returns -1.
345 */
346static int
347ptrace_restart(int op, struct tcb *tcp, int sig)
348{
349 int err;
350 const char *msg;
351
352 errno = 0;
353 ptrace(op, tcp->pid, (void *) 0, (long) sig);
354 err = errno;
Denys Vlasenko23506752012-03-21 10:32:49 +0100355 if (!err)
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100356 return 0;
357
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100358 msg = "SYSCALL";
359 if (op == PTRACE_CONT)
360 msg = "CONT";
361 if (op == PTRACE_DETACH)
362 msg = "DETACH";
363#ifdef PTRACE_LISTEN
364 if (op == PTRACE_LISTEN)
365 msg = "LISTEN";
366#endif
Denys Vlasenko23506752012-03-21 10:32:49 +0100367 /*
368 * Why curcol != 0? Otherwise sometimes we get this:
369 *
370 * 10252 kill(10253, SIGKILL) = 0
371 * <ptrace(SYSCALL,10252):No such process>10253 ...next decode...
372 *
373 * 10252 died after we retrieved syscall exit data,
374 * but before we tried to restart it. Log looks ugly.
375 */
376 if (curcol != 0) {
377 tprintf(" <ptrace(%s):%s>\n", msg, strerror(err));
378 line_ended();
379 }
380 if (err == ESRCH)
381 return 0;
382 errno = err;
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100383 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
384 return -1;
385}
386
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200387static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000388set_cloexec_flag(int fd)
389{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200390 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000391
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200392 flags = fcntl(fd, F_GETFD);
393 if (flags < 0) {
394 /* Can happen only if fd is bad.
395 * Should never happen: if it does, we have a bug
396 * in the caller. Therefore we just abort
397 * instead of propagating the error.
398 */
399 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400 }
401
402 newflags = flags | FD_CLOEXEC;
403 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200404 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000405
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200406 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000407}
408
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100409static void kill_save_errno(pid_t pid, int sig)
410{
411 int saved_errno = errno;
412
413 (void) kill(pid, sig);
414 errno = saved_errno;
415}
416
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100417/*
418 * When strace is setuid executable, we have to swap uids
419 * before and after filesystem and process management operations.
420 */
421static void
422swap_uid(void)
423{
424 int euid = geteuid(), uid = getuid();
425
426 if (euid != uid && setreuid(euid, uid) < 0) {
427 perror_msg_and_die("setreuid");
428 }
429}
430
431#if _LFS64_LARGEFILE
432# define fopen_for_output fopen64
433#else
434# define fopen_for_output fopen
435#endif
436
437static FILE *
438strace_fopen(const char *path)
439{
440 FILE *fp;
441
442 swap_uid();
443 fp = fopen_for_output(path, "w");
444 if (!fp)
445 perror_msg_and_die("Can't fopen '%s'", path);
446 swap_uid();
447 set_cloexec_flag(fileno(fp));
448 return fp;
449}
450
451static int popen_pid = 0;
452
453#ifndef _PATH_BSHELL
454# define _PATH_BSHELL "/bin/sh"
455#endif
456
457/*
458 * We cannot use standard popen(3) here because we have to distinguish
459 * popen child process from other processes we trace, and standard popen(3)
460 * does not export its child's pid.
461 */
462static FILE *
463strace_popen(const char *command)
464{
465 FILE *fp;
466 int fds[2];
467
468 swap_uid();
469 if (pipe(fds) < 0)
470 perror_msg_and_die("pipe");
471
472 set_cloexec_flag(fds[1]); /* never fails */
473
474 popen_pid = vfork();
475 if (popen_pid == -1)
476 perror_msg_and_die("vfork");
477
478 if (popen_pid == 0) {
479 /* child */
480 close(fds[1]);
481 if (fds[0] != 0) {
482 if (dup2(fds[0], 0))
483 perror_msg_and_die("dup2");
484 close(fds[0]);
485 }
486 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
487 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
488 }
489
490 /* parent */
491 close(fds[0]);
492 swap_uid();
493 fp = fdopen(fds[1], "w");
494 if (!fp)
495 die_out_of_memory();
496 return fp;
497}
498
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100499void
500tprintf(const char *fmt, ...)
501{
502 va_list args;
503
504 va_start(args, fmt);
505 if (outf) {
506 int n = vfprintf(outf, fmt, args);
507 if (n < 0) {
508 if (outf != stderr)
509 perror(outfname == NULL
510 ? "<writing to pipe>" : outfname);
511 } else
512 curcol += n;
513 }
514 va_end(args);
515}
516
517void
518tprints(const char *str)
519{
520 if (outf) {
521 int n = fputs(str, outf);
522 if (n >= 0) {
523 curcol += strlen(str);
524 return;
525 }
526 if (outf != stderr)
527 perror(outfname == NULL
528 ? "<writing to pipe>" : outfname);
529 }
530}
531
532void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100533line_ended(void)
534{
535 curcol = 0;
536 fflush(outf);
537 if (!printing_tcp)
538 return;
539 printing_tcp->curcol = 0;
540 printing_tcp = NULL;
541}
542
543void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100544printleader(struct tcb *tcp)
545{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100546 /* If -ff, "previous tcb we printed" is always the same as current,
547 * because we have per-tcb output files.
548 */
549 if (followfork >= 2)
550 printing_tcp = tcp;
551
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100552 if (printing_tcp) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100553 outf = printing_tcp->outf;
554 curcol = printing_tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100555 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
556 /*
557 * case 1: we have a shared log (i.e. not -ff), and last line
558 * wasn't finished (same or different tcb, doesn't matter).
559 * case 2: split log, we are the same tcb, but our last line
560 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
561 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100562 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100563 printing_tcp->flags |= TCB_REPRINT;
564 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100565 }
566 }
567
568 printing_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100569 outf = tcp->outf;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100570 curcol = 0;
571
572 if (print_pid_pfx)
573 tprintf("%-5d ", tcp->pid);
574 else if (nprocs > 1 && !outfname)
575 tprintf("[pid %5u] ", tcp->pid);
576
577 if (tflag) {
578 char str[sizeof("HH:MM:SS")];
579 struct timeval tv, dtv;
580 static struct timeval otv;
581
582 gettimeofday(&tv, NULL);
583 if (rflag) {
584 if (otv.tv_sec == 0)
585 otv = tv;
586 tv_sub(&dtv, &tv, &otv);
587 tprintf("%6ld.%06ld ",
588 (long) dtv.tv_sec, (long) dtv.tv_usec);
589 otv = tv;
590 }
591 else if (tflag > 2) {
592 tprintf("%ld.%06ld ",
593 (long) tv.tv_sec, (long) tv.tv_usec);
594 }
595 else {
596 time_t local = tv.tv_sec;
597 strftime(str, sizeof(str), "%T", localtime(&local));
598 if (tflag > 1)
599 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
600 else
601 tprintf("%s ", str);
602 }
603 }
604 if (iflag)
605 printcall(tcp);
606}
607
608void
609tabto(void)
610{
611 if (curcol < acolumn)
612 tprints(acolumn_spaces + curcol);
613}
614
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100615/* Should be only called directly *after successful attach* to a tracee.
616 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
617 * may create bogus empty FILE.<nonexistant_pid>, and then die.
618 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200619static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000620newoutf(struct tcb *tcp)
621{
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100622 tcp->outf = outf; /* if not -ff mode, the same file is for all */
623 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000624 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000625 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200626 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000627 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000628}
629
Denys Vlasenko558e5122012-03-12 23:32:16 +0100630static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100631expand_tcbtab(void)
632{
633 /* Allocate some more TCBs and expand the table.
634 We don't want to relocate the TCBs because our
635 callers have pointers and it would be a pain.
636 So tcbtab is a table of pointers. Since we never
637 free the TCBs, we allocate a single chunk of many. */
638 int i = tcbtabsize;
639 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
640 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
641 if (!newtab || !newtcbs)
642 die_out_of_memory();
643 tcbtabsize *= 2;
644 tcbtab = newtab;
645 while (i < tcbtabsize)
646 tcbtab[i++] = newtcbs++;
647}
648
649static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100650alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100651{
652 int i;
653 struct tcb *tcp;
654
655 if (nprocs == tcbtabsize)
656 expand_tcbtab();
657
658 for (i = 0; i < tcbtabsize; i++) {
659 tcp = tcbtab[i];
660 if ((tcp->flags & TCB_INUSE) == 0) {
661 memset(tcp, 0, sizeof(*tcp));
662 tcp->pid = pid;
663 tcp->flags = TCB_INUSE;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100664 /* tcp->outf = outf; - not needed? */
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100665#if SUPPORTED_PERSONALITIES > 1
666 tcp->currpers = current_personality;
667#endif
668 nprocs++;
669 if (debug_flag)
670 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100671 return tcp;
672 }
673 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100674 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100675}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100676
677static void
678droptcb(struct tcb *tcp)
679{
680 if (tcp->pid == 0)
681 return;
682
683 nprocs--;
684 if (debug_flag)
685 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
686
687 if (tcp->outf) {
688 if (outfname && followfork >= 2) {
689 if (tcp->curcol != 0)
690 fprintf(tcp->outf, " <detached ...>\n");
691 fclose(tcp->outf);
692 if (outf == tcp->outf)
693 outf = NULL;
694 } else {
695 if (printing_tcp == tcp && tcp->curcol != 0)
696 fprintf(tcp->outf, " <detached ...>\n");
697 fflush(tcp->outf);
698 }
699 }
700
701 if (printing_tcp == tcp)
702 printing_tcp = NULL;
703
704 memset(tcp, 0, sizeof(*tcp));
705}
706
707/* detach traced process; continue with sig
708 * Never call DETACH twice on the same process as both unattached and
709 * attached-unstopped processes give the same ESRCH. For unattached process we
710 * would SIGSTOP it and wait for its SIGSTOP notification forever.
711 */
712static int
713detach(struct tcb *tcp)
714{
715 int error;
716 int status, sigstop_expected;
717
718 if (tcp->flags & TCB_BPTSET)
719 clearbpt(tcp);
720
721 /*
722 * Linux wrongly insists the child be stopped
723 * before detaching. Arghh. We go through hoops
724 * to make a clean break of things.
725 */
726#if defined(SPARC)
727#undef PTRACE_DETACH
728#define PTRACE_DETACH PTRACE_SUNDETACH
729#endif
730
731 error = 0;
732 sigstop_expected = 0;
733 if (tcp->flags & TCB_ATTACHED) {
734 /*
735 * We attached but possibly didn't see the expected SIGSTOP.
736 * We must catch exactly one as otherwise the detached process
737 * would be left stopped (process state T).
738 */
739 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
740 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
741 if (error == 0) {
742 /* On a clear day, you can see forever. */
743 }
744 else if (errno != ESRCH) {
745 /* Shouldn't happen. */
746 perror("detach: ptrace(PTRACE_DETACH, ...)");
747 }
748 else if (my_tkill(tcp->pid, 0) < 0) {
749 if (errno != ESRCH)
750 perror("detach: checking sanity");
751 }
752 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
753 if (errno != ESRCH)
754 perror("detach: stopping child");
755 }
756 else
757 sigstop_expected = 1;
758 }
759
760 if (sigstop_expected) {
761 for (;;) {
762#ifdef __WALL
763 if (waitpid(tcp->pid, &status, __WALL) < 0) {
764 if (errno == ECHILD) /* Already gone. */
765 break;
766 if (errno != EINVAL) {
767 perror("detach: waiting");
768 break;
769 }
770#endif /* __WALL */
771 /* No __WALL here. */
772 if (waitpid(tcp->pid, &status, 0) < 0) {
773 if (errno != ECHILD) {
774 perror("detach: waiting");
775 break;
776 }
777#ifdef __WCLONE
778 /* If no processes, try clones. */
779 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
780 if (errno != ECHILD)
781 perror("detach: waiting");
782 break;
783 }
784#endif /* __WCLONE */
785 }
786#ifdef __WALL
787 }
788#endif
789 if (!WIFSTOPPED(status)) {
790 /* Au revoir, mon ami. */
791 break;
792 }
793 if (WSTOPSIG(status) == SIGSTOP) {
794 ptrace_restart(PTRACE_DETACH, tcp, 0);
795 break;
796 }
797 error = ptrace_restart(PTRACE_CONT, tcp,
798 WSTOPSIG(status) == syscall_trap_sig ? 0
799 : WSTOPSIG(status));
800 if (error < 0)
801 break;
802 }
803 }
804
805 if (!qflag && (tcp->flags & TCB_ATTACHED))
806 fprintf(stderr, "Process %u detached\n", tcp->pid);
807
808 droptcb(tcp);
809
810 return error;
811}
812
813static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100814process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100815{
816 while (*opt) {
817 /*
818 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
819 * pidof uses space as delim, pgrep uses newline. :(
820 */
821 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100822 char *delim = opt + strcspn(opt, ", \n\t");
823 char c = *delim;
824
825 *delim = '\0';
826 pid = atoi(opt); /* TODO: stricter parsing of the number? */
827 if (pid <= 0) {
828 error_msg("Invalid process id: '%s'", opt);
829 *delim = c;
830 return;
831 }
832 if (pid == strace_tracer_pid) {
833 error_msg("I'm sorry, I can't let you do that, Dave.");
834 *delim = c;
835 return;
836 }
837 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100838 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100839 if (c == '\0')
840 break;
841 opt = delim + 1;
842 }
843}
844
Roland McGrath02203312007-06-11 22:06:31 +0000845static void
846startup_attach(void)
847{
848 int tcbi;
849 struct tcb *tcp;
850
851 /*
852 * Block user interruptions as we would leave the traced
853 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200854 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200855 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000856 */
857 if (interactive)
858 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
859
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000860 if (daemonized_tracer) {
861 pid_t pid = fork();
862 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200863 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000864 }
865 if (pid) { /* parent */
866 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200867 * Wait for grandchild to attach to straced process
868 * (grandparent). Grandchild SIGKILLs us after it attached.
869 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000870 * it proceeds to exec the straced program.
871 */
872 pause();
873 _exit(0); /* paranoia */
874 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200875 /* grandchild */
876 /* We will be the tracer process. Remember our new pid: */
877 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000878 }
879
Roland McGrath02203312007-06-11 22:06:31 +0000880 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
881 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200882
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100883 if (!(tcp->flags & TCB_INUSE))
884 continue;
885
Denys Vlasenkod116a732011-09-05 14:01:33 +0200886 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100887 if (tcp->flags & TCB_ATTACHED)
888 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200889
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000890 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000891 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000892 DIR *dir;
893
894 sprintf(procdir, "/proc/%d/task", tcp->pid);
895 dir = opendir(procdir);
896 if (dir != NULL) {
897 unsigned int ntid = 0, nerr = 0;
898 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200899
Roland McGrath02203312007-06-11 22:06:31 +0000900 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200901 struct tcb *cur_tcp;
902 int tid;
903
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000904 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000905 continue;
906 tid = atoi(de->d_name);
907 if (tid <= 0)
908 continue;
909 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100910 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000911 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100912 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200913 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200914 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200915 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100916 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200917 fprintf(stderr, "attach to pid %d succeeded\n", tid);
918 cur_tcp = tcp;
919 if (tid != tcp->pid)
920 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100921 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100922 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000923 }
924 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200925 if (interactive) {
926 sigprocmask(SIG_SETMASK, &empty_set, NULL);
927 if (interrupted)
928 goto ret;
929 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
930 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000931 ntid -= nerr;
932 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000933 perror("attach: ptrace(PTRACE_ATTACH, ...)");
934 droptcb(tcp);
935 continue;
936 }
937 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000938 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100939? "Process %u attached with %u threads\n"
940: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200941 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000942 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100943 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200944 /* -p PID, we failed to attach to PID itself
945 * but did attach to some of its sibling threads.
946 * Drop PID's tcp.
947 */
948 droptcb(tcp);
949 }
Roland McGrath02203312007-06-11 22:06:31 +0000950 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000951 } /* if (opendir worked) */
952 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100953 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000954 perror("attach: ptrace(PTRACE_ATTACH, ...)");
955 droptcb(tcp);
956 continue;
957 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100958 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100959 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100960 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200961 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000962
963 if (daemonized_tracer) {
964 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000965 * Make parent go away.
966 * Also makes grandparent's wait() unblock.
967 */
968 kill(getppid(), SIGKILL);
969 }
970
Roland McGrath02203312007-06-11 22:06:31 +0000971 if (!qflag)
972 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100973 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000974 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200975 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000976
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200977 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000978 if (interactive)
979 sigprocmask(SIG_SETMASK, &empty_set, NULL);
980}
981
982static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200983startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000984{
985 struct stat statbuf;
986 const char *filename;
987 char pathname[MAXPATHLEN];
988 int pid = 0;
989 struct tcb *tcp;
990
991 filename = argv[0];
992 if (strchr(filename, '/')) {
993 if (strlen(filename) > sizeof pathname - 1) {
994 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200995 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000996 }
997 strcpy(pathname, filename);
998 }
999#ifdef USE_DEBUGGING_EXEC
1000 /*
1001 * Debuggers customarily check the current directory
1002 * first regardless of the path but doing that gives
1003 * security geeks a panic attack.
1004 */
1005 else if (stat(filename, &statbuf) == 0)
1006 strcpy(pathname, filename);
1007#endif /* USE_DEBUGGING_EXEC */
1008 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +00001009 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +00001010 int m, n, len;
1011
1012 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +01001013 const char *colon = strchr(path, ':');
1014 if (colon) {
1015 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +00001016 m = n + 1;
1017 }
1018 else
1019 m = n = strlen(path);
1020 if (n == 0) {
1021 if (!getcwd(pathname, MAXPATHLEN))
1022 continue;
1023 len = strlen(pathname);
1024 }
1025 else if (n > sizeof pathname - 1)
1026 continue;
1027 else {
1028 strncpy(pathname, path, n);
1029 len = n;
1030 }
1031 if (len && pathname[len - 1] != '/')
1032 pathname[len++] = '/';
1033 strcpy(pathname + len, filename);
1034 if (stat(pathname, &statbuf) == 0 &&
1035 /* Accept only regular files
1036 with some execute bits set.
1037 XXX not perfect, might still fail */
1038 S_ISREG(statbuf.st_mode) &&
1039 (statbuf.st_mode & 0111))
1040 break;
1041 }
1042 }
1043 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001044 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001045 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001046 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001047 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001048 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001049 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001050 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1051 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001052 ) {
1053 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001054 if (outf != stderr)
1055 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001056 if (!daemonized_tracer && !use_seize) {
1057 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001058 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001059 }
Roland McGrath02203312007-06-11 22:06:31 +00001060 }
Roland McGrath02203312007-06-11 22:06:31 +00001061
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001062 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001063 uid_t run_euid = run_uid;
1064 gid_t run_egid = run_gid;
1065
1066 if (statbuf.st_mode & S_ISUID)
1067 run_euid = statbuf.st_uid;
1068 if (statbuf.st_mode & S_ISGID)
1069 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001070 /*
1071 * It is important to set groups before we
1072 * lose privileges on setuid.
1073 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001074 if (initgroups(username, run_gid) < 0) {
1075 perror_msg_and_die("initgroups");
1076 }
1077 if (setregid(run_gid, run_egid) < 0) {
1078 perror_msg_and_die("setregid");
1079 }
1080 if (setreuid(run_uid, run_euid) < 0) {
1081 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001082 }
1083 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001084 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001085 setreuid(run_uid, run_uid);
1086
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001087 if (!daemonized_tracer) {
1088 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001089 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001090 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001091 * the immediately following execve syscall.
1092 * Can't do this on NOMMU systems, we are after
1093 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001094 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001095 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001096 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001097 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001098 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001099 /* we depend on SIGCHLD set to SIG_DFL by init code */
1100 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001101 wait(NULL);
1102 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001103 }
Roland McGrath02203312007-06-11 22:06:31 +00001104
1105 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001106 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001107 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001108
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001109 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001110
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001111 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001112 if (!use_seize) {
1113 /* child did PTRACE_TRACEME, nothing to do in parent */
1114 } else {
1115 if (!strace_vforked) {
1116 /* Wait until child stopped itself */
1117 int status;
1118 while (waitpid(pid, &status, WSTOPPED) < 0) {
1119 if (errno == EINTR)
1120 continue;
1121 perror_msg_and_die("waitpid");
1122 }
1123 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001124 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001125 perror_msg_and_die("Unexpected wait status %x", status);
1126 }
1127 }
1128 /* Else: vforked case, we have no way to sync.
1129 * Just attach to it as soon as possible.
1130 * This means that we may miss a few first syscalls...
1131 */
1132
1133 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001134 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001135 perror_msg_and_die("Can't attach to %d", pid);
1136 }
1137 if (!strace_vforked)
1138 kill(pid, SIGCONT);
1139 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001140 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001141 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001142 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001143 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001144 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001145 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001146 }
1147 else {
1148 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1149 strace_tracer_pid = getpid();
1150 /* The tracee is our parent: */
1151 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001152 alloctcb(pid);
1153 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001154 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001155 }
Roland McGrath02203312007-06-11 22:06:31 +00001156}
1157
Wang Chaob13c0de2010-11-12 17:25:19 +08001158/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001159 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001160 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001161 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001162 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001163static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001164test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001165{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001166 int pid, expected_grandchild = 0, found_grandchild = 0;
1167 const unsigned int test_options = PTRACE_O_TRACECLONE |
1168 PTRACE_O_TRACEFORK |
1169 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001170
Denys Vlasenko5d645812011-08-20 12:48:18 +02001171 pid = fork();
1172 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001173 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001174 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001175 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001176 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001177 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1178 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001179 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001180 if (fork() < 0)
1181 perror_msg_and_die("fork");
1182 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001183 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001184
1185 while (1) {
1186 int status, tracee_pid;
1187
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001188 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001189 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001190 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001191 if (errno == EINTR)
1192 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001193 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001194 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001195 kill_save_errno(pid, SIGKILL);
1196 perror_msg_and_die("%s: unexpected wait result %d",
1197 __func__, tracee_pid);
1198 }
1199 if (WIFEXITED(status)) {
1200 if (WEXITSTATUS(status)) {
1201 if (tracee_pid != pid)
1202 kill_save_errno(pid, SIGKILL);
1203 error_msg_and_die("%s: unexpected exit status %u",
1204 __func__, WEXITSTATUS(status));
1205 }
1206 continue;
1207 }
1208 if (WIFSIGNALED(status)) {
1209 if (tracee_pid != pid)
1210 kill_save_errno(pid, SIGKILL);
1211 error_msg_and_die("%s: unexpected signal %u",
1212 __func__, WTERMSIG(status));
1213 }
1214 if (!WIFSTOPPED(status)) {
1215 if (tracee_pid != pid)
1216 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001217 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001218 error_msg_and_die("%s: unexpected wait status %x",
1219 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001220 }
1221 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001222 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001223 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1224 kill_save_errno(tracee_pid, SIGKILL);
1225 kill_save_errno(pid, SIGKILL);
1226 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001227 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001228 continue;
1229 }
1230 switch (WSTOPSIG(status)) {
1231 case SIGSTOP:
1232 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1233 && errno != EINVAL && errno != EIO)
1234 perror_msg("PTRACE_SETOPTIONS");
1235 break;
1236 case SIGTRAP:
1237 if (status >> 16 == PTRACE_EVENT_FORK) {
1238 long msg = 0;
1239
1240 if (ptrace(PTRACE_GETEVENTMSG, pid,
1241 NULL, (long) &msg) == 0)
1242 expected_grandchild = msg;
1243 }
1244 break;
1245 }
1246 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1247 kill_save_errno(pid, SIGKILL);
1248 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001249 }
1250 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001251 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001252 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001253 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001254 fprintf(stderr, "ptrace_setoptions = %#x\n",
1255 ptrace_setoptions);
1256 return;
1257 }
1258 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1259 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001260}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001261
1262/*
1263 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1264 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1265 * and then see whether it will stop with (SIGTRAP | 0x80).
1266 *
1267 * Use of this option enables correct handling of user-generated SIGTRAPs,
1268 * and SIGTRAPs generated by special instructions such as int3 on x86:
1269 * _start: .globl _start
1270 * int3
1271 * movl $42, %ebx
1272 * movl $1, %eax
1273 * int $0x80
1274 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1275 */
1276static void
1277test_ptrace_setoptions_for_all(void)
1278{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001279 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1280 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001281 int pid;
1282 int it_worked = 0;
1283
1284 pid = fork();
1285 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001286 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001287
1288 if (pid == 0) {
1289 pid = getpid();
1290 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001291 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001292 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1293 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001294 kill(pid, SIGSTOP);
1295 _exit(0); /* parent should see entry into this syscall */
1296 }
1297
1298 while (1) {
1299 int status, tracee_pid;
1300
1301 errno = 0;
1302 tracee_pid = wait(&status);
1303 if (tracee_pid <= 0) {
1304 if (errno == EINTR)
1305 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001306 kill_save_errno(pid, SIGKILL);
1307 perror_msg_and_die("%s: unexpected wait result %d",
1308 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001309 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001310 if (WIFEXITED(status)) {
1311 if (WEXITSTATUS(status) == 0)
1312 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001313 error_msg_and_die("%s: unexpected exit status %u",
1314 __func__, WEXITSTATUS(status));
1315 }
1316 if (WIFSIGNALED(status)) {
1317 error_msg_and_die("%s: unexpected signal %u",
1318 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001319 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001320 if (!WIFSTOPPED(status)) {
1321 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001322 error_msg_and_die("%s: unexpected wait status %x",
1323 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001324 }
1325 if (WSTOPSIG(status) == SIGSTOP) {
1326 /*
1327 * We don't check "options aren't accepted" error.
1328 * If it happens, we'll never get (SIGTRAP | 0x80),
1329 * and thus will decide to not use the option.
1330 * IOW: the outcome of the test will be correct.
1331 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001332 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1333 && errno != EINVAL && errno != EIO)
1334 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001335 }
1336 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1337 it_worked = 1;
1338 }
1339 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001340 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001341 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001342 }
1343 }
1344
1345 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001346 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001347 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001348 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001349 fprintf(stderr, "ptrace_setoptions = %#x\n",
1350 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001351 return;
1352 }
1353
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001354 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1355 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001356}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001357
1358# ifdef USE_SEIZE
1359static void
1360test_ptrace_seize(void)
1361{
1362 int pid;
1363
1364 pid = fork();
1365 if (pid < 0)
1366 perror_msg_and_die("fork");
1367
1368 if (pid == 0) {
1369 pause();
1370 _exit(0);
1371 }
1372
1373 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1374 * attaching tracee continues to run unless a trap condition occurs.
1375 * PTRACE_SEIZE doesn't affect signal or group stop state.
1376 */
1377 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1378 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001379 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001380 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1381 }
1382
1383 kill(pid, SIGKILL);
1384
1385 while (1) {
1386 int status, tracee_pid;
1387
1388 errno = 0;
1389 tracee_pid = waitpid(pid, &status, 0);
1390 if (tracee_pid <= 0) {
1391 if (errno == EINTR)
1392 continue;
1393 perror_msg_and_die("%s: unexpected wait result %d",
1394 __func__, tracee_pid);
1395 }
1396 if (WIFSIGNALED(status)) {
1397 return;
1398 }
1399 error_msg_and_die("%s: unexpected wait status %x",
1400 __func__, status);
1401 }
1402}
1403# else /* !USE_SEIZE */
1404# define test_ptrace_seize() ((void)0)
1405# endif
1406
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001407static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001408get_os_release(void)
1409{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001410 unsigned rel;
1411 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001412 struct utsname u;
1413 if (uname(&u) < 0)
1414 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001415 /* u.release has this form: "3.2.9[-some-garbage]" */
1416 rel = 0;
1417 p = u.release;
1418 for (;;) {
1419 if (!(*p >= '0' && *p <= '9'))
1420 error_msg_and_die("Bad OS release string: '%s'", u.release);
1421 /* Note: this open-codes KERNEL_VERSION(): */
1422 rel = (rel << 8) | atoi(p);
1423 if (rel >= KERNEL_VERSION(1,0,0))
1424 break;
1425 while (*p >= '0' && *p <= '9')
1426 p++;
1427 if (*p != '.')
1428 error_msg_and_die("Bad OS release string: '%s'", u.release);
1429 p++;
1430 }
1431 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001432}
1433
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001434/*
1435 * Initialization part of main() was eating much stack (~0.5k),
1436 * which was unused after init.
1437 * We can reuse it if we move init code into a separate function.
1438 *
1439 * Don't want main() to inline us and defeat the reason
1440 * we have a separate function.
1441 */
1442static void __attribute__ ((noinline))
1443init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001446 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001447 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448 struct sigaction sa;
1449
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001450 progname = argv[0] ? argv[0] : "strace";
1451
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001452 /* Make sure SIGCHLD has the default action so that waitpid
1453 definitely works without losing track of children. The user
1454 should not have given us a bogus state to inherit, but he might
1455 have. Arguably we should detect SIG_IGN here and pass it on
1456 to children, but probably noone really needs that. */
1457 signal(SIGCHLD, SIG_DFL);
1458
Denys Vlasenko75422762011-05-27 14:36:01 +02001459 strace_tracer_pid = getpid();
1460
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001461 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001462
Roland McGrathee9d4352002-12-18 04:16:10 +00001463 /* Allocate the initial tcbtab. */
1464 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001465 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001466 if (!tcbtab)
1467 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001468 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001469 if (!tcp)
1470 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001471 for (c = 0; c < tcbtabsize; c++)
1472 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001473
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001474 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001475 set_sortby(DEFAULT_SORTBY);
1476 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477 qualify("trace=all");
1478 qualify("abbrev=all");
1479 qualify("verbose=all");
1480 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001482 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001483 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001484 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001486 case 'b':
1487 detach_on_execve = 1;
1488 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001490 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001491 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001492 }
1493 cflag = CFLAG_ONLY_STATS;
1494 break;
1495 case 'C':
1496 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001497 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001498 }
1499 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500 break;
1501 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001502 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001504 case 'D':
1505 daemonized_tracer = 1;
1506 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001507 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001508 optF = 1;
1509 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510 case 'f':
1511 followfork++;
1512 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 case 'h':
1514 usage(stdout, 0);
1515 break;
1516 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001517 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518 break;
1519 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001520 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521 break;
1522 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001523 rflag = 1;
1524 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525 case 't':
1526 tflag++;
1527 break;
1528 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001529 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530 break;
1531 case 'x':
1532 xflag++;
1533 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001534 case 'y':
1535 show_fd_path = 1;
1536 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537 case 'v':
1538 qualify("abbrev=none");
1539 break;
1540 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001541 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542 exit(0);
1543 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001544 case 'z':
1545 not_failing_only = 1;
1546 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 case 'a':
1548 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001549 if (acolumn < 0)
1550 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551 break;
1552 case 'e':
1553 qualify(optarg);
1554 break;
1555 case 'o':
1556 outfname = strdup(optarg);
1557 break;
1558 case 'O':
1559 set_overhead(atoi(optarg));
1560 break;
1561 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001562 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001564 case 'P':
1565 tracing_paths = 1;
1566 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001567 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001568 }
1569 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570 case 's':
1571 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001572 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001573 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001574 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575 break;
1576 case 'S':
1577 set_sortby(optarg);
1578 break;
1579 case 'u':
1580 username = strdup(optarg);
1581 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001582 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001583 if (putenv(optarg) < 0)
1584 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001585 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001586 case 'I':
1587 opt_intr = atoi(optarg);
1588 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1589 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1590 }
1591 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592 default:
1593 usage(stderr, 1);
1594 break;
1595 }
1596 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001597 argv += optind;
1598 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599
Denys Vlasenko102ec492011-08-25 01:27:59 +02001600 acolumn_spaces = malloc(acolumn + 1);
1601 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001602 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001603 memset(acolumn_spaces, ' ', acolumn);
1604 acolumn_spaces[acolumn] = '\0';
1605
Denys Vlasenko837399a2012-01-24 11:37:03 +01001606 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001607 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001608 usage(stderr, 1);
1609
Denys Vlasenkofd883382012-03-09 13:03:41 +01001610 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001611 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001612 }
1613
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001614 if (!followfork)
1615 followfork = optF;
1616
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001617 if (followfork >= 2 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001618 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001619 }
1620
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621 /* See if they want to run as another user. */
1622 if (username != NULL) {
1623 struct passwd *pent;
1624
1625 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001626 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001628 pent = getpwnam(username);
1629 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001630 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 }
1632 run_uid = pent->pw_uid;
1633 run_gid = pent->pw_gid;
1634 }
1635 else {
1636 run_uid = getuid();
1637 run_gid = getgid();
1638 }
1639
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001640 if (followfork)
1641 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001642 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001643 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001644
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645 /* Check if they want to redirect the output. */
1646 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001647 /* See if they want to pipe the output. */
1648 if (outfname[0] == '|' || outfname[0] == '!') {
1649 /*
1650 * We can't do the <outfname>.PID funny business
1651 * when using popen, so prohibit it.
1652 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001653 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001654 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1655 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001656 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001657 else if (followfork < 2)
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001658 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001659 } else {
1660 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001661 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001662 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663 }
1664
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001665 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001666 char *buf = malloc(BUFSIZ);
1667 if (!buf)
1668 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001670 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001671 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001672 if (!opt_intr)
1673 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001675 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001676 if (!opt_intr)
1677 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001678
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001679 /* argv[0] -pPID -oFILE Default interactive setting
1680 * yes 0 0 INTR_WHILE_WAIT
1681 * no 1 0 INTR_WHILE_WAIT
1682 * yes 0 1 INTR_NEVER
1683 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001684 */
1685
1686 /* STARTUP_CHILD must be called before the signal handlers get
1687 installed below as they are inherited into the spawned process.
1688 Also we do not need to be protected by them as during interruption
1689 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001690 if (argv[0]) {
1691 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001692 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001693 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001695 sigemptyset(&empty_set);
1696 sigemptyset(&blocked_set);
1697 sa.sa_handler = SIG_IGN;
1698 sigemptyset(&sa.sa_mask);
1699 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001700 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1701 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1702 if (opt_intr != INTR_ANYWHERE) {
1703 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1704 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1705 /*
1706 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1707 * fatal signals are blocked while syscall stop is processed,
1708 * and acted on in between, when waiting for new syscall stops.
1709 * In non-interactive mode, signals are ignored.
1710 */
1711 if (opt_intr == INTR_WHILE_WAIT) {
1712 sigaddset(&blocked_set, SIGHUP);
1713 sigaddset(&blocked_set, SIGINT);
1714 sigaddset(&blocked_set, SIGQUIT);
1715 sigaddset(&blocked_set, SIGPIPE);
1716 sigaddset(&blocked_set, SIGTERM);
1717 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001718 }
1719 /* SIG_IGN, or set handler for these */
1720 sigaction(SIGHUP, &sa, NULL);
1721 sigaction(SIGINT, &sa, NULL);
1722 sigaction(SIGQUIT, &sa, NULL);
1723 sigaction(SIGPIPE, &sa, NULL);
1724 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001726 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001727 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001728
Denys Vlasenkofd883382012-03-09 13:03:41 +01001729 /* Do we want pids printed in our -o OUTFILE?
1730 * -ff: no (every pid has its own file); or
1731 * -f: yes (there can be more pids in the future); or
1732 * -p PID1,PID2: yes (there are already more than one pid)
1733 */
1734 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735}
1736
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001737static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001738pid2tcb(int pid)
1739{
1740 int i;
1741
1742 if (pid <= 0)
1743 return NULL;
1744
1745 for (i = 0; i < tcbtabsize; i++) {
1746 struct tcb *tcp = tcbtab[i];
1747 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1748 return tcp;
1749 }
1750
1751 return NULL;
1752}
1753
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001755cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756{
1757 int i;
1758 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001759 int fatal_sig;
1760
1761 /* 'interrupted' is a volatile object, fetch it only once */
1762 fatal_sig = interrupted;
1763 if (!fatal_sig)
1764 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765
Roland McGrathee9d4352002-12-18 04:16:10 +00001766 for (i = 0; i < tcbtabsize; i++) {
1767 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768 if (!(tcp->flags & TCB_INUSE))
1769 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001770 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001771 fprintf(stderr,
1772 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001773 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001775 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001777 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778 }
1779 if (cflag)
1780 call_summary(outf);
1781}
1782
1783static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001784interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001786 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787}
1788
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001790trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001793 struct rusage *rup = cflag ? &ru : NULL;
1794# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001795 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001796# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797
Roland McGratheb9e2e82009-06-02 16:49:22 -07001798 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001799 int pid;
1800 int wait_errno;
1801 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001802 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001803 struct tcb *tcp;
1804 unsigned event;
1805
Denys Vlasenko222713a2009-03-17 14:29:59 +00001806 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001807 return 0;
1808 if (interactive)
1809 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001810# ifdef __WALL
1811 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001812 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001813 /* this kernel does not support __WALL */
1814 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001815 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001816 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001817 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001818 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001819 pid = wait4(-1, &status, __WCLONE, rup);
1820 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001821 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001822 }
1823 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001824# else
1825 pid = wait4(-1, &status, 0, rup);
1826# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001827 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001828 if (interactive)
1829 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001831 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001832 switch (wait_errno) {
1833 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001835 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001836 /*
1837 * We would like to verify this case
1838 * but sometimes a race in Solbourne's
1839 * version of SunOS sometimes reports
1840 * ECHILD before sending us SIGCHILD.
1841 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001842 return 0;
1843 default:
1844 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001845 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001846 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847 }
1848 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001849 if (pid == popen_pid) {
1850 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001851 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001852 continue;
1853 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001854
1855 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001856 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001857 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001858 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001859 strcpy(buf, "???");
1860 if (WIFSIGNALED(status))
1861#ifdef WCOREDUMP
1862 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1863 WCOREDUMP(status) ? "core," : "",
1864 signame(WTERMSIG(status)));
1865#else
1866 sprintf(buf, "WIFSIGNALED,sig=%s",
1867 signame(WTERMSIG(status)));
1868#endif
1869 if (WIFEXITED(status))
1870 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1871 if (WIFSTOPPED(status))
1872 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001873#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001874 if (WIFCONTINUED(status))
1875 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001876#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001877 evbuf[0] = '\0';
1878 if (event != 0) {
1879 static const char *const event_names[] = {
1880 [PTRACE_EVENT_CLONE] = "CLONE",
1881 [PTRACE_EVENT_FORK] = "FORK",
1882 [PTRACE_EVENT_VFORK] = "VFORK",
1883 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1884 [PTRACE_EVENT_EXEC] = "EXEC",
1885 [PTRACE_EVENT_EXIT] = "EXIT",
1886 };
1887 const char *e;
1888 if (event < ARRAY_SIZE(event_names))
1889 e = event_names[event];
1890 else {
1891 sprintf(buf, "?? (%u)", event);
1892 e = buf;
1893 }
1894 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1895 }
1896 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001897 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001899 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001900 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001901
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001902 /* Under Linux, execve changes pid to thread leader's pid,
1903 * and we see this changed pid on EVENT_EXEC and later,
1904 * execve sysexit. Leader "disappears" without exit
1905 * notification. Let user know that, drop leader's tcb,
1906 * and fix up pid in execve thread's tcb.
1907 * Effectively, execve thread's tcb replaces leader's tcb.
1908 *
1909 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1910 * on exit syscall) in multithreaded programs exactly
1911 * in order to handle this case.
1912 *
1913 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1914 * On 2.6 and earlier, it can return garbage.
1915 */
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001916 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001917 long old_pid = 0;
1918 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1919 && old_pid > 0
1920 && old_pid != pid
1921 ) {
1922 struct tcb *execve_thread = pid2tcb(old_pid);
1923 if (tcp) {
1924 outf = tcp->outf;
1925 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001926 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001927 if (execve_thread->curcol != 0) {
1928 /*
1929 * One case we are here is -ff:
1930 * try "strace -oLOG -ff test/threaded_execve"
1931 */
1932 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1933 execve_thread->curcol = 0;
1934 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001935 /* swap output FILEs (needed for -ff) */
1936 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001937 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001938 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001939 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001940 }
1941 droptcb(tcp);
1942 }
1943 tcp = execve_thread;
1944 if (tcp) {
1945 tcp->pid = pid;
1946 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001947 if (!cflag) {
1948 printleader(tcp);
1949 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1950 line_ended();
1951 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001952 }
1953 }
1954 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001955
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001956 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1957 if (!skip_startup_execve)
1958 detach(tcp);
1959 /* This was initial execve for "strace PROG". Skip. */
1960 skip_startup_execve = 0;
1961 }
1962
Denys Vlasenko5d645812011-08-20 12:48:18 +02001963 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001964 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001965 /* This is needed to go with the CLONE_PTRACE
1966 changes in process.c/util.c: we might see
1967 the child's initial trap before we see the
1968 parent return from the clone syscall.
1969 Leave the child suspended until the parent
1970 returns from its system call. Only then
1971 will we have the association of parent and
1972 child so that we know how to do clearbpt
1973 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001974 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001975 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001976 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001977 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001978 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001979 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001980 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001981 else
1982 /* This can happen if a clone call used
1983 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001984 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001985 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001986 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001987 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001988 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001990
1991 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001992 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001993 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001994
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001995 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001996 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1997 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001999
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002001 if (pid == strace_child)
2002 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002003 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2005 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002006#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002007 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002008 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002009 WCOREDUMP(status) ? "(core dumped) " : "");
2010#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002011 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002012 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002013#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002014 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 }
2016 droptcb(tcp);
2017 continue;
2018 }
2019 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002020 if (pid == strace_child)
2021 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002022 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2023 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002024 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002025 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002026 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002027 droptcb(tcp);
2028 continue;
2029 }
2030 if (!WIFSTOPPED(status)) {
2031 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2032 droptcb(tcp);
2033 continue;
2034 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002036 /* Is this the very first time we see this tracee stopped? */
2037 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002038 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002039 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002042 /*
2043 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002044 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002045 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002046 if (clearbpt(tcp) < 0) {
2047 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048 droptcb(tcp);
2049 cleanup();
2050 return -1;
2051 }
2052 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002053 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002054 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002055 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2056 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2057 if (errno != ESRCH) {
2058 /* Should never happen, really */
2059 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002060 }
2061 }
2062 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002063 }
2064
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002065 sig = WSTOPSIG(status);
2066
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002067 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002068 /* Ptrace event */
2069#ifdef USE_SEIZE
2070 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002071 /*
2072 * PTRACE_INTERRUPT-stop or group-stop.
2073 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2074 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002075 if (sig == SIGSTOP
2076 || sig == SIGTSTP
2077 || sig == SIGTTIN
2078 || sig == SIGTTOU
2079 ) {
2080 stopped = 1;
2081 goto show_stopsig;
2082 }
2083 }
2084#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002085 goto restart_tracee_with_sig_0;
2086 }
2087
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002088 /* Is this post-attach SIGSTOP?
2089 * Interestingly, the process may stop
2090 * with STOPSIG equal to some other signal
2091 * than SIGSTOP if we happend to attach
2092 * just before the process takes a signal.
2093 */
2094 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002095 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002096 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2097 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002098 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 }
2100
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002101 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002102 siginfo_t si;
2103
2104 /* Nonzero (true) if tracee is stopped by signal
2105 * (as opposed to "tracee received signal").
2106 */
2107 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002108#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002109 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002110#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002111 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002112 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002113#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002114 long pc = 0;
2115 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002116
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002117 upeek(tcp, PT_CR_IPSR, &psr);
2118 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002119
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002120# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002121 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002122# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002123# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002124#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002125# define PC_FORMAT_STR ""
2126# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002127#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002129 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002130 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002131 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002132 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002133 PC_FORMAT_ARG);
2134 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002135 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002136 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002137 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002138 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002140
2141 if (!stopped)
2142 /* It's signal-delivery-stop. Inject the signal */
2143 goto restart_tracee;
2144
2145 /* It's group-stop */
2146#ifdef USE_SEIZE
2147 if (use_seize) {
2148 /*
2149 * This ends ptrace-stop, but does *not* end group-stop.
2150 * This makes stopping signals work properly on straced process
2151 * (that is, process really stops. It used to continue to run).
2152 */
2153 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2154 cleanup();
2155 return -1;
2156 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002157 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002158 continue;
2159 }
2160 /* We don't have PTRACE_LISTEN support... */
2161#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002162 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002163 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002164
2165 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002166 if (interrupted)
2167 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002168
2169 /* This should be syscall entry or exit.
2170 * (Or it still can be that pesky post-execve SIGTRAP!)
2171 * Handle it.
2172 */
Denys Vlasenko23506752012-03-21 10:32:49 +01002173 if (trace_syscall(tcp) < 0) {
2174 /* ptrace() failed in trace_syscall().
Roland McGratheb9e2e82009-06-02 16:49:22 -07002175 * Likely a result of process disappearing mid-flight.
Denys Vlasenko23506752012-03-21 10:32:49 +01002176 * Observed case: exit_group() or SIGKILL terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002177 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002178 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002179 * We used to detach(tcp) here, but since we no longer
2180 * implement "detach before death" policy/hack,
2181 * we can let this process to report its death to us
2182 * normally, via WIFEXITED or WIFSIGNALED wait status.
2183 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002184 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002185 continue;
2186 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002187 restart_tracee_with_sig_0:
2188 sig = 0;
2189 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002190 /* Remember current print column before continuing. */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002191 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Denys Vlasenko23506752012-03-21 10:32:49 +01002192 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002193 cleanup();
2194 return -1;
2195 }
Denys Vlasenko23506752012-03-21 10:32:49 +01002196 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 }
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}