blob: 3df3fbb51c06281ae9965a514e9f414ae221d42e [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). */
Denys Vlasenko978fbc92012-09-13 10:28:43 +020057# warning "tkill(2) not available, risk of strace hangs!"
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +010058# 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)
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000518 perror_msg("%s", outfname);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100519 } else
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100520 current_tcp->curcol += n;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100521 }
522 va_end(args);
523}
524
525void
526tprints(const char *str)
527{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100528 if (current_tcp) {
Denys Vlasenko142aee02012-04-16 18:10:15 +0200529 int n = fputs_unlocked(str, current_tcp->outf);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100530 if (n >= 0) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100531 current_tcp->curcol += strlen(str);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100532 return;
533 }
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100534 if (current_tcp->outf != stderr)
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000535 perror_msg("%s", outfname);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100536 }
537}
538
539void
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100540line_ended(void)
541{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100542 if (current_tcp) {
543 current_tcp->curcol = 0;
544 fflush(current_tcp->outf);
545 }
546 if (printing_tcp) {
547 printing_tcp->curcol = 0;
548 printing_tcp = NULL;
549 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100550}
551
552void
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100553printleader(struct tcb *tcp)
554{
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100555 /* If -ff, "previous tcb we printed" is always the same as current,
556 * because we have per-tcb output files.
557 */
558 if (followfork >= 2)
559 printing_tcp = tcp;
560
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100561 if (printing_tcp) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100562 current_tcp = printing_tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100563 if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
564 /*
565 * case 1: we have a shared log (i.e. not -ff), and last line
566 * wasn't finished (same or different tcb, doesn't matter).
567 * case 2: split log, we are the same tcb, but our last line
568 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
569 */
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100570 tprints(" <unfinished ...>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +0100571 printing_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100572 }
573 }
574
575 printing_tcp = tcp;
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100576 current_tcp = tcp;
577 current_tcp->curcol = 0;
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100578
579 if (print_pid_pfx)
580 tprintf("%-5d ", tcp->pid);
581 else if (nprocs > 1 && !outfname)
582 tprintf("[pid %5u] ", tcp->pid);
583
584 if (tflag) {
585 char str[sizeof("HH:MM:SS")];
586 struct timeval tv, dtv;
587 static struct timeval otv;
588
589 gettimeofday(&tv, NULL);
590 if (rflag) {
591 if (otv.tv_sec == 0)
592 otv = tv;
593 tv_sub(&dtv, &tv, &otv);
594 tprintf("%6ld.%06ld ",
595 (long) dtv.tv_sec, (long) dtv.tv_usec);
596 otv = tv;
597 }
598 else if (tflag > 2) {
599 tprintf("%ld.%06ld ",
600 (long) tv.tv_sec, (long) tv.tv_usec);
601 }
602 else {
603 time_t local = tv.tv_sec;
604 strftime(str, sizeof(str), "%T", localtime(&local));
605 if (tflag > 1)
606 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
607 else
608 tprintf("%s ", str);
609 }
610 }
611 if (iflag)
612 printcall(tcp);
613}
614
615void
616tabto(void)
617{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100618 if (current_tcp->curcol < acolumn)
619 tprints(acolumn_spaces + current_tcp->curcol);
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100620}
621
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100622/* Should be only called directly *after successful attach* to a tracee.
623 * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
624 * may create bogus empty FILE.<nonexistant_pid>, and then die.
625 */
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200626static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000627newoutf(struct tcb *tcp)
628{
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100629 tcp->outf = shared_log; /* if not -ff mode, the same file is for all */
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100630 if (followfork >= 2) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000631 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000632 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200633 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000634 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000635}
636
Denys Vlasenko558e5122012-03-12 23:32:16 +0100637static void
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100638expand_tcbtab(void)
639{
640 /* Allocate some more TCBs and expand the table.
641 We don't want to relocate the TCBs because our
642 callers have pointers and it would be a pain.
643 So tcbtab is a table of pointers. Since we never
644 free the TCBs, we allocate a single chunk of many. */
645 int i = tcbtabsize;
646 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
647 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
648 if (!newtab || !newtcbs)
649 die_out_of_memory();
650 tcbtabsize *= 2;
651 tcbtab = newtab;
652 while (i < tcbtabsize)
653 tcbtab[i++] = newtcbs++;
654}
655
656static struct tcb *
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100657alloctcb(int pid)
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100658{
659 int i;
660 struct tcb *tcp;
661
662 if (nprocs == tcbtabsize)
663 expand_tcbtab();
664
665 for (i = 0; i < tcbtabsize; i++) {
666 tcp = tcbtab[i];
667 if ((tcp->flags & TCB_INUSE) == 0) {
668 memset(tcp, 0, sizeof(*tcp));
669 tcp->pid = pid;
670 tcp->flags = TCB_INUSE;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100671#if SUPPORTED_PERSONALITIES > 1
672 tcp->currpers = current_personality;
673#endif
674 nprocs++;
675 if (debug_flag)
676 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100677 return tcp;
678 }
679 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100680 error_msg_and_die("bug in alloctcb");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100681}
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100682
683static void
684droptcb(struct tcb *tcp)
685{
686 if (tcp->pid == 0)
687 return;
688
689 nprocs--;
690 if (debug_flag)
691 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
692
693 if (tcp->outf) {
Denys Vlasenko8511f2a2012-03-22 09:35:51 +0100694 if (followfork >= 2) {
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100695 if (tcp->curcol != 0)
696 fprintf(tcp->outf, " <detached ...>\n");
697 fclose(tcp->outf);
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100698 } else {
699 if (printing_tcp == tcp && tcp->curcol != 0)
700 fprintf(tcp->outf, " <detached ...>\n");
701 fflush(tcp->outf);
702 }
703 }
704
Denys Vlasenko6764f8f2012-03-22 09:56:20 +0100705 if (current_tcp == tcp)
706 current_tcp = NULL;
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100707 if (printing_tcp == tcp)
708 printing_tcp = NULL;
709
710 memset(tcp, 0, sizeof(*tcp));
711}
712
713/* detach traced process; continue with sig
714 * Never call DETACH twice on the same process as both unattached and
715 * attached-unstopped processes give the same ESRCH. For unattached process we
716 * would SIGSTOP it and wait for its SIGSTOP notification forever.
717 */
718static int
719detach(struct tcb *tcp)
720{
721 int error;
722 int status, sigstop_expected;
723
724 if (tcp->flags & TCB_BPTSET)
725 clearbpt(tcp);
726
727 /*
728 * Linux wrongly insists the child be stopped
729 * before detaching. Arghh. We go through hoops
730 * to make a clean break of things.
731 */
732#if defined(SPARC)
Denys Vlasenko978fbc92012-09-13 10:28:43 +0200733# undef PTRACE_DETACH
734# define PTRACE_DETACH PTRACE_SUNDETACH
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100735#endif
736
737 error = 0;
738 sigstop_expected = 0;
739 if (tcp->flags & TCB_ATTACHED) {
740 /*
741 * We attached but possibly didn't see the expected SIGSTOP.
742 * We must catch exactly one as otherwise the detached process
743 * would be left stopped (process state T).
744 */
745 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
746 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
747 if (error == 0) {
748 /* On a clear day, you can see forever. */
749 }
750 else if (errno != ESRCH) {
751 /* Shouldn't happen. */
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000752 perror_msg("%s", "detach: ptrace(PTRACE_DETACH, ...)");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100753 }
754 else if (my_tkill(tcp->pid, 0) < 0) {
755 if (errno != ESRCH)
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000756 perror_msg("%s", "detach: checking sanity");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100757 }
758 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
759 if (errno != ESRCH)
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000760 perror_msg("%s", "detach: stopping child");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100761 }
762 else
763 sigstop_expected = 1;
764 }
765
766 if (sigstop_expected) {
767 for (;;) {
768#ifdef __WALL
769 if (waitpid(tcp->pid, &status, __WALL) < 0) {
770 if (errno == ECHILD) /* Already gone. */
771 break;
772 if (errno != EINVAL) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000773 perror_msg("%s", "detach: waiting");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100774 break;
775 }
776#endif /* __WALL */
777 /* No __WALL here. */
778 if (waitpid(tcp->pid, &status, 0) < 0) {
779 if (errno != ECHILD) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000780 perror_msg("%s", "detach: waiting");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100781 break;
782 }
783#ifdef __WCLONE
784 /* If no processes, try clones. */
785 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
786 if (errno != ECHILD)
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000787 perror_msg("%s", "detach: waiting");
Denys Vlasenko800ec8f2012-03-16 15:11:34 +0100788 break;
789 }
790#endif /* __WCLONE */
791 }
792#ifdef __WALL
793 }
794#endif
795 if (!WIFSTOPPED(status)) {
796 /* Au revoir, mon ami. */
797 break;
798 }
799 if (WSTOPSIG(status) == SIGSTOP) {
800 ptrace_restart(PTRACE_DETACH, tcp, 0);
801 break;
802 }
803 error = ptrace_restart(PTRACE_CONT, tcp,
804 WSTOPSIG(status) == syscall_trap_sig ? 0
805 : WSTOPSIG(status));
806 if (error < 0)
807 break;
808 }
809 }
810
811 if (!qflag && (tcp->flags & TCB_ATTACHED))
812 fprintf(stderr, "Process %u detached\n", tcp->pid);
813
814 droptcb(tcp);
815
816 return error;
817}
818
819static void
Denys Vlasenko558e5122012-03-12 23:32:16 +0100820process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100821{
822 while (*opt) {
823 /*
824 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
825 * pidof uses space as delim, pgrep uses newline. :(
826 */
827 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100828 char *delim = opt + strcspn(opt, ", \n\t");
829 char c = *delim;
830
831 *delim = '\0';
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000832 pid = string_to_uint(opt);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100833 if (pid <= 0) {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000834 error_msg_and_die("Invalid process id: '%s'", opt);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100835 }
836 if (pid == strace_tracer_pid) {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000837 error_msg_and_die("I'm sorry, I can't let you do that, Dave.");
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100838 }
839 *delim = c;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100840 alloctcb(pid);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100841 if (c == '\0')
842 break;
843 opt = delim + 1;
844 }
845}
846
Roland McGrath02203312007-06-11 22:06:31 +0000847static void
848startup_attach(void)
849{
850 int tcbi;
851 struct tcb *tcp;
852
853 /*
854 * Block user interruptions as we would leave the traced
855 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200856 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200857 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000858 */
859 if (interactive)
860 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
861
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000862 if (daemonized_tracer) {
863 pid_t pid = fork();
864 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200865 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000866 }
867 if (pid) { /* parent */
868 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200869 * Wait for grandchild to attach to straced process
870 * (grandparent). Grandchild SIGKILLs us after it attached.
871 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000872 * it proceeds to exec the straced program.
873 */
874 pause();
875 _exit(0); /* paranoia */
876 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200877 /* grandchild */
878 /* We will be the tracer process. Remember our new pid: */
879 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000880 }
881
Roland McGrath02203312007-06-11 22:06:31 +0000882 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
883 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200884
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100885 if (!(tcp->flags & TCB_INUSE))
886 continue;
887
Denys Vlasenkod116a732011-09-05 14:01:33 +0200888 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100889 if (tcp->flags & TCB_ATTACHED)
890 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200891
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000892 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000893 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000894 DIR *dir;
895
896 sprintf(procdir, "/proc/%d/task", tcp->pid);
897 dir = opendir(procdir);
898 if (dir != NULL) {
899 unsigned int ntid = 0, nerr = 0;
900 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200901
Roland McGrath02203312007-06-11 22:06:31 +0000902 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200903 struct tcb *cur_tcp;
904 int tid;
905
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000906 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000907 continue;
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000908 /* we trust /proc filesystem */
Roland McGrath02203312007-06-11 22:06:31 +0000909 tid = atoi(de->d_name);
910 if (tid <= 0)
911 continue;
912 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100913 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000914 ++nerr;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100915 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200916 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200917 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200918 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100919 if (debug_flag)
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200920 fprintf(stderr, "attach to pid %d succeeded\n", tid);
921 cur_tcp = tcp;
922 if (tid != tcp->pid)
923 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100924 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100925 newoutf(cur_tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000926 }
927 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200928 if (interactive) {
929 sigprocmask(SIG_SETMASK, &empty_set, NULL);
930 if (interrupted)
931 goto ret;
932 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
933 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000934 ntid -= nerr;
935 if (ntid == 0) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000936 perror_msg("%s", "attach: ptrace(PTRACE_ATTACH, ...)");
Roland McGrath02203312007-06-11 22:06:31 +0000937 droptcb(tcp);
938 continue;
939 }
940 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000941 fprintf(stderr, ntid > 1
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100942? "Process %u attached with %u threads\n"
943: "Process %u attached\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200944 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000945 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100946 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200947 /* -p PID, we failed to attach to PID itself
948 * but did attach to some of its sibling threads.
949 * Drop PID's tcp.
950 */
951 droptcb(tcp);
952 }
Roland McGrath02203312007-06-11 22:06:31 +0000953 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000954 } /* if (opendir worked) */
955 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100956 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000957 perror_msg("%s", "attach: ptrace(PTRACE_ATTACH, ...)");
Roland McGrath02203312007-06-11 22:06:31 +0000958 droptcb(tcp);
959 continue;
960 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100961 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +0100962 newoutf(tcp);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100963 if (debug_flag)
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200964 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000965
966 if (daemonized_tracer) {
967 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000968 * Make parent go away.
969 * Also makes grandparent's wait() unblock.
970 */
971 kill(getppid(), SIGKILL);
972 }
973
Roland McGrath02203312007-06-11 22:06:31 +0000974 if (!qflag)
975 fprintf(stderr,
Denys Vlasenko9c3861d2012-03-16 15:21:49 +0100976 "Process %u attached\n",
Roland McGrath02203312007-06-11 22:06:31 +0000977 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200978 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000979
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200980 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000981 if (interactive)
982 sigprocmask(SIG_SETMASK, &empty_set, NULL);
983}
984
985static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200986startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000987{
988 struct stat statbuf;
989 const char *filename;
990 char pathname[MAXPATHLEN];
991 int pid = 0;
992 struct tcb *tcp;
993
994 filename = argv[0];
995 if (strchr(filename, '/')) {
996 if (strlen(filename) > sizeof pathname - 1) {
997 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200998 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000999 }
1000 strcpy(pathname, filename);
1001 }
1002#ifdef USE_DEBUGGING_EXEC
1003 /*
1004 * Debuggers customarily check the current directory
1005 * first regardless of the path but doing that gives
1006 * security geeks a panic attack.
1007 */
1008 else if (stat(filename, &statbuf) == 0)
1009 strcpy(pathname, filename);
1010#endif /* USE_DEBUGGING_EXEC */
1011 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +00001012 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +00001013 int m, n, len;
1014
1015 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +01001016 const char *colon = strchr(path, ':');
1017 if (colon) {
1018 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +00001019 m = n + 1;
1020 }
1021 else
1022 m = n = strlen(path);
1023 if (n == 0) {
1024 if (!getcwd(pathname, MAXPATHLEN))
1025 continue;
1026 len = strlen(pathname);
1027 }
1028 else if (n > sizeof pathname - 1)
1029 continue;
1030 else {
1031 strncpy(pathname, path, n);
1032 len = n;
1033 }
1034 if (len && pathname[len - 1] != '/')
1035 pathname[len++] = '/';
1036 strcpy(pathname + len, filename);
1037 if (stat(pathname, &statbuf) == 0 &&
1038 /* Accept only regular files
1039 with some execute bits set.
1040 XXX not perfect, might still fail */
1041 S_ISREG(statbuf.st_mode) &&
1042 (statbuf.st_mode & 0111))
1043 break;
1044 }
1045 }
1046 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001047 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +00001048 }
Dmitry V. Levina6809652008-11-10 17:14:58 +00001049 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001050 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001051 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001052 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001053 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
1054 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001055 ) {
1056 pid = getpid();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001057 if (shared_log != stderr)
1058 close(fileno(shared_log));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001059 if (!daemonized_tracer && !use_seize) {
1060 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001061 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001062 }
Roland McGrath02203312007-06-11 22:06:31 +00001063 }
Roland McGrath02203312007-06-11 22:06:31 +00001064
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001065 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +00001066 uid_t run_euid = run_uid;
1067 gid_t run_egid = run_gid;
1068
1069 if (statbuf.st_mode & S_ISUID)
1070 run_euid = statbuf.st_uid;
1071 if (statbuf.st_mode & S_ISGID)
1072 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +00001073 /*
1074 * It is important to set groups before we
1075 * lose privileges on setuid.
1076 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001077 if (initgroups(username, run_gid) < 0) {
1078 perror_msg_and_die("initgroups");
1079 }
1080 if (setregid(run_gid, run_egid) < 0) {
1081 perror_msg_and_die("setregid");
1082 }
1083 if (setreuid(run_uid, run_euid) < 0) {
1084 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +00001085 }
1086 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +02001087 else if (geteuid() != 0)
Dmitry V. Levin508279c2012-08-24 17:56:53 +00001088 if (setreuid(run_uid, run_uid) < 0) {
1089 perror_msg_and_die("setreuid");
1090 }
Roland McGrath02203312007-06-11 22:06:31 +00001091
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001092 if (!daemonized_tracer) {
1093 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001094 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001095 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001096 * the immediately following execve syscall.
1097 * Can't do this on NOMMU systems, we are after
1098 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001099 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04001100 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001101 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001102 } else {
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001103 alarm(3);
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001104 /* we depend on SIGCHLD set to SIG_DFL by init code */
1105 /* if it happens to be SIG_IGN'ed, wait won't block */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001106 wait(NULL);
1107 alarm(0);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001108 }
Roland McGrath02203312007-06-11 22:06:31 +00001109
1110 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001111 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +00001112 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001113
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001114 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +02001115
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001116 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001117 if (!use_seize) {
1118 /* child did PTRACE_TRACEME, nothing to do in parent */
1119 } else {
1120 if (!strace_vforked) {
1121 /* Wait until child stopped itself */
1122 int status;
1123 while (waitpid(pid, &status, WSTOPPED) < 0) {
1124 if (errno == EINTR)
1125 continue;
1126 perror_msg_and_die("waitpid");
1127 }
1128 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001129 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001130 perror_msg_and_die("Unexpected wait status %x", status);
1131 }
1132 }
1133 /* Else: vforked case, we have no way to sync.
1134 * Just attach to it as soon as possible.
1135 * This means that we may miss a few first syscalls...
1136 */
1137
1138 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001139 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001140 perror_msg_and_die("Can't attach to %d", pid);
1141 }
1142 if (!strace_vforked)
1143 kill(pid, SIGCONT);
1144 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001145 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001146 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001147 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001148 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001149 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001150 newoutf(tcp);
Denys Vlasenko2e968c02011-09-01 10:23:09 +02001151 }
1152 else {
1153 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
1154 strace_tracer_pid = getpid();
1155 /* The tracee is our parent: */
1156 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +01001157 alloctcb(pid);
1158 /* attaching will be done later, by startup_attach */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001159 /* note: we don't do newoutf(tcp) here either! */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001160 }
Roland McGrath02203312007-06-11 22:06:31 +00001161}
1162
Wang Chaob13c0de2010-11-12 17:25:19 +08001163/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001164 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +08001165 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001166 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +08001167 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001168static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001169test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +08001170{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001171 int pid, expected_grandchild = 0, found_grandchild = 0;
1172 const unsigned int test_options = PTRACE_O_TRACECLONE |
1173 PTRACE_O_TRACEFORK |
1174 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +08001175
Denys Vlasenko5d645812011-08-20 12:48:18 +02001176 pid = fork();
1177 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001178 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +02001179 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001180 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001181 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001182 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1183 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001184 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001185 if (fork() < 0)
1186 perror_msg_and_die("fork");
1187 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +08001188 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001189
1190 while (1) {
1191 int status, tracee_pid;
1192
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001193 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001194 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001195 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001196 if (errno == EINTR)
1197 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001198 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001199 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001200 kill_save_errno(pid, SIGKILL);
1201 perror_msg_and_die("%s: unexpected wait result %d",
1202 __func__, tracee_pid);
1203 }
1204 if (WIFEXITED(status)) {
1205 if (WEXITSTATUS(status)) {
1206 if (tracee_pid != pid)
1207 kill_save_errno(pid, SIGKILL);
1208 error_msg_and_die("%s: unexpected exit status %u",
1209 __func__, WEXITSTATUS(status));
1210 }
1211 continue;
1212 }
1213 if (WIFSIGNALED(status)) {
1214 if (tracee_pid != pid)
1215 kill_save_errno(pid, SIGKILL);
1216 error_msg_and_die("%s: unexpected signal %u",
1217 __func__, WTERMSIG(status));
1218 }
1219 if (!WIFSTOPPED(status)) {
1220 if (tracee_pid != pid)
1221 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001222 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001223 error_msg_and_die("%s: unexpected wait status %x",
1224 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +00001225 }
1226 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00001227 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001228 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
1229 kill_save_errno(tracee_pid, SIGKILL);
1230 kill_save_errno(pid, SIGKILL);
1231 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001232 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001233 continue;
1234 }
1235 switch (WSTOPSIG(status)) {
1236 case SIGSTOP:
1237 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
1238 && errno != EINVAL && errno != EIO)
1239 perror_msg("PTRACE_SETOPTIONS");
1240 break;
1241 case SIGTRAP:
1242 if (status >> 16 == PTRACE_EVENT_FORK) {
1243 long msg = 0;
1244
1245 if (ptrace(PTRACE_GETEVENTMSG, pid,
1246 NULL, (long) &msg) == 0)
1247 expected_grandchild = msg;
1248 }
1249 break;
1250 }
1251 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
1252 kill_save_errno(pid, SIGKILL);
1253 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +08001254 }
1255 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001256 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001257 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001258 if (debug_flag)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001259 fprintf(stderr, "ptrace_setoptions = %#x\n",
1260 ptrace_setoptions);
1261 return;
1262 }
1263 error_msg("Test for PTRACE_O_TRACECLONE failed, "
1264 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +08001265}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001266
1267/*
1268 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
1269 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
1270 * and then see whether it will stop with (SIGTRAP | 0x80).
1271 *
1272 * Use of this option enables correct handling of user-generated SIGTRAPs,
1273 * and SIGTRAPs generated by special instructions such as int3 on x86:
1274 * _start: .globl _start
1275 * int3
1276 * movl $42, %ebx
1277 * movl $1, %eax
1278 * int $0x80
1279 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1280 */
1281static void
1282test_ptrace_setoptions_for_all(void)
1283{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001284 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1285 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001286 int pid;
1287 int it_worked = 0;
1288
Mike Frysinger7ff5ed92012-04-05 01:52:25 -04001289 /* this fork test doesn't work on no-mmu systems */
1290 if (strace_vforked)
1291 return;
1292
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001293 pid = fork();
1294 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001295 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001296
1297 if (pid == 0) {
1298 pid = getpid();
1299 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001300 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001301 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1302 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001303 kill(pid, SIGSTOP);
1304 _exit(0); /* parent should see entry into this syscall */
1305 }
1306
1307 while (1) {
1308 int status, tracee_pid;
1309
1310 errno = 0;
1311 tracee_pid = wait(&status);
1312 if (tracee_pid <= 0) {
1313 if (errno == EINTR)
1314 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001315 kill_save_errno(pid, SIGKILL);
1316 perror_msg_and_die("%s: unexpected wait result %d",
1317 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001318 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001319 if (WIFEXITED(status)) {
1320 if (WEXITSTATUS(status) == 0)
1321 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001322 error_msg_and_die("%s: unexpected exit status %u",
1323 __func__, WEXITSTATUS(status));
1324 }
1325 if (WIFSIGNALED(status)) {
1326 error_msg_and_die("%s: unexpected signal %u",
1327 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001328 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001329 if (!WIFSTOPPED(status)) {
1330 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001331 error_msg_and_die("%s: unexpected wait status %x",
1332 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001333 }
1334 if (WSTOPSIG(status) == SIGSTOP) {
1335 /*
1336 * We don't check "options aren't accepted" error.
1337 * If it happens, we'll never get (SIGTRAP | 0x80),
1338 * and thus will decide to not use the option.
1339 * IOW: the outcome of the test will be correct.
1340 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001341 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1342 && errno != EINVAL && errno != EIO)
1343 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001344 }
1345 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1346 it_worked = 1;
1347 }
1348 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001349 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001350 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001351 }
1352 }
1353
1354 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001355 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001356 ptrace_setoptions |= test_options;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001357 if (debug_flag)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001358 fprintf(stderr, "ptrace_setoptions = %#x\n",
1359 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001360 return;
1361 }
1362
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001363 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1364 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001365}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001366
Denys Vlasenko978fbc92012-09-13 10:28:43 +02001367#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001368static void
1369test_ptrace_seize(void)
1370{
1371 int pid;
1372
1373 pid = fork();
1374 if (pid < 0)
1375 perror_msg_and_die("fork");
1376
1377 if (pid == 0) {
1378 pause();
1379 _exit(0);
1380 }
1381
1382 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1383 * attaching tracee continues to run unless a trap condition occurs.
1384 * PTRACE_SEIZE doesn't affect signal or group stop state.
1385 */
Denys Vlasenko26bc0602012-07-10 16:36:32 +02001386 if (ptrace(PTRACE_SEIZE, pid, 0, 0) == 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001387 post_attach_sigstop = 0; /* this sets use_seize to 1 */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001388 } else if (debug_flag) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001389 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1390 }
1391
1392 kill(pid, SIGKILL);
1393
1394 while (1) {
1395 int status, tracee_pid;
1396
1397 errno = 0;
1398 tracee_pid = waitpid(pid, &status, 0);
1399 if (tracee_pid <= 0) {
1400 if (errno == EINTR)
1401 continue;
1402 perror_msg_and_die("%s: unexpected wait result %d",
1403 __func__, tracee_pid);
1404 }
1405 if (WIFSIGNALED(status)) {
1406 return;
1407 }
1408 error_msg_and_die("%s: unexpected wait status %x",
1409 __func__, status);
1410 }
1411}
Denys Vlasenko978fbc92012-09-13 10:28:43 +02001412#else /* !USE_SEIZE */
1413# define test_ptrace_seize() ((void)0)
1414#endif
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001415
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001416static unsigned
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001417get_os_release(void)
1418{
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001419 unsigned rel;
1420 const char *p;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001421 struct utsname u;
1422 if (uname(&u) < 0)
1423 perror_msg_and_die("uname");
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001424 /* u.release has this form: "3.2.9[-some-garbage]" */
1425 rel = 0;
1426 p = u.release;
1427 for (;;) {
1428 if (!(*p >= '0' && *p <= '9'))
1429 error_msg_and_die("Bad OS release string: '%s'", u.release);
1430 /* Note: this open-codes KERNEL_VERSION(): */
1431 rel = (rel << 8) | atoi(p);
1432 if (rel >= KERNEL_VERSION(1,0,0))
1433 break;
1434 while (*p >= '0' && *p <= '9')
1435 p++;
Dmitry V. Levin0dbc80d2012-05-14 23:42:10 +00001436 if (*p != '.') {
1437 if (rel >= KERNEL_VERSION(0,1,0)) {
1438 /* "X.Y-something" means "X.Y.0" */
1439 rel <<= 8;
1440 break;
1441 }
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001442 error_msg_and_die("Bad OS release string: '%s'", u.release);
Dmitry V. Levin0dbc80d2012-05-14 23:42:10 +00001443 }
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001444 p++;
1445 }
1446 return rel;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001447}
1448
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001449/*
1450 * Initialization part of main() was eating much stack (~0.5k),
1451 * which was unused after init.
1452 * We can reuse it if we move init code into a separate function.
1453 *
1454 * Don't want main() to inline us and defeat the reason
1455 * we have a separate function.
1456 */
1457static void __attribute__ ((noinline))
1458init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 struct tcb *tcp;
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001461 int c, i;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001462 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001463 struct sigaction sa;
1464
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001465 progname = argv[0] ? argv[0] : "strace";
1466
Denys Vlasenkoa5090542012-03-15 17:27:49 +01001467 /* Make sure SIGCHLD has the default action so that waitpid
1468 definitely works without losing track of children. The user
1469 should not have given us a bogus state to inherit, but he might
1470 have. Arguably we should detect SIG_IGN here and pass it on
1471 to children, but probably noone really needs that. */
1472 signal(SIGCHLD, SIG_DFL);
1473
Denys Vlasenko75422762011-05-27 14:36:01 +02001474 strace_tracer_pid = getpid();
1475
Denys Vlasenko6e0bfd12012-03-15 14:36:28 +01001476 os_release = get_os_release();
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001477
Roland McGrathee9d4352002-12-18 04:16:10 +00001478 /* Allocate the initial tcbtab. */
1479 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001480 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001481 if (!tcbtab)
1482 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001483 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001484 if (!tcp)
1485 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001486 for (c = 0; c < tcbtabsize; c++)
1487 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001488
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001489 shared_log = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001490 set_sortby(DEFAULT_SORTBY);
1491 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 qualify("trace=all");
1493 qualify("abbrev=all");
1494 qualify("verbose=all");
1495 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001496 while ((c = getopt(argc, argv,
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001497 "+bcCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001498 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001499 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500 switch (c) {
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001501 case 'b':
1502 detach_on_execve = 1;
1503 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001505 if (cflag == CFLAG_BOTH) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001506 error_msg_and_die("-c and -C are mutually exclusive");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001507 }
1508 cflag = CFLAG_ONLY_STATS;
1509 break;
1510 case 'C':
1511 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001512 error_msg_and_die("-c and -C are mutually exclusive");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001513 }
1514 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 break;
1516 case 'd':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001517 debug_flag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001519 case 'D':
1520 daemonized_tracer = 1;
1521 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001522 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001523 optF = 1;
1524 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525 case 'f':
1526 followfork++;
1527 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528 case 'h':
1529 usage(stdout, 0);
1530 break;
1531 case 'i':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001532 iflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533 break;
1534 case 'q':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001535 qflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 break;
1537 case 'r':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001538 rflag = 1;
1539 /* fall through to tflag++ */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540 case 't':
1541 tflag++;
1542 break;
1543 case 'T':
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001544 Tflag = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545 break;
1546 case 'x':
1547 xflag++;
1548 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001549 case 'y':
1550 show_fd_path = 1;
1551 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552 case 'v':
1553 qualify("abbrev=none");
1554 break;
1555 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001556 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557 exit(0);
1558 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001559 case 'z':
1560 not_failing_only = 1;
1561 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562 case 'a':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001563 acolumn = string_to_uint(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001564 if (acolumn < 0)
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001565 error_opt_arg(c, optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566 break;
1567 case 'e':
1568 qualify(optarg);
1569 break;
1570 case 'o':
1571 outfname = strdup(optarg);
1572 break;
1573 case 'O':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001574 i = string_to_uint(optarg);
1575 if (i < 0)
1576 error_opt_arg(c, optarg);
1577 set_overhead(i);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578 break;
1579 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001580 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001582 case 'P':
1583 tracing_paths = 1;
1584 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001585 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001586 }
1587 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588 case 's':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001589 i = string_to_uint(optarg);
1590 if (i < 0)
1591 error_opt_arg(c, optarg);
1592 max_strlen = i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593 break;
1594 case 'S':
1595 set_sortby(optarg);
1596 break;
1597 case 'u':
1598 username = strdup(optarg);
1599 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001600 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001601 if (putenv(optarg) < 0)
1602 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001603 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001604 case 'I':
Dmitry V. Levinccee1692012-03-25 21:49:48 +00001605 opt_intr = string_to_uint(optarg);
1606 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS)
1607 error_opt_arg(c, optarg);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001608 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609 default:
1610 usage(stderr, 1);
1611 break;
1612 }
1613 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001614 argv += optind;
1615 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616
Denys Vlasenko102ec492011-08-25 01:27:59 +02001617 acolumn_spaces = malloc(acolumn + 1);
1618 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001619 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001620 memset(acolumn_spaces, ' ', acolumn);
1621 acolumn_spaces[acolumn] = '\0';
1622
Denys Vlasenko837399a2012-01-24 11:37:03 +01001623 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001624 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001625 usage(stderr, 1);
1626
Denys Vlasenkofd883382012-03-09 13:03:41 +01001627 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001628 error_msg_and_die("-D and -p are mutually exclusive");
Wang Chaod322a4b2010-08-05 14:30:11 +08001629 }
1630
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001631 if (!followfork)
1632 followfork = optF;
1633
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001634 if (followfork >= 2 && cflag) {
Denys Vlasenkoc5ccfa42012-03-26 13:10:50 +02001635 error_msg_and_die("(-c or -C) and -ff are mutually exclusive");
Roland McGrathcb9def62006-04-25 07:48:03 +00001636 }
1637
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 /* See if they want to run as another user. */
1639 if (username != NULL) {
1640 struct passwd *pent;
1641
1642 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001643 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001645 pent = getpwnam(username);
1646 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001647 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 }
1649 run_uid = pent->pw_uid;
1650 run_gid = pent->pw_gid;
1651 }
1652 else {
1653 run_uid = getuid();
1654 run_gid = getgid();
1655 }
1656
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001657 if (followfork)
1658 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001659 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001660 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001661
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662 /* Check if they want to redirect the output. */
1663 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001664 /* See if they want to pipe the output. */
1665 if (outfname[0] == '|' || outfname[0] == '!') {
1666 /*
1667 * We can't do the <outfname>.PID funny business
1668 * when using popen, so prohibit it.
1669 */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001670 if (followfork >= 2)
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001671 error_msg_and_die("Piping the output and -ff are mutually exclusive");
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001672 shared_log = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001673 }
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001674 else if (followfork < 2)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001675 shared_log = strace_fopen(outfname);
Denys Vlasenko328bf252012-03-12 23:34:13 +01001676 } else {
1677 /* -ff without -o FILE is the same as single -f */
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001678 if (followfork >= 2)
Denys Vlasenko328bf252012-03-12 23:34:13 +01001679 followfork = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 }
1681
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001682 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001683 char *buf = malloc(BUFSIZ);
1684 if (!buf)
1685 die_out_of_memory();
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001686 setvbuf(shared_log, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001687 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001688 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001689 if (!opt_intr)
1690 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001692 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001693 if (!opt_intr)
1694 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001695
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001696 /* argv[0] -pPID -oFILE Default interactive setting
1697 * yes 0 0 INTR_WHILE_WAIT
1698 * no 1 0 INTR_WHILE_WAIT
1699 * yes 0 1 INTR_NEVER
1700 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001701 */
1702
1703 /* STARTUP_CHILD must be called before the signal handlers get
1704 installed below as they are inherited into the spawned process.
1705 Also we do not need to be protected by them as during interruption
1706 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001707 if (argv[0]) {
1708 skip_startup_execve = 1;
Denys Vlasenko837399a2012-01-24 11:37:03 +01001709 startup_child(argv);
Denys Vlasenko61e7aad2012-03-15 13:44:17 +01001710 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 sigemptyset(&empty_set);
1713 sigemptyset(&blocked_set);
1714 sa.sa_handler = SIG_IGN;
1715 sigemptyset(&sa.sa_mask);
1716 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001717 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1718 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1719 if (opt_intr != INTR_ANYWHERE) {
1720 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1721 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1722 /*
1723 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1724 * fatal signals are blocked while syscall stop is processed,
1725 * and acted on in between, when waiting for new syscall stops.
1726 * In non-interactive mode, signals are ignored.
1727 */
1728 if (opt_intr == INTR_WHILE_WAIT) {
1729 sigaddset(&blocked_set, SIGHUP);
1730 sigaddset(&blocked_set, SIGINT);
1731 sigaddset(&blocked_set, SIGQUIT);
1732 sigaddset(&blocked_set, SIGPIPE);
1733 sigaddset(&blocked_set, SIGTERM);
1734 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001735 }
1736 /* SIG_IGN, or set handler for these */
1737 sigaction(SIGHUP, &sa, NULL);
1738 sigaction(SIGINT, &sa, NULL);
1739 sigaction(SIGQUIT, &sa, NULL);
1740 sigaction(SIGPIPE, &sa, NULL);
1741 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742 }
Denys Vlasenkofd883382012-03-09 13:03:41 +01001743 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001744 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001745
Denys Vlasenkofd883382012-03-09 13:03:41 +01001746 /* Do we want pids printed in our -o OUTFILE?
1747 * -ff: no (every pid has its own file); or
1748 * -f: yes (there can be more pids in the future); or
1749 * -p PID1,PID2: yes (there are already more than one pid)
1750 */
1751 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752}
1753
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001754static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001755pid2tcb(int pid)
1756{
1757 int i;
1758
1759 if (pid <= 0)
1760 return NULL;
1761
1762 for (i = 0; i < tcbtabsize; i++) {
1763 struct tcb *tcp = tcbtab[i];
1764 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1765 return tcp;
1766 }
1767
1768 return NULL;
1769}
1770
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001771static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001772cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773{
1774 int i;
1775 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001776 int fatal_sig;
1777
1778 /* 'interrupted' is a volatile object, fetch it only once */
1779 fatal_sig = interrupted;
1780 if (!fatal_sig)
1781 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782
Roland McGrathee9d4352002-12-18 04:16:10 +00001783 for (i = 0; i < tcbtabsize; i++) {
1784 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 if (!(tcp->flags & TCB_INUSE))
1786 continue;
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001787 if (debug_flag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 fprintf(stderr,
1789 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001790 if (tcp->flags & TCB_STRACE_CHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001792 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001794 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 }
1796 if (cflag)
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001797 call_summary(shared_log);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798}
1799
1800static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001801interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001803 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804}
1805
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001807trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001810 struct rusage *rup = cflag ? &ru : NULL;
Denys Vlasenko978fbc92012-09-13 10:28:43 +02001811#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001812 static int wait4_options = __WALL;
Denys Vlasenko978fbc92012-09-13 10:28:43 +02001813#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001814
Roland McGratheb9e2e82009-06-02 16:49:22 -07001815 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001816 int pid;
1817 int wait_errno;
1818 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001819 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001820 struct tcb *tcp;
1821 unsigned event;
1822
Denys Vlasenko222713a2009-03-17 14:29:59 +00001823 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001824 return 0;
1825 if (interactive)
1826 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko978fbc92012-09-13 10:28:43 +02001827#ifdef __WALL
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001828 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001829 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001830 /* this kernel does not support __WALL */
1831 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001832 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001833 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001834 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001835 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001836 pid = wait4(-1, &status, __WCLONE, rup);
1837 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001838 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001839 }
1840 }
Denys Vlasenko978fbc92012-09-13 10:28:43 +02001841#else
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001842 pid = wait4(-1, &status, 0, rup);
Denys Vlasenko978fbc92012-09-13 10:28:43 +02001843#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001845 if (interactive)
1846 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001848 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001849 switch (wait_errno) {
1850 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001852 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853 /*
1854 * We would like to verify this case
1855 * but sometimes a race in Solbourne's
1856 * version of SunOS sometimes reports
1857 * ECHILD before sending us SIGCHILD.
1858 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001859 return 0;
1860 default:
1861 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001862 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001863 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864 }
1865 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001866 if (pid == popen_pid) {
1867 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001868 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001869 continue;
1870 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001871
1872 event = ((unsigned)status >> 16);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001873 if (debug_flag) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001874 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001875 char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001876 strcpy(buf, "???");
1877 if (WIFSIGNALED(status))
1878#ifdef WCOREDUMP
1879 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1880 WCOREDUMP(status) ? "core," : "",
1881 signame(WTERMSIG(status)));
1882#else
1883 sprintf(buf, "WIFSIGNALED,sig=%s",
1884 signame(WTERMSIG(status)));
1885#endif
1886 if (WIFEXITED(status))
1887 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1888 if (WIFSTOPPED(status))
1889 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001890#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001891 if (WIFCONTINUED(status))
1892 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001893#endif
Denys Vlasenko67559ad2012-03-13 12:05:27 +01001894 evbuf[0] = '\0';
1895 if (event != 0) {
1896 static const char *const event_names[] = {
1897 [PTRACE_EVENT_CLONE] = "CLONE",
1898 [PTRACE_EVENT_FORK] = "FORK",
1899 [PTRACE_EVENT_VFORK] = "VFORK",
1900 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1901 [PTRACE_EVENT_EXEC] = "EXEC",
1902 [PTRACE_EVENT_EXIT] = "EXIT",
1903 };
1904 const char *e;
1905 if (event < ARRAY_SIZE(event_names))
1906 e = event_names[event];
1907 else {
1908 sprintf(buf, "?? (%u)", event);
1909 e = buf;
1910 }
1911 sprintf(evbuf, ",PTRACE_EVENT_%s", e);
1912 }
1913 fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001914 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001915
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001916 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001917 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001918
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001919 if (!tcp) {
Roland McGrath41c48222008-07-18 00:25:10 +00001920 if (followfork) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001921 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001922 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenko3db3b262012-03-16 15:15:14 +01001923 newoutf(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001924 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001925 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001926 pid);
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001927 } else {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001928 /* This can happen if a clone call used
1929 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001930 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001931 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001932 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001933 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934 }
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001935
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001936 clear_regs();
1937 if (WIFSTOPPED(status))
1938 get_regs(pid);
1939
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001940 /* Under Linux, execve changes pid to thread leader's pid,
1941 * and we see this changed pid on EVENT_EXEC and later,
1942 * execve sysexit. Leader "disappears" without exit
1943 * notification. Let user know that, drop leader's tcb,
1944 * and fix up pid in execve thread's tcb.
1945 * Effectively, execve thread's tcb replaces leader's tcb.
1946 *
1947 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1948 * on exit syscall) in multithreaded programs exactly
1949 * in order to handle this case.
1950 *
1951 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1952 * On 2.6 and earlier, it can return garbage.
1953 */
1954 if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001955 FILE *fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001956 struct tcb *execve_thread;
1957 long old_pid = 0;
1958
1959 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0)
1960 goto dont_switch_tcbs;
1961 if (old_pid <= 0 || old_pid == pid)
1962 goto dont_switch_tcbs;
1963 execve_thread = pid2tcb(old_pid);
1964 /* It should be !NULL, but I feel paranoid */
1965 if (!execve_thread)
1966 goto dont_switch_tcbs;
1967
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001968 if (execve_thread->curcol != 0) {
1969 /*
1970 * One case we are here is -ff:
1971 * try "strace -oLOG -ff test/threaded_execve"
1972 */
1973 fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001974 /*execve_thread->curcol = 0; - no need, see code below */
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001975 }
1976 /* Swap output FILEs (needed for -ff) */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001977 fp = execve_thread->outf;
1978 execve_thread->outf = tcp->outf;
1979 tcp->outf = fp;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001980 /* And their column positions */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01001981 execve_thread->curcol = tcp->curcol;
1982 tcp->curcol = 0;
Denys Vlasenko8511f2a2012-03-22 09:35:51 +01001983 /* Drop leader, but close execve'd thread outfile (if -ff) */
1984 droptcb(tcp);
1985 /* Switch to the thread, reusing leader's outfile and pid */
1986 tcp = execve_thread;
1987 tcp->pid = pid;
1988 if (cflag != CFLAG_ONLY_STATS) {
1989 printleader(tcp);
1990 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1991 line_ended();
1992 tcp->flags |= TCB_REPRINT;
1993 }
1994 }
1995 dont_switch_tcbs:
1996
1997 if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
1998 if (!skip_startup_execve)
1999 detach(tcp);
2000 /* This was initial execve for "strace PROG". Skip. */
2001 skip_startup_execve = 0;
2002 }
2003
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002004 /* Set current output file */
Denys Vlasenko6764f8f2012-03-22 09:56:20 +01002005 current_tcp = tcp;
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002006
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002007 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002008 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2009 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002011
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002013 if (pid == strace_child)
2014 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002015 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002016 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2017 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002018#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002019 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002020 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002021 WCOREDUMP(status) ? "(core dumped) " : "");
2022#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002023 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002024 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002025#endif
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002026 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002027 }
2028 droptcb(tcp);
2029 continue;
2030 }
2031 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002032 if (pid == strace_child)
2033 exit_code = WEXITSTATUS(status);
Denys Vlasenkob5e09082012-03-21 14:27:40 +01002034 if (cflag != CFLAG_ONLY_STATS) {
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002035 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002036 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002037 line_ended();
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002038 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002039 droptcb(tcp);
2040 continue;
2041 }
2042 if (!WIFSTOPPED(status)) {
2043 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2044 droptcb(tcp);
2045 continue;
2046 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002048 /* Is this the very first time we see this tracee stopped? */
2049 if (tcp->flags & TCB_STARTUP) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002050 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002051 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002054 /*
2055 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002056 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002057 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002058 if (clearbpt(tcp) < 0) {
2059 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002060 droptcb(tcp);
2061 cleanup();
2062 return -1;
2063 }
2064 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002065 if (ptrace_setoptions) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002066 if (debug_flag)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002067 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2068 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2069 if (errno != ESRCH) {
2070 /* Should never happen, really */
2071 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002072 }
2073 }
2074 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002075 }
2076
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002077 sig = WSTOPSIG(status);
2078
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002079 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002080 /* Ptrace event */
2081#ifdef USE_SEIZE
Denys Vlasenko26bc0602012-07-10 16:36:32 +02002082 if (event == PTRACE_EVENT_STOP) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002083 /*
2084 * PTRACE_INTERRUPT-stop or group-stop.
2085 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2086 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002087 if (sig == SIGSTOP
2088 || sig == SIGTSTP
2089 || sig == SIGTTIN
2090 || sig == SIGTTOU
2091 ) {
2092 stopped = 1;
2093 goto show_stopsig;
2094 }
2095 }
2096#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002097 goto restart_tracee_with_sig_0;
2098 }
2099
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002100 /* Is this post-attach SIGSTOP?
2101 * Interestingly, the process may stop
2102 * with STOPSIG equal to some other signal
2103 * than SIGSTOP if we happend to attach
2104 * just before the process takes a signal.
2105 */
2106 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002107 if (debug_flag)
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002108 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2109 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002110 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002111 }
2112
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002113 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002114 siginfo_t si;
2115
2116 /* Nonzero (true) if tracee is stopped by signal
2117 * (as opposed to "tracee received signal").
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002118 * TODO: shouldn't we check for errno == EINVAL too?
2119 * We can get ESRCH instead, you know...
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002120 */
2121 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002122#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002123 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002124#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002125 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002126 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002127#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002128 long pc = 0;
2129 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002130
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002131 upeek(tcp, PT_CR_IPSR, &psr);
2132 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002133
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002134# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002135 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002136# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002137# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002138#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002139# define PC_FORMAT_STR ""
2140# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002141#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002143 if (!stopped) {
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002144 tprintf("--- %s ", signame(sig));
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002145 printsiginfo(&si, verbose(tcp));
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002146 tprintf(PC_FORMAT_STR " ---\n"
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002147 PC_FORMAT_ARG);
2148 } else
Denys Vlasenko2c4fb902012-03-15 17:24:49 +01002149 tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002150 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002151 PC_FORMAT_ARG);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002152 line_ended();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002154
2155 if (!stopped)
2156 /* It's signal-delivery-stop. Inject the signal */
2157 goto restart_tracee;
2158
2159 /* It's group-stop */
2160#ifdef USE_SEIZE
2161 if (use_seize) {
2162 /*
2163 * This ends ptrace-stop, but does *not* end group-stop.
2164 * This makes stopping signals work properly on straced process
2165 * (that is, process really stops. It used to continue to run).
2166 */
2167 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2168 cleanup();
2169 return -1;
2170 }
2171 continue;
2172 }
2173 /* We don't have PTRACE_LISTEN support... */
2174#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002175 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002176 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002177
2178 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002179 if (interrupted)
2180 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002181
2182 /* This should be syscall entry or exit.
2183 * (Or it still can be that pesky post-execve SIGTRAP!)
2184 * Handle it.
2185 */
Denys Vlasenko23506752012-03-21 10:32:49 +01002186 if (trace_syscall(tcp) < 0) {
2187 /* ptrace() failed in trace_syscall().
Roland McGratheb9e2e82009-06-02 16:49:22 -07002188 * Likely a result of process disappearing mid-flight.
Denys Vlasenko23506752012-03-21 10:32:49 +01002189 * Observed case: exit_group() or SIGKILL terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002190 * all processes in thread group.
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002191 * We assume that ptrace error was caused by process death.
Denys Vlasenkof2025022012-03-09 15:29:45 +01002192 * We used to detach(tcp) here, but since we no longer
2193 * implement "detach before death" policy/hack,
2194 * we can let this process to report its death to us
2195 * normally, via WIFEXITED or WIFSIGNALED wait status.
2196 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 continue;
2198 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002199 restart_tracee_with_sig_0:
2200 sig = 0;
2201 restart_tracee:
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002202 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 cleanup();
2204 return -1;
2205 }
2206 }
2207 return 0;
2208}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002209
2210int
2211main(int argc, char *argv[])
2212{
2213 init(argc, argv);
2214
2215 /* Run main tracing loop */
2216 if (trace() < 0)
2217 return 1;
2218
2219 cleanup();
2220 fflush(NULL);
Dmitry V. Levincf534362012-07-12 20:54:46 +00002221 if (shared_log != stderr)
2222 fclose(shared_log);
2223 if (popen_pid) {
2224 while (waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR)
2225 ;
2226 }
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002227 if (exit_code > 0xff) {
2228 /* Avoid potential core file clobbering. */
2229 struct rlimit rlim = {0, 0};
2230 setrlimit(RLIMIT_CORE, &rlim);
2231
2232 /* Child was killed by a signal, mimic that. */
2233 exit_code &= 0xff;
2234 signal(exit_code, SIG_DFL);
2235 raise(exit_code);
2236 /* Paranoia - what if this signal is not fatal?
2237 Exit with 128 + signo then. */
2238 exit_code += 128;
2239 }
2240
2241 return exit_code;
2242}