blob: 5f590cdd73d0f75bd6f0dc39cfc48b36b67ffec7 [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 Vlasenko1f532ab2011-06-22 13:11:23 +0200339static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000340set_cloexec_flag(int fd)
341{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200342 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200344 flags = fcntl(fd, F_GETFD);
345 if (flags < 0) {
346 /* Can happen only if fd is bad.
347 * Should never happen: if it does, we have a bug
348 * in the caller. Therefore we just abort
349 * instead of propagating the error.
350 */
351 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000352 }
353
354 newflags = flags | FD_CLOEXEC;
355 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200356 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000357
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200358 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000359}
360
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100361static void kill_save_errno(pid_t pid, int sig)
362{
363 int saved_errno = errno;
364
365 (void) kill(pid, sig);
366 errno = saved_errno;
367}
368
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100369/*
370 * When strace is setuid executable, we have to swap uids
371 * before and after filesystem and process management operations.
372 */
373static void
374swap_uid(void)
375{
376 int euid = geteuid(), uid = getuid();
377
378 if (euid != uid && setreuid(euid, uid) < 0) {
379 perror_msg_and_die("setreuid");
380 }
381}
382
383#if _LFS64_LARGEFILE
384# define fopen_for_output fopen64
385#else
386# define fopen_for_output fopen
387#endif
388
389static FILE *
390strace_fopen(const char *path)
391{
392 FILE *fp;
393
394 swap_uid();
395 fp = fopen_for_output(path, "w");
396 if (!fp)
397 perror_msg_and_die("Can't fopen '%s'", path);
398 swap_uid();
399 set_cloexec_flag(fileno(fp));
400 return fp;
401}
402
403static int popen_pid = 0;
404
405#ifndef _PATH_BSHELL
406# define _PATH_BSHELL "/bin/sh"
407#endif
408
409/*
410 * We cannot use standard popen(3) here because we have to distinguish
411 * popen child process from other processes we trace, and standard popen(3)
412 * does not export its child's pid.
413 */
414static FILE *
415strace_popen(const char *command)
416{
417 FILE *fp;
418 int fds[2];
419
420 swap_uid();
421 if (pipe(fds) < 0)
422 perror_msg_and_die("pipe");
423
424 set_cloexec_flag(fds[1]); /* never fails */
425
426 popen_pid = vfork();
427 if (popen_pid == -1)
428 perror_msg_and_die("vfork");
429
430 if (popen_pid == 0) {
431 /* child */
432 close(fds[1]);
433 if (fds[0] != 0) {
434 if (dup2(fds[0], 0))
435 perror_msg_and_die("dup2");
436 close(fds[0]);
437 }
438 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
439 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
440 }
441
442 /* parent */
443 close(fds[0]);
444 swap_uid();
445 fp = fdopen(fds[1], "w");
446 if (!fp)
447 die_out_of_memory();
448 return fp;
449}
450
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100451void
452tprintf(const char *fmt, ...)
453{
454 va_list args;
455
456 va_start(args, fmt);
457 if (outf) {
458 int n = vfprintf(outf, fmt, args);
459 if (n < 0) {
460 if (outf != stderr)
461 perror(outfname == NULL
462 ? "<writing to pipe>" : outfname);
463 } else
464 curcol += n;
465 }
466 va_end(args);
467}
468
469void
470tprints(const char *str)
471{
472 if (outf) {
473 int n = fputs(str, outf);
474 if (n >= 0) {
475 curcol += strlen(str);
476 return;
477 }
478 if (outf != stderr)
479 perror(outfname == NULL
480 ? "<writing to pipe>" : outfname);
481 }
482}
483
484void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100485line_ended(void)
486{
487 curcol = 0;
488 fflush(outf);
489 if (!printing_tcp)
490 return;
491 printing_tcp->curcol = 0;
492 printing_tcp = NULL;
493}
494
495void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100496printleader(struct tcb *tcp)
497{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100498 /* If -ff, "previous tcb we printed" is always the same as current,
499 * because we have per-tcb output files.
500 */
501 if (followfork >= 2)
502 printing_tcp = tcp;
503
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100504 if (printing_tcp) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100505 outf = printing_tcp->outf;
506 curcol = printing_tcp->curcol;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100507 if (printing_tcp->ptrace_errno) {
508 if (printing_tcp->flags & TCB_INSYSCALL) {
509 tprints(" <unavailable>) ");
510 tabto();
511 }
512 tprints("= ? <unavailable>\n");
513 printing_tcp->ptrace_errno = 0;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100514 printing_tcp->curcol = 0;
515 }
516 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
517 /*
518 * case 1: we have a shared log (i.e. not -ff), and last line
519 * wasn't finished (same or different tcb, doesn't matter).
520 * case 2: split log, we are the same tcb, but our last line
521 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
522 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100523 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100524 printing_tcp->flags |= TCB_REPRINT;
525 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100526 }
527 }
528
529 printing_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100530 outf = tcp->outf;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100531 curcol = 0;
532
533 if (print_pid_pfx)
534 tprintf("%-5d ", tcp->pid);
535 else if (nprocs > 1 && !outfname)
536 tprintf("[pid %5u] ", tcp->pid);
537
538 if (tflag) {
539 char str[sizeof("HH:MM:SS")];
540 struct timeval tv, dtv;
541 static struct timeval otv;
542
543 gettimeofday(&tv, NULL);
544 if (rflag) {
545 if (otv.tv_sec == 0)
546 otv = tv;
547 tv_sub(&dtv, &tv, &otv);
548 tprintf("%6ld.%06ld ",
549 (long) dtv.tv_sec, (long) dtv.tv_usec);
550 otv = tv;
551 }
552 else if (tflag > 2) {
553 tprintf("%ld.%06ld ",
554 (long) tv.tv_sec, (long) tv.tv_usec);
555 }
556 else {
557 time_t local = tv.tv_sec;
558 strftime(str, sizeof(str), "%T", localtime(&local));
559 if (tflag > 1)
560 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
561 else
562 tprintf("%s ", str);
563 }
564 }
565 if (iflag)
566 printcall(tcp);
567}
568
569void
570tabto(void)
571{
572 if (curcol < acolumn)
573 tprints(acolumn_spaces + curcol);
574}
575
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100576/* Should be only called directly *after successful attach* to a tracee.
577 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
578 * may create bogus empty FILE.<nonexistant_pid>, and then die.
579 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200580static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000581newoutf(struct tcb *tcp)
582{
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100583 tcp->outf = outf; /* if not -ff mode, the same file is for all */
584 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000585 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000586 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200587 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000588 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000589}
590
Denys Vlasenko558e5122012-03-12 23:32:16 +0100591static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100592expand_tcbtab(void)
593{
594 /* Allocate some more TCBs and expand the table.
595 We don't want to relocate the TCBs because our
596 callers have pointers and it would be a pain.
597 So tcbtab is a table of pointers. Since we never
598 free the TCBs, we allocate a single chunk of many. */
599 int i = tcbtabsize;
600 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
601 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
602 if (!newtab || !newtcbs)
603 die_out_of_memory();
604 tcbtabsize *= 2;
605 tcbtab = newtab;
606 while (i < tcbtabsize)
607 tcbtab[i++] = newtcbs++;
608}
609
610static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100611alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100612{
613 int i;
614 struct tcb *tcp;
615
616 if (nprocs == tcbtabsize)
617 expand_tcbtab();
618
619 for (i = 0; i < tcbtabsize; i++) {
620 tcp = tcbtab[i];
621 if ((tcp->flags & TCB_INUSE) == 0) {
622 memset(tcp, 0, sizeof(*tcp));
623 tcp->pid = pid;
624 tcp->flags = TCB_INUSE;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100625 /* tcp->outf = outf; - not needed? */
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100626#if SUPPORTED_PERSONALITIES > 1
627 tcp->currpers = current_personality;
628#endif
629 nprocs++;
630 if (debug_flag)
631 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100632 return tcp;
633 }
634 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100635 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100636}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100637
638static void
639droptcb(struct tcb *tcp)
640{
641 if (tcp->pid == 0)
642 return;
643
644 nprocs--;
645 if (debug_flag)
646 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
647
648 if (tcp->outf) {
649 if (outfname && followfork >= 2) {
650 if (tcp->curcol != 0)
651 fprintf(tcp->outf, " <detached ...>\n");
652 fclose(tcp->outf);
653 if (outf == tcp->outf)
654 outf = NULL;
655 } else {
656 if (printing_tcp == tcp && tcp->curcol != 0)
657 fprintf(tcp->outf, " <detached ...>\n");
658 fflush(tcp->outf);
659 }
660 }
661
662 if (printing_tcp == tcp)
663 printing_tcp = NULL;
664
665 memset(tcp, 0, sizeof(*tcp));
666}
667
668/* detach traced process; continue with sig
669 * Never call DETACH twice on the same process as both unattached and
670 * attached-unstopped processes give the same ESRCH. For unattached process we
671 * would SIGSTOP it and wait for its SIGSTOP notification forever.
672 */
673static int
674detach(struct tcb *tcp)
675{
676 int error;
677 int status, sigstop_expected;
678
679 if (tcp->flags & TCB_BPTSET)
680 clearbpt(tcp);
681
682 /*
683 * Linux wrongly insists the child be stopped
684 * before detaching. Arghh. We go through hoops
685 * to make a clean break of things.
686 */
687#if defined(SPARC)
688#undef PTRACE_DETACH
689#define PTRACE_DETACH PTRACE_SUNDETACH
690#endif
691
692 error = 0;
693 sigstop_expected = 0;
694 if (tcp->flags & TCB_ATTACHED) {
695 /*
696 * We attached but possibly didn't see the expected SIGSTOP.
697 * We must catch exactly one as otherwise the detached process
698 * would be left stopped (process state T).
699 */
700 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
701 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
702 if (error == 0) {
703 /* On a clear day, you can see forever. */
704 }
705 else if (errno != ESRCH) {
706 /* Shouldn't happen. */
707 perror("detach: ptrace(PTRACE_DETACH, ...)");
708 }
709 else if (my_tkill(tcp->pid, 0) < 0) {
710 if (errno != ESRCH)
711 perror("detach: checking sanity");
712 }
713 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
714 if (errno != ESRCH)
715 perror("detach: stopping child");
716 }
717 else
718 sigstop_expected = 1;
719 }
720
721 if (sigstop_expected) {
722 for (;;) {
723#ifdef __WALL
724 if (waitpid(tcp->pid, &status, __WALL) < 0) {
725 if (errno == ECHILD) /* Already gone. */
726 break;
727 if (errno != EINVAL) {
728 perror("detach: waiting");
729 break;
730 }
731#endif /* __WALL */
732 /* No __WALL here. */
733 if (waitpid(tcp->pid, &status, 0) < 0) {
734 if (errno != ECHILD) {
735 perror("detach: waiting");
736 break;
737 }
738#ifdef __WCLONE
739 /* If no processes, try clones. */
740 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
741 if (errno != ECHILD)
742 perror("detach: waiting");
743 break;
744 }
745#endif /* __WCLONE */
746 }
747#ifdef __WALL
748 }
749#endif
750 if (!WIFSTOPPED(status)) {
751 /* Au revoir, mon ami. */
752 break;
753 }
754 if (WSTOPSIG(status) == SIGSTOP) {
755 ptrace_restart(PTRACE_DETACH, tcp, 0);
756 break;
757 }
758 error = ptrace_restart(PTRACE_CONT, tcp,
759 WSTOPSIG(status) == syscall_trap_sig ? 0
760 : WSTOPSIG(status));
761 if (error < 0)
762 break;
763 }
764 }
765
766 if (!qflag && (tcp->flags & TCB_ATTACHED))
767 fprintf(stderr, "Process %u detached\n", tcp->pid);
768
769 droptcb(tcp);
770
771 return error;
772}
773
774static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100775process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100776{
777 while (*opt) {
778 /*
779 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
780 * pidof uses space as delim, pgrep uses newline. :(
781 */
782 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100783 char *delim = opt + strcspn(opt, ", \n\t");
784 char c = *delim;
785
786 *delim = '\0';
787 pid = atoi(opt); /* TODO: stricter parsing of the number? */
788 if (pid <= 0) {
789 error_msg("Invalid process id: '%s'", opt);
790 *delim = c;
791 return;
792 }
793 if (pid == strace_tracer_pid) {
794 error_msg("I'm sorry, I can't let you do that, Dave.");
795 *delim = c;
796 return;
797 }
798 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100799 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100800 if (c == '\0')
801 break;
802 opt = delim + 1;
803 }
804}
805
Roland McGrath02203312007-06-11 22:06:31 +0000806static void
807startup_attach(void)
808{
809 int tcbi;
810 struct tcb *tcp;
811
812 /*
813 * Block user interruptions as we would leave the traced
814 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200815 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200816 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000817 */
818 if (interactive)
819 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
820
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000821 if (daemonized_tracer) {
822 pid_t pid = fork();
823 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200824 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000825 }
826 if (pid) { /* parent */
827 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200828 * Wait for grandchild to attach to straced process
829 * (grandparent). Grandchild SIGKILLs us after it attached.
830 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000831 * it proceeds to exec the straced program.
832 */
833 pause();
834 _exit(0); /* paranoia */
835 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200836 /* grandchild */
837 /* We will be the tracer process. Remember our new pid: */
838 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000839 }
840
Roland McGrath02203312007-06-11 22:06:31 +0000841 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
842 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200843
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100844 if (!(tcp->flags & TCB_INUSE))
845 continue;
846
Denys Vlasenkod116a732011-09-05 14:01:33 +0200847 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100848 if (tcp->flags & TCB_ATTACHED)
849 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200850
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000851 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000852 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000853 DIR *dir;
854
855 sprintf(procdir, "/proc/%d/task", tcp->pid);
856 dir = opendir(procdir);
857 if (dir != NULL) {
858 unsigned int ntid = 0, nerr = 0;
859 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200860
Roland McGrath02203312007-06-11 22:06:31 +0000861 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200862 struct tcb *cur_tcp;
863 int tid;
864
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000865 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000866 continue;
867 tid = atoi(de->d_name);
868 if (tid <= 0)
869 continue;
870 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100871 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000872 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100873 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200874 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200875 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200876 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100877 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200878 fprintf(stderr, "attach to pid %d succeeded\n", tid);
879 cur_tcp = tcp;
880 if (tid != tcp->pid)
881 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100882 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100883 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000884 }
885 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200886 if (interactive) {
887 sigprocmask(SIG_SETMASK, &empty_set, NULL);
888 if (interrupted)
889 goto ret;
890 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
891 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000892 ntid -= nerr;
893 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000894 perror("attach: ptrace(PTRACE_ATTACH, ...)");
895 droptcb(tcp);
896 continue;
897 }
898 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000899 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100900? "Process %u attached with %u threads\n"
901: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200902 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000903 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100904 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200905 /* -p PID, we failed to attach to PID itself
906 * but did attach to some of its sibling threads.
907 * Drop PID's tcp.
908 */
909 droptcb(tcp);
910 }
Roland McGrath02203312007-06-11 22:06:31 +0000911 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000912 } /* if (opendir worked) */
913 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100914 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000915 perror("attach: ptrace(PTRACE_ATTACH, ...)");
916 droptcb(tcp);
917 continue;
918 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100919 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100920 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100921 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200922 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000923
924 if (daemonized_tracer) {
925 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000926 * Make parent go away.
927 * Also makes grandparent's wait() unblock.
928 */
929 kill(getppid(), SIGKILL);
930 }
931
Roland McGrath02203312007-06-11 22:06:31 +0000932 if (!qflag)
933 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100934 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000935 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200936 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000937
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200938 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000939 if (interactive)
940 sigprocmask(SIG_SETMASK, &empty_set, NULL);
941}
942
943static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200944startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000945{
946 struct stat statbuf;
947 const char *filename;
948 char pathname[MAXPATHLEN];
949 int pid = 0;
950 struct tcb *tcp;
951
952 filename = argv[0];
953 if (strchr(filename, '/')) {
954 if (strlen(filename) > sizeof pathname - 1) {
955 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200956 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000957 }
958 strcpy(pathname, filename);
959 }
960#ifdef USE_DEBUGGING_EXEC
961 /*
962 * Debuggers customarily check the current directory
963 * first regardless of the path but doing that gives
964 * security geeks a panic attack.
965 */
966 else if (stat(filename, &statbuf) == 0)
967 strcpy(pathname, filename);
968#endif /* USE_DEBUGGING_EXEC */
969 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000970 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000971 int m, n, len;
972
973 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100974 const char *colon = strchr(path, ':');
975 if (colon) {
976 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000977 m = n + 1;
978 }
979 else
980 m = n = strlen(path);
981 if (n == 0) {
982 if (!getcwd(pathname, MAXPATHLEN))
983 continue;
984 len = strlen(pathname);
985 }
986 else if (n > sizeof pathname - 1)
987 continue;
988 else {
989 strncpy(pathname, path, n);
990 len = n;
991 }
992 if (len && pathname[len - 1] != '/')
993 pathname[len++] = '/';
994 strcpy(pathname + len, filename);
995 if (stat(pathname, &statbuf) == 0 &&
996 /* Accept only regular files
997 with some execute bits set.
998 XXX not perfect, might still fail */
999 S_ISREG(statbuf.st_mode) &&
1000 (statbuf.st_mode & 0111))
1001 break;
1002 }
1003 }
1004 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001005 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001006 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001007 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001008 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001009 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001010 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001011 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1012 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001013 ) {
1014 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001015 if (outf != stderr)
1016 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001017 if (!daemonized_tracer && !use_seize) {
1018 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001019 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001020 }
Roland McGrath02203312007-06-11 22:06:31 +00001021 }
Roland McGrath02203312007-06-11 22:06:31 +00001022
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001023 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001024 uid_t run_euid = run_uid;
1025 gid_t run_egid = run_gid;
1026
1027 if (statbuf.st_mode & S_ISUID)
1028 run_euid = statbuf.st_uid;
1029 if (statbuf.st_mode & S_ISGID)
1030 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001031 /*
1032 * It is important to set groups before we
1033 * lose privileges on setuid.
1034 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001035 if (initgroups(username, run_gid) < 0) {
1036 perror_msg_and_die("initgroups");
1037 }
1038 if (setregid(run_gid, run_egid) < 0) {
1039 perror_msg_and_die("setregid");
1040 }
1041 if (setreuid(run_uid, run_euid) < 0) {
1042 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001043 }
1044 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001045 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001046 setreuid(run_uid, run_uid);
1047
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001048 if (!daemonized_tracer) {
1049 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001050 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001051 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001052 * the immediately following execve syscall.
1053 * Can't do this on NOMMU systems, we are after
1054 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001055 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001056 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001057 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001058 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001059 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001060 /* we depend on SIGCHLD set to SIG_DFL by init code */
1061 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001062 wait(NULL);
1063 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001064 }
Roland McGrath02203312007-06-11 22:06:31 +00001065
1066 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001067 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001068 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001069
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001070 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001071
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001072 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001073 if (!use_seize) {
1074 /* child did PTRACE_TRACEME, nothing to do in parent */
1075 } else {
1076 if (!strace_vforked) {
1077 /* Wait until child stopped itself */
1078 int status;
1079 while (waitpid(pid, &status, WSTOPPED) < 0) {
1080 if (errno == EINTR)
1081 continue;
1082 perror_msg_and_die("waitpid");
1083 }
1084 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001085 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001086 perror_msg_and_die("Unexpected wait status %x", status);
1087 }
1088 }
1089 /* Else: vforked case, we have no way to sync.
1090 * Just attach to it as soon as possible.
1091 * This means that we may miss a few first syscalls...
1092 */
1093
1094 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001095 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001096 perror_msg_and_die("Can't attach to %d", pid);
1097 }
1098 if (!strace_vforked)
1099 kill(pid, SIGCONT);
1100 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001101 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001102 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001103 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001104 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001105 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001106 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001107 }
1108 else {
1109 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1110 strace_tracer_pid = getpid();
1111 /* The tracee is our parent: */
1112 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001113 alloctcb(pid);
1114 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001115 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001116 }
Roland McGrath02203312007-06-11 22:06:31 +00001117}
1118
Wang Chaob13c0de2010-11-12 17:25:19 +08001119/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001120 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001121 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001122 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001123 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001124static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001125test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001126{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001127 int pid, expected_grandchild = 0, found_grandchild = 0;
1128 const unsigned int test_options = PTRACE_O_TRACECLONE |
1129 PTRACE_O_TRACEFORK |
1130 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001131
Denys Vlasenko5d645812011-08-20 12:48:18 +02001132 pid = fork();
1133 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001134 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001135 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001136 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001137 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001138 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1139 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001140 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001141 if (fork() < 0)
1142 perror_msg_and_die("fork");
1143 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001144 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001145
1146 while (1) {
1147 int status, tracee_pid;
1148
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001149 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001150 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001151 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001152 if (errno == EINTR)
1153 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001154 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001155 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001156 kill_save_errno(pid, SIGKILL);
1157 perror_msg_and_die("%s: unexpected wait result %d",
1158 __func__, tracee_pid);
1159 }
1160 if (WIFEXITED(status)) {
1161 if (WEXITSTATUS(status)) {
1162 if (tracee_pid != pid)
1163 kill_save_errno(pid, SIGKILL);
1164 error_msg_and_die("%s: unexpected exit status %u",
1165 __func__, WEXITSTATUS(status));
1166 }
1167 continue;
1168 }
1169 if (WIFSIGNALED(status)) {
1170 if (tracee_pid != pid)
1171 kill_save_errno(pid, SIGKILL);
1172 error_msg_and_die("%s: unexpected signal %u",
1173 __func__, WTERMSIG(status));
1174 }
1175 if (!WIFSTOPPED(status)) {
1176 if (tracee_pid != pid)
1177 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001178 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001179 error_msg_and_die("%s: unexpected wait status %x",
1180 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001181 }
1182 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001183 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001184 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1185 kill_save_errno(tracee_pid, SIGKILL);
1186 kill_save_errno(pid, SIGKILL);
1187 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001188 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001189 continue;
1190 }
1191 switch (WSTOPSIG(status)) {
1192 case SIGSTOP:
1193 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1194 && errno != EINVAL && errno != EIO)
1195 perror_msg("PTRACE_SETOPTIONS");
1196 break;
1197 case SIGTRAP:
1198 if (status >> 16 == PTRACE_EVENT_FORK) {
1199 long msg = 0;
1200
1201 if (ptrace(PTRACE_GETEVENTMSG, pid,
1202 NULL, (long) &msg) == 0)
1203 expected_grandchild = msg;
1204 }
1205 break;
1206 }
1207 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1208 kill_save_errno(pid, SIGKILL);
1209 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001210 }
1211 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001212 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001213 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001214 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001215 fprintf(stderr, "ptrace_setoptions = %#x\n",
1216 ptrace_setoptions);
1217 return;
1218 }
1219 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1220 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001221}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001222
1223/*
1224 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1225 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1226 * and then see whether it will stop with (SIGTRAP | 0x80).
1227 *
1228 * Use of this option enables correct handling of user-generated SIGTRAPs,
1229 * and SIGTRAPs generated by special instructions such as int3 on x86:
1230 * _start: .globl _start
1231 * int3
1232 * movl $42, %ebx
1233 * movl $1, %eax
1234 * int $0x80
1235 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1236 */
1237static void
1238test_ptrace_setoptions_for_all(void)
1239{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001240 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1241 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001242 int pid;
1243 int it_worked = 0;
1244
1245 pid = fork();
1246 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001247 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001248
1249 if (pid == 0) {
1250 pid = getpid();
1251 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001252 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001253 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1254 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001255 kill(pid, SIGSTOP);
1256 _exit(0); /* parent should see entry into this syscall */
1257 }
1258
1259 while (1) {
1260 int status, tracee_pid;
1261
1262 errno = 0;
1263 tracee_pid = wait(&status);
1264 if (tracee_pid <= 0) {
1265 if (errno == EINTR)
1266 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001267 kill_save_errno(pid, SIGKILL);
1268 perror_msg_and_die("%s: unexpected wait result %d",
1269 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001270 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001271 if (WIFEXITED(status)) {
1272 if (WEXITSTATUS(status) == 0)
1273 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001274 error_msg_and_die("%s: unexpected exit status %u",
1275 __func__, WEXITSTATUS(status));
1276 }
1277 if (WIFSIGNALED(status)) {
1278 error_msg_and_die("%s: unexpected signal %u",
1279 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001280 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001281 if (!WIFSTOPPED(status)) {
1282 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001283 error_msg_and_die("%s: unexpected wait status %x",
1284 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001285 }
1286 if (WSTOPSIG(status) == SIGSTOP) {
1287 /*
1288 * We don't check "options aren't accepted" error.
1289 * If it happens, we'll never get (SIGTRAP | 0x80),
1290 * and thus will decide to not use the option.
1291 * IOW: the outcome of the test will be correct.
1292 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001293 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1294 && errno != EINVAL && errno != EIO)
1295 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001296 }
1297 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1298 it_worked = 1;
1299 }
1300 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001301 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001302 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001303 }
1304 }
1305
1306 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001307 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001308 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001309 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001310 fprintf(stderr, "ptrace_setoptions = %#x\n",
1311 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001312 return;
1313 }
1314
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001315 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1316 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001317}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001318
1319# ifdef USE_SEIZE
1320static void
1321test_ptrace_seize(void)
1322{
1323 int pid;
1324
1325 pid = fork();
1326 if (pid < 0)
1327 perror_msg_and_die("fork");
1328
1329 if (pid == 0) {
1330 pause();
1331 _exit(0);
1332 }
1333
1334 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1335 * attaching tracee continues to run unless a trap condition occurs.
1336 * PTRACE_SEIZE doesn't affect signal or group stop state.
1337 */
1338 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1339 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001340 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001341 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1342 }
1343
1344 kill(pid, SIGKILL);
1345
1346 while (1) {
1347 int status, tracee_pid;
1348
1349 errno = 0;
1350 tracee_pid = waitpid(pid, &status, 0);
1351 if (tracee_pid <= 0) {
1352 if (errno == EINTR)
1353 continue;
1354 perror_msg_and_die("%s: unexpected wait result %d",
1355 __func__, tracee_pid);
1356 }
1357 if (WIFSIGNALED(status)) {
1358 return;
1359 }
1360 error_msg_and_die("%s: unexpected wait status %x",
1361 __func__, status);
1362 }
1363}
1364# else /* !USE_SEIZE */
1365# define test_ptrace_seize() ((void)0)
1366# endif
1367
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001368static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001369get_os_release(void)
1370{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001371 unsigned rel;
1372 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001373 struct utsname u;
1374 if (uname(&u) < 0)
1375 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001376 /* u.release has this form: "3.2.9[-some-garbage]" */
1377 rel = 0;
1378 p = u.release;
1379 for (;;) {
1380 if (!(*p >= '0' && *p <= '9'))
1381 error_msg_and_die("Bad OS release string: '%s'", u.release);
1382 /* Note: this open-codes KERNEL_VERSION(): */
1383 rel = (rel << 8) | atoi(p);
1384 if (rel >= KERNEL_VERSION(1,0,0))
1385 break;
1386 while (*p >= '0' && *p <= '9')
1387 p++;
1388 if (*p != '.')
1389 error_msg_and_die("Bad OS release string: '%s'", u.release);
1390 p++;
1391 }
1392 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001393}
1394
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001395/*
1396 * Initialization part of main() was eating much stack (~0.5k),
1397 * which was unused after init.
1398 * We can reuse it if we move init code into a separate function.
1399 *
1400 * Don't want main() to inline us and defeat the reason
1401 * we have a separate function.
1402 */
1403static void __attribute__ ((noinline))
1404init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001407 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001408 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001409 struct sigaction sa;
1410
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001411 progname = argv[0] ? argv[0] : "strace";
1412
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001413 /* Make sure SIGCHLD has the default action so that waitpid
1414 definitely works without losing track of children. The user
1415 should not have given us a bogus state to inherit, but he might
1416 have. Arguably we should detect SIG_IGN here and pass it on
1417 to children, but probably noone really needs that. */
1418 signal(SIGCHLD, SIG_DFL);
1419
Denys Vlasenko75422762011-05-27 14:36:01 +02001420 strace_tracer_pid = getpid();
1421
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001422 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001423
Roland McGrathee9d4352002-12-18 04:16:10 +00001424 /* Allocate the initial tcbtab. */
1425 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001426 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001427 if (!tcbtab)
1428 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001429 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001430 if (!tcp)
1431 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001432 for (c = 0; c < tcbtabsize; c++)
1433 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001434
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001436 set_sortby(DEFAULT_SORTBY);
1437 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438 qualify("trace=all");
1439 qualify("abbrev=all");
1440 qualify("verbose=all");
1441 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001443 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001444 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001445 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001447 case 'b':
1448 detach_on_execve = 1;
1449 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001451 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001452 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001453 }
1454 cflag = CFLAG_ONLY_STATS;
1455 break;
1456 case 'C':
1457 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001458 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001459 }
1460 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 break;
1462 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001463 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001464 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001465 case 'D':
1466 daemonized_tracer = 1;
1467 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001468 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001469 optF = 1;
1470 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 case 'f':
1472 followfork++;
1473 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001474 case 'h':
1475 usage(stdout, 0);
1476 break;
1477 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001478 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479 break;
1480 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001481 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 break;
1483 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001484 rflag = 1;
1485 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001486 case 't':
1487 tflag++;
1488 break;
1489 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001490 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 break;
1492 case 'x':
1493 xflag++;
1494 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001495 case 'y':
1496 show_fd_path = 1;
1497 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498 case 'v':
1499 qualify("abbrev=none");
1500 break;
1501 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001502 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 exit(0);
1504 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001505 case 'z':
1506 not_failing_only = 1;
1507 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001508 case 'a':
1509 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001510 if (acolumn < 0)
1511 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 break;
1513 case 'e':
1514 qualify(optarg);
1515 break;
1516 case 'o':
1517 outfname = strdup(optarg);
1518 break;
1519 case 'O':
1520 set_overhead(atoi(optarg));
1521 break;
1522 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001523 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001525 case 'P':
1526 tracing_paths = 1;
1527 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001528 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001529 }
1530 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531 case 's':
1532 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001533 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001534 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001535 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 break;
1537 case 'S':
1538 set_sortby(optarg);
1539 break;
1540 case 'u':
1541 username = strdup(optarg);
1542 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001543 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001544 if (putenv(optarg) < 0)
1545 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001546 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001547 case 'I':
1548 opt_intr = atoi(optarg);
1549 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1550 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1551 }
1552 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553 default:
1554 usage(stderr, 1);
1555 break;
1556 }
1557 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001558 argv += optind;
1559 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001560
Denys Vlasenko102ec492011-08-25 01:27:59 +02001561 acolumn_spaces = malloc(acolumn + 1);
1562 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001563 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001564 memset(acolumn_spaces, ' ', acolumn);
1565 acolumn_spaces[acolumn] = '\0';
1566
Denys Vlasenko837399a2012-01-24 11:37:03 +01001567 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001568 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001569 usage(stderr, 1);
1570
Denys Vlasenkofd883382012-03-09 13:03:41 +01001571 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001572 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001573 }
1574
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001575 if (!followfork)
1576 followfork = optF;
1577
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001578 if (followfork >= 2 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001579 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001580 }
1581
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 /* See if they want to run as another user. */
1583 if (username != NULL) {
1584 struct passwd *pent;
1585
1586 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001587 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001589 pent = getpwnam(username);
1590 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001591 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592 }
1593 run_uid = pent->pw_uid;
1594 run_gid = pent->pw_gid;
1595 }
1596 else {
1597 run_uid = getuid();
1598 run_gid = getgid();
1599 }
1600
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001601 if (followfork)
1602 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001603 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001604 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001605
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001606 /* Check if they want to redirect the output. */
1607 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001608 /* See if they want to pipe the output. */
1609 if (outfname[0] == '|' || outfname[0] == '!') {
1610 /*
1611 * We can't do the <outfname>.PID funny business
1612 * when using popen, so prohibit it.
1613 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001614 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001615 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1616 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001617 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001618 else if (followfork < 2)
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001619 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001620 } else {
1621 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001622 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001623 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624 }
1625
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001626 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001627 char *buf = malloc(BUFSIZ);
1628 if (!buf)
1629 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001631 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001632 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001633 if (!opt_intr)
1634 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001636 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001637 if (!opt_intr)
1638 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001639
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001640 /* argv[0] -pPID -oFILE Default interactive setting
1641 * yes 0 0 INTR_WHILE_WAIT
1642 * no 1 0 INTR_WHILE_WAIT
1643 * yes 0 1 INTR_NEVER
1644 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001645 */
1646
1647 /* STARTUP_CHILD must be called before the signal handlers get
1648 installed below as they are inherited into the spawned process.
1649 Also we do not need to be protected by them as during interruption
1650 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001651 if (argv[0]) {
1652 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001653 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001654 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656 sigemptyset(&empty_set);
1657 sigemptyset(&blocked_set);
1658 sa.sa_handler = SIG_IGN;
1659 sigemptyset(&sa.sa_mask);
1660 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001661 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1662 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1663 if (opt_intr != INTR_ANYWHERE) {
1664 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1665 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1666 /*
1667 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1668 * fatal signals are blocked while syscall stop is processed,
1669 * and acted on in between, when waiting for new syscall stops.
1670 * In non-interactive mode, signals are ignored.
1671 */
1672 if (opt_intr == INTR_WHILE_WAIT) {
1673 sigaddset(&blocked_set, SIGHUP);
1674 sigaddset(&blocked_set, SIGINT);
1675 sigaddset(&blocked_set, SIGQUIT);
1676 sigaddset(&blocked_set, SIGPIPE);
1677 sigaddset(&blocked_set, SIGTERM);
1678 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001679 }
1680 /* SIG_IGN, or set handler for these */
1681 sigaction(SIGHUP, &sa, NULL);
1682 sigaction(SIGINT, &sa, NULL);
1683 sigaction(SIGQUIT, &sa, NULL);
1684 sigaction(SIGPIPE, &sa, NULL);
1685 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001687 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001688 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001689
Denys Vlasenkofd883382012-03-09 13:03:41 +01001690 /* Do we want pids printed in our -o OUTFILE?
1691 * -ff: no (every pid has its own file); or
1692 * -f: yes (there can be more pids in the future); or
1693 * -p PID1,PID2: yes (there are already more than one pid)
1694 */
1695 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696}
1697
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001698static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001699pid2tcb(int pid)
1700{
1701 int i;
1702
1703 if (pid <= 0)
1704 return NULL;
1705
1706 for (i = 0; i < tcbtabsize; i++) {
1707 struct tcb *tcp = tcbtab[i];
1708 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1709 return tcp;
1710 }
1711
1712 return NULL;
1713}
1714
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001716cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717{
1718 int i;
1719 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001720 int fatal_sig;
1721
1722 /* 'interrupted' is a volatile object, fetch it only once */
1723 fatal_sig = interrupted;
1724 if (!fatal_sig)
1725 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001726
Roland McGrathee9d4352002-12-18 04:16:10 +00001727 for (i = 0; i < tcbtabsize; i++) {
1728 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729 if (!(tcp->flags & TCB_INUSE))
1730 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001731 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 fprintf(stderr,
1733 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001734 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001736 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001738 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 }
1740 if (cflag)
1741 call_summary(outf);
1742}
1743
1744static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001745interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001747 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748}
1749
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001751trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001754 struct rusage *rup = cflag ? &ru : NULL;
1755# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001756 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001757# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
Roland McGratheb9e2e82009-06-02 16:49:22 -07001759 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001760 int pid;
1761 int wait_errno;
1762 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001763 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001764 struct tcb *tcp;
1765 unsigned event;
1766
Denys Vlasenko222713a2009-03-17 14:29:59 +00001767 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001768 return 0;
1769 if (interactive)
1770 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001771# ifdef __WALL
1772 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001773 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001774 /* this kernel does not support __WALL */
1775 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001776 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001777 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001778 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001779 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001780 pid = wait4(-1, &status, __WCLONE, rup);
1781 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001782 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001783 }
1784 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001785# else
1786 pid = wait4(-1, &status, 0, rup);
1787# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001789 if (interactive)
1790 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001792 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001793 switch (wait_errno) {
1794 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001796 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 /*
1798 * We would like to verify this case
1799 * but sometimes a race in Solbourne's
1800 * version of SunOS sometimes reports
1801 * ECHILD before sending us SIGCHILD.
1802 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001803 return 0;
1804 default:
1805 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001806 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001807 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 }
1809 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001810 if (pid == popen_pid) {
1811 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001812 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001813 continue;
1814 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001815
1816 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001817 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001818 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001819 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001820 strcpy(buf, "???");
1821 if (WIFSIGNALED(status))
1822#ifdef WCOREDUMP
1823 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1824 WCOREDUMP(status) ? "core," : "",
1825 signame(WTERMSIG(status)));
1826#else
1827 sprintf(buf, "WIFSIGNALED,sig=%s",
1828 signame(WTERMSIG(status)));
1829#endif
1830 if (WIFEXITED(status))
1831 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1832 if (WIFSTOPPED(status))
1833 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001834#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001835 if (WIFCONTINUED(status))
1836 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001837#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001838 evbuf[0] = '\0';
1839 if (event != 0) {
1840 static const char *const event_names[] = {
1841 [PTRACE_EVENT_CLONE] = "CLONE",
1842 [PTRACE_EVENT_FORK] = "FORK",
1843 [PTRACE_EVENT_VFORK] = "VFORK",
1844 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1845 [PTRACE_EVENT_EXEC] = "EXEC",
1846 [PTRACE_EVENT_EXIT] = "EXIT",
1847 };
1848 const char *e;
1849 if (event < ARRAY_SIZE(event_names))
1850 e = event_names[event];
1851 else {
1852 sprintf(buf, "?? (%u)", event);
1853 e = buf;
1854 }
1855 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1856 }
1857 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001858 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001860 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001861 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001862
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001863 /* Under Linux, execve changes pid to thread leader's pid,
1864 * and we see this changed pid on EVENT_EXEC and later,
1865 * execve sysexit. Leader "disappears" without exit
1866 * notification. Let user know that, drop leader's tcb,
1867 * and fix up pid in execve thread's tcb.
1868 * Effectively, execve thread's tcb replaces leader's tcb.
1869 *
1870 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1871 * on exit syscall) in multithreaded programs exactly
1872 * in order to handle this case.
1873 *
1874 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1875 * On 2.6 and earlier, it can return garbage.
1876 */
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001877 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001878 long old_pid = 0;
1879 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1880 && old_pid > 0
1881 && old_pid != pid
1882 ) {
1883 struct tcb *execve_thread = pid2tcb(old_pid);
1884 if (tcp) {
1885 outf = tcp->outf;
1886 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001887 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001888 if (execve_thread->curcol != 0) {
1889 /*
1890 * One case we are here is -ff:
1891 * try "strace -oLOG -ff test/threaded_execve"
1892 */
1893 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1894 execve_thread->curcol = 0;
1895 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001896 /* swap output FILEs (needed for -ff) */
1897 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001898 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001899 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001900 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001901 }
1902 droptcb(tcp);
1903 }
1904 tcp = execve_thread;
1905 if (tcp) {
1906 tcp->pid = pid;
1907 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001908 if (!cflag) {
1909 printleader(tcp);
1910 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1911 line_ended();
1912 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001913 }
1914 }
1915 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001916
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001917 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1918 if (!skip_startup_execve)
1919 detach(tcp);
1920 /* This was initial execve for "strace PROG". Skip. */
1921 skip_startup_execve = 0;
1922 }
1923
Denys Vlasenko5d645812011-08-20 12:48:18 +02001924 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001925 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001926 /* This is needed to go with the CLONE_PTRACE
1927 changes in process.c/util.c: we might see
1928 the child's initial trap before we see the
1929 parent return from the clone syscall.
1930 Leave the child suspended until the parent
1931 returns from its system call. Only then
1932 will we have the association of parent and
1933 child so that we know how to do clearbpt
1934 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001935 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001936 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001937 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001938 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001939 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001940 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001941 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001942 else
1943 /* This can happen if a clone call used
1944 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001945 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001946 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001947 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001948 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001949 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001951
1952 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001953 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001954 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001955
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001956 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1958 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001960
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001962 if (pid == strace_child)
1963 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001964 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1966 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001967#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001968 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001969 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001970 WCOREDUMP(status) ? "(core dumped) " : "");
1971#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001972 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001973 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001974#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001975 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976 }
1977 droptcb(tcp);
1978 continue;
1979 }
1980 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001981 if (pid == strace_child)
1982 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001983 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1984 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001985 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001986 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001987 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001988 droptcb(tcp);
1989 continue;
1990 }
1991 if (!WIFSTOPPED(status)) {
1992 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1993 droptcb(tcp);
1994 continue;
1995 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001996
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001997 /* Is this the very first time we see this tracee stopped? */
1998 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001999 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002000 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002002 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002003 /*
2004 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002005 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002006 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002007 if (clearbpt(tcp) < 0) {
2008 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 droptcb(tcp);
2010 cleanup();
2011 return -1;
2012 }
2013 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002014 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002015 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002016 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2017 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2018 if (errno != ESRCH) {
2019 /* Should never happen, really */
2020 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002021 }
2022 }
2023 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002024 }
2025
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002026 sig = WSTOPSIG(status);
2027
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002028 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002029 /* Ptrace event */
2030#ifdef USE_SEIZE
2031 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002032 /*
2033 * PTRACE_INTERRUPT-stop or group-stop.
2034 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2035 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002036 if (sig == SIGSTOP
2037 || sig == SIGTSTP
2038 || sig == SIGTTIN
2039 || sig == SIGTTOU
2040 ) {
2041 stopped = 1;
2042 goto show_stopsig;
2043 }
2044 }
2045#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002046 goto restart_tracee_with_sig_0;
2047 }
2048
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002049 /* Is this post-attach SIGSTOP?
2050 * Interestingly, the process may stop
2051 * with STOPSIG equal to some other signal
2052 * than SIGSTOP if we happend to attach
2053 * just before the process takes a signal.
2054 */
2055 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002056 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002057 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2058 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002059 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002060 }
2061
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002062 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002063 siginfo_t si;
2064
2065 /* Nonzero (true) if tracee is stopped by signal
2066 * (as opposed to "tracee received signal").
2067 */
2068 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002069#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002070 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002071#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002072 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002073 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002074#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002075 long pc = 0;
2076 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002077
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002078 upeek(tcp, PT_CR_IPSR, &psr);
2079 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002080
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002081# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002082 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002083# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002084# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002085#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002086# define PC_FORMAT_STR ""
2087# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002088#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002089 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002090 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002091 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002092 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002093 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002094 PC_FORMAT_ARG);
2095 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002096 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002097 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002098 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002099 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002101
2102 if (!stopped)
2103 /* It's signal-delivery-stop. Inject the signal */
2104 goto restart_tracee;
2105
2106 /* It's group-stop */
2107#ifdef USE_SEIZE
2108 if (use_seize) {
2109 /*
2110 * This ends ptrace-stop, but does *not* end group-stop.
2111 * This makes stopping signals work properly on straced process
2112 * (that is, process really stops. It used to continue to run).
2113 */
2114 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2115 cleanup();
2116 return -1;
2117 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002118 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002119 continue;
2120 }
2121 /* We don't have PTRACE_LISTEN support... */
2122#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002123 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002124 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002125
2126 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002127 if (interrupted)
2128 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002129
2130 /* This should be syscall entry or exit.
2131 * (Or it still can be that pesky post-execve SIGTRAP!)
2132 * Handle it.
2133 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002134 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2135 /* ptrace() failed in trace_syscall() with ESRCH.
2136 * Likely a result of process disappearing mid-flight.
2137 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002138 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002139 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002140 * We used to detach(tcp) here, but since we no longer
2141 * implement "detach before death" policy/hack,
2142 * we can let this process to report its death to us
2143 * normally, via WIFEXITED or WIFSIGNALED wait status.
2144 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002145 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 continue;
2147 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002148 restart_tracee_with_sig_0:
2149 sig = 0;
2150 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002151 /* Remember current print column before continuing. */
2152 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002153 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002154 cleanup();
2155 return -1;
2156 }
2157 }
2158 return 0;
2159}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002160
2161int
2162main(int argc, char *argv[])
2163{
2164 init(argc, argv);
2165
2166 /* Run main tracing loop */
2167 if (trace() < 0)
2168 return 1;
2169
2170 cleanup();
2171 fflush(NULL);
2172 if (exit_code > 0xff) {
2173 /* Avoid potential core file clobbering. */
2174 struct rlimit rlim = {0, 0};
2175 setrlimit(RLIMIT_CORE, &rlim);
2176
2177 /* Child was killed by a signal, mimic that. */
2178 exit_code &= 0xff;
2179 signal(exit_code, SIG_DFL);
2180 raise(exit_code);
2181 /* Paranoia - what if this signal is not fatal?
2182 Exit with 128 + signo then. */
2183 exit_code += 128;
2184 }
2185
2186 return exit_code;
2187}