blob: 799fce517c612b34c33eef0958b32272f5c7806e [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;
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000134static int acolumn = DEFAULT_ACOLUMN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200135static char *acolumn_spaces;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100136
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000137static char *outfname = NULL;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100138/* If -ff, points to stderr. Else, it's our common output log */
139static FILE *shared_log;
140
Denys Vlasenko000b6012012-01-28 01:25:03 +0100141struct tcb *printing_tcp = NULL;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100142static struct tcb *current_tcp;
143
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200144static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200145static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200146static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +0100148static unsigned os_release; /* generated from uname()'s u.release */
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100149
Denys Vlasenko4c196382012-01-04 15:11:09 +0100150static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100151static int trace(void);
152static void cleanup(void);
153static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154static sigset_t empty_set, blocked_set;
155
156#ifdef HAVE_SIG_ATOMIC_T
157static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100158#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100160#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100162#ifndef HAVE_STRERROR
163
164#if !HAVE_DECL_SYS_ERRLIST
165extern int sys_nerr;
166extern char *sys_errlist[];
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +0100167#endif
Denys Vlasenko2c4fb902012-03-15 17:24:49 +0100168
169const char *
170strerror(int err_no)
171{
172 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
173
174 if (err_no < 1 || err_no >= sys_nerr) {
175 sprintf(buf, "Unknown error %d", err_no);
176 return buf;
177 }
178 return sys_errlist[err_no];
179}
180
181#endif /* HAVE_STERRROR */
182
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200184usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185{
186 fprintf(ofp, "\
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +0200187usage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\
188 [-a column] [-o file] [-s strsize] [-P path]...\n\
189 -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
190 or: strace -c[df] [-I n] [-e expr]... [-O overhead] [-S sortby]\n\
191 -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000192-c -- count time, calls, and errors for each syscall and report summary\n\
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +0200193-C -- like -c but also print regular output\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100194-d -- enable debug output to stderr\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100195-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000196-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenko3e084ac2012-03-15 13:39:05 +0100197-F -- attempt to follow vforks (deprecated, use -f)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198-i -- print instruction pointer at time of syscall\n\
199-q -- suppress messages about attaching, detaching, etc.\n\
200-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100201-T -- print time spent in each syscall\n\
202-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000203-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000204-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +0200205-h -- print help message, -V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206-a column -- alignment COLUMN for printing syscall results (default %d)\n\
207-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
208 options: trace, abbrev, verbose, raw, signal, read, or write\n\
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +0200209-I interruptible --\n\
210 1: no signals are blocked\n\
211 2: fatal signals are blocked while decoding syscall (default)\n\
212 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
213 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
214 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215-o file -- send trace output to FILE instead of stderr\n\
216-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
217-p pid -- trace process with process id PID, may be repeated\n\
218-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
219-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
220-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000221-E var=val -- put var=val in the environment for command\n\
222-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000223-P path -- trace accesses to path\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100224"
225/* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000226-z -- print only succeeding syscalls\n\
Denys Vlasenko61e7aad2012-03-15 13:44:17 +0100227 */
228/* experimental, don't document it yet (option letter may change in the future!)
229-b -- detach on successful execve\n\
230 */
Roland McGrathde6e5332003-01-24 04:31:23 +0000231, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232 exit(exitval);
233}
234
Denys Vlasenko75422762011-05-27 14:36:01 +0200235static void die(void) __attribute__ ((noreturn));
236static void die(void)
237{
238 if (strace_tracer_pid == getpid()) {
239 cflag = 0;
240 cleanup();
241 }
242 exit(1);
243}
244
245static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200246{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100247 char *msg;
248
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000249 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100250
251 /* We want to print entire message with single fprintf to ensure
252 * message integrity if stderr is shared with other programs.
253 * Thus we use vasprintf + single fprintf.
254 */
255 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100256 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100257 if (err_no)
258 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
259 else
260 fprintf(stderr, "%s: %s\n", progname, msg);
261 free(msg);
262 } else {
263 /* malloc in vasprintf failed, try it without malloc */
264 fprintf(stderr, "%s: ", progname);
265 vfprintf(stderr, fmt, p);
266 if (err_no)
267 fprintf(stderr, ": %s\n", strerror(err_no));
268 else
269 putc('\n', stderr);
270 }
271 /* We don't switch stderr to buffered, thus fprintf(stderr)
272 * always flushes its output and this is not necessary: */
273 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200274}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200275
Denys Vlasenko75422762011-05-27 14:36:01 +0200276void error_msg(const char *fmt, ...)
277{
278 va_list p;
279 va_start(p, fmt);
280 verror_msg(0, fmt, p);
281 va_end(p);
282}
283
284void error_msg_and_die(const char *fmt, ...)
285{
286 va_list p;
287 va_start(p, fmt);
288 verror_msg(0, fmt, p);
289 die();
290}
291
292void perror_msg(const char *fmt, ...)
293{
294 va_list p;
295 va_start(p, fmt);
296 verror_msg(errno, fmt, p);
297 va_end(p);
298}
299
300void perror_msg_and_die(const char *fmt, ...)
301{
302 va_list p;
303 va_start(p, fmt);
304 verror_msg(errno, fmt, p);
305 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200306}
307
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200308void die_out_of_memory(void)
309{
310 static bool recursed = 0;
311 if (recursed)
312 exit(1);
313 recursed = 1;
314 error_msg_and_die("Out of memory");
315}
316
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000317static void
318error_opt_arg(int opt, const char *arg)
319{
320 error_msg_and_die("Invalid -%c argument: '%s'", opt, arg);
321}
322
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400323/* Glue for systems without a MMU that cannot provide fork() */
324#ifdef HAVE_FORK
325# define strace_vforked 0
326#else
327# define strace_vforked 1
328# define fork() vfork()
329#endif
330
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100331#ifdef USE_SEIZE
332static int
333ptrace_attach_or_seize(int pid)
334{
335 int r;
336 if (!use_seize)
337 return ptrace(PTRACE_ATTACH, pid, 0, 0);
Denys Vlasenko26bc0602012-07-10 16:36:32 +0200338 r = ptrace(PTRACE_SEIZE, pid, 0, 0);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100339 if (r)
340 return r;
341 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
342 return r;
343}
344#else
345# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
346#endif
347
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100348/*
349 * Used when we want to unblock stopped traced process.
350 * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
351 * Returns 0 on success or if error was ESRCH
352 * (presumably process was killed while we talk to it).
353 * Otherwise prints error message and returns -1.
354 */
355static int
356ptrace_restart(int op, struct tcb *tcp, int sig)
357{
358 int err;
359 const char *msg;
360
361 errno = 0;
362 ptrace(op, tcp->pid, (void *) 0, (long) sig);
363 err = errno;
Denys Vlasenko23506752012-03-21 10:32:49 +0100364 if (!err)
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100365 return 0;
366
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100367 msg = "SYSCALL";
368 if (op == PTRACE_CONT)
369 msg = "CONT";
370 if (op == PTRACE_DETACH)
371 msg = "DETACH";
372#ifdef PTRACE_LISTEN
373 if (op == PTRACE_LISTEN)
374 msg = "LISTEN";
375#endif
Denys Vlasenko23506752012-03-21 10:32:49 +0100376 /*
377 * Why curcol != 0? Otherwise sometimes we get this:
378 *
379 * 10252 kill(10253, SIGKILL) = 0
380 * <ptrace(SYSCALL,10252):No such process>10253 ...next decode...
381 *
382 * 10252 died after we retrieved syscall exit data,
383 * but before we tried to restart it. Log looks ugly.
384 */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100385 if (current_tcp && current_tcp->curcol != 0) {
Denys Vlasenko23506752012-03-21 10:32:49 +0100386 tprintf(" <ptrace(%s):%s>\n", msg, strerror(err));
387 line_ended();
388 }
389 if (err == ESRCH)
390 return 0;
391 errno = err;
Denys Vlasenko852f98a2012-03-20 16:26:25 +0100392 perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
393 return -1;
394}
395
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200396static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397set_cloexec_flag(int fd)
398{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200399 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200401 flags = fcntl(fd, F_GETFD);
402 if (flags < 0) {
403 /* Can happen only if fd is bad.
404 * Should never happen: if it does, we have a bug
405 * in the caller. Therefore we just abort
406 * instead of propagating the error.
407 */
408 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000409 }
410
411 newflags = flags | FD_CLOEXEC;
412 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200413 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000414
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200415 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000416}
417
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100418static void kill_save_errno(pid_t pid, int sig)
419{
420 int saved_errno = errno;
421
422 (void) kill(pid, sig);
423 errno = saved_errno;
424}
425
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100426/*
427 * When strace is setuid executable, we have to swap uids
428 * before and after filesystem and process management operations.
429 */
430static void
431swap_uid(void)
432{
433 int euid = geteuid(), uid = getuid();
434
435 if (euid != uid && setreuid(euid, uid) < 0) {
436 perror_msg_and_die("setreuid");
437 }
438}
439
440#if _LFS64_LARGEFILE
441# define fopen_for_output fopen64
442#else
443# define fopen_for_output fopen
444#endif
445
446static FILE *
447strace_fopen(const char *path)
448{
449 FILE *fp;
450
451 swap_uid();
452 fp = fopen_for_output(path, "w");
453 if (!fp)
454 perror_msg_and_die("Can't fopen '%s'", path);
455 swap_uid();
456 set_cloexec_flag(fileno(fp));
457 return fp;
458}
459
460static int popen_pid = 0;
461
462#ifndef _PATH_BSHELL
463# define _PATH_BSHELL "/bin/sh"
464#endif
465
466/*
467 * We cannot use standard popen(3) here because we have to distinguish
468 * popen child process from other processes we trace, and standard popen(3)
469 * does not export its child's pid.
470 */
471static FILE *
472strace_popen(const char *command)
473{
474 FILE *fp;
475 int fds[2];
476
477 swap_uid();
478 if (pipe(fds) < 0)
479 perror_msg_and_die("pipe");
480
481 set_cloexec_flag(fds[1]); /* never fails */
482
483 popen_pid = vfork();
484 if (popen_pid == -1)
485 perror_msg_and_die("vfork");
486
487 if (popen_pid == 0) {
488 /* child */
489 close(fds[1]);
490 if (fds[0] != 0) {
491 if (dup2(fds[0], 0))
492 perror_msg_and_die("dup2");
493 close(fds[0]);
494 }
495 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
496 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
497 }
498
499 /* parent */
500 close(fds[0]);
501 swap_uid();
502 fp = fdopen(fds[1], "w");
503 if (!fp)
504 die_out_of_memory();
505 return fp;
506}
507
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100508void
509tprintf(const char *fmt, ...)
510{
511 va_list args;
512
513 va_start(args, fmt);
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100514 if (current_tcp) {
Denys Vlasenko6e4f3c12012-04-16 18:22:19 +0200515 int n = strace_vfprintf(current_tcp->outf, fmt, args);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100516 if (n < 0) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100517 if (current_tcp->outf != stderr)
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100518 perror(outfname == NULL
519 ? "<writing to pipe>" : outfname);
520 } else
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100521 current_tcp->curcol += n;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100522 }
523 va_end(args);
524}
525
526void
527tprints(const char *str)
528{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100529 if (current_tcp) {
Denys Vlasenko142aee02012-04-16 18:10:15 +0200530 int n = fputs_unlocked(str, current_tcp->outf);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100531 if (n >= 0) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100532 current_tcp->curcol += strlen(str);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100533 return;
534 }
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100535 if (current_tcp->outf != stderr)
536 perror(!outfname ? "<writing to pipe>" : outfname);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100537 }
538}
539
540void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100541line_ended(void)
542{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100543 if (current_tcp) {
544 current_tcp->curcol = 0;
545 fflush(current_tcp->outf);
546 }
547 if (printing_tcp) {
548 printing_tcp->curcol = 0;
549 printing_tcp = NULL;
550 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100551}
552
553void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100554printleader(struct tcb *tcp)
555{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100556 /* If -ff, "previous tcb we printed" is always the same as current,
557 * because we have per-tcb output files.
558 */
559 if (followfork >= 2)
560 printing_tcp = tcp;
561
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100562 if (printing_tcp) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100563 current_tcp = printing_tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100564 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
565 /*
566 * case 1: we have a shared log (i.e. not -ff), and last line
567 * wasn't finished (same or different tcb, doesn't matter).
568 * case 2: split log, we are the same tcb, but our last line
569 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
570 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100571 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100572 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100573 }
574 }
575
576 printing_tcp = tcp;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100577 current_tcp = tcp;
578 current_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100579
580 if (print_pid_pfx)
581 tprintf("%-5d ", tcp->pid);
582 else if (nprocs > 1 && !outfname)
583 tprintf("[pid %5u] ", tcp->pid);
584
585 if (tflag) {
586 char str[sizeof("HH:MM:SS")];
587 struct timeval tv, dtv;
588 static struct timeval otv;
589
590 gettimeofday(&tv, NULL);
591 if (rflag) {
592 if (otv.tv_sec == 0)
593 otv = tv;
594 tv_sub(&dtv, &tv, &otv);
595 tprintf("%6ld.%06ld ",
596 (long) dtv.tv_sec, (long) dtv.tv_usec);
597 otv = tv;
598 }
599 else if (tflag > 2) {
600 tprintf("%ld.%06ld ",
601 (long) tv.tv_sec, (long) tv.tv_usec);
602 }
603 else {
604 time_t local = tv.tv_sec;
605 strftime(str, sizeof(str), "%T", localtime(&local));
606 if (tflag > 1)
607 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
608 else
609 tprintf("%s ", str);
610 }
611 }
612 if (iflag)
613 printcall(tcp);
614}
615
616void
617tabto(void)
618{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100619 if (current_tcp->curcol < acolumn)
620 tprints(acolumn_spaces + current_tcp->curcol);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100621}
622
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100623/* Should be only called directly *after successful attach* to a tracee.
624 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
625 * may create bogus empty FILE.<nonexistant_pid>, and then die.
626 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200627static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000628newoutf(struct tcb *tcp)
629{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100630 tcp->outf = shared_log; /* if not -ff mode, the same file is for all */
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100631 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000632 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000633 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200634 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000635 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000636}
637
Denys Vlasenko558e5122012-03-12 23:32:16 +0100638static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100639expand_tcbtab(void)
640{
641 /* Allocate some more TCBs and expand the table.
642 We don't want to relocate the TCBs because our
643 callers have pointers and it would be a pain.
644 So tcbtab is a table of pointers. Since we never
645 free the TCBs, we allocate a single chunk of many. */
646 int i = tcbtabsize;
647 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
648 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
649 if (!newtab || !newtcbs)
650 die_out_of_memory();
651 tcbtabsize *= 2;
652 tcbtab = newtab;
653 while (i < tcbtabsize)
654 tcbtab[i++] = newtcbs++;
655}
656
657static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100658alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100659{
660 int i;
661 struct tcb *tcp;
662
663 if (nprocs == tcbtabsize)
664 expand_tcbtab();
665
666 for (i = 0; i < tcbtabsize; i++) {
667 tcp = tcbtab[i];
668 if ((tcp->flags & TCB_INUSE) == 0) {
669 memset(tcp, 0, sizeof(*tcp));
670 tcp->pid = pid;
671 tcp->flags = TCB_INUSE;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100672#if SUPPORTED_PERSONALITIES > 1
673 tcp->currpers = current_personality;
674#endif
675 nprocs++;
676 if (debug_flag)
677 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100678 return tcp;
679 }
680 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100681 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100682}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100683
684static void
685droptcb(struct tcb *tcp)
686{
687 if (tcp->pid == 0)
688 return;
689
690 nprocs--;
691 if (debug_flag)
692 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
693
694 if (tcp->outf) {
Denys Vlasenko8511f2a2012-03-22 09:35:51 +0100695 if (followfork >= 2) {
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100696 if (tcp->curcol != 0)
697 fprintf(tcp->outf, " <detached ...>\n");
698 fclose(tcp->outf);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100699 } else {
700 if (printing_tcp == tcp && tcp->curcol != 0)
701 fprintf(tcp->outf, " <detached ...>\n");
702 fflush(tcp->outf);
703 }
704 }
705
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100706 if (current_tcp == tcp)
707 current_tcp = NULL;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100708 if (printing_tcp == tcp)
709 printing_tcp = NULL;
710
711 memset(tcp, 0, sizeof(*tcp));
712}
713
714/* detach traced process; continue with sig
715 * Never call DETACH twice on the same process as both unattached and
716 * attached-unstopped processes give the same ESRCH. For unattached process we
717 * would SIGSTOP it and wait for its SIGSTOP notification forever.
718 */
719static int
720detach(struct tcb *tcp)
721{
722 int error;
723 int status, sigstop_expected;
724
725 if (tcp->flags & TCB_BPTSET)
726 clearbpt(tcp);
727
728 /*
729 * Linux wrongly insists the child be stopped
730 * before detaching. Arghh. We go through hoops
731 * to make a clean break of things.
732 */
733#if defined(SPARC)
734#undef PTRACE_DETACH
735#define PTRACE_DETACH PTRACE_SUNDETACH
736#endif
737
738 error = 0;
739 sigstop_expected = 0;
740 if (tcp->flags & TCB_ATTACHED) {
741 /*
742 * We attached but possibly didn't see the expected SIGSTOP.
743 * We must catch exactly one as otherwise the detached process
744 * would be left stopped (process state T).
745 */
746 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
747 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
748 if (error == 0) {
749 /* On a clear day, you can see forever. */
750 }
751 else if (errno != ESRCH) {
752 /* Shouldn't happen. */
753 perror("detach: ptrace(PTRACE_DETACH, ...)");
754 }
755 else if (my_tkill(tcp->pid, 0) < 0) {
756 if (errno != ESRCH)
757 perror("detach: checking sanity");
758 }
759 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
760 if (errno != ESRCH)
761 perror("detach: stopping child");
762 }
763 else
764 sigstop_expected = 1;
765 }
766
767 if (sigstop_expected) {
768 for (;;) {
769#ifdef __WALL
770 if (waitpid(tcp->pid, &status, __WALL) < 0) {
771 if (errno == ECHILD) /* Already gone. */
772 break;
773 if (errno != EINVAL) {
774 perror("detach: waiting");
775 break;
776 }
777#endif /* __WALL */
778 /* No __WALL here. */
779 if (waitpid(tcp->pid, &status, 0) < 0) {
780 if (errno != ECHILD) {
781 perror("detach: waiting");
782 break;
783 }
784#ifdef __WCLONE
785 /* If no processes, try clones. */
786 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
787 if (errno != ECHILD)
788 perror("detach: waiting");
789 break;
790 }
791#endif /* __WCLONE */
792 }
793#ifdef __WALL
794 }
795#endif
796 if (!WIFSTOPPED(status)) {
797 /* Au revoir, mon ami. */
798 break;
799 }
800 if (WSTOPSIG(status) == SIGSTOP) {
801 ptrace_restart(PTRACE_DETACH, tcp, 0);
802 break;
803 }
804 error = ptrace_restart(PTRACE_CONT, tcp,
805 WSTOPSIG(status) == syscall_trap_sig ? 0
806 : WSTOPSIG(status));
807 if (error < 0)
808 break;
809 }
810 }
811
812 if (!qflag && (tcp->flags & TCB_ATTACHED))
813 fprintf(stderr, "Process %u detached\n", tcp->pid);
814
815 droptcb(tcp);
816
817 return error;
818}
819
820static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100821process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100822{
823 while (*opt) {
824 /*
825 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
826 * pidof uses space as delim, pgrep uses newline. :(
827 */
828 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100829 char *delim = opt + strcspn(opt, ", \n\t");
830 char c = *delim;
831
832 *delim = '\0';
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000833 pid = string_to_uint(opt);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100834 if (pid <= 0) {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000835 error_msg_and_die("Invalid process id: '%s'", opt);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100836 }
837 if (pid == strace_tracer_pid) {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000838 error_msg_and_die("I'm sorry, I can't let you do that, Dave.");
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100839 }
840 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100841 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100842 if (c == '\0')
843 break;
844 opt = delim + 1;
845 }
846}
847
Roland McGrath02203312007-06-11 22:06:31 +0000848static void
849startup_attach(void)
850{
851 int tcbi;
852 struct tcb *tcp;
853
854 /*
855 * Block user interruptions as we would leave the traced
856 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200857 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200858 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000859 */
860 if (interactive)
861 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
862
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000863 if (daemonized_tracer) {
864 pid_t pid = fork();
865 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200866 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000867 }
868 if (pid) { /* parent */
869 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200870 * Wait for grandchild to attach to straced process
871 * (grandparent). Grandchild SIGKILLs us after it attached.
872 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000873 * it proceeds to exec the straced program.
874 */
875 pause();
876 _exit(0); /* paranoia */
877 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200878 /* grandchild */
879 /* We will be the tracer process. Remember our new pid: */
880 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000881 }
882
Roland McGrath02203312007-06-11 22:06:31 +0000883 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
884 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200885
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100886 if (!(tcp->flags & TCB_INUSE))
887 continue;
888
Denys Vlasenkod116a732011-09-05 14:01:33 +0200889 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100890 if (tcp->flags & TCB_ATTACHED)
891 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200892
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000893 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000894 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000895 DIR *dir;
896
897 sprintf(procdir, "/proc/%d/task", tcp->pid);
898 dir = opendir(procdir);
899 if (dir != NULL) {
900 unsigned int ntid = 0, nerr = 0;
901 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200902
Roland McGrath02203312007-06-11 22:06:31 +0000903 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200904 struct tcb *cur_tcp;
905 int tid;
906
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000907 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000908 continue;
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000909 /* we trust /proc filesystem */
Roland McGrath02203312007-06-11 22:06:31 +0000910 tid = atoi(de->d_name);
911 if (tid <= 0)
912 continue;
913 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100914 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000915 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100916 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200917 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200918 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200919 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100920 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200921 fprintf(stderr, "attach to pid %d succeeded\n", tid);
922 cur_tcp = tcp;
923 if (tid != tcp->pid)
924 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100925 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100926 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000927 }
928 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200929 if (interactive) {
930 sigprocmask(SIG_SETMASK, &empty_set, NULL);
931 if (interrupted)
932 goto ret;
933 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
934 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000935 ntid -= nerr;
936 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000937 perror("attach: ptrace(PTRACE_ATTACH, ...)");
938 droptcb(tcp);
939 continue;
940 }
941 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000942 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100943? "Process %u attached with %u threads\n"
944: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200945 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000946 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100947 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200948 /* -p PID, we failed to attach to PID itself
949 * but did attach to some of its sibling threads.
950 * Drop PID's tcp.
951 */
952 droptcb(tcp);
953 }
Roland McGrath02203312007-06-11 22:06:31 +0000954 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000955 } /* if (opendir worked) */
956 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100957 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000958 perror("attach: ptrace(PTRACE_ATTACH, ...)");
959 droptcb(tcp);
960 continue;
961 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100962 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100963 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100964 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200965 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000966
967 if (daemonized_tracer) {
968 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000969 * Make parent go away.
970 * Also makes grandparent's wait() unblock.
971 */
972 kill(getppid(), SIGKILL);
973 }
974
Roland McGrath02203312007-06-11 22:06:31 +0000975 if (!qflag)
976 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100977 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000978 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200979 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000980
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200981 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000982 if (interactive)
983 sigprocmask(SIG_SETMASK, &empty_set, NULL);
984}
985
986static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200987startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000988{
989 struct stat statbuf;
990 const char *filename;
991 char pathname[MAXPATHLEN];
992 int pid = 0;
993 struct tcb *tcp;
994
995 filename = argv[0];
996 if (strchr(filename, '/')) {
997 if (strlen(filename) > sizeof pathname - 1) {
998 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200999 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001000 }
1001 strcpy(pathname, filename);
1002 }
1003#ifdef USE_DEBUGGING_EXEC
1004 /*
1005 * Debuggers customarily check the current directory
1006 * first regardless of the path but doing that gives
1007 * security geeks a panic attack.
1008 */
1009 else if (stat(filename, &statbuf) == 0)
1010 strcpy(pathname, filename);
1011#endif /* USE_DEBUGGING_EXEC */
1012 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +00001013 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +00001014 int m, n, len;
1015
1016 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +01001017 const char *colon = strchr(path, ':');
1018 if (colon) {
1019 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +00001020 m = n + 1;
1021 }
1022 else
1023 m = n = strlen(path);
1024 if (n == 0) {
1025 if (!getcwd(pathname, MAXPATHLEN))
1026 continue;
1027 len = strlen(pathname);
1028 }
1029 else if (n > sizeof pathname - 1)
1030 continue;
1031 else {
1032 strncpy(pathname, path, n);
1033 len = n;
1034 }
1035 if (len && pathname[len - 1] != '/')
1036 pathname[len++] = '/';
1037 strcpy(pathname + len, filename);
1038 if (stat(pathname, &statbuf) == 0 &&
1039 /* Accept only regular files
1040 with some execute bits set.
1041 XXX not perfect, might still fail */
1042 S_ISREG(statbuf.st_mode) &&
1043 (statbuf.st_mode & 0111))
1044 break;
1045 }
1046 }
1047 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001048 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001049 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001050 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001051 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001052 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001053 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001054 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1055 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001056 ) {
1057 pid = getpid();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001058 if (shared_log != stderr)
1059 close(fileno(shared_log));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001060 if (!daemonized_tracer && !use_seize) {
1061 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001062 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001063 }
Roland McGrath02203312007-06-11 22:06:31 +00001064 }
Roland McGrath02203312007-06-11 22:06:31 +00001065
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001066 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001067 uid_t run_euid = run_uid;
1068 gid_t run_egid = run_gid;
1069
1070 if (statbuf.st_mode & S_ISUID)
1071 run_euid = statbuf.st_uid;
1072 if (statbuf.st_mode & S_ISGID)
1073 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001074 /*
1075 * It is important to set groups before we
1076 * lose privileges on setuid.
1077 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001078 if (initgroups(username, run_gid) < 0) {
1079 perror_msg_and_die("initgroups");
1080 }
1081 if (setregid(run_gid, run_egid) < 0) {
1082 perror_msg_and_die("setregid");
1083 }
1084 if (setreuid(run_uid, run_euid) < 0) {
1085 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001086 }
1087 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001088 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +00001089 setreuid(run_uid, run_uid);
1090
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001091 if (!daemonized_tracer) {
1092 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001093 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001094 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001095 * the immediately following execve syscall.
1096 * Can't do this on NOMMU systems, we are after
1097 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001098 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001099 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001100 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001101 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001102 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001103 /* we depend on SIGCHLD set to SIG_DFL by init code */
1104 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001105 wait(NULL);
1106 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001107 }
Roland McGrath02203312007-06-11 22:06:31 +00001108
1109 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001110 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001111 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001112
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001113 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001114
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001115 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001116 if (!use_seize) {
1117 /* child did PTRACE_TRACEME, nothing to do in parent */
1118 } else {
1119 if (!strace_vforked) {
1120 /* Wait until child stopped itself */
1121 int status;
1122 while (waitpid(pid, &status, WSTOPPED) < 0) {
1123 if (errno == EINTR)
1124 continue;
1125 perror_msg_and_die("waitpid");
1126 }
1127 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
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("Unexpected wait status %x", status);
1130 }
1131 }
1132 /* Else: vforked case, we have no way to sync.
1133 * Just attach to it as soon as possible.
1134 * This means that we may miss a few first syscalls...
1135 */
1136
1137 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001138 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001139 perror_msg_and_die("Can't attach to %d", pid);
1140 }
1141 if (!strace_vforked)
1142 kill(pid, SIGCONT);
1143 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001144 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001145 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001146 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001147 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001148 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001149 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001150 }
1151 else {
1152 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1153 strace_tracer_pid = getpid();
1154 /* The tracee is our parent: */
1155 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001156 alloctcb(pid);
1157 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001158 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001159 }
Roland McGrath02203312007-06-11 22:06:31 +00001160}
1161
Wang Chaob13c0de2010-11-12 17:25:19 +08001162/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001163 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001164 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001165 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001166 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001167static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001168test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001169{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001170 int pid, expected_grandchild = 0, found_grandchild = 0;
1171 const unsigned int test_options = PTRACE_O_TRACECLONE |
1172 PTRACE_O_TRACEFORK |
1173 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001174
Denys Vlasenko5d645812011-08-20 12:48:18 +02001175 pid = fork();
1176 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001177 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001178 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001179 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001180 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001181 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1182 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001183 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001184 if (fork() < 0)
1185 perror_msg_and_die("fork");
1186 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001187 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001188
1189 while (1) {
1190 int status, tracee_pid;
1191
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001192 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001193 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001194 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001195 if (errno == EINTR)
1196 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001197 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001198 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001199 kill_save_errno(pid, SIGKILL);
1200 perror_msg_and_die("%s: unexpected wait result %d",
1201 __func__, tracee_pid);
1202 }
1203 if (WIFEXITED(status)) {
1204 if (WEXITSTATUS(status)) {
1205 if (tracee_pid != pid)
1206 kill_save_errno(pid, SIGKILL);
1207 error_msg_and_die("%s: unexpected exit status %u",
1208 __func__, WEXITSTATUS(status));
1209 }
1210 continue;
1211 }
1212 if (WIFSIGNALED(status)) {
1213 if (tracee_pid != pid)
1214 kill_save_errno(pid, SIGKILL);
1215 error_msg_and_die("%s: unexpected signal %u",
1216 __func__, WTERMSIG(status));
1217 }
1218 if (!WIFSTOPPED(status)) {
1219 if (tracee_pid != pid)
1220 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001221 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001222 error_msg_and_die("%s: unexpected wait status %x",
1223 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001224 }
1225 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001226 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001227 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1228 kill_save_errno(tracee_pid, SIGKILL);
1229 kill_save_errno(pid, SIGKILL);
1230 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001231 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001232 continue;
1233 }
1234 switch (WSTOPSIG(status)) {
1235 case SIGSTOP:
1236 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1237 && errno != EINVAL && errno != EIO)
1238 perror_msg("PTRACE_SETOPTIONS");
1239 break;
1240 case SIGTRAP:
1241 if (status >> 16 == PTRACE_EVENT_FORK) {
1242 long msg = 0;
1243
1244 if (ptrace(PTRACE_GETEVENTMSG, pid,
1245 NULL, (long) &msg) == 0)
1246 expected_grandchild = msg;
1247 }
1248 break;
1249 }
1250 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1251 kill_save_errno(pid, SIGKILL);
1252 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001253 }
1254 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001255 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001256 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001257 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001258 fprintf(stderr, "ptrace_setoptions = %#x\n",
1259 ptrace_setoptions);
1260 return;
1261 }
1262 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1263 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001264}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001265
1266/*
1267 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1268 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1269 * and then see whether it will stop with (SIGTRAP | 0x80).
1270 *
1271 * Use of this option enables correct handling of user-generated SIGTRAPs,
1272 * and SIGTRAPs generated by special instructions such as int3 on x86:
1273 * _start: .globl _start
1274 * int3
1275 * movl $42, %ebx
1276 * movl $1, %eax
1277 * int $0x80
1278 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1279 */
1280static void
1281test_ptrace_setoptions_for_all(void)
1282{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001283 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1284 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001285 int pid;
1286 int it_worked = 0;
1287
Mike Frysinger7ff5ed92012-04-05 01:52:25 -04001288 /* this fork test doesn't work on no-mmu systems */
1289 if (strace_vforked)
1290 return;
1291
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001292 pid = fork();
1293 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001294 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001295
1296 if (pid == 0) {
1297 pid = getpid();
1298 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001299 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001300 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1301 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001302 kill(pid, SIGSTOP);
1303 _exit(0); /* parent should see entry into this syscall */
1304 }
1305
1306 while (1) {
1307 int status, tracee_pid;
1308
1309 errno = 0;
1310 tracee_pid = wait(&status);
1311 if (tracee_pid <= 0) {
1312 if (errno == EINTR)
1313 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001314 kill_save_errno(pid, SIGKILL);
1315 perror_msg_and_die("%s: unexpected wait result %d",
1316 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001317 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001318 if (WIFEXITED(status)) {
1319 if (WEXITSTATUS(status) == 0)
1320 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001321 error_msg_and_die("%s: unexpected exit status %u",
1322 __func__, WEXITSTATUS(status));
1323 }
1324 if (WIFSIGNALED(status)) {
1325 error_msg_and_die("%s: unexpected signal %u",
1326 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001327 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001328 if (!WIFSTOPPED(status)) {
1329 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001330 error_msg_and_die("%s: unexpected wait status %x",
1331 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001332 }
1333 if (WSTOPSIG(status) == SIGSTOP) {
1334 /*
1335 * We don't check "options aren't accepted" error.
1336 * If it happens, we'll never get (SIGTRAP | 0x80),
1337 * and thus will decide to not use the option.
1338 * IOW: the outcome of the test will be correct.
1339 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001340 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1341 && errno != EINVAL && errno != EIO)
1342 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001343 }
1344 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1345 it_worked = 1;
1346 }
1347 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001348 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001349 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001350 }
1351 }
1352
1353 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001354 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001355 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001356 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001357 fprintf(stderr, "ptrace_setoptions = %#x\n",
1358 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001359 return;
1360 }
1361
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001362 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1363 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001364}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001365
1366# ifdef USE_SEIZE
1367static void
1368test_ptrace_seize(void)
1369{
1370 int pid;
1371
1372 pid = fork();
1373 if (pid < 0)
1374 perror_msg_and_die("fork");
1375
1376 if (pid == 0) {
1377 pause();
1378 _exit(0);
1379 }
1380
1381 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1382 * attaching tracee continues to run unless a trap condition occurs.
1383 * PTRACE_SEIZE doesn't affect signal or group stop state.
1384 */
Denys Vlasenko26bc0602012-07-10 16:36:32 +02001385 if (ptrace(PTRACE_SEIZE, pid, 0, 0) == 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001386 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001387 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001388 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1389 }
1390
1391 kill(pid, SIGKILL);
1392
1393 while (1) {
1394 int status, tracee_pid;
1395
1396 errno = 0;
1397 tracee_pid = waitpid(pid, &status, 0);
1398 if (tracee_pid <= 0) {
1399 if (errno == EINTR)
1400 continue;
1401 perror_msg_and_die("%s: unexpected wait result %d",
1402 __func__, tracee_pid);
1403 }
1404 if (WIFSIGNALED(status)) {
1405 return;
1406 }
1407 error_msg_and_die("%s: unexpected wait status %x",
1408 __func__, status);
1409 }
1410}
1411# else /* !USE_SEIZE */
1412# define test_ptrace_seize() ((void)0)
1413# endif
1414
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001415static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001416get_os_release(void)
1417{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001418 unsigned rel;
1419 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001420 struct utsname u;
1421 if (uname(&u) < 0)
1422 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001423 /* u.release has this form: "3.2.9[-some-garbage]" */
1424 rel = 0;
1425 p = u.release;
1426 for (;;) {
1427 if (!(*p >= '0' && *p <= '9'))
1428 error_msg_and_die("Bad OS release string: '%s'", u.release);
1429 /* Note: this open-codes KERNEL_VERSION(): */
1430 rel = (rel << 8) | atoi(p);
1431 if (rel >= KERNEL_VERSION(1,0,0))
1432 break;
1433 while (*p >= '0' && *p <= '9')
1434 p++;
Dmitry V. Levin0dbc80d2012-05-14 23:42:10 +00001435 if (*p != '.') {
1436 if (rel >= KERNEL_VERSION(0,1,0)) {
1437 /* "X.Y-something" means "X.Y.0" */
1438 rel <<= 8;
1439 break;
1440 }
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001441 error_msg_and_die("Bad OS release string: '%s'", u.release);
Dmitry V. Levin0dbc80d2012-05-14 23:42:10 +00001442 }
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001443 p++;
1444 }
1445 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001446}
1447
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001448/*
1449 * Initialization part of main() was eating much stack (~0.5k),
1450 * which was unused after init.
1451 * We can reuse it if we move init code into a separate function.
1452 *
1453 * Don't want main() to inline us and defeat the reason
1454 * we have a separate function.
1455 */
1456static void __attribute__ ((noinline))
1457init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 struct tcb *tcp;
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001460 int c, i;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001461 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462 struct sigaction sa;
1463
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001464 progname = argv[0] ? argv[0] : "strace";
1465
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001466 /* Make sure SIGCHLD has the default action so that waitpid
1467 definitely works without losing track of children. The user
1468 should not have given us a bogus state to inherit, but he might
1469 have. Arguably we should detect SIG_IGN here and pass it on
1470 to children, but probably noone really needs that. */
1471 signal(SIGCHLD, SIG_DFL);
1472
Denys Vlasenko75422762011-05-27 14:36:01 +02001473 strace_tracer_pid = getpid();
1474
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001475 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001476
Roland McGrathee9d4352002-12-18 04:16:10 +00001477 /* Allocate the initial tcbtab. */
1478 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001479 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001480 if (!tcbtab)
1481 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001482 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001483 if (!tcp)
1484 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001485 for (c = 0; c < tcbtabsize; c++)
1486 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001487
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001488 shared_log = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001489 set_sortby(DEFAULT_SORTBY);
1490 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 qualify("trace=all");
1492 qualify("abbrev=all");
1493 qualify("verbose=all");
1494 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001496 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001497 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001498 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001500 case 'b':
1501 detach_on_execve = 1;
1502 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001504 if (cflag == CFLAG_BOTH) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001505 error_msg_and_die("-c and -C are mutually exclusive");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001506 }
1507 cflag = CFLAG_ONLY_STATS;
1508 break;
1509 case 'C':
1510 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001511 error_msg_and_die("-c and -C are mutually exclusive");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001512 }
1513 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001514 break;
1515 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001516 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001518 case 'D':
1519 daemonized_tracer = 1;
1520 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001521 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001522 optF = 1;
1523 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524 case 'f':
1525 followfork++;
1526 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527 case 'h':
1528 usage(stdout, 0);
1529 break;
1530 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001531 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532 break;
1533 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001534 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535 break;
1536 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001537 rflag = 1;
1538 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539 case 't':
1540 tflag++;
1541 break;
1542 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001543 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544 break;
1545 case 'x':
1546 xflag++;
1547 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001548 case 'y':
1549 show_fd_path = 1;
1550 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551 case 'v':
1552 qualify("abbrev=none");
1553 break;
1554 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001555 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556 exit(0);
1557 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001558 case 'z':
1559 not_failing_only = 1;
1560 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561 case 'a':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001562 acolumn = string_to_uint(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001563 if (acolumn < 0)
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001564 error_opt_arg(c, optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565 break;
1566 case 'e':
1567 qualify(optarg);
1568 break;
1569 case 'o':
1570 outfname = strdup(optarg);
1571 break;
1572 case 'O':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001573 i = string_to_uint(optarg);
1574 if (i < 0)
1575 error_opt_arg(c, optarg);
1576 set_overhead(i);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577 break;
1578 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001579 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001581 case 'P':
1582 tracing_paths = 1;
1583 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001584 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001585 }
1586 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587 case 's':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001588 i = string_to_uint(optarg);
1589 if (i < 0)
1590 error_opt_arg(c, optarg);
1591 max_strlen = i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592 break;
1593 case 'S':
1594 set_sortby(optarg);
1595 break;
1596 case 'u':
1597 username = strdup(optarg);
1598 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001599 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001600 if (putenv(optarg) < 0)
1601 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001602 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001603 case 'I':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001604 opt_intr = string_to_uint(optarg);
1605 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS)
1606 error_opt_arg(c, optarg);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001607 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608 default:
1609 usage(stderr, 1);
1610 break;
1611 }
1612 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001613 argv += optind;
1614 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615
Denys Vlasenko102ec492011-08-25 01:27:59 +02001616 acolumn_spaces = malloc(acolumn + 1);
1617 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001618 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001619 memset(acolumn_spaces, ' ', acolumn);
1620 acolumn_spaces[acolumn] = '\0';
1621
Denys Vlasenko837399a2012-01-24 11:37:03 +01001622 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001623 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001624 usage(stderr, 1);
1625
Denys Vlasenkofd883382012-03-09 13:03:41 +01001626 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001627 error_msg_and_die("-D and -p are mutually exclusive");
Wang Chaod322a4b2010-08-05 14:30:11 +08001628 }
1629
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001630 if (!followfork)
1631 followfork = optF;
1632
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001633 if (followfork >= 2 && cflag) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001634 error_msg_and_die("(-c or -C) and -ff are mutually exclusive");
Roland McGrathcb9def62006-04-25 07:48:03 +00001635 }
1636
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637 /* See if they want to run as another user. */
1638 if (username != NULL) {
1639 struct passwd *pent;
1640
1641 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001642 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001644 pent = getpwnam(username);
1645 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001646 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647 }
1648 run_uid = pent->pw_uid;
1649 run_gid = pent->pw_gid;
1650 }
1651 else {
1652 run_uid = getuid();
1653 run_gid = getgid();
1654 }
1655
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001656 if (followfork)
1657 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001658 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001659 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001660
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661 /* Check if they want to redirect the output. */
1662 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001663 /* See if they want to pipe the output. */
1664 if (outfname[0] == '|' || outfname[0] == '!') {
1665 /*
1666 * We can't do the <outfname>.PID funny business
1667 * when using popen, so prohibit it.
1668 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001669 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001670 error_msg_and_die("Piping the output and -ff are mutually exclusive");
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001671 shared_log = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001672 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001673 else if (followfork < 2)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001674 shared_log = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001675 } else {
1676 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001677 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001678 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001679 }
1680
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001681 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001682 char *buf = malloc(BUFSIZ);
1683 if (!buf)
1684 die_out_of_memory();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001685 setvbuf(shared_log, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001686 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001687 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001688 if (!opt_intr)
1689 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001691 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001692 if (!opt_intr)
1693 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001694
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001695 /* argv[0] -pPID -oFILE Default interactive setting
1696 * yes 0 0 INTR_WHILE_WAIT
1697 * no 1 0 INTR_WHILE_WAIT
1698 * yes 0 1 INTR_NEVER
1699 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001700 */
1701
1702 /* STARTUP_CHILD must be called before the signal handlers get
1703 installed below as they are inherited into the spawned process.
1704 Also we do not need to be protected by them as during interruption
1705 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001706 if (argv[0]) {
1707 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001708 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001709 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711 sigemptyset(&empty_set);
1712 sigemptyset(&blocked_set);
1713 sa.sa_handler = SIG_IGN;
1714 sigemptyset(&sa.sa_mask);
1715 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001716 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1717 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1718 if (opt_intr != INTR_ANYWHERE) {
1719 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1720 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1721 /*
1722 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1723 * fatal signals are blocked while syscall stop is processed,
1724 * and acted on in between, when waiting for new syscall stops.
1725 * In non-interactive mode, signals are ignored.
1726 */
1727 if (opt_intr == INTR_WHILE_WAIT) {
1728 sigaddset(&blocked_set, SIGHUP);
1729 sigaddset(&blocked_set, SIGINT);
1730 sigaddset(&blocked_set, SIGQUIT);
1731 sigaddset(&blocked_set, SIGPIPE);
1732 sigaddset(&blocked_set, SIGTERM);
1733 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001734 }
1735 /* SIG_IGN, or set handler for these */
1736 sigaction(SIGHUP, &sa, NULL);
1737 sigaction(SIGINT, &sa, NULL);
1738 sigaction(SIGQUIT, &sa, NULL);
1739 sigaction(SIGPIPE, &sa, NULL);
1740 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001741 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001742 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001743 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001744
Denys Vlasenkofd883382012-03-09 13:03:41 +01001745 /* Do we want pids printed in our -o OUTFILE?
1746 * -ff: no (every pid has its own file); or
1747 * -f: yes (there can be more pids in the future); or
1748 * -p PID1,PID2: yes (there are already more than one pid)
1749 */
1750 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001751}
1752
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001753static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001754pid2tcb(int pid)
1755{
1756 int i;
1757
1758 if (pid <= 0)
1759 return NULL;
1760
1761 for (i = 0; i < tcbtabsize; i++) {
1762 struct tcb *tcp = tcbtab[i];
1763 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1764 return tcp;
1765 }
1766
1767 return NULL;
1768}
1769
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001771cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772{
1773 int i;
1774 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001775 int fatal_sig;
1776
1777 /* 'interrupted' is a volatile object, fetch it only once */
1778 fatal_sig = interrupted;
1779 if (!fatal_sig)
1780 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781
Roland McGrathee9d4352002-12-18 04:16:10 +00001782 for (i = 0; i < tcbtabsize; i++) {
1783 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784 if (!(tcp->flags & TCB_INUSE))
1785 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001786 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 fprintf(stderr,
1788 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001789 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001791 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001793 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 }
1795 if (cflag)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001796 call_summary(shared_log);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797}
1798
1799static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001800interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001802 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803}
1804
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001806trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001809 struct rusage *rup = cflag ? &ru : NULL;
1810# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001811 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001812# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813
Roland McGratheb9e2e82009-06-02 16:49:22 -07001814 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001815 int pid;
1816 int wait_errno;
1817 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001818 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001819 struct tcb *tcp;
1820 unsigned event;
1821
Denys Vlasenko222713a2009-03-17 14:29:59 +00001822 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001823 return 0;
1824 if (interactive)
1825 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001826# ifdef __WALL
1827 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001828 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001829 /* this kernel does not support __WALL */
1830 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001831 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001832 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001833 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001834 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001835 pid = wait4(-1, &status, __WCLONE, rup);
1836 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001837 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001838 }
1839 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001840# else
1841 pid = wait4(-1, &status, 0, rup);
1842# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001843 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001844 if (interactive)
1845 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001847 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001848 switch (wait_errno) {
1849 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001850 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001851 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852 /*
1853 * We would like to verify this case
1854 * but sometimes a race in Solbourne's
1855 * version of SunOS sometimes reports
1856 * ECHILD before sending us SIGCHILD.
1857 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001858 return 0;
1859 default:
1860 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001861 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001862 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001863 }
1864 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001865 if (pid == popen_pid) {
1866 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001867 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001868 continue;
1869 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001870
1871 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001872 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001873 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001874 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001875 strcpy(buf, "???");
1876 if (WIFSIGNALED(status))
1877#ifdef WCOREDUMP
1878 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1879 WCOREDUMP(status) ? "core," : "",
1880 signame(WTERMSIG(status)));
1881#else
1882 sprintf(buf, "WIFSIGNALED,sig=%s",
1883 signame(WTERMSIG(status)));
1884#endif
1885 if (WIFEXITED(status))
1886 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1887 if (WIFSTOPPED(status))
1888 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001889#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001890 if (WIFCONTINUED(status))
1891 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001892#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001893 evbuf[0] = '\0';
1894 if (event != 0) {
1895 static const char *const event_names[] = {
1896 [PTRACE_EVENT_CLONE] = "CLONE",
1897 [PTRACE_EVENT_FORK] = "FORK",
1898 [PTRACE_EVENT_VFORK] = "VFORK",
1899 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1900 [PTRACE_EVENT_EXEC] = "EXEC",
1901 [PTRACE_EVENT_EXIT] = "EXIT",
1902 };
1903 const char *e;
1904 if (event < ARRAY_SIZE(event_names))
1905 e = event_names[event];
1906 else {
1907 sprintf(buf, "?? (%u)", event);
1908 e = buf;
1909 }
1910 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1911 }
1912 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001913 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001915 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001916 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001917
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001918 if (!tcp) {
Roland McGrath41c48222008-07-18 00:25:10 +00001919 if (followfork) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001920 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001921 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001922 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001923 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001924 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001925 pid);
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001926 } else {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001927 /* This can happen if a clone call used
1928 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001929 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001930 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001931 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001932 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001933 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001934
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001935 /* Under Linux, execve changes pid to thread leader's pid,
1936 * and we see this changed pid on EVENT_EXEC and later,
1937 * execve sysexit. Leader "disappears" without exit
1938 * notification. Let user know that, drop leader's tcb,
1939 * and fix up pid in execve thread's tcb.
1940 * Effectively, execve thread's tcb replaces leader's tcb.
1941 *
1942 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1943 * on exit syscall) in multithreaded programs exactly
1944 * in order to handle this case.
1945 *
1946 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1947 * On 2.6 and earlier, it can return garbage.
1948 */
1949 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001950 FILE *fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001951 struct tcb *execve_thread;
1952 long old_pid = 0;
1953
1954 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0)
1955 goto dont_switch_tcbs;
1956 if (old_pid <= 0 || old_pid == pid)
1957 goto dont_switch_tcbs;
1958 execve_thread = pid2tcb(old_pid);
1959 /* It should be !NULL, but I feel paranoid */
1960 if (!execve_thread)
1961 goto dont_switch_tcbs;
1962
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001963 if (execve_thread->curcol != 0) {
1964 /*
1965 * One case we are here is -ff:
1966 * try "strace -oLOG -ff test/threaded_execve"
1967 */
1968 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001969 /*execve_thread->curcol = 0; - no need, see code below */
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001970 }
1971 /* Swap output FILEs (needed for -ff) */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001972 fp = execve_thread->outf;
1973 execve_thread->outf = tcp->outf;
1974 tcp->outf = fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001975 /* And their column positions */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001976 execve_thread->curcol = tcp->curcol;
1977 tcp->curcol = 0;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001978 /* Drop leader, but close execve'd thread outfile (if -ff) */
1979 droptcb(tcp);
1980 /* Switch to the thread, reusing leader's outfile and pid */
1981 tcp = execve_thread;
1982 tcp->pid = pid;
1983 if (cflag != CFLAG_ONLY_STATS) {
1984 printleader(tcp);
1985 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1986 line_ended();
1987 tcp->flags |= TCB_REPRINT;
1988 }
1989 }
1990 dont_switch_tcbs:
1991
1992 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1993 if (!skip_startup_execve)
1994 detach(tcp);
1995 /* This was initial execve for "strace PROG". Skip. */
1996 skip_startup_execve = 0;
1997 }
1998
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001999 /* Set current output file */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01002000 current_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002001
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002002 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002003 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2004 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002005 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002006
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002007 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002008 if (pid == strace_child)
2009 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002010 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2012 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002013#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002014 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002015 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002016 WCOREDUMP(status) ? "(core dumped) " : "");
2017#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002018 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002019 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002020#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002021 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002022 }
2023 droptcb(tcp);
2024 continue;
2025 }
2026 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002027 if (pid == strace_child)
2028 exit_code = WEXITSTATUS(status);
Denys Vlasenkob5e09082012-03-21 14:27:40 +01002029 if (cflag != CFLAG_ONLY_STATS) {
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002030 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002031 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002032 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002033 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 droptcb(tcp);
2035 continue;
2036 }
2037 if (!WIFSTOPPED(status)) {
2038 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2039 droptcb(tcp);
2040 continue;
2041 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002043 /* Is this the very first time we see this tracee stopped? */
2044 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002045 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002046 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002049 /*
2050 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002051 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002052 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002053 if (clearbpt(tcp) < 0) {
2054 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 droptcb(tcp);
2056 cleanup();
2057 return -1;
2058 }
2059 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002060 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002061 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002062 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2063 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2064 if (errno != ESRCH) {
2065 /* Should never happen, really */
2066 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002067 }
2068 }
2069 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002070 }
2071
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002072 sig = WSTOPSIG(status);
2073
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002074 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002075 /* Ptrace event */
2076#ifdef USE_SEIZE
Denys Vlasenko26bc0602012-07-10 16:36:32 +02002077 if (event == PTRACE_EVENT_STOP) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002078 /*
2079 * PTRACE_INTERRUPT-stop or group-stop.
2080 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2081 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002082 if (sig == SIGSTOP
2083 || sig == SIGTSTP
2084 || sig == SIGTTIN
2085 || sig == SIGTTOU
2086 ) {
2087 stopped = 1;
2088 goto show_stopsig;
2089 }
2090 }
2091#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002092 goto restart_tracee_with_sig_0;
2093 }
2094
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002095 /* Is this post-attach SIGSTOP?
2096 * Interestingly, the process may stop
2097 * with STOPSIG equal to some other signal
2098 * than SIGSTOP if we happend to attach
2099 * just before the process takes a signal.
2100 */
2101 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002102 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002103 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2104 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002105 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106 }
2107
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002108 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002109 siginfo_t si;
2110
2111 /* Nonzero (true) if tracee is stopped by signal
2112 * (as opposed to "tracee received signal").
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002113 * TODO: shouldn't we check for errno == EINVAL too?
2114 * We can get ESRCH instead, you know...
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002115 */
2116 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002117#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002118 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002119#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002120 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002121 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002122#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002123 long pc = 0;
2124 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002125
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002126 upeek(tcp, PT_CR_IPSR, &psr);
2127 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002128
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002129# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002130 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002131# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002132# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002133#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002134# define PC_FORMAT_STR ""
2135# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002136#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002137 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002138 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002139 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002140 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002141 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002142 PC_FORMAT_ARG);
2143 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002144 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002145 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002146 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002147 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002149
2150 if (!stopped)
2151 /* It's signal-delivery-stop. Inject the signal */
2152 goto restart_tracee;
2153
2154 /* It's group-stop */
2155#ifdef USE_SEIZE
2156 if (use_seize) {
2157 /*
2158 * This ends ptrace-stop, but does *not* end group-stop.
2159 * This makes stopping signals work properly on straced process
2160 * (that is, process really stops. It used to continue to run).
2161 */
2162 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2163 cleanup();
2164 return -1;
2165 }
2166 continue;
2167 }
2168 /* We don't have PTRACE_LISTEN support... */
2169#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002170 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002172
2173 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002174 if (interrupted)
2175 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002176
2177 /* This should be syscall entry or exit.
2178 * (Or it still can be that pesky post-execve SIGTRAP!)
2179 * Handle it.
2180 */
Denys Vlasenko23506752012-03-21 10:32:49 +01002181 if (trace_syscall(tcp) < 0) {
2182 /* ptrace() failed in trace_syscall().
Roland McGratheb9e2e82009-06-02 16:49:22 -07002183 * Likely a result of process disappearing mid-flight.
Denys Vlasenko23506752012-03-21 10:32:49 +01002184 * Observed case: exit_group() or SIGKILL terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002185 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002186 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002187 * We used to detach(tcp) here, but since we no longer
2188 * implement "detach before death" policy/hack,
2189 * we can let this process to report its death to us
2190 * normally, via WIFEXITED or WIFSIGNALED wait status.
2191 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192 continue;
2193 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002194 restart_tracee_with_sig_0:
2195 sig = 0;
2196 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002197 /* Remember current print column before continuing. */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002198 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199 cleanup();
2200 return -1;
2201 }
2202 }
2203 return 0;
2204}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002205
2206int
2207main(int argc, char *argv[])
2208{
2209 init(argc, argv);
2210
2211 /* Run main tracing loop */
2212 if (trace() < 0)
2213 return 1;
2214
2215 cleanup();
2216 fflush(NULL);
Dmitry V. Levincf534362012-07-12 20:54:46 +00002217 if (shared_log != stderr)
2218 fclose(shared_log);
2219 if (popen_pid) {
2220 while (waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR)
2221 ;
2222 }
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002223 if (exit_code > 0xff) {
2224 /* Avoid potential core file clobbering. */
2225 struct rlimit rlim = {0, 0};
2226 setrlimit(RLIMIT_CORE, &rlim);
2227
2228 /* Child was killed by a signal, mimic that. */
2229 exit_code &= 0xff;
2230 signal(exit_code, SIG_DFL);
2231 raise(exit_code);
2232 /* Paranoia - what if this signal is not fatal?
2233 Exit with 128 + signo then. */
2234 exit_code += 128;
2235 }
2236
2237 return exit_code;
2238}