blob: 04efd1e6f53d9edb1cfb835e1bfc740b977dfdb7 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000029 */
30
31#include "defs.h"
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020032#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000033#include <sys/param.h>
34#include <fcntl.h>
35#include <sys/resource.h>
36#include <sys/wait.h>
37#include <sys/stat.h>
38#include <pwd.h>
39#include <grp.h>
Roland McGrath70b08532004-04-09 00:25:21 +000040#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010041#include <sys/utsname.h>
Denys Vlasenko84703742012-02-25 02:38:52 +010042#if defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000043# include <asm/ptrace_offsets.h>
44#endif
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010045/* In some libc, these aren't declared. Do it ourself: */
Denys Vlasenko96d5a762008-12-29 19:13:27 +000046extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000047extern int optind;
48extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000049
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010050
51#if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
53#else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
58# define my_tkill(tid, sig) kill((tid), (sig))
59#endif
60
61#undef KERNEL_VERSION
62#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
63
64cflag_t cflag = CFLAG_NONE;
65unsigned int followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020066unsigned int ptrace_setoptions = 0;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010067unsigned int xflag = 0;
68bool debug_flag = 0;
69bool Tflag = 0;
70bool qflag = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020071/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020072static unsigned int syscall_trap_sig = SIGTRAP;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010073static unsigned int tflag = 0;
74static bool iflag = 0;
75static bool rflag = 0;
76static bool print_pid_pfx = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010077
78/* -I n */
79enum {
80 INTR_NOT_SET = 0,
81 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
82 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
83 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
84 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
85 NUM_INTR_OPTS
86};
87static int opt_intr;
88/* We play with signal mask only if this mode is active: */
89#define interactive (opt_intr == INTR_WHILE_WAIT)
90
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100105#ifdef USE_SEIZE
106static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
107# define use_seize (post_attach_sigstop == 0)
108#else
109# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
110# define use_seize 0
111#endif
112
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000113/* Sometimes we want to print only succeeding syscalls. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100114bool not_failing_only = 0;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000115
Grant Edwards8a082772011-04-07 20:25:40 +0000116/* Show path associated with fd arguments */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100117bool show_fd_path = 0;
Grant Edwards8a082772011-04-07 20:25:40 +0000118
119/* are we filtering traces based on paths? */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100120bool tracing_paths = 0;
Grant Edwards8a082772011-04-07 20:25:40 +0000121
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100122static bool detach_on_execve = 0;
123static bool skip_startup_execve = 0;
124
Dmitry V. Levina6809652008-11-10 17:14:58 +0000125static int exit_code = 0;
126static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200127static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700128
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000129static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200130static uid_t run_uid;
131static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100133unsigned int max_strlen = DEFAULT_STRLEN;
134static unsigned int acolumn = DEFAULT_ACOLUMN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200135static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000136static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200137static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100138struct tcb *printing_tcp = NULL;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100139static unsigned int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200140static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200141static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200142static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +0100144static unsigned os_release; /* generated from uname()'s u.release */
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100145
Denys Vlasenko4c196382012-01-04 15:11:09 +0100146static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100147static int trace(void);
148static void cleanup(void);
149static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150static sigset_t empty_set, blocked_set;
151
152#ifdef HAVE_SIG_ATOMIC_T
153static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100154#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100156#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100158#ifndef HAVE_STRERROR
159
160#if !HAVE_DECL_SYS_ERRLIST
161extern int sys_nerr;
162extern char *sys_errlist[];
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +0100163#endif
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100164
165const char *
166strerror(int err_no)
167{
168 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
169
170 if (err_no < 1 || err_no >= sys_nerr) {
171 sprintf(buf, "Unknown error %d", err_no);
172 return buf;
173 }
174 return sys_errlist[err_no];
175}
176
177#endif /* HAVE_STERRROR */
178
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000179static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200180usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181{
182 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100183usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
184 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100185 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100186 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100187 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200189-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100190-d -- enable debug output to stderr\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100191-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000192-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100193-F -- attempt to follow vforks (deprecated, use -f)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100195-I interruptible\n\
196 1: no signals are blocked\n\
197 2: fatal signals are blocked while decoding syscall (default)\n\
198 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
199 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
200 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201-q -- suppress messages about attaching, detaching, etc.\n\
202-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100203-T -- print time spent in each syscall\n\
204-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000206-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100207-h -- print help message\n\
208-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209-a column -- alignment COLUMN for printing syscall results (default %d)\n\
210-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
211 options: trace, abbrev, verbose, raw, signal, read, or write\n\
212-o file -- send trace output to FILE instead of stderr\n\
213-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
214-p pid -- trace process with process id PID, may be repeated\n\
215-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
216-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
217-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000218-E var=val -- put var=val in the environment for command\n\
219-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000220-P path -- trace accesses to path\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100221"
222/* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000223-z -- print only succeeding syscalls\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100224 */
225/* experimental, don't document it yet (option letter may change in the future!)
226-b -- detach on successful execve\n\
227 */
Roland McGrathde6e5332003-01-24 04:31:23 +0000228, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229 exit(exitval);
230}
231
Denys Vlasenko75422762011-05-27 14:36:01 +0200232static void die(void) __attribute__ ((noreturn));
233static void die(void)
234{
235 if (strace_tracer_pid == getpid()) {
236 cflag = 0;
237 cleanup();
238 }
239 exit(1);
240}
241
242static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200243{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100244 char *msg;
245
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000246 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100247
248 /* We want to print entire message with single fprintf to ensure
249 * message integrity if stderr is shared with other programs.
250 * Thus we use vasprintf + single fprintf.
251 */
252 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100253 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100254 if (err_no)
255 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
256 else
257 fprintf(stderr, "%s: %s\n", progname, msg);
258 free(msg);
259 } else {
260 /* malloc in vasprintf failed, try it without malloc */
261 fprintf(stderr, "%s: ", progname);
262 vfprintf(stderr, fmt, p);
263 if (err_no)
264 fprintf(stderr, ": %s\n", strerror(err_no));
265 else
266 putc('\n', stderr);
267 }
268 /* We don't switch stderr to buffered, thus fprintf(stderr)
269 * always flushes its output and this is not necessary: */
270 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200271}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200272
Denys Vlasenko75422762011-05-27 14:36:01 +0200273void error_msg(const char *fmt, ...)
274{
275 va_list p;
276 va_start(p, fmt);
277 verror_msg(0, fmt, p);
278 va_end(p);
279}
280
281void error_msg_and_die(const char *fmt, ...)
282{
283 va_list p;
284 va_start(p, fmt);
285 verror_msg(0, fmt, p);
286 die();
287}
288
289void perror_msg(const char *fmt, ...)
290{
291 va_list p;
292 va_start(p, fmt);
293 verror_msg(errno, fmt, p);
294 va_end(p);
295}
296
297void perror_msg_and_die(const char *fmt, ...)
298{
299 va_list p;
300 va_start(p, fmt);
301 verror_msg(errno, fmt, p);
302 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200303}
304
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200305void die_out_of_memory(void)
306{
307 static bool recursed = 0;
308 if (recursed)
309 exit(1);
310 recursed = 1;
311 error_msg_and_die("Out of memory");
312}
313
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400314/* Glue for systems without a MMU that cannot provide fork() */
315#ifdef HAVE_FORK
316# define strace_vforked 0
317#else
318# define strace_vforked 1
319# define fork() vfork()
320#endif
321
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100322#ifdef USE_SEIZE
323static int
324ptrace_attach_or_seize(int pid)
325{
326 int r;
327 if (!use_seize)
328 return ptrace(PTRACE_ATTACH, pid, 0, 0);
329 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
330 if (r)
331 return r;
332 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
333 return r;
334}
335#else
336# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
337#endif
338
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100339/*
340 * Used when we want to unblock stopped traced process.
341 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
342 * Returns 0 on success or if error was ESRCH
343 * (presumably process was killed while we talk to it).
344 * Otherwise prints error message and returns -1.
345 */
346static int
347ptrace_restart(int op, struct tcb *tcp, int sig)
348{
349 int err;
350 const char *msg;
351
352 errno = 0;
353 ptrace(op, tcp->pid, (void *) 0, (long) sig);
354 err = errno;
355 if (!err || err == ESRCH)
356 return 0;
357
358 tcp->ptrace_errno = err;
359 msg = "SYSCALL";
360 if (op == PTRACE_CONT)
361 msg = "CONT";
362 if (op == PTRACE_DETACH)
363 msg = "DETACH";
364#ifdef PTRACE_LISTEN
365 if (op == PTRACE_LISTEN)
366 msg = "LISTEN";
367#endif
368 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
369 return -1;
370}
371
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200372static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000373set_cloexec_flag(int fd)
374{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200375 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200377 flags = fcntl(fd, F_GETFD);
378 if (flags < 0) {
379 /* Can happen only if fd is bad.
380 * Should never happen: if it does, we have a bug
381 * in the caller. Therefore we just abort
382 * instead of propagating the error.
383 */
384 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000385 }
386
387 newflags = flags | FD_CLOEXEC;
388 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200389 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000390
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200391 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000392}
393
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100394static void kill_save_errno(pid_t pid, int sig)
395{
396 int saved_errno = errno;
397
398 (void) kill(pid, sig);
399 errno = saved_errno;
400}
401
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100402/*
403 * When strace is setuid executable, we have to swap uids
404 * before and after filesystem and process management operations.
405 */
406static void
407swap_uid(void)
408{
409 int euid = geteuid(), uid = getuid();
410
411 if (euid != uid && setreuid(euid, uid) < 0) {
412 perror_msg_and_die("setreuid");
413 }
414}
415
416#if _LFS64_LARGEFILE
417# define fopen_for_output fopen64
418#else
419# define fopen_for_output fopen
420#endif
421
422static FILE *
423strace_fopen(const char *path)
424{
425 FILE *fp;
426
427 swap_uid();
428 fp = fopen_for_output(path, "w");
429 if (!fp)
430 perror_msg_and_die("Can't fopen '%s'", path);
431 swap_uid();
432 set_cloexec_flag(fileno(fp));
433 return fp;
434}
435
436static int popen_pid = 0;
437
438#ifndef _PATH_BSHELL
439# define _PATH_BSHELL "/bin/sh"
440#endif
441
442/*
443 * We cannot use standard popen(3) here because we have to distinguish
444 * popen child process from other processes we trace, and standard popen(3)
445 * does not export its child's pid.
446 */
447static FILE *
448strace_popen(const char *command)
449{
450 FILE *fp;
451 int fds[2];
452
453 swap_uid();
454 if (pipe(fds) < 0)
455 perror_msg_and_die("pipe");
456
457 set_cloexec_flag(fds[1]); /* never fails */
458
459 popen_pid = vfork();
460 if (popen_pid == -1)
461 perror_msg_and_die("vfork");
462
463 if (popen_pid == 0) {
464 /* child */
465 close(fds[1]);
466 if (fds[0] != 0) {
467 if (dup2(fds[0], 0))
468 perror_msg_and_die("dup2");
469 close(fds[0]);
470 }
471 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
472 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
473 }
474
475 /* parent */
476 close(fds[0]);
477 swap_uid();
478 fp = fdopen(fds[1], "w");
479 if (!fp)
480 die_out_of_memory();
481 return fp;
482}
483
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100484void
485tprintf(const char *fmt, ...)
486{
487 va_list args;
488
489 va_start(args, fmt);
490 if (outf) {
491 int n = vfprintf(outf, fmt, args);
492 if (n < 0) {
493 if (outf != stderr)
494 perror(outfname == NULL
495 ? "<writing to pipe>" : outfname);
496 } else
497 curcol += n;
498 }
499 va_end(args);
500}
501
502void
503tprints(const char *str)
504{
505 if (outf) {
506 int n = fputs(str, outf);
507 if (n >= 0) {
508 curcol += strlen(str);
509 return;
510 }
511 if (outf != stderr)
512 perror(outfname == NULL
513 ? "<writing to pipe>" : outfname);
514 }
515}
516
517void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100518line_ended(void)
519{
520 curcol = 0;
521 fflush(outf);
522 if (!printing_tcp)
523 return;
524 printing_tcp->curcol = 0;
525 printing_tcp = NULL;
526}
527
528void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100529printleader(struct tcb *tcp)
530{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100531 /* If -ff, "previous tcb we printed" is always the same as current,
532 * because we have per-tcb output files.
533 */
534 if (followfork >= 2)
535 printing_tcp = tcp;
536
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100537 if (printing_tcp) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100538 outf = printing_tcp->outf;
539 curcol = printing_tcp->curcol;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100540 if (printing_tcp->ptrace_errno) {
541 if (printing_tcp->flags & TCB_INSYSCALL) {
542 tprints(" <unavailable>) ");
543 tabto();
544 }
545 tprints("= ? <unavailable>\n");
546 printing_tcp->ptrace_errno = 0;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100547 printing_tcp->curcol = 0;
548 }
549 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
550 /*
551 * case 1: we have a shared log (i.e. not -ff), and last line
552 * wasn't finished (same or different tcb, doesn't matter).
553 * case 2: split log, we are the same tcb, but our last line
554 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
555 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100556 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100557 printing_tcp->flags |= TCB_REPRINT;
558 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100559 }
560 }
561
562 printing_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100563 outf = tcp->outf;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100564 curcol = 0;
565
566 if (print_pid_pfx)
567 tprintf("%-5d ", tcp->pid);
568 else if (nprocs > 1 && !outfname)
569 tprintf("[pid %5u] ", tcp->pid);
570
571 if (tflag) {
572 char str[sizeof("HH:MM:SS")];
573 struct timeval tv, dtv;
574 static struct timeval otv;
575
576 gettimeofday(&tv, NULL);
577 if (rflag) {
578 if (otv.tv_sec == 0)
579 otv = tv;
580 tv_sub(&dtv, &tv, &otv);
581 tprintf("%6ld.%06ld ",
582 (long) dtv.tv_sec, (long) dtv.tv_usec);
583 otv = tv;
584 }
585 else if (tflag > 2) {
586 tprintf("%ld.%06ld ",
587 (long) tv.tv_sec, (long) tv.tv_usec);
588 }
589 else {
590 time_t local = tv.tv_sec;
591 strftime(str, sizeof(str), "%T", localtime(&local));
592 if (tflag > 1)
593 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
594 else
595 tprintf("%s ", str);
596 }
597 }
598 if (iflag)
599 printcall(tcp);
600}
601
602void
603tabto(void)
604{
605 if (curcol < acolumn)
606 tprints(acolumn_spaces + curcol);
607}
608
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100609/* Should be only called directly *after successful attach* to a tracee.
610 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
611 * may create bogus empty FILE.<nonexistant_pid>, and then die.
612 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200613static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000614newoutf(struct tcb *tcp)
615{
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100616 tcp->outf = outf; /* if not -ff mode, the same file is for all */
617 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000618 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000619 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200620 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000621 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000622}
623
Denys Vlasenko558e5122012-03-12 23:32:16 +0100624static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100625expand_tcbtab(void)
626{
627 /* Allocate some more TCBs and expand the table.
628 We don't want to relocate the TCBs because our
629 callers have pointers and it would be a pain.
630 So tcbtab is a table of pointers. Since we never
631 free the TCBs, we allocate a single chunk of many. */
632 int i = tcbtabsize;
633 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
634 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
635 if (!newtab || !newtcbs)
636 die_out_of_memory();
637 tcbtabsize *= 2;
638 tcbtab = newtab;
639 while (i < tcbtabsize)
640 tcbtab[i++] = newtcbs++;
641}
642
643static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100644alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100645{
646 int i;
647 struct tcb *tcp;
648
649 if (nprocs == tcbtabsize)
650 expand_tcbtab();
651
652 for (i = 0; i < tcbtabsize; i++) {
653 tcp = tcbtab[i];
654 if ((tcp->flags & TCB_INUSE) == 0) {
655 memset(tcp, 0, sizeof(*tcp));
656 tcp->pid = pid;
657 tcp->flags = TCB_INUSE;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100658 /* tcp->outf = outf; - not needed? */
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100659#if SUPPORTED_PERSONALITIES > 1
660 tcp->currpers = current_personality;
661#endif
662 nprocs++;
663 if (debug_flag)
664 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100665 return tcp;
666 }
667 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100668 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100669}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100670
671static void
672droptcb(struct tcb *tcp)
673{
674 if (tcp->pid == 0)
675 return;
676
677 nprocs--;
678 if (debug_flag)
679 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
680
681 if (tcp->outf) {
682 if (outfname && followfork >= 2) {
683 if (tcp->curcol != 0)
684 fprintf(tcp->outf, " <detached ...>\n");
685 fclose(tcp->outf);
686 if (outf == tcp->outf)
687 outf = NULL;
688 } else {
689 if (printing_tcp == tcp && tcp->curcol != 0)
690 fprintf(tcp->outf, " <detached ...>\n");
691 fflush(tcp->outf);
692 }
693 }
694
695 if (printing_tcp == tcp)
696 printing_tcp = NULL;
697
698 memset(tcp, 0, sizeof(*tcp));
699}
700
701/* detach traced process; continue with sig
702 * Never call DETACH twice on the same process as both unattached and
703 * attached-unstopped processes give the same ESRCH. For unattached process we
704 * would SIGSTOP it and wait for its SIGSTOP notification forever.
705 */
706static int
707detach(struct tcb *tcp)
708{
709 int error;
710 int status, sigstop_expected;
711
712 if (tcp->flags & TCB_BPTSET)
713 clearbpt(tcp);
714
715 /*
716 * Linux wrongly insists the child be stopped
717 * before detaching. Arghh. We go through hoops
718 * to make a clean break of things.
719 */
720#if defined(SPARC)
721#undef PTRACE_DETACH
722#define PTRACE_DETACH PTRACE_SUNDETACH
723#endif
724
725 error = 0;
726 sigstop_expected = 0;
727 if (tcp->flags & TCB_ATTACHED) {
728 /*
729 * We attached but possibly didn't see the expected SIGSTOP.
730 * We must catch exactly one as otherwise the detached process
731 * would be left stopped (process state T).
732 */
733 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
734 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
735 if (error == 0) {
736 /* On a clear day, you can see forever. */
737 }
738 else if (errno != ESRCH) {
739 /* Shouldn't happen. */
740 perror("detach: ptrace(PTRACE_DETACH, ...)");
741 }
742 else if (my_tkill(tcp->pid, 0) < 0) {
743 if (errno != ESRCH)
744 perror("detach: checking sanity");
745 }
746 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
747 if (errno != ESRCH)
748 perror("detach: stopping child");
749 }
750 else
751 sigstop_expected = 1;
752 }
753
754 if (sigstop_expected) {
755 for (;;) {
756#ifdef __WALL
757 if (waitpid(tcp->pid, &status, __WALL) < 0) {
758 if (errno == ECHILD) /* Already gone. */
759 break;
760 if (errno != EINVAL) {
761 perror("detach: waiting");
762 break;
763 }
764#endif /* __WALL */
765 /* No __WALL here. */
766 if (waitpid(tcp->pid, &status, 0) < 0) {
767 if (errno != ECHILD) {
768 perror("detach: waiting");
769 break;
770 }
771#ifdef __WCLONE
772 /* If no processes, try clones. */
773 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
774 if (errno != ECHILD)
775 perror("detach: waiting");
776 break;
777 }
778#endif /* __WCLONE */
779 }
780#ifdef __WALL
781 }
782#endif
783 if (!WIFSTOPPED(status)) {
784 /* Au revoir, mon ami. */
785 break;
786 }
787 if (WSTOPSIG(status) == SIGSTOP) {
788 ptrace_restart(PTRACE_DETACH, tcp, 0);
789 break;
790 }
791 error = ptrace_restart(PTRACE_CONT, tcp,
792 WSTOPSIG(status) == syscall_trap_sig ? 0
793 : WSTOPSIG(status));
794 if (error < 0)
795 break;
796 }
797 }
798
799 if (!qflag && (tcp->flags & TCB_ATTACHED))
800 fprintf(stderr, "Process %u detached\n", tcp->pid);
801
802 droptcb(tcp);
803
804 return error;
805}
806
807static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100808process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100809{
810 while (*opt) {
811 /*
812 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
813 * pidof uses space as delim, pgrep uses newline. :(
814 */
815 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100816 char *delim = opt + strcspn(opt, ", \n\t");
817 char c = *delim;
818
819 *delim = '\0';
820 pid = atoi(opt); /* TODO: stricter parsing of the number? */
821 if (pid <= 0) {
822 error_msg("Invalid process id: '%s'", opt);
823 *delim = c;
824 return;
825 }
826 if (pid == strace_tracer_pid) {
827 error_msg("I'm sorry, I can't let you do that, Dave.");
828 *delim = c;
829 return;
830 }
831 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100832 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100833 if (c == '\0')
834 break;
835 opt = delim + 1;
836 }
837}
838
Roland McGrath02203312007-06-11 22:06:31 +0000839static void
840startup_attach(void)
841{
842 int tcbi;
843 struct tcb *tcp;
844
845 /*
846 * Block user interruptions as we would leave the traced
847 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200848 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200849 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000850 */
851 if (interactive)
852 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
853
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000854 if (daemonized_tracer) {
855 pid_t pid = fork();
856 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200857 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000858 }
859 if (pid) { /* parent */
860 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200861 * Wait for grandchild to attach to straced process
862 * (grandparent). Grandchild SIGKILLs us after it attached.
863 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000864 * it proceeds to exec the straced program.
865 */
866 pause();
867 _exit(0); /* paranoia */
868 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200869 /* grandchild */
870 /* We will be the tracer process. Remember our new pid: */
871 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000872 }
873
Roland McGrath02203312007-06-11 22:06:31 +0000874 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
875 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200876
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100877 if (!(tcp->flags & TCB_INUSE))
878 continue;
879
Denys Vlasenkod116a732011-09-05 14:01:33 +0200880 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100881 if (tcp->flags & TCB_ATTACHED)
882 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200883
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000884 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000885 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000886 DIR *dir;
887
888 sprintf(procdir, "/proc/%d/task", tcp->pid);
889 dir = opendir(procdir);
890 if (dir != NULL) {
891 unsigned int ntid = 0, nerr = 0;
892 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200893
Roland McGrath02203312007-06-11 22:06:31 +0000894 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200895 struct tcb *cur_tcp;
896 int tid;
897
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000898 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000899 continue;
900 tid = atoi(de->d_name);
901 if (tid <= 0)
902 continue;
903 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100904 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000905 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100906 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200907 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200908 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200909 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100910 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200911 fprintf(stderr, "attach to pid %d succeeded\n", tid);
912 cur_tcp = tcp;
913 if (tid != tcp->pid)
914 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100915 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100916 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000917 }
918 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200919 if (interactive) {
920 sigprocmask(SIG_SETMASK, &empty_set, NULL);
921 if (interrupted)
922 goto ret;
923 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
924 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000925 ntid -= nerr;
926 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000927 perror("attach: ptrace(PTRACE_ATTACH, ...)");
928 droptcb(tcp);
929 continue;
930 }
931 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000932 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100933? "Process %u attached with %u threads\n"
934: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200935 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000936 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100937 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200938 /* -p PID, we failed to attach to PID itself
939 * but did attach to some of its sibling threads.
940 * Drop PID's tcp.
941 */
942 droptcb(tcp);
943 }
Roland McGrath02203312007-06-11 22:06:31 +0000944 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000945 } /* if (opendir worked) */
946 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100947 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000948 perror("attach: ptrace(PTRACE_ATTACH, ...)");
949 droptcb(tcp);
950 continue;
951 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100952 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100953 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100954 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200955 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000956
957 if (daemonized_tracer) {
958 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000959 * Make parent go away.
960 * Also makes grandparent's wait() unblock.
961 */
962 kill(getppid(), SIGKILL);
963 }
964
Roland McGrath02203312007-06-11 22:06:31 +0000965 if (!qflag)
966 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100967 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000968 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200969 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000970
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200971 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000972 if (interactive)
973 sigprocmask(SIG_SETMASK, &empty_set, NULL);
974}
975
976static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200977startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000978{
979 struct stat statbuf;
980 const char *filename;
981 char pathname[MAXPATHLEN];
982 int pid = 0;
983 struct tcb *tcp;
984
985 filename = argv[0];
986 if (strchr(filename, '/')) {
987 if (strlen(filename) > sizeof pathname - 1) {
988 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200989 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000990 }
991 strcpy(pathname, filename);
992 }
993#ifdef USE_DEBUGGING_EXEC
994 /*
995 * Debuggers customarily check the current directory
996 * first regardless of the path but doing that gives
997 * security geeks a panic attack.
998 */
999 else if (stat(filename, &statbuf) == 0)
1000 strcpy(pathname, filename);
1001#endif /* USE_DEBUGGING_EXEC */
1002 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +00001003 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +00001004 int m, n, len;
1005
1006 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +01001007 const char *colon = strchr(path, ':');
1008 if (colon) {
1009 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +00001010 m = n + 1;
1011 }
1012 else
1013 m = n = strlen(path);
1014 if (n == 0) {
1015 if (!getcwd(pathname, MAXPATHLEN))
1016 continue;
1017 len = strlen(pathname);
1018 }
1019 else if (n > sizeof pathname - 1)
1020 continue;
1021 else {
1022 strncpy(pathname, path, n);
1023 len = n;
1024 }
1025 if (len && pathname[len - 1] != '/')
1026 pathname[len++] = '/';
1027 strcpy(pathname + len, filename);
1028 if (stat(pathname, &statbuf) == 0 &&
1029 /* Accept only regular files
1030 with some execute bits set.
1031 XXX not perfect, might still fail */
1032 S_ISREG(statbuf.st_mode) &&
1033 (statbuf.st_mode & 0111))
1034 break;
1035 }
1036 }
1037 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001038 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001039 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001040 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001041 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001042 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001043 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001044 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1045 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001046 ) {
1047 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001048 if (outf != stderr)
1049 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001050 if (!daemonized_tracer && !use_seize) {
1051 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001052 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001053 }
Roland McGrath02203312007-06-11 22:06:31 +00001054 }
Roland McGrath02203312007-06-11 22:06:31 +00001055
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001056 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001057 uid_t run_euid = run_uid;
1058 gid_t run_egid = run_gid;
1059
1060 if (statbuf.st_mode & S_ISUID)
1061 run_euid = statbuf.st_uid;
1062 if (statbuf.st_mode & S_ISGID)
1063 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001064 /*
1065 * It is important to set groups before we
1066 * lose privileges on setuid.
1067 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001068 if (initgroups(username, run_gid) < 0) {
1069 perror_msg_and_die("initgroups");
1070 }
1071 if (setregid(run_gid, run_egid) < 0) {
1072 perror_msg_and_die("setregid");
1073 }
1074 if (setreuid(run_uid, run_euid) < 0) {
1075 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001076 }
1077 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001078 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001079 setreuid(run_uid, run_uid);
1080
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001081 if (!daemonized_tracer) {
1082 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001083 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001084 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001085 * the immediately following execve syscall.
1086 * Can't do this on NOMMU systems, we are after
1087 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001088 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001089 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001090 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001091 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001092 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001093 /* we depend on SIGCHLD set to SIG_DFL by init code */
1094 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001095 wait(NULL);
1096 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001097 }
Roland McGrath02203312007-06-11 22:06:31 +00001098
1099 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001100 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001101 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001102
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001103 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001104
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001105 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001106 if (!use_seize) {
1107 /* child did PTRACE_TRACEME, nothing to do in parent */
1108 } else {
1109 if (!strace_vforked) {
1110 /* Wait until child stopped itself */
1111 int status;
1112 while (waitpid(pid, &status, WSTOPPED) < 0) {
1113 if (errno == EINTR)
1114 continue;
1115 perror_msg_and_die("waitpid");
1116 }
1117 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001118 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001119 perror_msg_and_die("Unexpected wait status %x", status);
1120 }
1121 }
1122 /* Else: vforked case, we have no way to sync.
1123 * Just attach to it as soon as possible.
1124 * This means that we may miss a few first syscalls...
1125 */
1126
1127 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001128 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001129 perror_msg_and_die("Can't attach to %d", pid);
1130 }
1131 if (!strace_vforked)
1132 kill(pid, SIGCONT);
1133 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001134 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001135 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001136 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001137 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001138 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001139 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001140 }
1141 else {
1142 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1143 strace_tracer_pid = getpid();
1144 /* The tracee is our parent: */
1145 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001146 alloctcb(pid);
1147 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001148 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001149 }
Roland McGrath02203312007-06-11 22:06:31 +00001150}
1151
Wang Chaob13c0de2010-11-12 17:25:19 +08001152/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001153 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001154 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001155 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001156 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001157static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001158test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001159{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001160 int pid, expected_grandchild = 0, found_grandchild = 0;
1161 const unsigned int test_options = PTRACE_O_TRACECLONE |
1162 PTRACE_O_TRACEFORK |
1163 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001164
Denys Vlasenko5d645812011-08-20 12:48:18 +02001165 pid = fork();
1166 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001167 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001168 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001169 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001170 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001171 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1172 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001173 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001174 if (fork() < 0)
1175 perror_msg_and_die("fork");
1176 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001177 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001178
1179 while (1) {
1180 int status, tracee_pid;
1181
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001182 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001183 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001184 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001185 if (errno == EINTR)
1186 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001187 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001188 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001189 kill_save_errno(pid, SIGKILL);
1190 perror_msg_and_die("%s: unexpected wait result %d",
1191 __func__, tracee_pid);
1192 }
1193 if (WIFEXITED(status)) {
1194 if (WEXITSTATUS(status)) {
1195 if (tracee_pid != pid)
1196 kill_save_errno(pid, SIGKILL);
1197 error_msg_and_die("%s: unexpected exit status %u",
1198 __func__, WEXITSTATUS(status));
1199 }
1200 continue;
1201 }
1202 if (WIFSIGNALED(status)) {
1203 if (tracee_pid != pid)
1204 kill_save_errno(pid, SIGKILL);
1205 error_msg_and_die("%s: unexpected signal %u",
1206 __func__, WTERMSIG(status));
1207 }
1208 if (!WIFSTOPPED(status)) {
1209 if (tracee_pid != pid)
1210 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001211 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001212 error_msg_and_die("%s: unexpected wait status %x",
1213 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001214 }
1215 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001216 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001217 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1218 kill_save_errno(tracee_pid, SIGKILL);
1219 kill_save_errno(pid, SIGKILL);
1220 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001221 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001222 continue;
1223 }
1224 switch (WSTOPSIG(status)) {
1225 case SIGSTOP:
1226 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1227 && errno != EINVAL && errno != EIO)
1228 perror_msg("PTRACE_SETOPTIONS");
1229 break;
1230 case SIGTRAP:
1231 if (status >> 16 == PTRACE_EVENT_FORK) {
1232 long msg = 0;
1233
1234 if (ptrace(PTRACE_GETEVENTMSG, pid,
1235 NULL, (long) &msg) == 0)
1236 expected_grandchild = msg;
1237 }
1238 break;
1239 }
1240 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1241 kill_save_errno(pid, SIGKILL);
1242 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001243 }
1244 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001245 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001246 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001247 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001248 fprintf(stderr, "ptrace_setoptions = %#x\n",
1249 ptrace_setoptions);
1250 return;
1251 }
1252 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1253 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001254}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001255
1256/*
1257 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1258 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1259 * and then see whether it will stop with (SIGTRAP | 0x80).
1260 *
1261 * Use of this option enables correct handling of user-generated SIGTRAPs,
1262 * and SIGTRAPs generated by special instructions such as int3 on x86:
1263 * _start: .globl _start
1264 * int3
1265 * movl $42, %ebx
1266 * movl $1, %eax
1267 * int $0x80
1268 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1269 */
1270static void
1271test_ptrace_setoptions_for_all(void)
1272{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001273 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1274 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001275 int pid;
1276 int it_worked = 0;
1277
1278 pid = fork();
1279 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001280 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001281
1282 if (pid == 0) {
1283 pid = getpid();
1284 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001285 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001286 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1287 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001288 kill(pid, SIGSTOP);
1289 _exit(0); /* parent should see entry into this syscall */
1290 }
1291
1292 while (1) {
1293 int status, tracee_pid;
1294
1295 errno = 0;
1296 tracee_pid = wait(&status);
1297 if (tracee_pid <= 0) {
1298 if (errno == EINTR)
1299 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001300 kill_save_errno(pid, SIGKILL);
1301 perror_msg_and_die("%s: unexpected wait result %d",
1302 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001303 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001304 if (WIFEXITED(status)) {
1305 if (WEXITSTATUS(status) == 0)
1306 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001307 error_msg_and_die("%s: unexpected exit status %u",
1308 __func__, WEXITSTATUS(status));
1309 }
1310 if (WIFSIGNALED(status)) {
1311 error_msg_and_die("%s: unexpected signal %u",
1312 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001313 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001314 if (!WIFSTOPPED(status)) {
1315 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001316 error_msg_and_die("%s: unexpected wait status %x",
1317 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001318 }
1319 if (WSTOPSIG(status) == SIGSTOP) {
1320 /*
1321 * We don't check "options aren't accepted" error.
1322 * If it happens, we'll never get (SIGTRAP | 0x80),
1323 * and thus will decide to not use the option.
1324 * IOW: the outcome of the test will be correct.
1325 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001326 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1327 && errno != EINVAL && errno != EIO)
1328 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001329 }
1330 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1331 it_worked = 1;
1332 }
1333 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001334 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001335 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001336 }
1337 }
1338
1339 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001340 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001341 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001342 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001343 fprintf(stderr, "ptrace_setoptions = %#x\n",
1344 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001345 return;
1346 }
1347
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001348 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1349 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001350}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001351
1352# ifdef USE_SEIZE
1353static void
1354test_ptrace_seize(void)
1355{
1356 int pid;
1357
1358 pid = fork();
1359 if (pid < 0)
1360 perror_msg_and_die("fork");
1361
1362 if (pid == 0) {
1363 pause();
1364 _exit(0);
1365 }
1366
1367 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1368 * attaching tracee continues to run unless a trap condition occurs.
1369 * PTRACE_SEIZE doesn't affect signal or group stop state.
1370 */
1371 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1372 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001373 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001374 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1375 }
1376
1377 kill(pid, SIGKILL);
1378
1379 while (1) {
1380 int status, tracee_pid;
1381
1382 errno = 0;
1383 tracee_pid = waitpid(pid, &status, 0);
1384 if (tracee_pid <= 0) {
1385 if (errno == EINTR)
1386 continue;
1387 perror_msg_and_die("%s: unexpected wait result %d",
1388 __func__, tracee_pid);
1389 }
1390 if (WIFSIGNALED(status)) {
1391 return;
1392 }
1393 error_msg_and_die("%s: unexpected wait status %x",
1394 __func__, status);
1395 }
1396}
1397# else /* !USE_SEIZE */
1398# define test_ptrace_seize() ((void)0)
1399# endif
1400
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001401static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001402get_os_release(void)
1403{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001404 unsigned rel;
1405 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001406 struct utsname u;
1407 if (uname(&u) < 0)
1408 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001409 /* u.release has this form: "3.2.9[-some-garbage]" */
1410 rel = 0;
1411 p = u.release;
1412 for (;;) {
1413 if (!(*p >= '0' && *p <= '9'))
1414 error_msg_and_die("Bad OS release string: '%s'", u.release);
1415 /* Note: this open-codes KERNEL_VERSION(): */
1416 rel = (rel << 8) | atoi(p);
1417 if (rel >= KERNEL_VERSION(1,0,0))
1418 break;
1419 while (*p >= '0' && *p <= '9')
1420 p++;
1421 if (*p != '.')
1422 error_msg_and_die("Bad OS release string: '%s'", u.release);
1423 p++;
1424 }
1425 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001426}
1427
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001428/*
1429 * Initialization part of main() was eating much stack (~0.5k),
1430 * which was unused after init.
1431 * We can reuse it if we move init code into a separate function.
1432 *
1433 * Don't want main() to inline us and defeat the reason
1434 * we have a separate function.
1435 */
1436static void __attribute__ ((noinline))
1437init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001440 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001441 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 struct sigaction sa;
1443
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001444 progname = argv[0] ? argv[0] : "strace";
1445
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001446 /* Make sure SIGCHLD has the default action so that waitpid
1447 definitely works without losing track of children. The user
1448 should not have given us a bogus state to inherit, but he might
1449 have. Arguably we should detect SIG_IGN here and pass it on
1450 to children, but probably noone really needs that. */
1451 signal(SIGCHLD, SIG_DFL);
1452
Denys Vlasenko75422762011-05-27 14:36:01 +02001453 strace_tracer_pid = getpid();
1454
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001455 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001456
Roland McGrathee9d4352002-12-18 04:16:10 +00001457 /* Allocate the initial tcbtab. */
1458 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001459 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001460 if (!tcbtab)
1461 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001462 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001463 if (!tcp)
1464 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001465 for (c = 0; c < tcbtabsize; c++)
1466 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001467
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001468 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001469 set_sortby(DEFAULT_SORTBY);
1470 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 qualify("trace=all");
1472 qualify("abbrev=all");
1473 qualify("verbose=all");
1474 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001476 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001477 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001478 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001480 case 'b':
1481 detach_on_execve = 1;
1482 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001484 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001485 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001486 }
1487 cflag = CFLAG_ONLY_STATS;
1488 break;
1489 case 'C':
1490 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001491 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001492 }
1493 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 break;
1495 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001496 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001497 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001498 case 'D':
1499 daemonized_tracer = 1;
1500 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001501 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001502 optF = 1;
1503 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 case 'f':
1505 followfork++;
1506 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507 case 'h':
1508 usage(stdout, 0);
1509 break;
1510 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001511 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 break;
1513 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001514 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 break;
1516 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001517 rflag = 1;
1518 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 case 't':
1520 tflag++;
1521 break;
1522 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001523 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524 break;
1525 case 'x':
1526 xflag++;
1527 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001528 case 'y':
1529 show_fd_path = 1;
1530 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531 case 'v':
1532 qualify("abbrev=none");
1533 break;
1534 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001535 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 exit(0);
1537 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001538 case 'z':
1539 not_failing_only = 1;
1540 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541 case 'a':
1542 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001543 if (acolumn < 0)
1544 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545 break;
1546 case 'e':
1547 qualify(optarg);
1548 break;
1549 case 'o':
1550 outfname = strdup(optarg);
1551 break;
1552 case 'O':
1553 set_overhead(atoi(optarg));
1554 break;
1555 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001556 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001558 case 'P':
1559 tracing_paths = 1;
1560 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001561 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001562 }
1563 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 case 's':
1565 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001566 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001567 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001568 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569 break;
1570 case 'S':
1571 set_sortby(optarg);
1572 break;
1573 case 'u':
1574 username = strdup(optarg);
1575 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001576 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001577 if (putenv(optarg) < 0)
1578 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001579 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001580 case 'I':
1581 opt_intr = atoi(optarg);
1582 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1583 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1584 }
1585 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586 default:
1587 usage(stderr, 1);
1588 break;
1589 }
1590 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001591 argv += optind;
1592 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593
Denys Vlasenko102ec492011-08-25 01:27:59 +02001594 acolumn_spaces = malloc(acolumn + 1);
1595 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001596 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001597 memset(acolumn_spaces, ' ', acolumn);
1598 acolumn_spaces[acolumn] = '\0';
1599
Denys Vlasenko837399a2012-01-24 11:37:03 +01001600 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001601 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001602 usage(stderr, 1);
1603
Denys Vlasenkofd883382012-03-09 13:03:41 +01001604 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001605 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001606 }
1607
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001608 if (!followfork)
1609 followfork = optF;
1610
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001611 if (followfork >= 2 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001612 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001613 }
1614
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615 /* See if they want to run as another user. */
1616 if (username != NULL) {
1617 struct passwd *pent;
1618
1619 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001620 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001622 pent = getpwnam(username);
1623 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001624 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625 }
1626 run_uid = pent->pw_uid;
1627 run_gid = pent->pw_gid;
1628 }
1629 else {
1630 run_uid = getuid();
1631 run_gid = getgid();
1632 }
1633
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001634 if (followfork)
1635 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001636 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001637 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001638
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 /* Check if they want to redirect the output. */
1640 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001641 /* See if they want to pipe the output. */
1642 if (outfname[0] == '|' || outfname[0] == '!') {
1643 /*
1644 * We can't do the <outfname>.PID funny business
1645 * when using popen, so prohibit it.
1646 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001647 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001648 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1649 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001650 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001651 else if (followfork < 2)
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001652 outf = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001653 } else {
1654 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001655 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001656 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657 }
1658
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001659 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001660 char *buf = malloc(BUFSIZ);
1661 if (!buf)
1662 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001664 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001665 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001666 if (!opt_intr)
1667 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001669 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001670 if (!opt_intr)
1671 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001672
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001673 /* argv[0] -pPID -oFILE Default interactive setting
1674 * yes 0 0 INTR_WHILE_WAIT
1675 * no 1 0 INTR_WHILE_WAIT
1676 * yes 0 1 INTR_NEVER
1677 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001678 */
1679
1680 /* STARTUP_CHILD must be called before the signal handlers get
1681 installed below as they are inherited into the spawned process.
1682 Also we do not need to be protected by them as during interruption
1683 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001684 if (argv[0]) {
1685 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001686 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001687 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689 sigemptyset(&empty_set);
1690 sigemptyset(&blocked_set);
1691 sa.sa_handler = SIG_IGN;
1692 sigemptyset(&sa.sa_mask);
1693 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001694 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1695 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1696 if (opt_intr != INTR_ANYWHERE) {
1697 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1698 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1699 /*
1700 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1701 * fatal signals are blocked while syscall stop is processed,
1702 * and acted on in between, when waiting for new syscall stops.
1703 * In non-interactive mode, signals are ignored.
1704 */
1705 if (opt_intr == INTR_WHILE_WAIT) {
1706 sigaddset(&blocked_set, SIGHUP);
1707 sigaddset(&blocked_set, SIGINT);
1708 sigaddset(&blocked_set, SIGQUIT);
1709 sigaddset(&blocked_set, SIGPIPE);
1710 sigaddset(&blocked_set, SIGTERM);
1711 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001712 }
1713 /* SIG_IGN, or set handler for these */
1714 sigaction(SIGHUP, &sa, NULL);
1715 sigaction(SIGINT, &sa, NULL);
1716 sigaction(SIGQUIT, &sa, NULL);
1717 sigaction(SIGPIPE, &sa, NULL);
1718 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001720 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001721 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001722
Denys Vlasenkofd883382012-03-09 13:03:41 +01001723 /* Do we want pids printed in our -o OUTFILE?
1724 * -ff: no (every pid has its own file); or
1725 * -f: yes (there can be more pids in the future); or
1726 * -p PID1,PID2: yes (there are already more than one pid)
1727 */
1728 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729}
1730
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001731static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001732pid2tcb(int pid)
1733{
1734 int i;
1735
1736 if (pid <= 0)
1737 return NULL;
1738
1739 for (i = 0; i < tcbtabsize; i++) {
1740 struct tcb *tcp = tcbtab[i];
1741 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1742 return tcp;
1743 }
1744
1745 return NULL;
1746}
1747
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001749cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750{
1751 int i;
1752 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001753 int fatal_sig;
1754
1755 /* 'interrupted' is a volatile object, fetch it only once */
1756 fatal_sig = interrupted;
1757 if (!fatal_sig)
1758 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759
Roland McGrathee9d4352002-12-18 04:16:10 +00001760 for (i = 0; i < tcbtabsize; i++) {
1761 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762 if (!(tcp->flags & TCB_INUSE))
1763 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001764 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765 fprintf(stderr,
1766 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001767 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001769 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001771 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 }
1773 if (cflag)
1774 call_summary(outf);
1775}
1776
1777static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001778interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001780 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781}
1782
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001784trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001787 struct rusage *rup = cflag ? &ru : NULL;
1788# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001789 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001790# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791
Roland McGratheb9e2e82009-06-02 16:49:22 -07001792 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001793 int pid;
1794 int wait_errno;
1795 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001796 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001797 struct tcb *tcp;
1798 unsigned event;
1799
Denys Vlasenko222713a2009-03-17 14:29:59 +00001800 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001801 return 0;
1802 if (interactive)
1803 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001804# ifdef __WALL
1805 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001806 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001807 /* this kernel does not support __WALL */
1808 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001809 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001810 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001811 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001812 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001813 pid = wait4(-1, &status, __WCLONE, rup);
1814 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001815 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001816 }
1817 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001818# else
1819 pid = wait4(-1, &status, 0, rup);
1820# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001822 if (interactive)
1823 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001824
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001825 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001826 switch (wait_errno) {
1827 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001829 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830 /*
1831 * We would like to verify this case
1832 * but sometimes a race in Solbourne's
1833 * version of SunOS sometimes reports
1834 * ECHILD before sending us SIGCHILD.
1835 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001836 return 0;
1837 default:
1838 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001839 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001840 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841 }
1842 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001843 if (pid == popen_pid) {
1844 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001845 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001846 continue;
1847 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001848
1849 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001850 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001851 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001852 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001853 strcpy(buf, "???");
1854 if (WIFSIGNALED(status))
1855#ifdef WCOREDUMP
1856 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1857 WCOREDUMP(status) ? "core," : "",
1858 signame(WTERMSIG(status)));
1859#else
1860 sprintf(buf, "WIFSIGNALED,sig=%s",
1861 signame(WTERMSIG(status)));
1862#endif
1863 if (WIFEXITED(status))
1864 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1865 if (WIFSTOPPED(status))
1866 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001867#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001868 if (WIFCONTINUED(status))
1869 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001870#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001871 evbuf[0] = '\0';
1872 if (event != 0) {
1873 static const char *const event_names[] = {
1874 [PTRACE_EVENT_CLONE] = "CLONE",
1875 [PTRACE_EVENT_FORK] = "FORK",
1876 [PTRACE_EVENT_VFORK] = "VFORK",
1877 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1878 [PTRACE_EVENT_EXEC] = "EXEC",
1879 [PTRACE_EVENT_EXIT] = "EXIT",
1880 };
1881 const char *e;
1882 if (event < ARRAY_SIZE(event_names))
1883 e = event_names[event];
1884 else {
1885 sprintf(buf, "?? (%u)", event);
1886 e = buf;
1887 }
1888 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1889 }
1890 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001891 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001892
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001893 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001894 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001895
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001896 /* Under Linux, execve changes pid to thread leader's pid,
1897 * and we see this changed pid on EVENT_EXEC and later,
1898 * execve sysexit. Leader "disappears" without exit
1899 * notification. Let user know that, drop leader's tcb,
1900 * and fix up pid in execve thread's tcb.
1901 * Effectively, execve thread's tcb replaces leader's tcb.
1902 *
1903 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1904 * on exit syscall) in multithreaded programs exactly
1905 * in order to handle this case.
1906 *
1907 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1908 * On 2.6 and earlier, it can return garbage.
1909 */
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001910 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001911 long old_pid = 0;
1912 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1913 && old_pid > 0
1914 && old_pid != pid
1915 ) {
1916 struct tcb *execve_thread = pid2tcb(old_pid);
1917 if (tcp) {
1918 outf = tcp->outf;
1919 curcol = tcp->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001920 if (execve_thread) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001921 if (execve_thread->curcol != 0) {
1922 /*
1923 * One case we are here is -ff:
1924 * try "strace -oLOG -ff test/threaded_execve"
1925 */
1926 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
1927 execve_thread->curcol = 0;
1928 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001929 /* swap output FILEs (needed for -ff) */
1930 tcp->outf = execve_thread->outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001931 tcp->curcol = execve_thread->curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001932 execve_thread->outf = outf;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001933 execve_thread->curcol = curcol;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001934 }
1935 droptcb(tcp);
1936 }
1937 tcp = execve_thread;
1938 if (tcp) {
1939 tcp->pid = pid;
1940 tcp->flags |= TCB_REPRINT;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001941 if (!cflag) {
1942 printleader(tcp);
1943 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1944 line_ended();
1945 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001946 }
1947 }
1948 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001949
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001950 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1951 if (!skip_startup_execve)
1952 detach(tcp);
1953 /* This was initial execve for "strace PROG". Skip. */
1954 skip_startup_execve = 0;
1955 }
1956
Denys Vlasenko5d645812011-08-20 12:48:18 +02001957 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001958 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001959 /* This is needed to go with the CLONE_PTRACE
1960 changes in process.c/util.c: we might see
1961 the child's initial trap before we see the
1962 parent return from the clone syscall.
1963 Leave the child suspended until the parent
1964 returns from its system call. Only then
1965 will we have the association of parent and
1966 child so that we know how to do clearbpt
1967 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001968 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001969 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001970 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001971 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001972 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001973 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001974 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001975 else
1976 /* This can happen if a clone call used
1977 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001978 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001979 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001980 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001981 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001982 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001983 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001984
1985 /* Set current output file */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001986 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001987 curcol = tcp->curcol;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001988
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001989 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001990 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1991 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001992 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001993
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001994 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001995 if (pid == strace_child)
1996 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001997 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1999 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002000#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002001 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002002 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002003 WCOREDUMP(status) ? "(core dumped) " : "");
2004#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002005 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002006 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002007#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002008 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 }
2010 droptcb(tcp);
2011 continue;
2012 }
2013 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002014 if (pid == strace_child)
2015 exit_code = WEXITSTATUS(status);
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002016 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2017 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002018 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002019 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002020 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 droptcb(tcp);
2022 continue;
2023 }
2024 if (!WIFSTOPPED(status)) {
2025 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2026 droptcb(tcp);
2027 continue;
2028 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002030 /* Is this the very first time we see this tracee stopped? */
2031 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002032 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002033 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002036 /*
2037 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002038 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002039 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002040 if (clearbpt(tcp) < 0) {
2041 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042 droptcb(tcp);
2043 cleanup();
2044 return -1;
2045 }
2046 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002047 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002048 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002049 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2050 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2051 if (errno != ESRCH) {
2052 /* Should never happen, really */
2053 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002054 }
2055 }
2056 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002057 }
2058
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002059 sig = WSTOPSIG(status);
2060
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002061 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002062 /* Ptrace event */
2063#ifdef USE_SEIZE
2064 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002065 /*
2066 * PTRACE_INTERRUPT-stop or group-stop.
2067 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2068 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002069 if (sig == SIGSTOP
2070 || sig == SIGTSTP
2071 || sig == SIGTTIN
2072 || sig == SIGTTOU
2073 ) {
2074 stopped = 1;
2075 goto show_stopsig;
2076 }
2077 }
2078#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002079 goto restart_tracee_with_sig_0;
2080 }
2081
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002082 /* Is this post-attach SIGSTOP?
2083 * Interestingly, the process may stop
2084 * with STOPSIG equal to some other signal
2085 * than SIGSTOP if we happend to attach
2086 * just before the process takes a signal.
2087 */
2088 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002089 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002090 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2091 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002092 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002093 }
2094
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002095 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002096 siginfo_t si;
2097
2098 /* Nonzero (true) if tracee is stopped by signal
2099 * (as opposed to "tracee received signal").
2100 */
2101 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002102#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002103 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002104#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002105 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002106 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002107#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002108 long pc = 0;
2109 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002110
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002111 upeek(tcp, PT_CR_IPSR, &psr);
2112 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002113
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002114# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002115 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002116# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002117# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002118#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002119# define PC_FORMAT_STR ""
2120# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002121#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002122 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002123 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002124 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002125 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002126 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002127 PC_FORMAT_ARG);
2128 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002129 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002130 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002131 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002132 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002133 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002134
2135 if (!stopped)
2136 /* It's signal-delivery-stop. Inject the signal */
2137 goto restart_tracee;
2138
2139 /* It's group-stop */
2140#ifdef USE_SEIZE
2141 if (use_seize) {
2142 /*
2143 * This ends ptrace-stop, but does *not* end group-stop.
2144 * This makes stopping signals work properly on straced process
2145 * (that is, process really stops. It used to continue to run).
2146 */
2147 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2148 cleanup();
2149 return -1;
2150 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002151 tcp->curcol = curcol;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002152 continue;
2153 }
2154 /* We don't have PTRACE_LISTEN support... */
2155#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002156 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002157 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002158
2159 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002160 if (interrupted)
2161 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002162
2163 /* This should be syscall entry or exit.
2164 * (Or it still can be that pesky post-execve SIGTRAP!)
2165 * Handle it.
2166 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002167 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2168 /* ptrace() failed in trace_syscall() with ESRCH.
2169 * Likely a result of process disappearing mid-flight.
2170 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002171 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002172 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002173 * We used to detach(tcp) here, but since we no longer
2174 * implement "detach before death" policy/hack,
2175 * we can let this process to report its death to us
2176 * normally, via WIFEXITED or WIFSIGNALED wait status.
2177 */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002178 tcp->curcol = curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002179 continue;
2180 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002181 restart_tracee_with_sig_0:
2182 sig = 0;
2183 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002184 /* Remember current print column before continuing. */
2185 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002186 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 cleanup();
2188 return -1;
2189 }
2190 }
2191 return 0;
2192}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002193
2194int
2195main(int argc, char *argv[])
2196{
2197 init(argc, argv);
2198
2199 /* Run main tracing loop */
2200 if (trace() < 0)
2201 return 1;
2202
2203 cleanup();
2204 fflush(NULL);
2205 if (exit_code > 0xff) {
2206 /* Avoid potential core file clobbering. */
2207 struct rlimit rlim = {0, 0};
2208 setrlimit(RLIMIT_CORE, &rlim);
2209
2210 /* Child was killed by a signal, mimic that. */
2211 exit_code &= 0xff;
2212 signal(exit_code, SIG_DFL);
2213 raise(exit_code);
2214 /* Paranoia - what if this signal is not fatal?
2215 Exit with 128 + signo then. */
2216 exit_code += 128;
2217 }
2218
2219 return exit_code;
2220}