blob: 17ee74960012555681874e8f93f0d5f915758543 [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
Roland McGrath02203312007-06-11 22:06:31 +0000851
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000852 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000853 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000854 DIR *dir;
855
856 sprintf(procdir, "/proc/%d/task", tcp->pid);
857 dir = opendir(procdir);
858 if (dir != NULL) {
859 unsigned int ntid = 0, nerr = 0;
860 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200861
Roland McGrath02203312007-06-11 22:06:31 +0000862 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200863 struct tcb *cur_tcp;
864 int tid;
865
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000866 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000867 continue;
868 tid = atoi(de->d_name);
869 if (tid <= 0)
870 continue;
871 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100872 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000873 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100874 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200875 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200876 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200877 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100878 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200879 fprintf(stderr, "attach to pid %d succeeded\n", tid);
880 cur_tcp = tcp;
881 if (tid != tcp->pid)
882 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100883 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100884 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000885 }
886 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200887 if (interactive) {
888 sigprocmask(SIG_SETMASK, &empty_set, NULL);
889 if (interrupted)
890 goto ret;
891 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
892 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000893 ntid -= nerr;
894 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000895 perror("attach: ptrace(PTRACE_ATTACH, ...)");
896 droptcb(tcp);
897 continue;
898 }
899 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000900 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100901? "Process %u attached with %u threads\n"
902: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200903 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000904 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100905 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200906 /* -p PID, we failed to attach to PID itself
907 * but did attach to some of its sibling threads.
908 * Drop PID's tcp.
909 */
910 droptcb(tcp);
911 }
Roland McGrath02203312007-06-11 22:06:31 +0000912 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000913 } /* if (opendir worked) */
914 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100915 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000916 perror("attach: ptrace(PTRACE_ATTACH, ...)");
917 droptcb(tcp);
918 continue;
919 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100920 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100921 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100922 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200923 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000924
925 if (daemonized_tracer) {
926 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000927 * Make parent go away.
928 * Also makes grandparent's wait() unblock.
929 */
930 kill(getppid(), SIGKILL);
931 }
932
Roland McGrath02203312007-06-11 22:06:31 +0000933 if (!qflag)
934 fprintf(stderr,
935 "Process %u attached - interrupt to quit\n",
936 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200937 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000938
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200939 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000940 if (interactive)
941 sigprocmask(SIG_SETMASK, &empty_set, NULL);
942}
943
944static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200945startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000946{
947 struct stat statbuf;
948 const char *filename;
949 char pathname[MAXPATHLEN];
950 int pid = 0;
951 struct tcb *tcp;
952
953 filename = argv[0];
954 if (strchr(filename, '/')) {
955 if (strlen(filename) > sizeof pathname - 1) {
956 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200957 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000958 }
959 strcpy(pathname, filename);
960 }
961#ifdef USE_DEBUGGING_EXEC
962 /*
963 * Debuggers customarily check the current directory
964 * first regardless of the path but doing that gives
965 * security geeks a panic attack.
966 */
967 else if (stat(filename, &statbuf) == 0)
968 strcpy(pathname, filename);
969#endif /* USE_DEBUGGING_EXEC */
970 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000971 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000972 int m, n, len;
973
974 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100975 const char *colon = strchr(path, ':');
976 if (colon) {
977 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000978 m = n + 1;
979 }
980 else
981 m = n = strlen(path);
982 if (n == 0) {
983 if (!getcwd(pathname, MAXPATHLEN))
984 continue;
985 len = strlen(pathname);
986 }
987 else if (n > sizeof pathname - 1)
988 continue;
989 else {
990 strncpy(pathname, path, n);
991 len = n;
992 }
993 if (len && pathname[len - 1] != '/')
994 pathname[len++] = '/';
995 strcpy(pathname + len, filename);
996 if (stat(pathname, &statbuf) == 0 &&
997 /* Accept only regular files
998 with some execute bits set.
999 XXX not perfect, might still fail */
1000 S_ISREG(statbuf.st_mode) &&
1001 (statbuf.st_mode & 0111))
1002 break;
1003 }
1004 }
1005 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001006 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001007 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001008 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001009 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001010 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001011 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001012 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1013 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001014 ) {
1015 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001016 if (outf != stderr)
1017 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001018 if (!daemonized_tracer && !use_seize) {
1019 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001020 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001021 }
Roland McGrath02203312007-06-11 22:06:31 +00001022 }
Roland McGrath02203312007-06-11 22:06:31 +00001023
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001024 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001025 uid_t run_euid = run_uid;
1026 gid_t run_egid = run_gid;
1027
1028 if (statbuf.st_mode & S_ISUID)
1029 run_euid = statbuf.st_uid;
1030 if (statbuf.st_mode & S_ISGID)
1031 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001032 /*
1033 * It is important to set groups before we
1034 * lose privileges on setuid.
1035 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001036 if (initgroups(username, run_gid) < 0) {
1037 perror_msg_and_die("initgroups");
1038 }
1039 if (setregid(run_gid, run_egid) < 0) {
1040 perror_msg_and_die("setregid");
1041 }
1042 if (setreuid(run_uid, run_euid) < 0) {
1043 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001044 }
1045 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001046 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001047 setreuid(run_uid, run_uid);
1048
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001049 if (!daemonized_tracer) {
1050 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001051 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001052 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001053 * the immediately following execve syscall.
1054 * Can't do this on NOMMU systems, we are after
1055 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001056 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001057 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001058 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001059 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001060 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001061 /* we depend on SIGCHLD set to SIG_DFL by init code */
1062 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001063 wait(NULL);
1064 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001065 }
Roland McGrath02203312007-06-11 22:06:31 +00001066
1067 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001068 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001069 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001070
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001071 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001072
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001073 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001074 if (!use_seize) {
1075 /* child did PTRACE_TRACEME, nothing to do in parent */
1076 } else {
1077 if (!strace_vforked) {
1078 /* Wait until child stopped itself */
1079 int status;
1080 while (waitpid(pid, &status, WSTOPPED) < 0) {
1081 if (errno == EINTR)
1082 continue;
1083 perror_msg_and_die("waitpid");
1084 }
1085 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001086 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001087 perror_msg_and_die("Unexpected wait status %x", status);
1088 }
1089 }
1090 /* Else: vforked case, we have no way to sync.
1091 * Just attach to it as soon as possible.
1092 * This means that we may miss a few first syscalls...
1093 */
1094
1095 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001096 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001097 perror_msg_and_die("Can't attach to %d", pid);
1098 }
1099 if (!strace_vforked)
1100 kill(pid, SIGCONT);
1101 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001102 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001103 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001104 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001105 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001106 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001107 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001108 }
1109 else {
1110 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1111 strace_tracer_pid = getpid();
1112 /* The tracee is our parent: */
1113 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001114 alloctcb(pid);
1115 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001116 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001117 }
Roland McGrath02203312007-06-11 22:06:31 +00001118}
1119
Wang Chaob13c0de2010-11-12 17:25:19 +08001120/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001121 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001122 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001123 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001124 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001125static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001126test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001127{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001128 int pid, expected_grandchild = 0, found_grandchild = 0;
1129 const unsigned int test_options = PTRACE_O_TRACECLONE |
1130 PTRACE_O_TRACEFORK |
1131 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001132
Denys Vlasenko5d645812011-08-20 12:48:18 +02001133 pid = fork();
1134 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001135 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001136 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001137 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001138 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001139 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1140 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001141 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001142 if (fork() < 0)
1143 perror_msg_and_die("fork");
1144 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001145 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001146
1147 while (1) {
1148 int status, tracee_pid;
1149
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001150 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001151 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001152 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001153 if (errno == EINTR)
1154 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001155 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001156 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001157 kill_save_errno(pid, SIGKILL);
1158 perror_msg_and_die("%s: unexpected wait result %d",
1159 __func__, tracee_pid);
1160 }
1161 if (WIFEXITED(status)) {
1162 if (WEXITSTATUS(status)) {
1163 if (tracee_pid != pid)
1164 kill_save_errno(pid, SIGKILL);
1165 error_msg_and_die("%s: unexpected exit status %u",
1166 __func__, WEXITSTATUS(status));
1167 }
1168 continue;
1169 }
1170 if (WIFSIGNALED(status)) {
1171 if (tracee_pid != pid)
1172 kill_save_errno(pid, SIGKILL);
1173 error_msg_and_die("%s: unexpected signal %u",
1174 __func__, WTERMSIG(status));
1175 }
1176 if (!WIFSTOPPED(status)) {
1177 if (tracee_pid != pid)
1178 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001179 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001180 error_msg_and_die("%s: unexpected wait status %x",
1181 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001182 }
1183 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001184 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001185 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1186 kill_save_errno(tracee_pid, SIGKILL);
1187 kill_save_errno(pid, SIGKILL);
1188 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001189 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001190 continue;
1191 }
1192 switch (WSTOPSIG(status)) {
1193 case SIGSTOP:
1194 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1195 && errno != EINVAL && errno != EIO)
1196 perror_msg("PTRACE_SETOPTIONS");
1197 break;
1198 case SIGTRAP:
1199 if (status >> 16 == PTRACE_EVENT_FORK) {
1200 long msg = 0;
1201
1202 if (ptrace(PTRACE_GETEVENTMSG, pid,
1203 NULL, (long) &msg) == 0)
1204 expected_grandchild = msg;
1205 }
1206 break;
1207 }
1208 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1209 kill_save_errno(pid, SIGKILL);
1210 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001211 }
1212 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001213 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001214 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001215 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001216 fprintf(stderr, "ptrace_setoptions = %#x\n",
1217 ptrace_setoptions);
1218 return;
1219 }
1220 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1221 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001222}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001223
1224/*
1225 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1226 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1227 * and then see whether it will stop with (SIGTRAP | 0x80).
1228 *
1229 * Use of this option enables correct handling of user-generated SIGTRAPs,
1230 * and SIGTRAPs generated by special instructions such as int3 on x86:
1231 * _start: .globl _start
1232 * int3
1233 * movl $42, %ebx
1234 * movl $1, %eax
1235 * int $0x80
1236 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1237 */
1238static void
1239test_ptrace_setoptions_for_all(void)
1240{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001241 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1242 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001243 int pid;
1244 int it_worked = 0;
1245
1246 pid = fork();
1247 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001248 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001249
1250 if (pid == 0) {
1251 pid = getpid();
1252 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001253 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001254 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1255 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001256 kill(pid, SIGSTOP);
1257 _exit(0); /* parent should see entry into this syscall */
1258 }
1259
1260 while (1) {
1261 int status, tracee_pid;
1262
1263 errno = 0;
1264 tracee_pid = wait(&status);
1265 if (tracee_pid <= 0) {
1266 if (errno == EINTR)
1267 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001268 kill_save_errno(pid, SIGKILL);
1269 perror_msg_and_die("%s: unexpected wait result %d",
1270 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001271 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001272 if (WIFEXITED(status)) {
1273 if (WEXITSTATUS(status) == 0)
1274 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001275 error_msg_and_die("%s: unexpected exit status %u",
1276 __func__, WEXITSTATUS(status));
1277 }
1278 if (WIFSIGNALED(status)) {
1279 error_msg_and_die("%s: unexpected signal %u",
1280 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001281 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001282 if (!WIFSTOPPED(status)) {
1283 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001284 error_msg_and_die("%s: unexpected wait status %x",
1285 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001286 }
1287 if (WSTOPSIG(status) == SIGSTOP) {
1288 /*
1289 * We don't check "options aren't accepted" error.
1290 * If it happens, we'll never get (SIGTRAP | 0x80),
1291 * and thus will decide to not use the option.
1292 * IOW: the outcome of the test will be correct.
1293 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001294 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1295 && errno != EINVAL && errno != EIO)
1296 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001297 }
1298 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1299 it_worked = 1;
1300 }
1301 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001302 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001303 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001304 }
1305 }
1306
1307 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001308 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001309 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001310 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001311 fprintf(stderr, "ptrace_setoptions = %#x\n",
1312 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001313 return;
1314 }
1315
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001316 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1317 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001318}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001319
1320# ifdef USE_SEIZE
1321static void
1322test_ptrace_seize(void)
1323{
1324 int pid;
1325
1326 pid = fork();
1327 if (pid < 0)
1328 perror_msg_and_die("fork");
1329
1330 if (pid == 0) {
1331 pause();
1332 _exit(0);
1333 }
1334
1335 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1336 * attaching tracee continues to run unless a trap condition occurs.
1337 * PTRACE_SEIZE doesn't affect signal or group stop state.
1338 */
1339 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1340 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001341 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001342 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1343 }
1344
1345 kill(pid, SIGKILL);
1346
1347 while (1) {
1348 int status, tracee_pid;
1349
1350 errno = 0;
1351 tracee_pid = waitpid(pid, &status, 0);
1352 if (tracee_pid <= 0) {
1353 if (errno == EINTR)
1354 continue;
1355 perror_msg_and_die("%s: unexpected wait result %d",
1356 __func__, tracee_pid);
1357 }
1358 if (WIFSIGNALED(status)) {
1359 return;
1360 }
1361 error_msg_and_die("%s: unexpected wait status %x",
1362 __func__, status);
1363 }
1364}
1365# else /* !USE_SEIZE */
1366# define test_ptrace_seize() ((void)0)
1367# endif
1368
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001369static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001370get_os_release(void)
1371{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001372 unsigned rel;
1373 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001374 struct utsname u;
1375 if (uname(&u) < 0)
1376 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001377 /* u.release has this form: "3.2.9[-some-garbage]" */
1378 rel = 0;
1379 p = u.release;
1380 for (;;) {
1381 if (!(*p >= '0' && *p <= '9'))
1382 error_msg_and_die("Bad OS release string: '%s'", u.release);
1383 /* Note: this open-codes KERNEL_VERSION(): */
1384 rel = (rel << 8) | atoi(p);
1385 if (rel >= KERNEL_VERSION(1,0,0))
1386 break;
1387 while (*p >= '0' && *p <= '9')
1388 p++;
1389 if (*p != '.')
1390 error_msg_and_die("Bad OS release string: '%s'", u.release);
1391 p++;
1392 }
1393 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001394}
1395
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001396/*
1397 * Initialization part of main() was eating much stack (~0.5k),
1398 * which was unused after init.
1399 * We can reuse it if we move init code into a separate function.
1400 *
1401 * Don't want main() to inline us and defeat the reason
1402 * we have a separate function.
1403 */
1404static void __attribute__ ((noinline))
1405init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001408 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001409 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410 struct sigaction sa;
1411
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001412 progname = argv[0] ? argv[0] : "strace";
1413
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001414 /* Make sure SIGCHLD has the default action so that waitpid
1415 definitely works without losing track of children. The user
1416 should not have given us a bogus state to inherit, but he might
1417 have. Arguably we should detect SIG_IGN here and pass it on
1418 to children, but probably noone really needs that. */
1419 signal(SIGCHLD, SIG_DFL);
1420
Denys Vlasenko75422762011-05-27 14:36:01 +02001421 strace_tracer_pid = getpid();
1422
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001423 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001424
Roland McGrathee9d4352002-12-18 04:16:10 +00001425 /* Allocate the initial tcbtab. */
1426 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001427 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001428 if (!tcbtab)
1429 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001430 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001431 if (!tcp)
1432 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001433 for (c = 0; c < tcbtabsize; c++)
1434 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001435
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001437 set_sortby(DEFAULT_SORTBY);
1438 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439 qualify("trace=all");
1440 qualify("abbrev=all");
1441 qualify("verbose=all");
1442 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001444 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001445 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001446 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001448 case 'b':
1449 detach_on_execve = 1;
1450 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001452 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001453 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001454 }
1455 cflag = CFLAG_ONLY_STATS;
1456 break;
1457 case 'C':
1458 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001459 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001460 }
1461 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462 break;
1463 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001464 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001465 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001466 case 'D':
1467 daemonized_tracer = 1;
1468 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001469 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001470 optF = 1;
1471 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001472 case 'f':
1473 followfork++;
1474 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475 case 'h':
1476 usage(stdout, 0);
1477 break;
1478 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001479 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480 break;
1481 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001482 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 break;
1484 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001485 rflag = 1;
1486 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 case 't':
1488 tflag++;
1489 break;
1490 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001491 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 break;
1493 case 'x':
1494 xflag++;
1495 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001496 case 'y':
1497 show_fd_path = 1;
1498 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 case 'v':
1500 qualify("abbrev=none");
1501 break;
1502 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001503 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 exit(0);
1505 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001506 case 'z':
1507 not_failing_only = 1;
1508 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 case 'a':
1510 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001511 if (acolumn < 0)
1512 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 break;
1514 case 'e':
1515 qualify(optarg);
1516 break;
1517 case 'o':
1518 outfname = strdup(optarg);
1519 break;
1520 case 'O':
1521 set_overhead(atoi(optarg));
1522 break;
1523 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001524 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001526 case 'P':
1527 tracing_paths = 1;
1528 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001529 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001530 }
1531 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532 case 's':
1533 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001534 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001535 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001536 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537 break;
1538 case 'S':
1539 set_sortby(optarg);
1540 break;
1541 case 'u':
1542 username = strdup(optarg);
1543 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001544 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001545 if (putenv(optarg) < 0)
1546 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001547 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001548 case 'I':
1549 opt_intr = atoi(optarg);
1550 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1551 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1552 }
1553 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554 default:
1555 usage(stderr, 1);
1556 break;
1557 }
1558 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001559 argv += optind;
1560 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561
Denys Vlasenko102ec492011-08-25 01:27:59 +02001562 acolumn_spaces = malloc(acolumn + 1);
1563 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001564 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001565 memset(acolumn_spaces, ' ', acolumn);
1566 acolumn_spaces[acolumn] = '\0';
1567
Denys Vlasenko837399a2012-01-24 11:37:03 +01001568 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001569 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001570 usage(stderr, 1);
1571
Denys Vlasenkofd883382012-03-09 13:03:41 +01001572 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001573 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001574 }
1575
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001576 if (!followfork)
1577 followfork = optF;
1578
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001579 if (followfork >= 2 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001580 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001581 }
1582
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583 /* See if they want to run as another user. */
1584 if (username != NULL) {
1585 struct passwd *pent;
1586
1587 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001588 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001590 pent = getpwnam(username);
1591 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001592 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593 }
1594 run_uid = pent->pw_uid;
1595 run_gid = pent->pw_gid;
1596 }
1597 else {
1598 run_uid = getuid();
1599 run_gid = getgid();
1600 }
1601
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001602 if (followfork)
1603 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001604 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001605 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001606
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607 /* Check if they want to redirect the output. */
1608 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001609 /* See if they want to pipe the output. */
1610 if (outfname[0] == '|' || outfname[0] == '!') {
1611 /*
1612 * We can't do the <outfname>.PID funny business
1613 * when using popen, so prohibit it.
1614 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001615 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001616 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1617 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001618 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001619 else if (followfork < 2)
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001620 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001621 } else {
1622 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001623 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001624 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625 }
1626
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001627 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001628 char *buf = malloc(BUFSIZ);
1629 if (!buf)
1630 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001632 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001633 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001634 if (!opt_intr)
1635 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001637 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001638 if (!opt_intr)
1639 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001640
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001641 /* argv[0] -pPID -oFILE Default interactive setting
1642 * yes 0 0 INTR_WHILE_WAIT
1643 * no 1 0 INTR_WHILE_WAIT
1644 * yes 0 1 INTR_NEVER
1645 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001646 */
1647
1648 /* STARTUP_CHILD must be called before the signal handlers get
1649 installed below as they are inherited into the spawned process.
1650 Also we do not need to be protected by them as during interruption
1651 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001652 if (argv[0]) {
1653 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001654 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001655 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657 sigemptyset(&empty_set);
1658 sigemptyset(&blocked_set);
1659 sa.sa_handler = SIG_IGN;
1660 sigemptyset(&sa.sa_mask);
1661 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001662 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1663 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1664 if (opt_intr != INTR_ANYWHERE) {
1665 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1666 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1667 /*
1668 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1669 * fatal signals are blocked while syscall stop is processed,
1670 * and acted on in between, when waiting for new syscall stops.
1671 * In non-interactive mode, signals are ignored.
1672 */
1673 if (opt_intr == INTR_WHILE_WAIT) {
1674 sigaddset(&blocked_set, SIGHUP);
1675 sigaddset(&blocked_set, SIGINT);
1676 sigaddset(&blocked_set, SIGQUIT);
1677 sigaddset(&blocked_set, SIGPIPE);
1678 sigaddset(&blocked_set, SIGTERM);
1679 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001680 }
1681 /* SIG_IGN, or set handler for these */
1682 sigaction(SIGHUP, &sa, NULL);
1683 sigaction(SIGINT, &sa, NULL);
1684 sigaction(SIGQUIT, &sa, NULL);
1685 sigaction(SIGPIPE, &sa, NULL);
1686 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001688 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001689 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001690
Denys Vlasenkofd883382012-03-09 13:03:41 +01001691 /* Do we want pids printed in our -o OUTFILE?
1692 * -ff: no (every pid has its own file); or
1693 * -f: yes (there can be more pids in the future); or
1694 * -p PID1,PID2: yes (there are already more than one pid)
1695 */
1696 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697}
1698
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001699static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001700pid2tcb(int pid)
1701{
1702 int i;
1703
1704 if (pid <= 0)
1705 return NULL;
1706
1707 for (i = 0; i < tcbtabsize; i++) {
1708 struct tcb *tcp = tcbtab[i];
1709 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1710 return tcp;
1711 }
1712
1713 return NULL;
1714}
1715
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001717cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718{
1719 int i;
1720 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001721 int fatal_sig;
1722
1723 /* 'interrupted' is a volatile object, fetch it only once */
1724 fatal_sig = interrupted;
1725 if (!fatal_sig)
1726 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727
Roland McGrathee9d4352002-12-18 04:16:10 +00001728 for (i = 0; i < tcbtabsize; i++) {
1729 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730 if (!(tcp->flags & TCB_INUSE))
1731 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001732 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001733 fprintf(stderr,
1734 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001735 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001737 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001738 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001739 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001740 }
1741 if (cflag)
1742 call_summary(outf);
1743}
1744
1745static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001746interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001747{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001748 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749}
1750
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001751static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001752trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001755 struct rusage *rup = cflag ? &ru : NULL;
1756# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001757 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001758# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759
Roland McGratheb9e2e82009-06-02 16:49:22 -07001760 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001761 int pid;
1762 int wait_errno;
1763 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001764 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001765 struct tcb *tcp;
1766 unsigned event;
1767
Denys Vlasenko222713a2009-03-17 14:29:59 +00001768 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001769 return 0;
1770 if (interactive)
1771 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001772# ifdef __WALL
1773 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001774 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001775 /* this kernel does not support __WALL */
1776 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001777 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001778 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001779 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001780 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001781 pid = wait4(-1, &status, __WCLONE, rup);
1782 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001783 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001784 }
1785 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001786# else
1787 pid = wait4(-1, &status, 0, rup);
1788# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001790 if (interactive)
1791 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001793 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001794 switch (wait_errno) {
1795 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001797 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798 /*
1799 * We would like to verify this case
1800 * but sometimes a race in Solbourne's
1801 * version of SunOS sometimes reports
1802 * ECHILD before sending us SIGCHILD.
1803 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001804 return 0;
1805 default:
1806 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001807 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001808 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 }
1810 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001811 if (pid == popen_pid) {
1812 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001813 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001814 continue;
1815 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001816
1817 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001818 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001819 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001820 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001821 strcpy(buf, "???");
1822 if (WIFSIGNALED(status))
1823#ifdef WCOREDUMP
1824 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1825 WCOREDUMP(status) ? "core," : "",
1826 signame(WTERMSIG(status)));
1827#else
1828 sprintf(buf, "WIFSIGNALED,sig=%s",
1829 signame(WTERMSIG(status)));
1830#endif
1831 if (WIFEXITED(status))
1832 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1833 if (WIFSTOPPED(status))
1834 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001835#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001836 if (WIFCONTINUED(status))
1837 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001838#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001839 evbuf[0] = '\0';
1840 if (event != 0) {
1841 static const char *const event_names[] = {
1842 [PTRACE_EVENT_CLONE] = "CLONE",
1843 [PTRACE_EVENT_FORK] = "FORK",
1844 [PTRACE_EVENT_VFORK] = "VFORK",
1845 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1846 [PTRACE_EVENT_EXEC] = "EXEC",
1847 [PTRACE_EVENT_EXIT] = "EXIT",
1848 };
1849 const char *e;
1850 if (event < ARRAY_SIZE(event_names))
1851 e = event_names[event];
1852 else {
1853 sprintf(buf, "?? (%u)", event);
1854 e = buf;
1855 }
1856 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1857 }
1858 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001859 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001860
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001861 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001862 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001863
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001864 /* Under Linux, execve changes pid to thread leader's pid,
1865 * and we see this changed pid on EVENT_EXEC and later,
1866 * execve sysexit. Leader "disappears" without exit
1867 * notification. Let user know that, drop leader's tcb,
1868 * and fix up pid in execve thread's tcb.
1869 * Effectively, execve thread's tcb replaces leader's tcb.
1870 *
1871 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1872 * on exit syscall) in multithreaded programs exactly
1873 * in order to handle this case.
1874 *
1875 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1876 * On 2.6 and earlier, it can return garbage.
1877 */
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001878 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001879 long old_pid = 0;
1880 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1881 && old_pid > 0
1882 && old_pid != pid
1883 ) {
1884 struct tcb *execve_thread = pid2tcb(old_pid);
1885 if (tcp) {
1886 outf = tcp->outf;
1887 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001888 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001889 if (execve_thread->curcol != 0) {
1890 /*
1891 * One case we are here is -ff:
1892 * try "strace -oLOG -ff test/threaded_execve"
1893 */
1894 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1895 execve_thread->curcol = 0;
1896 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001897 /* swap output FILEs (needed for -ff) */
1898 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001899 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001900 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001901 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001902 }
1903 droptcb(tcp);
1904 }
1905 tcp = execve_thread;
1906 if (tcp) {
1907 tcp->pid = pid;
1908 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001909 if (!cflag) {
1910 printleader(tcp);
1911 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1912 line_ended();
1913 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001914 }
1915 }
1916 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001917
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001918 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1919 if (!skip_startup_execve)
1920 detach(tcp);
1921 /* This was initial execve for "strace PROG". Skip. */
1922 skip_startup_execve = 0;
1923 }
1924
Denys Vlasenko5d645812011-08-20 12:48:18 +02001925 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001926 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001927 /* This is needed to go with the CLONE_PTRACE
1928 changes in process.c/util.c: we might see
1929 the child's initial trap before we see the
1930 parent return from the clone syscall.
1931 Leave the child suspended until the parent
1932 returns from its system call. Only then
1933 will we have the association of parent and
1934 child so that we know how to do clearbpt
1935 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001936 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001937 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001938 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001939 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001940 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001941 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001942 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001943 else
1944 /* This can happen if a clone call used
1945 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001946 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001947 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001948 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001949 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001950 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001951 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001952
1953 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001954 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001955 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001956
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001957 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001958 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1959 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001961
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001963 if (pid == strace_child)
1964 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001965 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1967 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001968#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001969 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001970 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001971 WCOREDUMP(status) ? "(core dumped) " : "");
1972#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001973 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001974 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001975#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001976 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001977 }
1978 droptcb(tcp);
1979 continue;
1980 }
1981 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001982 if (pid == strace_child)
1983 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001984 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1985 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001986 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001987 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001988 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989 droptcb(tcp);
1990 continue;
1991 }
1992 if (!WIFSTOPPED(status)) {
1993 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1994 droptcb(tcp);
1995 continue;
1996 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001998 /* Is this the very first time we see this tracee stopped? */
1999 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002000 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002001 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002002 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002003 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002004 /*
2005 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002006 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002007 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002008 if (clearbpt(tcp) < 0) {
2009 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010 droptcb(tcp);
2011 cleanup();
2012 return -1;
2013 }
2014 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002015 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002016 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002017 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2018 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2019 if (errno != ESRCH) {
2020 /* Should never happen, really */
2021 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002022 }
2023 }
2024 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002025 }
2026
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002027 sig = WSTOPSIG(status);
2028
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002029 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002030 /* Ptrace event */
2031#ifdef USE_SEIZE
2032 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002033 /*
2034 * PTRACE_INTERRUPT-stop or group-stop.
2035 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2036 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002037 if (sig == SIGSTOP
2038 || sig == SIGTSTP
2039 || sig == SIGTTIN
2040 || sig == SIGTTOU
2041 ) {
2042 stopped = 1;
2043 goto show_stopsig;
2044 }
2045 }
2046#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002047 goto restart_tracee_with_sig_0;
2048 }
2049
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002050 /* Is this post-attach SIGSTOP?
2051 * Interestingly, the process may stop
2052 * with STOPSIG equal to some other signal
2053 * than SIGSTOP if we happend to attach
2054 * just before the process takes a signal.
2055 */
2056 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002057 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002058 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2059 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002060 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002061 }
2062
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002063 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002064 siginfo_t si;
2065
2066 /* Nonzero (true) if tracee is stopped by signal
2067 * (as opposed to "tracee received signal").
2068 */
2069 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002070#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002071 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002072#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002073 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002074 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002075#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002076 long pc = 0;
2077 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002078
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002079 upeek(tcp, PT_CR_IPSR, &psr);
2080 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002081
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002082# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002083 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002084# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002085# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002086#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002087# define PC_FORMAT_STR ""
2088# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002089#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002091 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002092 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002093 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002094 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002095 PC_FORMAT_ARG);
2096 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002097 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002098 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002099 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002100 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002102
2103 if (!stopped)
2104 /* It's signal-delivery-stop. Inject the signal */
2105 goto restart_tracee;
2106
2107 /* It's group-stop */
2108#ifdef USE_SEIZE
2109 if (use_seize) {
2110 /*
2111 * This ends ptrace-stop, but does *not* end group-stop.
2112 * This makes stopping signals work properly on straced process
2113 * (that is, process really stops. It used to continue to run).
2114 */
2115 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2116 cleanup();
2117 return -1;
2118 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002119 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002120 continue;
2121 }
2122 /* We don't have PTRACE_LISTEN support... */
2123#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002124 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002125 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002126
2127 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002128 if (interrupted)
2129 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002130
2131 /* This should be syscall entry or exit.
2132 * (Or it still can be that pesky post-execve SIGTRAP!)
2133 * Handle it.
2134 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002135 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2136 /* ptrace() failed in trace_syscall() with ESRCH.
2137 * Likely a result of process disappearing mid-flight.
2138 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002139 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002140 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002141 * We used to detach(tcp) here, but since we no longer
2142 * implement "detach before death" policy/hack,
2143 * we can let this process to report its death to us
2144 * normally, via WIFEXITED or WIFSIGNALED wait status.
2145 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002146 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002147 continue;
2148 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002149 restart_tracee_with_sig_0:
2150 sig = 0;
2151 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002152 /* Remember current print column before continuing. */
2153 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002154 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002155 cleanup();
2156 return -1;
2157 }
2158 }
2159 return 0;
2160}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002161
2162int
2163main(int argc, char *argv[])
2164{
2165 init(argc, argv);
2166
2167 /* Run main tracing loop */
2168 if (trace() < 0)
2169 return 1;
2170
2171 cleanup();
2172 fflush(NULL);
2173 if (exit_code > 0xff) {
2174 /* Avoid potential core file clobbering. */
2175 struct rlimit rlim = {0, 0};
2176 setrlimit(RLIMIT_CORE, &rlim);
2177
2178 /* Child was killed by a signal, mimic that. */
2179 exit_code &= 0xff;
2180 signal(exit_code, SIG_DFL);
2181 raise(exit_code);
2182 /* Paranoia - what if this signal is not fatal?
2183 Exit with 128 + signo then. */
2184 exit_code += 128;
2185 }
2186
2187 return exit_code;
2188}