blob: 727e490b55575f874ef87d5ea4e6f71f9f4e6720 [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.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#include <pwd.h>
45#include <grp.h>
46#include <string.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010048#include <sys/utsname.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020051# if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000053# else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020058# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000059# endif
Roland McGrath134813a2007-06-02 00:07:33 +000060
Denys Vlasenko84703742012-02-25 02:38:52 +010061#if defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000062# include <asm/ptrace_offsets.h>
63#endif
64
Denys Vlasenko96d5a762008-12-29 19:13:27 +000065extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000066extern int optind;
67extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000068
Roland McGrath41c48222008-07-18 00:25:10 +000069int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020070unsigned int ptrace_setoptions = 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;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000073int dtime = 0, xflag = 0, qflag = 0;
74cflag_t cflag = CFLAG_NONE;
Denys Vlasenkofd883382012-03-09 13:03:41 +010075static int iflag = 0, rflag = 0, tflag = 0;
76static int 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. */
114int not_failing_only = 0;
115
Grant Edwards8a082772011-04-07 20:25:40 +0000116/* Show path associated with fd arguments */
117int show_fd_path = 0;
118
119/* are we filtering traces based on paths? */
120int tracing_paths = 0;
121
Dmitry V. Levina6809652008-11-10 17:14:58 +0000122static int exit_code = 0;
123static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200124static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700125
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static uid_t run_uid;
128static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200131static int acolumn = DEFAULT_ACOLUMN;
132static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000133static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200134static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100135struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100136static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200137static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200138static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200139static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100141static char *os_release; /* from uname() */
142
Denys Vlasenko4c196382012-01-04 15:11:09 +0100143static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100144static int trace(void);
145static void cleanup(void);
146static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147static sigset_t empty_set, blocked_set;
148
149#ifdef HAVE_SIG_ATOMIC_T
150static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100151#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100153#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200156usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157{
158 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100159usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
160 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100161 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100162 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100163 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200165-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100166-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100168-F -- attempt to follow vforks\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100170-I interruptible\n\
171 1: no signals are blocked\n\
172 2: fatal signals are blocked while decoding syscall (default)\n\
173 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
174 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
175 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176-q -- suppress messages about attaching, detaching, etc.\n\
177-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100178-T -- print time spent in each syscall\n\
179-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000181-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100182-h -- print help message\n\
183-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-a column -- alignment COLUMN for printing syscall results (default %d)\n\
185-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
186 options: trace, abbrev, verbose, raw, signal, read, or write\n\
187-o file -- send trace output to FILE instead of stderr\n\
188-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
189-p pid -- trace process with process id PID, may be repeated\n\
190-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
191-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
192-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000193-E var=val -- put var=val in the environment for command\n\
194-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000195-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000196" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000197-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000198 */
199, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 exit(exitval);
201}
202
Denys Vlasenko75422762011-05-27 14:36:01 +0200203static void die(void) __attribute__ ((noreturn));
204static void die(void)
205{
206 if (strace_tracer_pid == getpid()) {
207 cflag = 0;
208 cleanup();
209 }
210 exit(1);
211}
212
213static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200214{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100215 char *msg;
216
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000217 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100218
219 /* We want to print entire message with single fprintf to ensure
220 * message integrity if stderr is shared with other programs.
221 * Thus we use vasprintf + single fprintf.
222 */
223 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100224 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100225 if (err_no)
226 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
227 else
228 fprintf(stderr, "%s: %s\n", progname, msg);
229 free(msg);
230 } else {
231 /* malloc in vasprintf failed, try it without malloc */
232 fprintf(stderr, "%s: ", progname);
233 vfprintf(stderr, fmt, p);
234 if (err_no)
235 fprintf(stderr, ": %s\n", strerror(err_no));
236 else
237 putc('\n', stderr);
238 }
239 /* We don't switch stderr to buffered, thus fprintf(stderr)
240 * always flushes its output and this is not necessary: */
241 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200242}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200243
Denys Vlasenko75422762011-05-27 14:36:01 +0200244void error_msg(const char *fmt, ...)
245{
246 va_list p;
247 va_start(p, fmt);
248 verror_msg(0, fmt, p);
249 va_end(p);
250}
251
252void error_msg_and_die(const char *fmt, ...)
253{
254 va_list p;
255 va_start(p, fmt);
256 verror_msg(0, fmt, p);
257 die();
258}
259
260void perror_msg(const char *fmt, ...)
261{
262 va_list p;
263 va_start(p, fmt);
264 verror_msg(errno, fmt, p);
265 va_end(p);
266}
267
268void perror_msg_and_die(const char *fmt, ...)
269{
270 va_list p;
271 va_start(p, fmt);
272 verror_msg(errno, fmt, p);
273 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200274}
275
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200276void die_out_of_memory(void)
277{
278 static bool recursed = 0;
279 if (recursed)
280 exit(1);
281 recursed = 1;
282 error_msg_and_die("Out of memory");
283}
284
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400285/* Glue for systems without a MMU that cannot provide fork() */
286#ifdef HAVE_FORK
287# define strace_vforked 0
288#else
289# define strace_vforked 1
290# define fork() vfork()
291#endif
292
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100293#ifdef USE_SEIZE
294static int
295ptrace_attach_or_seize(int pid)
296{
297 int r;
298 if (!use_seize)
299 return ptrace(PTRACE_ATTACH, pid, 0, 0);
300 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
301 if (r)
302 return r;
303 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
304 return r;
305}
306#else
307# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
308#endif
309
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200310static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000311set_cloexec_flag(int fd)
312{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200313 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000314
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200315 flags = fcntl(fd, F_GETFD);
316 if (flags < 0) {
317 /* Can happen only if fd is bad.
318 * Should never happen: if it does, we have a bug
319 * in the caller. Therefore we just abort
320 * instead of propagating the error.
321 */
322 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000323 }
324
325 newflags = flags | FD_CLOEXEC;
326 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200327 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000328
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200329 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330}
331
332/*
333 * When strace is setuid executable, we have to swap uids
334 * before and after filesystem and process management operations.
335 */
336static void
337swap_uid(void)
338{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000339 int euid = geteuid(), uid = getuid();
340
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200341 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200342 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000344}
345
Roland McGrath4bfa6262007-07-05 20:03:16 +0000346#if _LFS64_LARGEFILE
347# define fopen_for_output fopen64
348#else
349# define fopen_for_output fopen
350#endif
351
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000352static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200353strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000354{
355 FILE *fp;
356
357 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200358 fp = fopen_for_output(path, "w");
359 if (!fp)
360 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000361 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200362 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000363 return fp;
364}
365
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200366static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000367
368#ifndef _PATH_BSHELL
369# define _PATH_BSHELL "/bin/sh"
370#endif
371
372/*
373 * We cannot use standard popen(3) here because we have to distinguish
374 * popen child process from other processes we trace, and standard popen(3)
375 * does not export its child's pid.
376 */
377static FILE *
378strace_popen(const char *command)
379{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200380 FILE *fp;
381 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000382
383 swap_uid();
384 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200385 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000386
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200387 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000388
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200389 popen_pid = vfork();
390 if (popen_pid == -1)
391 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000392
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200393 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000394 /* child */
395 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200396 if (fds[0] != 0) {
397 if (dup2(fds[0], 0))
398 perror_msg_and_die("dup2");
399 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400 }
401 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200402 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000403 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200404
405 /* parent */
406 close(fds[0]);
407 swap_uid();
408 fp = fdopen(fds[1], "w");
409 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200410 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200411 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000412}
413
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200414static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000415newoutf(struct tcb *tcp)
416{
417 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000418 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000419 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200420 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000421 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000422}
423
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100424static void process_opt_p_list(char *opt)
425{
426 while (*opt) {
427 /*
428 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
429 * pidof uses space as delim, pgrep uses newline. :(
430 */
431 int pid;
432 struct tcb *tcp;
433 char *delim = opt + strcspn(opt, ", \n\t");
434 char c = *delim;
435
436 *delim = '\0';
437 pid = atoi(opt); /* TODO: stricter parsing of the number? */
438 if (pid <= 0) {
439 error_msg("Invalid process id: '%s'", opt);
440 *delim = c;
441 return;
442 }
443 if (pid == strace_tracer_pid) {
444 error_msg("I'm sorry, I can't let you do that, Dave.");
445 *delim = c;
446 return;
447 }
448 *delim = c;
449 tcp = alloc_tcb(pid, 0);
450 tcp->flags |= TCB_ATTACHED;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100451 if (c == '\0')
452 break;
453 opt = delim + 1;
454 }
455}
456
Roland McGrath02203312007-06-11 22:06:31 +0000457static void
458startup_attach(void)
459{
460 int tcbi;
461 struct tcb *tcp;
462
463 /*
464 * Block user interruptions as we would leave the traced
465 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200466 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200467 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000468 */
469 if (interactive)
470 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
471
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000472 if (daemonized_tracer) {
473 pid_t pid = fork();
474 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200475 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000476 }
477 if (pid) { /* parent */
478 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200479 * Wait for grandchild to attach to straced process
480 * (grandparent). Grandchild SIGKILLs us after it attached.
481 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000482 * it proceeds to exec the straced program.
483 */
484 pause();
485 _exit(0); /* paranoia */
486 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200487 /* grandchild */
488 /* We will be the tracer process. Remember our new pid: */
489 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000490 }
491
Roland McGrath02203312007-06-11 22:06:31 +0000492 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
493 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200494
Denys Vlasenkod116a732011-09-05 14:01:33 +0200495 /* Is this a process we should attach to, but not yet attached? */
496 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
497 continue; /* no */
498
499 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000500 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200501 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000502
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000503 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000504 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000505 DIR *dir;
506
507 sprintf(procdir, "/proc/%d/task", tcp->pid);
508 dir = opendir(procdir);
509 if (dir != NULL) {
510 unsigned int ntid = 0, nerr = 0;
511 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200512
Roland McGrath02203312007-06-11 22:06:31 +0000513 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200514 struct tcb *cur_tcp;
515 int tid;
516
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000517 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000518 continue;
519 tid = atoi(de->d_name);
520 if (tid <= 0)
521 continue;
522 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100523 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000524 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200525 if (debug)
526 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200527 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200528 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200529 if (debug)
530 fprintf(stderr, "attach to pid %d succeeded\n", tid);
531 cur_tcp = tcp;
532 if (tid != tcp->pid)
533 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100534 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000535 }
536 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200537 if (interactive) {
538 sigprocmask(SIG_SETMASK, &empty_set, NULL);
539 if (interrupted)
540 goto ret;
541 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
542 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000543 ntid -= nerr;
544 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000545 perror("attach: ptrace(PTRACE_ATTACH, ...)");
546 droptcb(tcp);
547 continue;
548 }
549 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000550 fprintf(stderr, ntid > 1
551? "Process %u attached with %u threads - interrupt to quit\n"
552: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200553 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000554 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200555 if (!(tcp->flags & TCB_STARTUP)) {
556 /* -p PID, we failed to attach to PID itself
557 * but did attach to some of its sibling threads.
558 * Drop PID's tcp.
559 */
560 droptcb(tcp);
561 }
Roland McGrath02203312007-06-11 22:06:31 +0000562 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000563 } /* if (opendir worked) */
564 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100565 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000566 perror("attach: ptrace(PTRACE_ATTACH, ...)");
567 droptcb(tcp);
568 continue;
569 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100570 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200571 if (debug)
572 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000573
574 if (daemonized_tracer) {
575 /*
576 * It is our grandparent we trace, not a -p PID.
577 * Don't want to just detach on exit, so...
578 */
579 tcp->flags &= ~TCB_ATTACHED;
580 /*
581 * Make parent go away.
582 * Also makes grandparent's wait() unblock.
583 */
584 kill(getppid(), SIGKILL);
585 }
586
Roland McGrath02203312007-06-11 22:06:31 +0000587 if (!qflag)
588 fprintf(stderr,
589 "Process %u attached - interrupt to quit\n",
590 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200591 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000592
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200593 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000594 if (interactive)
595 sigprocmask(SIG_SETMASK, &empty_set, NULL);
596}
597
598static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200599startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000600{
601 struct stat statbuf;
602 const char *filename;
603 char pathname[MAXPATHLEN];
604 int pid = 0;
605 struct tcb *tcp;
606
607 filename = argv[0];
608 if (strchr(filename, '/')) {
609 if (strlen(filename) > sizeof pathname - 1) {
610 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200611 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000612 }
613 strcpy(pathname, filename);
614 }
615#ifdef USE_DEBUGGING_EXEC
616 /*
617 * Debuggers customarily check the current directory
618 * first regardless of the path but doing that gives
619 * security geeks a panic attack.
620 */
621 else if (stat(filename, &statbuf) == 0)
622 strcpy(pathname, filename);
623#endif /* USE_DEBUGGING_EXEC */
624 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000625 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000626 int m, n, len;
627
628 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100629 const char *colon = strchr(path, ':');
630 if (colon) {
631 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000632 m = n + 1;
633 }
634 else
635 m = n = strlen(path);
636 if (n == 0) {
637 if (!getcwd(pathname, MAXPATHLEN))
638 continue;
639 len = strlen(pathname);
640 }
641 else if (n > sizeof pathname - 1)
642 continue;
643 else {
644 strncpy(pathname, path, n);
645 len = n;
646 }
647 if (len && pathname[len - 1] != '/')
648 pathname[len++] = '/';
649 strcpy(pathname + len, filename);
650 if (stat(pathname, &statbuf) == 0 &&
651 /* Accept only regular files
652 with some execute bits set.
653 XXX not perfect, might still fail */
654 S_ISREG(statbuf.st_mode) &&
655 (statbuf.st_mode & 0111))
656 break;
657 }
658 }
659 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200660 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000661 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000662 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000663 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200664 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000665 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200666 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
667 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000668 ) {
669 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200670 if (outf != stderr)
671 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100672 if (!daemonized_tracer && !use_seize) {
673 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200674 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000675 }
Roland McGrath02203312007-06-11 22:06:31 +0000676 }
Roland McGrath02203312007-06-11 22:06:31 +0000677
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200678 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000679 uid_t run_euid = run_uid;
680 gid_t run_egid = run_gid;
681
682 if (statbuf.st_mode & S_ISUID)
683 run_euid = statbuf.st_uid;
684 if (statbuf.st_mode & S_ISGID)
685 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000686 /*
687 * It is important to set groups before we
688 * lose privileges on setuid.
689 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200690 if (initgroups(username, run_gid) < 0) {
691 perror_msg_and_die("initgroups");
692 }
693 if (setregid(run_gid, run_egid) < 0) {
694 perror_msg_and_die("setregid");
695 }
696 if (setreuid(run_uid, run_euid) < 0) {
697 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000698 }
699 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200700 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000701 setreuid(run_uid, run_uid);
702
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000703 if (!daemonized_tracer) {
704 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200705 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000706 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200707 * the immediately following execve syscall.
708 * Can't do this on NOMMU systems, we are after
709 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000710 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400711 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200712 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000713 } else {
714 struct sigaction sv_sigchld;
715 sigaction(SIGCHLD, NULL, &sv_sigchld);
716 /*
717 * Make sure it is not SIG_IGN, otherwise wait
718 * will not block.
719 */
720 signal(SIGCHLD, SIG_DFL);
721 /*
722 * Wait for grandchild to attach to us.
723 * It kills child after that, and wait() unblocks.
724 */
725 alarm(3);
726 wait(NULL);
727 alarm(0);
728 sigaction(SIGCHLD, &sv_sigchld, NULL);
729 }
Roland McGrath02203312007-06-11 22:06:31 +0000730
731 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200732 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000733 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000734
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200735 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200736
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200737 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100738 if (!use_seize) {
739 /* child did PTRACE_TRACEME, nothing to do in parent */
740 } else {
741 if (!strace_vforked) {
742 /* Wait until child stopped itself */
743 int status;
744 while (waitpid(pid, &status, WSTOPPED) < 0) {
745 if (errno == EINTR)
746 continue;
747 perror_msg_and_die("waitpid");
748 }
749 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
750 kill(pid, SIGKILL);
751 perror_msg_and_die("Unexpected wait status %x", status);
752 }
753 }
754 /* Else: vforked case, we have no way to sync.
755 * Just attach to it as soon as possible.
756 * This means that we may miss a few first syscalls...
757 */
758
759 if (ptrace_attach_or_seize(pid)) {
760 kill(pid, SIGKILL);
761 perror_msg_and_die("Can't attach to %d", pid);
762 }
763 if (!strace_vforked)
764 kill(pid, SIGCONT);
765 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200766 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200767 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100768 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200769 else
770 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200771 }
772 else {
773 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
774 strace_tracer_pid = getpid();
775 /* The tracee is our parent: */
776 pid = getppid();
777 tcp = alloctcb(pid);
778 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000779 tcp->flags |= TCB_ATTACHED;
780 }
Roland McGrath02203312007-06-11 22:06:31 +0000781}
782
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000783static void kill_save_errno(pid_t pid, int sig)
784{
785 int saved_errno = errno;
786
787 (void) kill(pid, sig);
788 errno = saved_errno;
789}
790
Wang Chaob13c0de2010-11-12 17:25:19 +0800791/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000792 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800793 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000794 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800795 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000796static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200797test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800798{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000799 int pid, expected_grandchild = 0, found_grandchild = 0;
800 const unsigned int test_options = PTRACE_O_TRACECLONE |
801 PTRACE_O_TRACEFORK |
802 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800803
Denys Vlasenko5d645812011-08-20 12:48:18 +0200804 pid = fork();
805 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000806 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200807 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000808 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100809 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000810 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
811 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100812 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000813 if (fork() < 0)
814 perror_msg_and_die("fork");
815 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800816 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000817
818 while (1) {
819 int status, tracee_pid;
820
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000821 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000822 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000823 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000824 if (errno == EINTR)
825 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100826 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000827 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000828 kill_save_errno(pid, SIGKILL);
829 perror_msg_and_die("%s: unexpected wait result %d",
830 __func__, tracee_pid);
831 }
832 if (WIFEXITED(status)) {
833 if (WEXITSTATUS(status)) {
834 if (tracee_pid != pid)
835 kill_save_errno(pid, SIGKILL);
836 error_msg_and_die("%s: unexpected exit status %u",
837 __func__, WEXITSTATUS(status));
838 }
839 continue;
840 }
841 if (WIFSIGNALED(status)) {
842 if (tracee_pid != pid)
843 kill_save_errno(pid, SIGKILL);
844 error_msg_and_die("%s: unexpected signal %u",
845 __func__, WTERMSIG(status));
846 }
847 if (!WIFSTOPPED(status)) {
848 if (tracee_pid != pid)
849 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100850 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000851 error_msg_and_die("%s: unexpected wait status %x",
852 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000853 }
854 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000855 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000856 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
857 kill_save_errno(tracee_pid, SIGKILL);
858 kill_save_errno(pid, SIGKILL);
859 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800860 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000861 continue;
862 }
863 switch (WSTOPSIG(status)) {
864 case SIGSTOP:
865 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
866 && errno != EINVAL && errno != EIO)
867 perror_msg("PTRACE_SETOPTIONS");
868 break;
869 case SIGTRAP:
870 if (status >> 16 == PTRACE_EVENT_FORK) {
871 long msg = 0;
872
873 if (ptrace(PTRACE_GETEVENTMSG, pid,
874 NULL, (long) &msg) == 0)
875 expected_grandchild = msg;
876 }
877 break;
878 }
879 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
880 kill_save_errno(pid, SIGKILL);
881 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800882 }
883 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000884 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200885 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000886 if (debug)
887 fprintf(stderr, "ptrace_setoptions = %#x\n",
888 ptrace_setoptions);
889 return;
890 }
891 error_msg("Test for PTRACE_O_TRACECLONE failed, "
892 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800893}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200894
895/*
896 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
897 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
898 * and then see whether it will stop with (SIGTRAP | 0x80).
899 *
900 * Use of this option enables correct handling of user-generated SIGTRAPs,
901 * and SIGTRAPs generated by special instructions such as int3 on x86:
902 * _start: .globl _start
903 * int3
904 * movl $42, %ebx
905 * movl $1, %eax
906 * int $0x80
907 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
908 */
909static void
910test_ptrace_setoptions_for_all(void)
911{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000912 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
913 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200914 int pid;
915 int it_worked = 0;
916
917 pid = fork();
918 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200919 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200920
921 if (pid == 0) {
922 pid = getpid();
923 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200924 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000925 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
926 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200927 kill(pid, SIGSTOP);
928 _exit(0); /* parent should see entry into this syscall */
929 }
930
931 while (1) {
932 int status, tracee_pid;
933
934 errno = 0;
935 tracee_pid = wait(&status);
936 if (tracee_pid <= 0) {
937 if (errno == EINTR)
938 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000939 kill_save_errno(pid, SIGKILL);
940 perror_msg_and_die("%s: unexpected wait result %d",
941 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200942 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200943 if (WIFEXITED(status)) {
944 if (WEXITSTATUS(status) == 0)
945 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000946 error_msg_and_die("%s: unexpected exit status %u",
947 __func__, WEXITSTATUS(status));
948 }
949 if (WIFSIGNALED(status)) {
950 error_msg_and_die("%s: unexpected signal %u",
951 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200952 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200953 if (!WIFSTOPPED(status)) {
954 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000955 error_msg_and_die("%s: unexpected wait status %x",
956 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200957 }
958 if (WSTOPSIG(status) == SIGSTOP) {
959 /*
960 * We don't check "options aren't accepted" error.
961 * If it happens, we'll never get (SIGTRAP | 0x80),
962 * and thus will decide to not use the option.
963 * IOW: the outcome of the test will be correct.
964 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000965 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
966 && errno != EINVAL && errno != EIO)
967 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200968 }
969 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
970 it_worked = 1;
971 }
972 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000973 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200974 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200975 }
976 }
977
978 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200979 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200980 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200981 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200982 fprintf(stderr, "ptrace_setoptions = %#x\n",
983 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200984 return;
985 }
986
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000987 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
988 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200989}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100990
991# ifdef USE_SEIZE
992static void
993test_ptrace_seize(void)
994{
995 int pid;
996
997 pid = fork();
998 if (pid < 0)
999 perror_msg_and_die("fork");
1000
1001 if (pid == 0) {
1002 pause();
1003 _exit(0);
1004 }
1005
1006 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1007 * attaching tracee continues to run unless a trap condition occurs.
1008 * PTRACE_SEIZE doesn't affect signal or group stop state.
1009 */
1010 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1011 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1012 } else if (debug) {
1013 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1014 }
1015
1016 kill(pid, SIGKILL);
1017
1018 while (1) {
1019 int status, tracee_pid;
1020
1021 errno = 0;
1022 tracee_pid = waitpid(pid, &status, 0);
1023 if (tracee_pid <= 0) {
1024 if (errno == EINTR)
1025 continue;
1026 perror_msg_and_die("%s: unexpected wait result %d",
1027 __func__, tracee_pid);
1028 }
1029 if (WIFSIGNALED(status)) {
1030 return;
1031 }
1032 error_msg_and_die("%s: unexpected wait status %x",
1033 __func__, status);
1034 }
1035}
1036# else /* !USE_SEIZE */
1037# define test_ptrace_seize() ((void)0)
1038# endif
1039
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001040/* Noinline: don't want main to have struct utsname permanently on stack */
1041static void __attribute__ ((noinline))
1042get_os_release(void)
1043{
1044 struct utsname u;
1045 if (uname(&u) < 0)
1046 perror_msg_and_die("uname");
1047 os_release = strdup(u.release);
1048 if (!os_release)
1049 die_out_of_memory();
1050}
1051
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001053main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001056 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001057 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 struct sigaction sa;
1059
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001060 progname = argv[0] ? argv[0] : "strace";
1061
Denys Vlasenko75422762011-05-27 14:36:01 +02001062 strace_tracer_pid = getpid();
1063
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001064 get_os_release();
1065
Roland McGrathee9d4352002-12-18 04:16:10 +00001066 /* Allocate the initial tcbtab. */
1067 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001068 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001069 if (!tcbtab)
1070 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001071 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001072 if (!tcp)
1073 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001074 for (c = 0; c < tcbtabsize; c++)
1075 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001076
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001078 set_sortby(DEFAULT_SORTBY);
1079 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001080 qualify("trace=all");
1081 qualify("abbrev=all");
1082 qualify("verbose=all");
1083 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001085 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001086 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001087 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 switch (c) {
1089 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001090 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001091 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001092 }
1093 cflag = CFLAG_ONLY_STATS;
1094 break;
1095 case 'C':
1096 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001097 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001098 }
1099 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 break;
1101 case 'd':
1102 debug++;
1103 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001104 case 'D':
1105 daemonized_tracer = 1;
1106 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001107 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001108 optF = 1;
1109 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 case 'f':
1111 followfork++;
1112 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001113 case 'h':
1114 usage(stdout, 0);
1115 break;
1116 case 'i':
1117 iflag++;
1118 break;
1119 case 'q':
1120 qflag++;
1121 break;
1122 case 'r':
1123 rflag++;
1124 tflag++;
1125 break;
1126 case 't':
1127 tflag++;
1128 break;
1129 case 'T':
1130 dtime++;
1131 break;
1132 case 'x':
1133 xflag++;
1134 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001135 case 'y':
1136 show_fd_path = 1;
1137 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138 case 'v':
1139 qualify("abbrev=none");
1140 break;
1141 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001142 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 exit(0);
1144 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001145 case 'z':
1146 not_failing_only = 1;
1147 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 case 'a':
1149 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001150 if (acolumn < 0)
1151 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 break;
1153 case 'e':
1154 qualify(optarg);
1155 break;
1156 case 'o':
1157 outfname = strdup(optarg);
1158 break;
1159 case 'O':
1160 set_overhead(atoi(optarg));
1161 break;
1162 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001163 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001165 case 'P':
1166 tracing_paths = 1;
1167 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001168 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001169 }
1170 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171 case 's':
1172 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001173 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001174 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001175 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176 break;
1177 case 'S':
1178 set_sortby(optarg);
1179 break;
1180 case 'u':
1181 username = strdup(optarg);
1182 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001183 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001184 if (putenv(optarg) < 0)
1185 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001186 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001187 case 'I':
1188 opt_intr = atoi(optarg);
1189 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1190 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1191 }
1192 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193 default:
1194 usage(stderr, 1);
1195 break;
1196 }
1197 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001198 argv += optind;
1199 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200
Denys Vlasenko102ec492011-08-25 01:27:59 +02001201 acolumn_spaces = malloc(acolumn + 1);
1202 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001203 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001204 memset(acolumn_spaces, ' ', acolumn);
1205 acolumn_spaces[acolumn] = '\0';
1206
Denys Vlasenko837399a2012-01-24 11:37:03 +01001207 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001208 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001209 usage(stderr, 1);
1210
Denys Vlasenkofd883382012-03-09 13:03:41 +01001211 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001212 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001213 }
1214
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001215 if (!followfork)
1216 followfork = optF;
1217
Roland McGrathcb9def62006-04-25 07:48:03 +00001218 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001219 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001220 }
1221
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 /* See if they want to run as another user. */
1223 if (username != NULL) {
1224 struct passwd *pent;
1225
1226 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001227 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001229 pent = getpwnam(username);
1230 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001231 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232 }
1233 run_uid = pent->pw_uid;
1234 run_gid = pent->pw_gid;
1235 }
1236 else {
1237 run_uid = getuid();
1238 run_gid = getgid();
1239 }
1240
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001241 if (followfork)
1242 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001243 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001244 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001245
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001246 /* Check if they want to redirect the output. */
1247 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001248 /* See if they want to pipe the output. */
1249 if (outfname[0] == '|' || outfname[0] == '!') {
1250 /*
1251 * We can't do the <outfname>.PID funny business
1252 * when using popen, so prohibit it.
1253 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001254 if (followfork > 1)
1255 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1256 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001257 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001258 else if (followfork <= 1)
1259 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 }
1261
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001262 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001263 char *buf = malloc(BUFSIZ);
1264 if (!buf)
1265 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001267 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001268 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001269 if (!opt_intr)
1270 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001272 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001273 if (!opt_intr)
1274 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001275
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001276 /* argv[0] -pPID -oFILE Default interactive setting
1277 * yes 0 0 INTR_WHILE_WAIT
1278 * no 1 0 INTR_WHILE_WAIT
1279 * yes 0 1 INTR_NEVER
1280 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001281 */
1282
1283 /* STARTUP_CHILD must be called before the signal handlers get
1284 installed below as they are inherited into the spawned process.
1285 Also we do not need to be protected by them as during interruption
1286 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001287 if (argv[0])
1288 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001290 sigemptyset(&empty_set);
1291 sigemptyset(&blocked_set);
1292 sa.sa_handler = SIG_IGN;
1293 sigemptyset(&sa.sa_mask);
1294 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001295 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1296 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1297 if (opt_intr != INTR_ANYWHERE) {
1298 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1299 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1300 /*
1301 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1302 * fatal signals are blocked while syscall stop is processed,
1303 * and acted on in between, when waiting for new syscall stops.
1304 * In non-interactive mode, signals are ignored.
1305 */
1306 if (opt_intr == INTR_WHILE_WAIT) {
1307 sigaddset(&blocked_set, SIGHUP);
1308 sigaddset(&blocked_set, SIGINT);
1309 sigaddset(&blocked_set, SIGQUIT);
1310 sigaddset(&blocked_set, SIGPIPE);
1311 sigaddset(&blocked_set, SIGTERM);
1312 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001313 }
1314 /* SIG_IGN, or set handler for these */
1315 sigaction(SIGHUP, &sa, NULL);
1316 sigaction(SIGINT, &sa, NULL);
1317 sigaction(SIGQUIT, &sa, NULL);
1318 sigaction(SIGPIPE, &sa, NULL);
1319 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 }
Roland McGrath553a6092002-12-16 20:40:39 +00001321 /* Make sure SIGCHLD has the default action so that waitpid
1322 definitely works without losing track of children. The user
1323 should not have given us a bogus state to inherit, but he might
1324 have. Arguably we should detect SIG_IGN here and pass it on
1325 to children, but probably noone really needs that. */
1326 sa.sa_handler = SIG_DFL;
1327 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328
Denys Vlasenkofd883382012-03-09 13:03:41 +01001329 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001330 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001331
Denys Vlasenkofd883382012-03-09 13:03:41 +01001332 /* Do we want pids printed in our -o OUTFILE?
1333 * -ff: no (every pid has its own file); or
1334 * -f: yes (there can be more pids in the future); or
1335 * -p PID1,PID2: yes (there are already more than one pid)
1336 */
1337 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
1338
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339 if (trace() < 0)
1340 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001341
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001343 fflush(NULL);
1344 if (exit_code > 0xff) {
Dmitry V. Levin6c381562012-02-22 00:15:27 +00001345 /* Avoid potential core file clobbering. */
1346 struct rlimit rlim = {0, 0};
1347 setrlimit(RLIMIT_CORE, &rlim);
1348
Dmitry V. Levina6809652008-11-10 17:14:58 +00001349 /* Child was killed by a signal, mimic that. */
1350 exit_code &= 0xff;
1351 signal(exit_code, SIG_DFL);
1352 raise(exit_code);
1353 /* Paranoia - what if this signal is not fatal?
1354 Exit with 128 + signo then. */
1355 exit_code += 128;
1356 }
1357 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358}
1359
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001360static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001361expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001362{
1363 /* Allocate some more TCBs and expand the table.
1364 We don't want to relocate the TCBs because our
1365 callers have pointers and it would be a pain.
1366 So tcbtab is a table of pointers. Since we never
1367 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001368 int i = tcbtabsize;
1369 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1370 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001371 if (!newtab || !newtcbs)
1372 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001373 tcbtabsize *= 2;
1374 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001375 while (i < tcbtabsize)
1376 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001377}
1378
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001379struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001380alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001381{
1382 int i;
1383 struct tcb *tcp;
1384
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001385 if (nprocs == tcbtabsize)
1386 expand_tcbtab();
1387
Roland McGrathee9d4352002-12-18 04:16:10 +00001388 for (i = 0; i < tcbtabsize; i++) {
1389 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001390 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001391 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001393 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001394 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001395#if SUPPORTED_PERSONALITIES > 1
1396 tcp->currpers = current_personality;
1397#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001399 if (debug)
1400 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001401 if (command_options_parsed)
1402 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001403 return tcp;
1404 }
1405 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001406 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407}
1408
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001409static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001410pid2tcb(int pid)
1411{
1412 int i;
1413
1414 if (pid <= 0)
1415 return NULL;
1416
1417 for (i = 0; i < tcbtabsize; i++) {
1418 struct tcb *tcp = tcbtab[i];
1419 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1420 return tcp;
1421 }
1422
1423 return NULL;
1424}
1425
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426void
Denys Vlasenko12014262011-05-30 14:00:14 +02001427droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428{
1429 if (tcp->pid == 0)
1430 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001431
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001432 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001433 if (debug)
1434 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001435
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001436 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001438
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001439 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001440}
1441
Roland McGrath0a463882007-07-05 18:43:16 +00001442/* detach traced process; continue with sig
1443 Never call DETACH twice on the same process as both unattached and
1444 attached-unstopped processes give the same ESRCH. For unattached process we
1445 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446
1447static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001448detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449{
1450 int error = 0;
Roland McGrath1bfd3102007-08-03 10:02:00 +00001451 int status, catch_sigstop;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001452
1453 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001454 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456 /*
1457 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001458 * before detaching. Arghh. We go through hoops
1459 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001461#if defined(SPARC)
1462#undef PTRACE_DETACH
1463#define PTRACE_DETACH PTRACE_SUNDETACH
1464#endif
Roland McGrath02203312007-06-11 22:06:31 +00001465 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001466 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001467 * We must catch exactly one as otherwise the detached process
1468 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001469 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001470 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001471 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001472 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001474 }
1475 else if (errno != ESRCH) {
1476 /* Shouldn't happen. */
1477 perror("detach: ptrace(PTRACE_DETACH, ...)");
1478 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001479 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001480 if (errno != ESRCH)
1481 perror("detach: checking sanity");
1482 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001483 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001484 if (errno != ESRCH)
1485 perror("detach: stopping child");
1486 }
Roland McGrath02203312007-06-11 22:06:31 +00001487 else
1488 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001489 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001491#ifdef __WALL
1492 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1493 if (errno == ECHILD) /* Already gone. */
1494 break;
1495 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001496 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001497 break;
1498 }
1499#endif /* __WALL */
1500 /* No __WALL here. */
1501 if (waitpid(tcp->pid, &status, 0) < 0) {
1502 if (errno != ECHILD) {
1503 perror("detach: waiting");
1504 break;
1505 }
1506#ifdef __WCLONE
1507 /* If no processes, try clones. */
1508 if (wait4(tcp->pid, &status, __WCLONE,
1509 NULL) < 0) {
1510 if (errno != ECHILD)
1511 perror("detach: waiting");
1512 break;
1513 }
1514#endif /* __WCLONE */
1515 }
1516#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001517 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001518#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 if (!WIFSTOPPED(status)) {
1520 /* Au revoir, mon ami. */
1521 break;
1522 }
1523 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001524 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525 break;
1526 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001527 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001528 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001529 : WSTOPSIG(status));
1530 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001533 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535 if (!qflag)
1536 fprintf(stderr, "Process %u detached\n", tcp->pid);
1537
1538 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001539
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540 return error;
1541}
1542
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001544cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545{
1546 int i;
1547 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001548 int fatal_sig;
1549
1550 /* 'interrupted' is a volatile object, fetch it only once */
1551 fatal_sig = interrupted;
1552 if (!fatal_sig)
1553 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554
Roland McGrathee9d4352002-12-18 04:16:10 +00001555 for (i = 0; i < tcbtabsize; i++) {
1556 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557 if (!(tcp->flags & TCB_INUSE))
1558 continue;
1559 if (debug)
1560 fprintf(stderr,
1561 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001562 if (printing_tcp &&
1563 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1564 tprints(" <unfinished ...>\n");
1565 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566 }
1567 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001568 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569 else {
1570 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001571 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572 }
1573 }
1574 if (cflag)
1575 call_summary(outf);
1576}
1577
1578static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001579interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001581 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582}
1583
1584#ifndef HAVE_STRERROR
1585
Roland McGrath6d2b3492002-12-30 00:51:30 +00001586#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587extern int sys_nerr;
1588extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001589#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590
1591const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001592strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001594 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001595
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001596 if (err_no < 1 || err_no >= sys_nerr) {
1597 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598 return buf;
1599 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001600 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601}
1602
1603#endif /* HAVE_STERRROR */
1604
1605#ifndef HAVE_STRSIGNAL
1606
Roland McGrath8f474e02003-01-14 07:53:33 +00001607#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001608extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001610#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1611extern char *_sys_siglist[];
1612#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613
1614const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001615strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001617 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618
1619 if (sig < 1 || sig >= NSIG) {
1620 sprintf(buf, "Unknown signal %d", sig);
1621 return buf;
1622 }
1623#ifdef HAVE__SYS_SIGLIST
1624 return _sys_siglist[sig];
1625#else
1626 return sys_siglist[sig];
1627#endif
1628}
1629
1630#endif /* HAVE_STRSIGNAL */
1631
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001633trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001636 struct rusage *rup = cflag ? &ru : NULL;
1637# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001638 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001639# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640
Roland McGratheb9e2e82009-06-02 16:49:22 -07001641 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001642 int pid;
1643 int wait_errno;
1644 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001645 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001646 struct tcb *tcp;
1647 unsigned event;
1648
Denys Vlasenko222713a2009-03-17 14:29:59 +00001649 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001650 return 0;
1651 if (interactive)
1652 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001653# ifdef __WALL
1654 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001655 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001656 /* this kernel does not support __WALL */
1657 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001658 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001659 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001660 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001661 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001662 pid = wait4(-1, &status, __WCLONE, rup);
1663 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001664 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001665 }
1666 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001667# else
1668 pid = wait4(-1, &status, 0, rup);
1669# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001671 if (interactive)
1672 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001674 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001675 switch (wait_errno) {
1676 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001678 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001679 /*
1680 * We would like to verify this case
1681 * but sometimes a race in Solbourne's
1682 * version of SunOS sometimes reports
1683 * ECHILD before sending us SIGCHILD.
1684 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001685 return 0;
1686 default:
1687 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001688 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001689 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 }
1691 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001692 if (pid == popen_pid) {
1693 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001694 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001695 continue;
1696 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001697
1698 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001699 if (debug) {
1700 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001701 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001702 static const char *const event_names[] = {
1703 [PTRACE_EVENT_CLONE] = "CLONE",
1704 [PTRACE_EVENT_FORK] = "FORK",
1705 [PTRACE_EVENT_VFORK] = "VFORK",
1706 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1707 [PTRACE_EVENT_EXEC] = "EXEC",
1708 [PTRACE_EVENT_EXIT] = "EXIT",
1709 };
1710 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001711 if (event < ARRAY_SIZE(event_names))
1712 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001713 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001714 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001715 e = buf;
1716 }
1717 fprintf(stderr, " PTRACE_EVENT_%s", e);
1718 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001719 strcpy(buf, "???");
1720 if (WIFSIGNALED(status))
1721#ifdef WCOREDUMP
1722 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1723 WCOREDUMP(status) ? "core," : "",
1724 signame(WTERMSIG(status)));
1725#else
1726 sprintf(buf, "WIFSIGNALED,sig=%s",
1727 signame(WTERMSIG(status)));
1728#endif
1729 if (WIFEXITED(status))
1730 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1731 if (WIFSTOPPED(status))
1732 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001733#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001734 if (WIFCONTINUED(status))
1735 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001736#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001737 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1738 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001740 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001741 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001742
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001743 /* Under Linux, execve changes pid to thread leader's pid,
1744 * and we see this changed pid on EVENT_EXEC and later,
1745 * execve sysexit. Leader "disappears" without exit
1746 * notification. Let user know that, drop leader's tcb,
1747 * and fix up pid in execve thread's tcb.
1748 * Effectively, execve thread's tcb replaces leader's tcb.
1749 *
1750 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1751 * on exit syscall) in multithreaded programs exactly
1752 * in order to handle this case.
1753 *
1754 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1755 * On 2.6 and earlier, it can return garbage.
1756 */
1757 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1758 long old_pid = 0;
1759 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1760 && old_pid > 0
1761 && old_pid != pid
1762 ) {
1763 struct tcb *execve_thread = pid2tcb(old_pid);
1764 if (tcp) {
1765 outf = tcp->outf;
1766 curcol = tcp->curcol;
1767 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001768 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001769 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001770 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001771 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1772 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001773 fflush(outf);
1774 }
1775 if (execve_thread) {
1776 /* swap output FILEs (needed for -ff) */
1777 tcp->outf = execve_thread->outf;
1778 execve_thread->outf = outf;
1779 }
1780 droptcb(tcp);
1781 }
1782 tcp = execve_thread;
1783 if (tcp) {
1784 tcp->pid = pid;
1785 tcp->flags |= TCB_REPRINT;
1786 }
1787 }
1788 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001789
Denys Vlasenko5d645812011-08-20 12:48:18 +02001790 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001791 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001792 /* This is needed to go with the CLONE_PTRACE
1793 changes in process.c/util.c: we might see
1794 the child's initial trap before we see the
1795 parent return from the clone syscall.
1796 Leave the child suspended until the parent
1797 returns from its system call. Only then
1798 will we have the association of parent and
1799 child so that we know how to do clearbpt
1800 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001801 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001802 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001803 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001804 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001805 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001806 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001807 else
1808 /* This can happen if a clone call used
1809 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001810 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001811 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001812 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001813 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001814 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001815 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001816 /* set current output file */
1817 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001818 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001819 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1821 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001823
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001824 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001825 if (pid == strace_child)
1826 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001827 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1829 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001830#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001831 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001832 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001833 WCOREDUMP(status) ? "(core dumped) " : "");
1834#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001835 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001836 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001837#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001838 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001840 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841 droptcb(tcp);
1842 continue;
1843 }
1844 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001845 if (pid == strace_child)
1846 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001847 if (tcp == printing_tcp) {
1848 tprints(" <unfinished ...>\n");
1849 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001850 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001851 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1852 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001853 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1854 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001855 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001856 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 droptcb(tcp);
1858 continue;
1859 }
1860 if (!WIFSTOPPED(status)) {
1861 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1862 droptcb(tcp);
1863 continue;
1864 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001866 /* Is this the very first time we see this tracee stopped? */
1867 if (tcp->flags & TCB_STARTUP) {
1868 if (debug)
1869 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001872 /*
1873 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001874 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001875 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001876 if (clearbpt(tcp) < 0) {
1877 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878 droptcb(tcp);
1879 cleanup();
1880 return -1;
1881 }
1882 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001883 if (ptrace_setoptions) {
1884 if (debug)
1885 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1886 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1887 if (errno != ESRCH) {
1888 /* Should never happen, really */
1889 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001890 }
1891 }
1892 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001893 }
1894
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001895 sig = WSTOPSIG(status);
1896
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001897 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001898 /* Ptrace event */
1899#ifdef USE_SEIZE
1900 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001901 /*
1902 * PTRACE_INTERRUPT-stop or group-stop.
1903 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1904 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001905 if (sig == SIGSTOP
1906 || sig == SIGTSTP
1907 || sig == SIGTTIN
1908 || sig == SIGTTOU
1909 ) {
1910 stopped = 1;
1911 goto show_stopsig;
1912 }
1913 }
1914#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001915 goto restart_tracee_with_sig_0;
1916 }
1917
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001918 /* Is this post-attach SIGSTOP?
1919 * Interestingly, the process may stop
1920 * with STOPSIG equal to some other signal
1921 * than SIGSTOP if we happend to attach
1922 * just before the process takes a signal.
1923 */
1924 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
1925 if (debug)
1926 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
1927 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001928 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001929 }
1930
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001931 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001932 siginfo_t si;
1933
1934 /* Nonzero (true) if tracee is stopped by signal
1935 * (as opposed to "tracee received signal").
1936 */
1937 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01001938#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001939 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01001940#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001941 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001942 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00001943#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001944 long pc = 0;
1945 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001946
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001947 upeek(tcp, PT_CR_IPSR, &psr);
1948 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001949
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001950# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001951 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001952# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001953# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001954#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001955# define PC_FORMAT_STR ""
1956# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001957#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001958 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001959 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001960 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001961 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01001962 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001963 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001964 PC_FORMAT_ARG);
1965 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001966 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001967 strsignal(sig),
1968 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001969 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001970 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001971 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001972 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001973
1974 if (!stopped)
1975 /* It's signal-delivery-stop. Inject the signal */
1976 goto restart_tracee;
1977
1978 /* It's group-stop */
1979#ifdef USE_SEIZE
1980 if (use_seize) {
1981 /*
1982 * This ends ptrace-stop, but does *not* end group-stop.
1983 * This makes stopping signals work properly on straced process
1984 * (that is, process really stops. It used to continue to run).
1985 */
1986 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
1987 cleanup();
1988 return -1;
1989 }
1990 continue;
1991 }
1992 /* We don't have PTRACE_LISTEN support... */
1993#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001994 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001996
1997 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00001998 if (interrupted)
1999 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002000
2001 /* This should be syscall entry or exit.
2002 * (Or it still can be that pesky post-execve SIGTRAP!)
2003 * Handle it.
2004 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002005 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2006 /* ptrace() failed in trace_syscall() with ESRCH.
2007 * Likely a result of process disappearing mid-flight.
2008 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002009 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002010 */
2011 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002012 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002013 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002014 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002015 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002016 printing_tcp->flags |= TCB_REPRINT;
2017 tprints(" <unfinished ...>\n");
2018 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002019 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002020 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002021 /* We assume that ptrace error was caused by process death.
2022 * We used to detach(tcp) here, but since we no longer
2023 * implement "detach before death" policy/hack,
2024 * we can let this process to report its death to us
2025 * normally, via WIFEXITED or WIFSIGNALED wait status.
2026 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002027 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002028 /* It's our real child (and we also trace it) */
2029 /* my_tkill(pid, SIGKILL); - why? */
2030 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031 }
2032 continue;
2033 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002034 restart_tracee_with_sig_0:
2035 sig = 0;
2036 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002037 /* Remember current print column before continuing. */
2038 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002039 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 cleanup();
2041 return -1;
2042 }
2043 }
2044 return 0;
2045}
2046
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049{
2050 va_list args;
2051
Andreas Schwabe5355de2009-10-27 16:56:43 +01002052 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002053 if (outf) {
2054 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002055 if (n < 0) {
2056 if (outf != stderr)
2057 perror(outfname == NULL
2058 ? "<writing to pipe>" : outfname);
2059 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002060 curcol += n;
2061 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002063}
2064
2065void
2066tprints(const char *str)
2067{
2068 if (outf) {
2069 int n = fputs(str, outf);
2070 if (n >= 0) {
2071 curcol += strlen(str);
2072 return;
2073 }
2074 if (outf != stderr)
2075 perror(outfname == NULL
2076 ? "<writing to pipe>" : outfname);
2077 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078}
2079
2080void
Denys Vlasenko12014262011-05-30 14:00:14 +02002081printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002082{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002083 if (printing_tcp) {
2084 if (printing_tcp->ptrace_errno) {
2085 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002086 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002087 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002088 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002089 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002090 printing_tcp->ptrace_errno = 0;
2091 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2092 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002093 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002094 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002096
2097 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002098 curcol = 0;
Denys Vlasenkofd883382012-03-09 13:03:41 +01002099
2100 if (print_pid_pfx)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 tprintf("%-5d ", tcp->pid);
2102 else if (nprocs > 1 && !outfname)
2103 tprintf("[pid %5u] ", tcp->pid);
Denys Vlasenkofd883382012-03-09 13:03:41 +01002104
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002105 if (tflag) {
2106 char str[sizeof("HH:MM:SS")];
2107 struct timeval tv, dtv;
2108 static struct timeval otv;
2109
2110 gettimeofday(&tv, NULL);
2111 if (rflag) {
2112 if (otv.tv_sec == 0)
2113 otv = tv;
2114 tv_sub(&dtv, &tv, &otv);
2115 tprintf("%6ld.%06ld ",
2116 (long) dtv.tv_sec, (long) dtv.tv_usec);
2117 otv = tv;
2118 }
2119 else if (tflag > 2) {
2120 tprintf("%ld.%06ld ",
2121 (long) tv.tv_sec, (long) tv.tv_usec);
2122 }
2123 else {
2124 time_t local = tv.tv_sec;
2125 strftime(str, sizeof(str), "%T", localtime(&local));
2126 if (tflag > 1)
2127 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2128 else
2129 tprintf("%s ", str);
2130 }
2131 }
2132 if (iflag)
2133 printcall(tcp);
2134}
2135
2136void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002137tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002139 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002140 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141}