blob: 1ade018bd8b5c839d4a3fd89de711957a69df439 [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->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100564 }
565 }
566
567 printing_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100568 outf = tcp->outf;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100569 curcol = 0;
570
571 if (print_pid_pfx)
572 tprintf("%-5d ", tcp->pid);
573 else if (nprocs > 1 && !outfname)
574 tprintf("[pid %5u] ", tcp->pid);
575
576 if (tflag) {
577 char str[sizeof("HH:MM:SS")];
578 struct timeval tv, dtv;
579 static struct timeval otv;
580
581 gettimeofday(&tv, NULL);
582 if (rflag) {
583 if (otv.tv_sec == 0)
584 otv = tv;
585 tv_sub(&dtv, &tv, &otv);
586 tprintf("%6ld.%06ld ",
587 (long) dtv.tv_sec, (long) dtv.tv_usec);
588 otv = tv;
589 }
590 else if (tflag > 2) {
591 tprintf("%ld.%06ld ",
592 (long) tv.tv_sec, (long) tv.tv_usec);
593 }
594 else {
595 time_t local = tv.tv_sec;
596 strftime(str, sizeof(str), "%T", localtime(&local));
597 if (tflag > 1)
598 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
599 else
600 tprintf("%s ", str);
601 }
602 }
603 if (iflag)
604 printcall(tcp);
605}
606
607void
608tabto(void)
609{
610 if (curcol < acolumn)
611 tprints(acolumn_spaces + curcol);
612}
613
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100614/* Should be only called directly *after successful attach* to a tracee.
615 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
616 * may create bogus empty FILE.<nonexistant_pid>, and then die.
617 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200618static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000619newoutf(struct tcb *tcp)
620{
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100621 tcp->outf = outf; /* if not -ff mode, the same file is for all */
622 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000623 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000624 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200625 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000626 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000627}
628
Denys Vlasenko558e5122012-03-12 23:32:16 +0100629static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100630expand_tcbtab(void)
631{
632 /* Allocate some more TCBs and expand the table.
633 We don't want to relocate the TCBs because our
634 callers have pointers and it would be a pain.
635 So tcbtab is a table of pointers. Since we never
636 free the TCBs, we allocate a single chunk of many. */
637 int i = tcbtabsize;
638 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
639 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
640 if (!newtab || !newtcbs)
641 die_out_of_memory();
642 tcbtabsize *= 2;
643 tcbtab = newtab;
644 while (i < tcbtabsize)
645 tcbtab[i++] = newtcbs++;
646}
647
648static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100649alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100650{
651 int i;
652 struct tcb *tcp;
653
654 if (nprocs == tcbtabsize)
655 expand_tcbtab();
656
657 for (i = 0; i < tcbtabsize; i++) {
658 tcp = tcbtab[i];
659 if ((tcp->flags & TCB_INUSE) == 0) {
660 memset(tcp, 0, sizeof(*tcp));
661 tcp->pid = pid;
662 tcp->flags = TCB_INUSE;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100663 /* tcp->outf = outf; - not needed? */
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100664#if SUPPORTED_PERSONALITIES > 1
665 tcp->currpers = current_personality;
666#endif
667 nprocs++;
668 if (debug_flag)
669 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100670 return tcp;
671 }
672 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100673 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100674}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100675
676static void
677droptcb(struct tcb *tcp)
678{
679 if (tcp->pid == 0)
680 return;
681
682 nprocs--;
683 if (debug_flag)
684 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
685
686 if (tcp->outf) {
Denys Vlasenko8511f2a2012-03-22 09:35:51 +0100687 if (followfork >= 2) {
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100688 if (tcp->curcol != 0)
689 fprintf(tcp->outf, " <detached ...>\n");
690 fclose(tcp->outf);
691 if (outf == tcp->outf)
692 outf = NULL;
693 } else {
694 if (printing_tcp == tcp && tcp->curcol != 0)
695 fprintf(tcp->outf, " <detached ...>\n");
696 fflush(tcp->outf);
697 }
698 }
699
700 if (printing_tcp == tcp)
701 printing_tcp = NULL;
702
703 memset(tcp, 0, sizeof(*tcp));
704}
705
706/* detach traced process; continue with sig
707 * Never call DETACH twice on the same process as both unattached and
708 * attached-unstopped processes give the same ESRCH. For unattached process we
709 * would SIGSTOP it and wait for its SIGSTOP notification forever.
710 */
711static int
712detach(struct tcb *tcp)
713{
714 int error;
715 int status, sigstop_expected;
716
717 if (tcp->flags & TCB_BPTSET)
718 clearbpt(tcp);
719
720 /*
721 * Linux wrongly insists the child be stopped
722 * before detaching. Arghh. We go through hoops
723 * to make a clean break of things.
724 */
725#if defined(SPARC)
726#undef PTRACE_DETACH
727#define PTRACE_DETACH PTRACE_SUNDETACH
728#endif
729
730 error = 0;
731 sigstop_expected = 0;
732 if (tcp->flags & TCB_ATTACHED) {
733 /*
734 * We attached but possibly didn't see the expected SIGSTOP.
735 * We must catch exactly one as otherwise the detached process
736 * would be left stopped (process state T).
737 */
738 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
739 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
740 if (error == 0) {
741 /* On a clear day, you can see forever. */
742 }
743 else if (errno != ESRCH) {
744 /* Shouldn't happen. */
745 perror("detach: ptrace(PTRACE_DETACH, ...)");
746 }
747 else if (my_tkill(tcp->pid, 0) < 0) {
748 if (errno != ESRCH)
749 perror("detach: checking sanity");
750 }
751 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
752 if (errno != ESRCH)
753 perror("detach: stopping child");
754 }
755 else
756 sigstop_expected = 1;
757 }
758
759 if (sigstop_expected) {
760 for (;;) {
761#ifdef __WALL
762 if (waitpid(tcp->pid, &status, __WALL) < 0) {
763 if (errno == ECHILD) /* Already gone. */
764 break;
765 if (errno != EINVAL) {
766 perror("detach: waiting");
767 break;
768 }
769#endif /* __WALL */
770 /* No __WALL here. */
771 if (waitpid(tcp->pid, &status, 0) < 0) {
772 if (errno != ECHILD) {
773 perror("detach: waiting");
774 break;
775 }
776#ifdef __WCLONE
777 /* If no processes, try clones. */
778 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
779 if (errno != ECHILD)
780 perror("detach: waiting");
781 break;
782 }
783#endif /* __WCLONE */
784 }
785#ifdef __WALL
786 }
787#endif
788 if (!WIFSTOPPED(status)) {
789 /* Au revoir, mon ami. */
790 break;
791 }
792 if (WSTOPSIG(status) == SIGSTOP) {
793 ptrace_restart(PTRACE_DETACH, tcp, 0);
794 break;
795 }
796 error = ptrace_restart(PTRACE_CONT, tcp,
797 WSTOPSIG(status) == syscall_trap_sig ? 0
798 : WSTOPSIG(status));
799 if (error < 0)
800 break;
801 }
802 }
803
804 if (!qflag && (tcp->flags & TCB_ATTACHED))
805 fprintf(stderr, "Process %u detached\n", tcp->pid);
806
807 droptcb(tcp);
808
809 return error;
810}
811
812static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100813process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100814{
815 while (*opt) {
816 /*
817 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
818 * pidof uses space as delim, pgrep uses newline. :(
819 */
820 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100821 char *delim = opt + strcspn(opt, ", \n\t");
822 char c = *delim;
823
824 *delim = '\0';
825 pid = atoi(opt); /* TODO: stricter parsing of the number? */
826 if (pid <= 0) {
827 error_msg("Invalid process id: '%s'", opt);
828 *delim = c;
829 return;
830 }
831 if (pid == strace_tracer_pid) {
832 error_msg("I'm sorry, I can't let you do that, Dave.");
833 *delim = c;
834 return;
835 }
836 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100837 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100838 if (c == '\0')
839 break;
840 opt = delim + 1;
841 }
842}
843
Roland McGrath02203312007-06-11 22:06:31 +0000844static void
845startup_attach(void)
846{
847 int tcbi;
848 struct tcb *tcp;
849
850 /*
851 * Block user interruptions as we would leave the traced
852 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200853 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200854 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000855 */
856 if (interactive)
857 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
858
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000859 if (daemonized_tracer) {
860 pid_t pid = fork();
861 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200862 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000863 }
864 if (pid) { /* parent */
865 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200866 * Wait for grandchild to attach to straced process
867 * (grandparent). Grandchild SIGKILLs us after it attached.
868 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000869 * it proceeds to exec the straced program.
870 */
871 pause();
872 _exit(0); /* paranoia */
873 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200874 /* grandchild */
875 /* We will be the tracer process. Remember our new pid: */
876 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000877 }
878
Roland McGrath02203312007-06-11 22:06:31 +0000879 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
880 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200881
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100882 if (!(tcp->flags & TCB_INUSE))
883 continue;
884
Denys Vlasenkod116a732011-09-05 14:01:33 +0200885 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100886 if (tcp->flags & TCB_ATTACHED)
887 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200888
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000889 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000890 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000891 DIR *dir;
892
893 sprintf(procdir, "/proc/%d/task", tcp->pid);
894 dir = opendir(procdir);
895 if (dir != NULL) {
896 unsigned int ntid = 0, nerr = 0;
897 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200898
Roland McGrath02203312007-06-11 22:06:31 +0000899 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200900 struct tcb *cur_tcp;
901 int tid;
902
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000903 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000904 continue;
905 tid = atoi(de->d_name);
906 if (tid <= 0)
907 continue;
908 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100909 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000910 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100911 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200912 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200913 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200914 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100915 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200916 fprintf(stderr, "attach to pid %d succeeded\n", tid);
917 cur_tcp = tcp;
918 if (tid != tcp->pid)
919 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100920 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100921 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000922 }
923 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200924 if (interactive) {
925 sigprocmask(SIG_SETMASK, &empty_set, NULL);
926 if (interrupted)
927 goto ret;
928 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
929 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000930 ntid -= nerr;
931 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000932 perror("attach: ptrace(PTRACE_ATTACH, ...)");
933 droptcb(tcp);
934 continue;
935 }
936 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000937 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100938? "Process %u attached with %u threads\n"
939: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200940 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000941 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100942 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200943 /* -p PID, we failed to attach to PID itself
944 * but did attach to some of its sibling threads.
945 * Drop PID's tcp.
946 */
947 droptcb(tcp);
948 }
Roland McGrath02203312007-06-11 22:06:31 +0000949 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000950 } /* if (opendir worked) */
951 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100952 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000953 perror("attach: ptrace(PTRACE_ATTACH, ...)");
954 droptcb(tcp);
955 continue;
956 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100957 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100958 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100959 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200960 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000961
962 if (daemonized_tracer) {
963 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000964 * Make parent go away.
965 * Also makes grandparent's wait() unblock.
966 */
967 kill(getppid(), SIGKILL);
968 }
969
Roland McGrath02203312007-06-11 22:06:31 +0000970 if (!qflag)
971 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100972 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000973 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200974 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000975
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200976 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000977 if (interactive)
978 sigprocmask(SIG_SETMASK, &empty_set, NULL);
979}
980
981static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200982startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000983{
984 struct stat statbuf;
985 const char *filename;
986 char pathname[MAXPATHLEN];
987 int pid = 0;
988 struct tcb *tcp;
989
990 filename = argv[0];
991 if (strchr(filename, '/')) {
992 if (strlen(filename) > sizeof pathname - 1) {
993 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200994 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000995 }
996 strcpy(pathname, filename);
997 }
998#ifdef USE_DEBUGGING_EXEC
999 /*
1000 * Debuggers customarily check the current directory
1001 * first regardless of the path but doing that gives
1002 * security geeks a panic attack.
1003 */
1004 else if (stat(filename, &statbuf) == 0)
1005 strcpy(pathname, filename);
1006#endif /* USE_DEBUGGING_EXEC */
1007 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +00001008 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +00001009 int m, n, len;
1010
1011 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +01001012 const char *colon = strchr(path, ':');
1013 if (colon) {
1014 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +00001015 m = n + 1;
1016 }
1017 else
1018 m = n = strlen(path);
1019 if (n == 0) {
1020 if (!getcwd(pathname, MAXPATHLEN))
1021 continue;
1022 len = strlen(pathname);
1023 }
1024 else if (n > sizeof pathname - 1)
1025 continue;
1026 else {
1027 strncpy(pathname, path, n);
1028 len = n;
1029 }
1030 if (len && pathname[len - 1] != '/')
1031 pathname[len++] = '/';
1032 strcpy(pathname + len, filename);
1033 if (stat(pathname, &statbuf) == 0 &&
1034 /* Accept only regular files
1035 with some execute bits set.
1036 XXX not perfect, might still fail */
1037 S_ISREG(statbuf.st_mode) &&
1038 (statbuf.st_mode & 0111))
1039 break;
1040 }
1041 }
1042 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001043 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001044 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001045 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001046 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001047 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001048 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001049 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1050 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001051 ) {
1052 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001053 if (outf != stderr)
1054 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001055 if (!daemonized_tracer && !use_seize) {
1056 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001057 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001058 }
Roland McGrath02203312007-06-11 22:06:31 +00001059 }
Roland McGrath02203312007-06-11 22:06:31 +00001060
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001061 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001062 uid_t run_euid = run_uid;
1063 gid_t run_egid = run_gid;
1064
1065 if (statbuf.st_mode & S_ISUID)
1066 run_euid = statbuf.st_uid;
1067 if (statbuf.st_mode & S_ISGID)
1068 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001069 /*
1070 * It is important to set groups before we
1071 * lose privileges on setuid.
1072 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001073 if (initgroups(username, run_gid) < 0) {
1074 perror_msg_and_die("initgroups");
1075 }
1076 if (setregid(run_gid, run_egid) < 0) {
1077 perror_msg_and_die("setregid");
1078 }
1079 if (setreuid(run_uid, run_euid) < 0) {
1080 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001081 }
1082 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001083 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001084 setreuid(run_uid, run_uid);
1085
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001086 if (!daemonized_tracer) {
1087 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001088 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001089 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001090 * the immediately following execve syscall.
1091 * Can't do this on NOMMU systems, we are after
1092 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001093 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001094 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001095 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001096 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001097 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001098 /* we depend on SIGCHLD set to SIG_DFL by init code */
1099 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001100 wait(NULL);
1101 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001102 }
Roland McGrath02203312007-06-11 22:06:31 +00001103
1104 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001105 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001106 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001107
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001108 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001109
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001110 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001111 if (!use_seize) {
1112 /* child did PTRACE_TRACEME, nothing to do in parent */
1113 } else {
1114 if (!strace_vforked) {
1115 /* Wait until child stopped itself */
1116 int status;
1117 while (waitpid(pid, &status, WSTOPPED) < 0) {
1118 if (errno == EINTR)
1119 continue;
1120 perror_msg_and_die("waitpid");
1121 }
1122 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001123 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001124 perror_msg_and_die("Unexpected wait status %x", status);
1125 }
1126 }
1127 /* Else: vforked case, we have no way to sync.
1128 * Just attach to it as soon as possible.
1129 * This means that we may miss a few first syscalls...
1130 */
1131
1132 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001133 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001134 perror_msg_and_die("Can't attach to %d", pid);
1135 }
1136 if (!strace_vforked)
1137 kill(pid, SIGCONT);
1138 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001139 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001140 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001141 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001142 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001143 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001144 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001145 }
1146 else {
1147 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1148 strace_tracer_pid = getpid();
1149 /* The tracee is our parent: */
1150 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001151 alloctcb(pid);
1152 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001153 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001154 }
Roland McGrath02203312007-06-11 22:06:31 +00001155}
1156
Wang Chaob13c0de2010-11-12 17:25:19 +08001157/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001158 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001159 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001160 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001161 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001162static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001163test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001164{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001165 int pid, expected_grandchild = 0, found_grandchild = 0;
1166 const unsigned int test_options = PTRACE_O_TRACECLONE |
1167 PTRACE_O_TRACEFORK |
1168 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001169
Denys Vlasenko5d645812011-08-20 12:48:18 +02001170 pid = fork();
1171 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001172 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001173 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001174 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001175 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001176 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1177 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001178 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001179 if (fork() < 0)
1180 perror_msg_and_die("fork");
1181 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001182 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001183
1184 while (1) {
1185 int status, tracee_pid;
1186
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001187 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001188 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001189 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001190 if (errno == EINTR)
1191 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001192 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001193 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001194 kill_save_errno(pid, SIGKILL);
1195 perror_msg_and_die("%s: unexpected wait result %d",
1196 __func__, tracee_pid);
1197 }
1198 if (WIFEXITED(status)) {
1199 if (WEXITSTATUS(status)) {
1200 if (tracee_pid != pid)
1201 kill_save_errno(pid, SIGKILL);
1202 error_msg_and_die("%s: unexpected exit status %u",
1203 __func__, WEXITSTATUS(status));
1204 }
1205 continue;
1206 }
1207 if (WIFSIGNALED(status)) {
1208 if (tracee_pid != pid)
1209 kill_save_errno(pid, SIGKILL);
1210 error_msg_and_die("%s: unexpected signal %u",
1211 __func__, WTERMSIG(status));
1212 }
1213 if (!WIFSTOPPED(status)) {
1214 if (tracee_pid != pid)
1215 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001216 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001217 error_msg_and_die("%s: unexpected wait status %x",
1218 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001219 }
1220 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001221 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001222 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1223 kill_save_errno(tracee_pid, SIGKILL);
1224 kill_save_errno(pid, SIGKILL);
1225 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001226 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001227 continue;
1228 }
1229 switch (WSTOPSIG(status)) {
1230 case SIGSTOP:
1231 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1232 && errno != EINVAL && errno != EIO)
1233 perror_msg("PTRACE_SETOPTIONS");
1234 break;
1235 case SIGTRAP:
1236 if (status >> 16 == PTRACE_EVENT_FORK) {
1237 long msg = 0;
1238
1239 if (ptrace(PTRACE_GETEVENTMSG, pid,
1240 NULL, (long) &msg) == 0)
1241 expected_grandchild = msg;
1242 }
1243 break;
1244 }
1245 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1246 kill_save_errno(pid, SIGKILL);
1247 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001248 }
1249 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001250 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001251 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001252 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001253 fprintf(stderr, "ptrace_setoptions = %#x\n",
1254 ptrace_setoptions);
1255 return;
1256 }
1257 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1258 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001259}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001260
1261/*
1262 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1263 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1264 * and then see whether it will stop with (SIGTRAP | 0x80).
1265 *
1266 * Use of this option enables correct handling of user-generated SIGTRAPs,
1267 * and SIGTRAPs generated by special instructions such as int3 on x86:
1268 * _start: .globl _start
1269 * int3
1270 * movl $42, %ebx
1271 * movl $1, %eax
1272 * int $0x80
1273 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1274 */
1275static void
1276test_ptrace_setoptions_for_all(void)
1277{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001278 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1279 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001280 int pid;
1281 int it_worked = 0;
1282
1283 pid = fork();
1284 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001285 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001286
1287 if (pid == 0) {
1288 pid = getpid();
1289 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001290 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001291 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1292 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001293 kill(pid, SIGSTOP);
1294 _exit(0); /* parent should see entry into this syscall */
1295 }
1296
1297 while (1) {
1298 int status, tracee_pid;
1299
1300 errno = 0;
1301 tracee_pid = wait(&status);
1302 if (tracee_pid <= 0) {
1303 if (errno == EINTR)
1304 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001305 kill_save_errno(pid, SIGKILL);
1306 perror_msg_and_die("%s: unexpected wait result %d",
1307 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001308 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001309 if (WIFEXITED(status)) {
1310 if (WEXITSTATUS(status) == 0)
1311 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001312 error_msg_and_die("%s: unexpected exit status %u",
1313 __func__, WEXITSTATUS(status));
1314 }
1315 if (WIFSIGNALED(status)) {
1316 error_msg_and_die("%s: unexpected signal %u",
1317 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001318 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001319 if (!WIFSTOPPED(status)) {
1320 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001321 error_msg_and_die("%s: unexpected wait status %x",
1322 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001323 }
1324 if (WSTOPSIG(status) == SIGSTOP) {
1325 /*
1326 * We don't check "options aren't accepted" error.
1327 * If it happens, we'll never get (SIGTRAP | 0x80),
1328 * and thus will decide to not use the option.
1329 * IOW: the outcome of the test will be correct.
1330 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001331 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1332 && errno != EINVAL && errno != EIO)
1333 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001334 }
1335 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1336 it_worked = 1;
1337 }
1338 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001339 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001340 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001341 }
1342 }
1343
1344 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001345 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001346 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001347 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001348 fprintf(stderr, "ptrace_setoptions = %#x\n",
1349 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001350 return;
1351 }
1352
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001353 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1354 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001355}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001356
1357# ifdef USE_SEIZE
1358static void
1359test_ptrace_seize(void)
1360{
1361 int pid;
1362
1363 pid = fork();
1364 if (pid < 0)
1365 perror_msg_and_die("fork");
1366
1367 if (pid == 0) {
1368 pause();
1369 _exit(0);
1370 }
1371
1372 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1373 * attaching tracee continues to run unless a trap condition occurs.
1374 * PTRACE_SEIZE doesn't affect signal or group stop state.
1375 */
1376 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1377 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001378 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001379 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1380 }
1381
1382 kill(pid, SIGKILL);
1383
1384 while (1) {
1385 int status, tracee_pid;
1386
1387 errno = 0;
1388 tracee_pid = waitpid(pid, &status, 0);
1389 if (tracee_pid <= 0) {
1390 if (errno == EINTR)
1391 continue;
1392 perror_msg_and_die("%s: unexpected wait result %d",
1393 __func__, tracee_pid);
1394 }
1395 if (WIFSIGNALED(status)) {
1396 return;
1397 }
1398 error_msg_and_die("%s: unexpected wait status %x",
1399 __func__, status);
1400 }
1401}
1402# else /* !USE_SEIZE */
1403# define test_ptrace_seize() ((void)0)
1404# endif
1405
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001406static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001407get_os_release(void)
1408{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001409 unsigned rel;
1410 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001411 struct utsname u;
1412 if (uname(&u) < 0)
1413 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001414 /* u.release has this form: "3.2.9[-some-garbage]" */
1415 rel = 0;
1416 p = u.release;
1417 for (;;) {
1418 if (!(*p >= '0' && *p <= '9'))
1419 error_msg_and_die("Bad OS release string: '%s'", u.release);
1420 /* Note: this open-codes KERNEL_VERSION(): */
1421 rel = (rel << 8) | atoi(p);
1422 if (rel >= KERNEL_VERSION(1,0,0))
1423 break;
1424 while (*p >= '0' && *p <= '9')
1425 p++;
1426 if (*p != '.')
1427 error_msg_and_die("Bad OS release string: '%s'", u.release);
1428 p++;
1429 }
1430 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001431}
1432
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001433/*
1434 * Initialization part of main() was eating much stack (~0.5k),
1435 * which was unused after init.
1436 * We can reuse it if we move init code into a separate function.
1437 *
1438 * Don't want main() to inline us and defeat the reason
1439 * we have a separate function.
1440 */
1441static void __attribute__ ((noinline))
1442init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001445 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001446 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 struct sigaction sa;
1448
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001449 progname = argv[0] ? argv[0] : "strace";
1450
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001451 /* Make sure SIGCHLD has the default action so that waitpid
1452 definitely works without losing track of children. The user
1453 should not have given us a bogus state to inherit, but he might
1454 have. Arguably we should detect SIG_IGN here and pass it on
1455 to children, but probably noone really needs that. */
1456 signal(SIGCHLD, SIG_DFL);
1457
Denys Vlasenko75422762011-05-27 14:36:01 +02001458 strace_tracer_pid = getpid();
1459
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001460 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001461
Roland McGrathee9d4352002-12-18 04:16:10 +00001462 /* Allocate the initial tcbtab. */
1463 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001464 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001465 if (!tcbtab)
1466 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001467 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001468 if (!tcp)
1469 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001470 for (c = 0; c < tcbtabsize; c++)
1471 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001472
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001474 set_sortby(DEFAULT_SORTBY);
1475 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 qualify("trace=all");
1477 qualify("abbrev=all");
1478 qualify("verbose=all");
1479 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001481 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001482 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001483 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001484 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001485 case 'b':
1486 detach_on_execve = 1;
1487 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001489 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001490 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001491 }
1492 cflag = CFLAG_ONLY_STATS;
1493 break;
1494 case 'C':
1495 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001496 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001497 }
1498 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 break;
1500 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001501 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001503 case 'D':
1504 daemonized_tracer = 1;
1505 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001506 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001507 optF = 1;
1508 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 case 'f':
1510 followfork++;
1511 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 case 'h':
1513 usage(stdout, 0);
1514 break;
1515 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001516 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517 break;
1518 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001519 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001520 break;
1521 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001522 rflag = 1;
1523 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524 case 't':
1525 tflag++;
1526 break;
1527 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001528 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529 break;
1530 case 'x':
1531 xflag++;
1532 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001533 case 'y':
1534 show_fd_path = 1;
1535 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 case 'v':
1537 qualify("abbrev=none");
1538 break;
1539 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001540 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541 exit(0);
1542 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001543 case 'z':
1544 not_failing_only = 1;
1545 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546 case 'a':
1547 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001548 if (acolumn < 0)
1549 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550 break;
1551 case 'e':
1552 qualify(optarg);
1553 break;
1554 case 'o':
1555 outfname = strdup(optarg);
1556 break;
1557 case 'O':
1558 set_overhead(atoi(optarg));
1559 break;
1560 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001561 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001563 case 'P':
1564 tracing_paths = 1;
1565 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001566 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001567 }
1568 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569 case 's':
1570 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001571 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001572 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001573 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 break;
1575 case 'S':
1576 set_sortby(optarg);
1577 break;
1578 case 'u':
1579 username = strdup(optarg);
1580 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001581 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001582 if (putenv(optarg) < 0)
1583 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001584 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001585 case 'I':
1586 opt_intr = atoi(optarg);
1587 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1588 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1589 }
1590 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001591 default:
1592 usage(stderr, 1);
1593 break;
1594 }
1595 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001596 argv += optind;
1597 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598
Denys Vlasenko102ec492011-08-25 01:27:59 +02001599 acolumn_spaces = malloc(acolumn + 1);
1600 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001601 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001602 memset(acolumn_spaces, ' ', acolumn);
1603 acolumn_spaces[acolumn] = '\0';
1604
Denys Vlasenko837399a2012-01-24 11:37:03 +01001605 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001606 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001607 usage(stderr, 1);
1608
Denys Vlasenkofd883382012-03-09 13:03:41 +01001609 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001610 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001611 }
1612
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001613 if (!followfork)
1614 followfork = optF;
1615
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001616 if (followfork >= 2 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001617 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001618 }
1619
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620 /* See if they want to run as another user. */
1621 if (username != NULL) {
1622 struct passwd *pent;
1623
1624 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001625 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001627 pent = getpwnam(username);
1628 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001629 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630 }
1631 run_uid = pent->pw_uid;
1632 run_gid = pent->pw_gid;
1633 }
1634 else {
1635 run_uid = getuid();
1636 run_gid = getgid();
1637 }
1638
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001639 if (followfork)
1640 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001641 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001642 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001643
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644 /* Check if they want to redirect the output. */
1645 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001646 /* See if they want to pipe the output. */
1647 if (outfname[0] == '|' || outfname[0] == '!') {
1648 /*
1649 * We can't do the <outfname>.PID funny business
1650 * when using popen, so prohibit it.
1651 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001652 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001653 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1654 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001655 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001656 else if (followfork < 2)
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001657 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001658 } else {
1659 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001660 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001661 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662 }
1663
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001664 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001665 char *buf = malloc(BUFSIZ);
1666 if (!buf)
1667 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001669 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001670 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001671 if (!opt_intr)
1672 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001674 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001675 if (!opt_intr)
1676 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001677
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001678 /* argv[0] -pPID -oFILE Default interactive setting
1679 * yes 0 0 INTR_WHILE_WAIT
1680 * no 1 0 INTR_WHILE_WAIT
1681 * yes 0 1 INTR_NEVER
1682 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001683 */
1684
1685 /* STARTUP_CHILD must be called before the signal handlers get
1686 installed below as they are inherited into the spawned process.
1687 Also we do not need to be protected by them as during interruption
1688 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001689 if (argv[0]) {
1690 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001691 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001692 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694 sigemptyset(&empty_set);
1695 sigemptyset(&blocked_set);
1696 sa.sa_handler = SIG_IGN;
1697 sigemptyset(&sa.sa_mask);
1698 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001699 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1700 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1701 if (opt_intr != INTR_ANYWHERE) {
1702 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1703 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1704 /*
1705 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1706 * fatal signals are blocked while syscall stop is processed,
1707 * and acted on in between, when waiting for new syscall stops.
1708 * In non-interactive mode, signals are ignored.
1709 */
1710 if (opt_intr == INTR_WHILE_WAIT) {
1711 sigaddset(&blocked_set, SIGHUP);
1712 sigaddset(&blocked_set, SIGINT);
1713 sigaddset(&blocked_set, SIGQUIT);
1714 sigaddset(&blocked_set, SIGPIPE);
1715 sigaddset(&blocked_set, SIGTERM);
1716 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001717 }
1718 /* SIG_IGN, or set handler for these */
1719 sigaction(SIGHUP, &sa, NULL);
1720 sigaction(SIGINT, &sa, NULL);
1721 sigaction(SIGQUIT, &sa, NULL);
1722 sigaction(SIGPIPE, &sa, NULL);
1723 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001725 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001726 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001727
Denys Vlasenkofd883382012-03-09 13:03:41 +01001728 /* Do we want pids printed in our -o OUTFILE?
1729 * -ff: no (every pid has its own file); or
1730 * -f: yes (there can be more pids in the future); or
1731 * -p PID1,PID2: yes (there are already more than one pid)
1732 */
1733 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734}
1735
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001736static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001737pid2tcb(int pid)
1738{
1739 int i;
1740
1741 if (pid <= 0)
1742 return NULL;
1743
1744 for (i = 0; i < tcbtabsize; i++) {
1745 struct tcb *tcp = tcbtab[i];
1746 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1747 return tcp;
1748 }
1749
1750 return NULL;
1751}
1752
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001754cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755{
1756 int i;
1757 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001758 int fatal_sig;
1759
1760 /* 'interrupted' is a volatile object, fetch it only once */
1761 fatal_sig = interrupted;
1762 if (!fatal_sig)
1763 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001764
Roland McGrathee9d4352002-12-18 04:16:10 +00001765 for (i = 0; i < tcbtabsize; i++) {
1766 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 if (!(tcp->flags & TCB_INUSE))
1768 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001769 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770 fprintf(stderr,
1771 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001772 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001774 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001776 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777 }
1778 if (cflag)
1779 call_summary(outf);
1780}
1781
1782static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001783interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001785 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786}
1787
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001789trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001792 struct rusage *rup = cflag ? &ru : NULL;
1793# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001794 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001795# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796
Roland McGratheb9e2e82009-06-02 16:49:22 -07001797 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001798 int pid;
1799 int wait_errno;
1800 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001801 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001802 struct tcb *tcp;
1803 unsigned event;
1804
Denys Vlasenko222713a2009-03-17 14:29:59 +00001805 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001806 return 0;
1807 if (interactive)
1808 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001809# ifdef __WALL
1810 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001811 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001812 /* this kernel does not support __WALL */
1813 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001814 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001815 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001816 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001817 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001818 pid = wait4(-1, &status, __WCLONE, rup);
1819 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001820 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001821 }
1822 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001823# else
1824 pid = wait4(-1, &status, 0, rup);
1825# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001827 if (interactive)
1828 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001830 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001831 switch (wait_errno) {
1832 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001834 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001835 /*
1836 * We would like to verify this case
1837 * but sometimes a race in Solbourne's
1838 * version of SunOS sometimes reports
1839 * ECHILD before sending us SIGCHILD.
1840 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001841 return 0;
1842 default:
1843 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001844 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001845 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846 }
1847 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001848 if (pid == popen_pid) {
1849 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001850 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001851 continue;
1852 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001853
1854 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001855 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001856 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001857 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001858 strcpy(buf, "???");
1859 if (WIFSIGNALED(status))
1860#ifdef WCOREDUMP
1861 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1862 WCOREDUMP(status) ? "core," : "",
1863 signame(WTERMSIG(status)));
1864#else
1865 sprintf(buf, "WIFSIGNALED,sig=%s",
1866 signame(WTERMSIG(status)));
1867#endif
1868 if (WIFEXITED(status))
1869 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1870 if (WIFSTOPPED(status))
1871 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001872#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001873 if (WIFCONTINUED(status))
1874 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001875#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001876 evbuf[0] = '\0';
1877 if (event != 0) {
1878 static const char *const event_names[] = {
1879 [PTRACE_EVENT_CLONE] = "CLONE",
1880 [PTRACE_EVENT_FORK] = "FORK",
1881 [PTRACE_EVENT_VFORK] = "VFORK",
1882 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1883 [PTRACE_EVENT_EXEC] = "EXEC",
1884 [PTRACE_EVENT_EXIT] = "EXIT",
1885 };
1886 const char *e;
1887 if (event < ARRAY_SIZE(event_names))
1888 e = event_names[event];
1889 else {
1890 sprintf(buf, "?? (%u)", event);
1891 e = buf;
1892 }
1893 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1894 }
1895 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001896 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001898 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001899 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001900
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001901 if (!tcp) {
Roland McGrath41c48222008-07-18 00:25:10 +00001902 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001903 /* This is needed to go with the CLONE_PTRACE
1904 changes in process.c/util.c: we might see
1905 the child's initial trap before we see the
1906 parent return from the clone syscall.
1907 Leave the child suspended until the parent
1908 returns from its system call. Only then
1909 will we have the association of parent and
1910 child so that we know how to do clearbpt
1911 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001912 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001913 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001914 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001915 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001916 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001917 pid);
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001918 } else {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001919 /* This can happen if a clone call used
1920 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001921 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001922 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001923 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001924 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001925 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001926
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001927 /* Under Linux, execve changes pid to thread leader's pid,
1928 * and we see this changed pid on EVENT_EXEC and later,
1929 * execve sysexit. Leader "disappears" without exit
1930 * notification. Let user know that, drop leader's tcb,
1931 * and fix up pid in execve thread's tcb.
1932 * Effectively, execve thread's tcb replaces leader's tcb.
1933 *
1934 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1935 * on exit syscall) in multithreaded programs exactly
1936 * in order to handle this case.
1937 *
1938 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1939 * On 2.6 and earlier, it can return garbage.
1940 */
1941 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
1942 struct tcb *execve_thread;
1943 long old_pid = 0;
1944
1945 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0)
1946 goto dont_switch_tcbs;
1947 if (old_pid <= 0 || old_pid == pid)
1948 goto dont_switch_tcbs;
1949 execve_thread = pid2tcb(old_pid);
1950 /* It should be !NULL, but I feel paranoid */
1951 if (!execve_thread)
1952 goto dont_switch_tcbs;
1953
1954 outf = tcp->outf;
1955 curcol = tcp->curcol;
1956 if (execve_thread->curcol != 0) {
1957 /*
1958 * One case we are here is -ff:
1959 * try "strace -oLOG -ff test/threaded_execve"
1960 */
1961 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1962 execve_thread->curcol = 0;
1963 }
1964 /* Swap output FILEs (needed for -ff) */
1965 tcp->outf = execve_thread->outf;
1966 tcp->curcol = execve_thread->curcol;
1967 /* And their column positions */
1968 execve_thread->outf = outf;
1969 execve_thread->curcol = curcol;
1970 /* Drop leader, but close execve'd thread outfile (if -ff) */
1971 droptcb(tcp);
1972 /* Switch to the thread, reusing leader's outfile and pid */
1973 tcp = execve_thread;
1974 tcp->pid = pid;
1975 if (cflag != CFLAG_ONLY_STATS) {
1976 printleader(tcp);
1977 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1978 line_ended();
1979 tcp->flags |= TCB_REPRINT;
1980 }
1981 }
1982 dont_switch_tcbs:
1983
1984 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1985 if (!skip_startup_execve)
1986 detach(tcp);
1987 /* This was initial execve for "strace PROG". Skip. */
1988 skip_startup_execve = 0;
1989 }
1990
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001991 /* 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 Vlasenkob5e09082012-03-21 14:27:40 +01002022 if (cflag != CFLAG_ONLY_STATS) {
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002023 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").
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002106 * TODO: shouldn't we check for errno == EINVAL too?
2107 * We can get ESRCH instead, you know...
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002108 */
2109 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002110#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002111 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002112#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002113 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002114 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002115#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002116 long pc = 0;
2117 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002118
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002119 upeek(tcp, PT_CR_IPSR, &psr);
2120 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002121
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002122# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002123 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002124# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002125# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002126#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002127# define PC_FORMAT_STR ""
2128# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002129#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002131 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002132 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002133 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002134 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002135 PC_FORMAT_ARG);
2136 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002137 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002138 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002139 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002140 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002142
2143 if (!stopped)
2144 /* It's signal-delivery-stop. Inject the signal */
2145 goto restart_tracee;
2146
2147 /* It's group-stop */
2148#ifdef USE_SEIZE
2149 if (use_seize) {
2150 /*
2151 * This ends ptrace-stop, but does *not* end group-stop.
2152 * This makes stopping signals work properly on straced process
2153 * (that is, process really stops. It used to continue to run).
2154 */
2155 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
Denys Vlasenkob5e09082012-03-21 14:27:40 +01002156 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002157 cleanup();
2158 return -1;
2159 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002160 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002161 continue;
2162 }
2163 /* We don't have PTRACE_LISTEN support... */
2164#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002165 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002166 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002167
2168 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002169 if (interrupted)
2170 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002171
2172 /* This should be syscall entry or exit.
2173 * (Or it still can be that pesky post-execve SIGTRAP!)
2174 * Handle it.
2175 */
Denys Vlasenko23506752012-03-21 10:32:49 +01002176 if (trace_syscall(tcp) < 0) {
2177 /* ptrace() failed in trace_syscall().
Roland McGratheb9e2e82009-06-02 16:49:22 -07002178 * Likely a result of process disappearing mid-flight.
Denys Vlasenko23506752012-03-21 10:32:49 +01002179 * Observed case: exit_group() or SIGKILL terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002180 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002181 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002182 * We used to detach(tcp) here, but since we no longer
2183 * implement "detach before death" policy/hack,
2184 * we can let this process to report its death to us
2185 * normally, via WIFEXITED or WIFSIGNALED wait status.
2186 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002187 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188 continue;
2189 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002190 restart_tracee_with_sig_0:
2191 sig = 0;
2192 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002193 /* Remember current print column before continuing. */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002194 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Denys Vlasenko23506752012-03-21 10:32:49 +01002195 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 cleanup();
2197 return -1;
2198 }
Denys Vlasenko23506752012-03-21 10:32:49 +01002199 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 }
2201 return 0;
2202}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002203
2204int
2205main(int argc, char *argv[])
2206{
2207 init(argc, argv);
2208
2209 /* Run main tracing loop */
2210 if (trace() < 0)
2211 return 1;
2212
2213 cleanup();
2214 fflush(NULL);
2215 if (exit_code > 0xff) {
2216 /* Avoid potential core file clobbering. */
2217 struct rlimit rlim = {0, 0};
2218 setrlimit(RLIMIT_CORE, &rlim);
2219
2220 /* Child was killed by a signal, mimic that. */
2221 exit_code &= 0xff;
2222 signal(exit_code, SIG_DFL);
2223 raise(exit_code);
2224 /* Paranoia - what if this signal is not fatal?
2225 Exit with 128 + signo then. */
2226 exit_code += 128;
2227 }
2228
2229 return exit_code;
2230}