blob: 89a7dc9d3db5bd813b2ec4b1ef3edd9318013c4a [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
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100332static void kill_save_errno(pid_t pid, int sig)
333{
334 int saved_errno = errno;
335
336 (void) kill(pid, sig);
337 errno = saved_errno;
338}
339
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000340/*
341 * When strace is setuid executable, we have to swap uids
342 * before and after filesystem and process management operations.
343 */
344static void
345swap_uid(void)
346{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000347 int euid = geteuid(), uid = getuid();
348
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200349 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200350 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000351 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000352}
353
Roland McGrath4bfa6262007-07-05 20:03:16 +0000354#if _LFS64_LARGEFILE
355# define fopen_for_output fopen64
356#else
357# define fopen_for_output fopen
358#endif
359
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200361strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362{
363 FILE *fp;
364
365 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200366 fp = fopen_for_output(path, "w");
367 if (!fp)
368 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000369 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200370 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000371 return fp;
372}
373
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200374static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000375
376#ifndef _PATH_BSHELL
377# define _PATH_BSHELL "/bin/sh"
378#endif
379
380/*
381 * We cannot use standard popen(3) here because we have to distinguish
382 * popen child process from other processes we trace, and standard popen(3)
383 * does not export its child's pid.
384 */
385static FILE *
386strace_popen(const char *command)
387{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200388 FILE *fp;
389 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000390
391 swap_uid();
392 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200393 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000394
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200395 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000396
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200397 popen_pid = vfork();
398 if (popen_pid == -1)
399 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200401 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000402 /* child */
403 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200404 if (fds[0] != 0) {
405 if (dup2(fds[0], 0))
406 perror_msg_and_die("dup2");
407 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000408 }
409 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200410 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000411 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200412
413 /* parent */
414 close(fds[0]);
415 swap_uid();
416 fp = fdopen(fds[1], "w");
417 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200418 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200419 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000420}
421
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200422static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000423newoutf(struct tcb *tcp)
424{
425 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000426 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000427 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200428 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000429 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000430}
431
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100432static void process_opt_p_list(char *opt)
433{
434 while (*opt) {
435 /*
436 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
437 * pidof uses space as delim, pgrep uses newline. :(
438 */
439 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100440 char *delim = opt + strcspn(opt, ", \n\t");
441 char c = *delim;
442
443 *delim = '\0';
444 pid = atoi(opt); /* TODO: stricter parsing of the number? */
445 if (pid <= 0) {
446 error_msg("Invalid process id: '%s'", opt);
447 *delim = c;
448 return;
449 }
450 if (pid == strace_tracer_pid) {
451 error_msg("I'm sorry, I can't let you do that, Dave.");
452 *delim = c;
453 return;
454 }
455 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100456 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100457 if (c == '\0')
458 break;
459 opt = delim + 1;
460 }
461}
462
Roland McGrath02203312007-06-11 22:06:31 +0000463static void
464startup_attach(void)
465{
466 int tcbi;
467 struct tcb *tcp;
468
469 /*
470 * Block user interruptions as we would leave the traced
471 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200472 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200473 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000474 */
475 if (interactive)
476 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
477
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000478 if (daemonized_tracer) {
479 pid_t pid = fork();
480 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200481 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000482 }
483 if (pid) { /* parent */
484 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200485 * Wait for grandchild to attach to straced process
486 * (grandparent). Grandchild SIGKILLs us after it attached.
487 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000488 * it proceeds to exec the straced program.
489 */
490 pause();
491 _exit(0); /* paranoia */
492 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200493 /* grandchild */
494 /* We will be the tracer process. Remember our new pid: */
495 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000496 }
497
Roland McGrath02203312007-06-11 22:06:31 +0000498 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
499 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200500
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100501 if (!(tcp->flags & TCB_INUSE))
502 continue;
503
Denys Vlasenkod116a732011-09-05 14:01:33 +0200504 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100505 if (tcp->flags & TCB_ATTACHED)
506 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200507
508 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000509 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200510 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000511
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000512 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000513 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000514 DIR *dir;
515
516 sprintf(procdir, "/proc/%d/task", tcp->pid);
517 dir = opendir(procdir);
518 if (dir != NULL) {
519 unsigned int ntid = 0, nerr = 0;
520 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200521
Roland McGrath02203312007-06-11 22:06:31 +0000522 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200523 struct tcb *cur_tcp;
524 int tid;
525
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000526 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000527 continue;
528 tid = atoi(de->d_name);
529 if (tid <= 0)
530 continue;
531 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100532 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000533 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200534 if (debug)
535 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200536 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200537 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200538 if (debug)
539 fprintf(stderr, "attach to pid %d succeeded\n", tid);
540 cur_tcp = tcp;
541 if (tid != tcp->pid)
542 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100543 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000544 }
545 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200546 if (interactive) {
547 sigprocmask(SIG_SETMASK, &empty_set, NULL);
548 if (interrupted)
549 goto ret;
550 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
551 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000552 ntid -= nerr;
553 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000554 perror("attach: ptrace(PTRACE_ATTACH, ...)");
555 droptcb(tcp);
556 continue;
557 }
558 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000559 fprintf(stderr, ntid > 1
560? "Process %u attached with %u threads - interrupt to quit\n"
561: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200562 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000563 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100564 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200565 /* -p PID, we failed to attach to PID itself
566 * but did attach to some of its sibling threads.
567 * Drop PID's tcp.
568 */
569 droptcb(tcp);
570 }
Roland McGrath02203312007-06-11 22:06:31 +0000571 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000572 } /* if (opendir worked) */
573 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100574 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000575 perror("attach: ptrace(PTRACE_ATTACH, ...)");
576 droptcb(tcp);
577 continue;
578 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100579 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200580 if (debug)
581 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000582
583 if (daemonized_tracer) {
584 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000585 * Make parent go away.
586 * Also makes grandparent's wait() unblock.
587 */
588 kill(getppid(), SIGKILL);
589 }
590
Roland McGrath02203312007-06-11 22:06:31 +0000591 if (!qflag)
592 fprintf(stderr,
593 "Process %u attached - interrupt to quit\n",
594 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200595 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000596
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200597 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000598 if (interactive)
599 sigprocmask(SIG_SETMASK, &empty_set, NULL);
600}
601
602static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200603startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000604{
605 struct stat statbuf;
606 const char *filename;
607 char pathname[MAXPATHLEN];
608 int pid = 0;
609 struct tcb *tcp;
610
611 filename = argv[0];
612 if (strchr(filename, '/')) {
613 if (strlen(filename) > sizeof pathname - 1) {
614 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200615 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000616 }
617 strcpy(pathname, filename);
618 }
619#ifdef USE_DEBUGGING_EXEC
620 /*
621 * Debuggers customarily check the current directory
622 * first regardless of the path but doing that gives
623 * security geeks a panic attack.
624 */
625 else if (stat(filename, &statbuf) == 0)
626 strcpy(pathname, filename);
627#endif /* USE_DEBUGGING_EXEC */
628 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000629 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000630 int m, n, len;
631
632 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100633 const char *colon = strchr(path, ':');
634 if (colon) {
635 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000636 m = n + 1;
637 }
638 else
639 m = n = strlen(path);
640 if (n == 0) {
641 if (!getcwd(pathname, MAXPATHLEN))
642 continue;
643 len = strlen(pathname);
644 }
645 else if (n > sizeof pathname - 1)
646 continue;
647 else {
648 strncpy(pathname, path, n);
649 len = n;
650 }
651 if (len && pathname[len - 1] != '/')
652 pathname[len++] = '/';
653 strcpy(pathname + len, filename);
654 if (stat(pathname, &statbuf) == 0 &&
655 /* Accept only regular files
656 with some execute bits set.
657 XXX not perfect, might still fail */
658 S_ISREG(statbuf.st_mode) &&
659 (statbuf.st_mode & 0111))
660 break;
661 }
662 }
663 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200664 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000665 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000666 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000667 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200668 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000669 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200670 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
671 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000672 ) {
673 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200674 if (outf != stderr)
675 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100676 if (!daemonized_tracer && !use_seize) {
677 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200678 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000679 }
Roland McGrath02203312007-06-11 22:06:31 +0000680 }
Roland McGrath02203312007-06-11 22:06:31 +0000681
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200682 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000683 uid_t run_euid = run_uid;
684 gid_t run_egid = run_gid;
685
686 if (statbuf.st_mode & S_ISUID)
687 run_euid = statbuf.st_uid;
688 if (statbuf.st_mode & S_ISGID)
689 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000690 /*
691 * It is important to set groups before we
692 * lose privileges on setuid.
693 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200694 if (initgroups(username, run_gid) < 0) {
695 perror_msg_and_die("initgroups");
696 }
697 if (setregid(run_gid, run_egid) < 0) {
698 perror_msg_and_die("setregid");
699 }
700 if (setreuid(run_uid, run_euid) < 0) {
701 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000702 }
703 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200704 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000705 setreuid(run_uid, run_uid);
706
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000707 if (!daemonized_tracer) {
708 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200709 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000710 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200711 * the immediately following execve syscall.
712 * Can't do this on NOMMU systems, we are after
713 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400715 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200716 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000717 } else {
718 struct sigaction sv_sigchld;
719 sigaction(SIGCHLD, NULL, &sv_sigchld);
720 /*
721 * Make sure it is not SIG_IGN, otherwise wait
722 * will not block.
723 */
724 signal(SIGCHLD, SIG_DFL);
725 /*
726 * Wait for grandchild to attach to us.
727 * It kills child after that, and wait() unblocks.
728 */
729 alarm(3);
730 wait(NULL);
731 alarm(0);
732 sigaction(SIGCHLD, &sv_sigchld, NULL);
733 }
Roland McGrath02203312007-06-11 22:06:31 +0000734
735 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200736 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000737 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000738
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200739 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200740
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200741 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100742 if (!use_seize) {
743 /* child did PTRACE_TRACEME, nothing to do in parent */
744 } else {
745 if (!strace_vforked) {
746 /* Wait until child stopped itself */
747 int status;
748 while (waitpid(pid, &status, WSTOPPED) < 0) {
749 if (errno == EINTR)
750 continue;
751 perror_msg_and_die("waitpid");
752 }
753 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100754 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100755 perror_msg_and_die("Unexpected wait status %x", status);
756 }
757 }
758 /* Else: vforked case, we have no way to sync.
759 * Just attach to it as soon as possible.
760 * This means that we may miss a few first syscalls...
761 */
762
763 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100764 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100765 perror_msg_and_die("Can't attach to %d", pid);
766 }
767 if (!strace_vforked)
768 kill(pid, SIGCONT);
769 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200770 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200771 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100772 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200773 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100774 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200775 }
776 else {
777 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
778 strace_tracer_pid = getpid();
779 /* The tracee is our parent: */
780 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100781 alloctcb(pid);
782 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000783 }
Roland McGrath02203312007-06-11 22:06:31 +0000784}
785
Wang Chaob13c0de2010-11-12 17:25:19 +0800786/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000787 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800788 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000789 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800790 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000791static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200792test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800793{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000794 int pid, expected_grandchild = 0, found_grandchild = 0;
795 const unsigned int test_options = PTRACE_O_TRACECLONE |
796 PTRACE_O_TRACEFORK |
797 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800798
Denys Vlasenko5d645812011-08-20 12:48:18 +0200799 pid = fork();
800 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000801 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200802 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000803 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100804 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000805 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
806 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100807 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000808 if (fork() < 0)
809 perror_msg_and_die("fork");
810 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800811 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000812
813 while (1) {
814 int status, tracee_pid;
815
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000816 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000817 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000818 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000819 if (errno == EINTR)
820 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100821 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000822 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000823 kill_save_errno(pid, SIGKILL);
824 perror_msg_and_die("%s: unexpected wait result %d",
825 __func__, tracee_pid);
826 }
827 if (WIFEXITED(status)) {
828 if (WEXITSTATUS(status)) {
829 if (tracee_pid != pid)
830 kill_save_errno(pid, SIGKILL);
831 error_msg_and_die("%s: unexpected exit status %u",
832 __func__, WEXITSTATUS(status));
833 }
834 continue;
835 }
836 if (WIFSIGNALED(status)) {
837 if (tracee_pid != pid)
838 kill_save_errno(pid, SIGKILL);
839 error_msg_and_die("%s: unexpected signal %u",
840 __func__, WTERMSIG(status));
841 }
842 if (!WIFSTOPPED(status)) {
843 if (tracee_pid != pid)
844 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100845 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000846 error_msg_and_die("%s: unexpected wait status %x",
847 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000848 }
849 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000850 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000851 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
852 kill_save_errno(tracee_pid, SIGKILL);
853 kill_save_errno(pid, SIGKILL);
854 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800855 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000856 continue;
857 }
858 switch (WSTOPSIG(status)) {
859 case SIGSTOP:
860 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
861 && errno != EINVAL && errno != EIO)
862 perror_msg("PTRACE_SETOPTIONS");
863 break;
864 case SIGTRAP:
865 if (status >> 16 == PTRACE_EVENT_FORK) {
866 long msg = 0;
867
868 if (ptrace(PTRACE_GETEVENTMSG, pid,
869 NULL, (long) &msg) == 0)
870 expected_grandchild = msg;
871 }
872 break;
873 }
874 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
875 kill_save_errno(pid, SIGKILL);
876 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800877 }
878 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000879 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200880 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000881 if (debug)
882 fprintf(stderr, "ptrace_setoptions = %#x\n",
883 ptrace_setoptions);
884 return;
885 }
886 error_msg("Test for PTRACE_O_TRACECLONE failed, "
887 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800888}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200889
890/*
891 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
892 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
893 * and then see whether it will stop with (SIGTRAP | 0x80).
894 *
895 * Use of this option enables correct handling of user-generated SIGTRAPs,
896 * and SIGTRAPs generated by special instructions such as int3 on x86:
897 * _start: .globl _start
898 * int3
899 * movl $42, %ebx
900 * movl $1, %eax
901 * int $0x80
902 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
903 */
904static void
905test_ptrace_setoptions_for_all(void)
906{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000907 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
908 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200909 int pid;
910 int it_worked = 0;
911
912 pid = fork();
913 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200914 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200915
916 if (pid == 0) {
917 pid = getpid();
918 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200919 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000920 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
921 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200922 kill(pid, SIGSTOP);
923 _exit(0); /* parent should see entry into this syscall */
924 }
925
926 while (1) {
927 int status, tracee_pid;
928
929 errno = 0;
930 tracee_pid = wait(&status);
931 if (tracee_pid <= 0) {
932 if (errno == EINTR)
933 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000934 kill_save_errno(pid, SIGKILL);
935 perror_msg_and_die("%s: unexpected wait result %d",
936 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200937 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200938 if (WIFEXITED(status)) {
939 if (WEXITSTATUS(status) == 0)
940 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000941 error_msg_and_die("%s: unexpected exit status %u",
942 __func__, WEXITSTATUS(status));
943 }
944 if (WIFSIGNALED(status)) {
945 error_msg_and_die("%s: unexpected signal %u",
946 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200947 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200948 if (!WIFSTOPPED(status)) {
949 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000950 error_msg_and_die("%s: unexpected wait status %x",
951 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200952 }
953 if (WSTOPSIG(status) == SIGSTOP) {
954 /*
955 * We don't check "options aren't accepted" error.
956 * If it happens, we'll never get (SIGTRAP | 0x80),
957 * and thus will decide to not use the option.
958 * IOW: the outcome of the test will be correct.
959 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000960 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
961 && errno != EINVAL && errno != EIO)
962 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200963 }
964 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
965 it_worked = 1;
966 }
967 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000968 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200969 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200970 }
971 }
972
973 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200974 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200975 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200976 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200977 fprintf(stderr, "ptrace_setoptions = %#x\n",
978 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200979 return;
980 }
981
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000982 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
983 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200984}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100985
986# ifdef USE_SEIZE
987static void
988test_ptrace_seize(void)
989{
990 int pid;
991
992 pid = fork();
993 if (pid < 0)
994 perror_msg_and_die("fork");
995
996 if (pid == 0) {
997 pause();
998 _exit(0);
999 }
1000
1001 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1002 * attaching tracee continues to run unless a trap condition occurs.
1003 * PTRACE_SEIZE doesn't affect signal or group stop state.
1004 */
1005 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1006 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1007 } else if (debug) {
1008 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1009 }
1010
1011 kill(pid, SIGKILL);
1012
1013 while (1) {
1014 int status, tracee_pid;
1015
1016 errno = 0;
1017 tracee_pid = waitpid(pid, &status, 0);
1018 if (tracee_pid <= 0) {
1019 if (errno == EINTR)
1020 continue;
1021 perror_msg_and_die("%s: unexpected wait result %d",
1022 __func__, tracee_pid);
1023 }
1024 if (WIFSIGNALED(status)) {
1025 return;
1026 }
1027 error_msg_and_die("%s: unexpected wait status %x",
1028 __func__, status);
1029 }
1030}
1031# else /* !USE_SEIZE */
1032# define test_ptrace_seize() ((void)0)
1033# endif
1034
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001035/* Noinline: don't want main to have struct utsname permanently on stack */
1036static void __attribute__ ((noinline))
1037get_os_release(void)
1038{
1039 struct utsname u;
1040 if (uname(&u) < 0)
1041 perror_msg_and_die("uname");
1042 os_release = strdup(u.release);
1043 if (!os_release)
1044 die_out_of_memory();
1045}
1046
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001048main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001051 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001052 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 struct sigaction sa;
1054
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001055 progname = argv[0] ? argv[0] : "strace";
1056
Denys Vlasenko75422762011-05-27 14:36:01 +02001057 strace_tracer_pid = getpid();
1058
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001059 get_os_release();
1060
Roland McGrathee9d4352002-12-18 04:16:10 +00001061 /* Allocate the initial tcbtab. */
1062 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001063 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001064 if (!tcbtab)
1065 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001066 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001067 if (!tcp)
1068 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001069 for (c = 0; c < tcbtabsize; c++)
1070 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001071
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001072 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001073 set_sortby(DEFAULT_SORTBY);
1074 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 qualify("trace=all");
1076 qualify("abbrev=all");
1077 qualify("verbose=all");
1078 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001080 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001081 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001082 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001083 switch (c) {
1084 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001085 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001086 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001087 }
1088 cflag = CFLAG_ONLY_STATS;
1089 break;
1090 case 'C':
1091 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001092 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001093 }
1094 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001095 break;
1096 case 'd':
1097 debug++;
1098 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001099 case 'D':
1100 daemonized_tracer = 1;
1101 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001102 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001103 optF = 1;
1104 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 case 'f':
1106 followfork++;
1107 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 case 'h':
1109 usage(stdout, 0);
1110 break;
1111 case 'i':
1112 iflag++;
1113 break;
1114 case 'q':
1115 qflag++;
1116 break;
1117 case 'r':
1118 rflag++;
1119 tflag++;
1120 break;
1121 case 't':
1122 tflag++;
1123 break;
1124 case 'T':
1125 dtime++;
1126 break;
1127 case 'x':
1128 xflag++;
1129 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001130 case 'y':
1131 show_fd_path = 1;
1132 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 case 'v':
1134 qualify("abbrev=none");
1135 break;
1136 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001137 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138 exit(0);
1139 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001140 case 'z':
1141 not_failing_only = 1;
1142 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 case 'a':
1144 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001145 if (acolumn < 0)
1146 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 break;
1148 case 'e':
1149 qualify(optarg);
1150 break;
1151 case 'o':
1152 outfname = strdup(optarg);
1153 break;
1154 case 'O':
1155 set_overhead(atoi(optarg));
1156 break;
1157 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001158 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001160 case 'P':
1161 tracing_paths = 1;
1162 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001163 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001164 }
1165 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 case 's':
1167 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001168 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001169 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001170 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171 break;
1172 case 'S':
1173 set_sortby(optarg);
1174 break;
1175 case 'u':
1176 username = strdup(optarg);
1177 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001178 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001179 if (putenv(optarg) < 0)
1180 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001181 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001182 case 'I':
1183 opt_intr = atoi(optarg);
1184 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1185 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1186 }
1187 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 default:
1189 usage(stderr, 1);
1190 break;
1191 }
1192 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001193 argv += optind;
1194 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195
Denys Vlasenko102ec492011-08-25 01:27:59 +02001196 acolumn_spaces = malloc(acolumn + 1);
1197 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001198 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001199 memset(acolumn_spaces, ' ', acolumn);
1200 acolumn_spaces[acolumn] = '\0';
1201
Denys Vlasenko837399a2012-01-24 11:37:03 +01001202 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001203 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001204 usage(stderr, 1);
1205
Denys Vlasenkofd883382012-03-09 13:03:41 +01001206 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001207 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001208 }
1209
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001210 if (!followfork)
1211 followfork = optF;
1212
Roland McGrathcb9def62006-04-25 07:48:03 +00001213 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001214 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001215 }
1216
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217 /* See if they want to run as another user. */
1218 if (username != NULL) {
1219 struct passwd *pent;
1220
1221 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001222 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001224 pent = getpwnam(username);
1225 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001226 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227 }
1228 run_uid = pent->pw_uid;
1229 run_gid = pent->pw_gid;
1230 }
1231 else {
1232 run_uid = getuid();
1233 run_gid = getgid();
1234 }
1235
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001236 if (followfork)
1237 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001238 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001239 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001240
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 /* Check if they want to redirect the output. */
1242 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001243 /* See if they want to pipe the output. */
1244 if (outfname[0] == '|' || outfname[0] == '!') {
1245 /*
1246 * We can't do the <outfname>.PID funny business
1247 * when using popen, so prohibit it.
1248 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001249 if (followfork > 1)
1250 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1251 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001252 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001253 else if (followfork <= 1)
1254 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255 }
1256
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001257 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001258 char *buf = malloc(BUFSIZ);
1259 if (!buf)
1260 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001262 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001263 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001264 if (!opt_intr)
1265 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001267 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001268 if (!opt_intr)
1269 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001270
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001271 /* argv[0] -pPID -oFILE Default interactive setting
1272 * yes 0 0 INTR_WHILE_WAIT
1273 * no 1 0 INTR_WHILE_WAIT
1274 * yes 0 1 INTR_NEVER
1275 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001276 */
1277
1278 /* STARTUP_CHILD must be called before the signal handlers get
1279 installed below as they are inherited into the spawned process.
1280 Also we do not need to be protected by them as during interruption
1281 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001282 if (argv[0])
1283 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285 sigemptyset(&empty_set);
1286 sigemptyset(&blocked_set);
1287 sa.sa_handler = SIG_IGN;
1288 sigemptyset(&sa.sa_mask);
1289 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001290 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1291 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1292 if (opt_intr != INTR_ANYWHERE) {
1293 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1294 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1295 /*
1296 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1297 * fatal signals are blocked while syscall stop is processed,
1298 * and acted on in between, when waiting for new syscall stops.
1299 * In non-interactive mode, signals are ignored.
1300 */
1301 if (opt_intr == INTR_WHILE_WAIT) {
1302 sigaddset(&blocked_set, SIGHUP);
1303 sigaddset(&blocked_set, SIGINT);
1304 sigaddset(&blocked_set, SIGQUIT);
1305 sigaddset(&blocked_set, SIGPIPE);
1306 sigaddset(&blocked_set, SIGTERM);
1307 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001308 }
1309 /* SIG_IGN, or set handler for these */
1310 sigaction(SIGHUP, &sa, NULL);
1311 sigaction(SIGINT, &sa, NULL);
1312 sigaction(SIGQUIT, &sa, NULL);
1313 sigaction(SIGPIPE, &sa, NULL);
1314 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315 }
Roland McGrath553a6092002-12-16 20:40:39 +00001316 /* Make sure SIGCHLD has the default action so that waitpid
1317 definitely works without losing track of children. The user
1318 should not have given us a bogus state to inherit, but he might
1319 have. Arguably we should detect SIG_IGN here and pass it on
1320 to children, but probably noone really needs that. */
1321 sa.sa_handler = SIG_DFL;
1322 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323
Denys Vlasenkofd883382012-03-09 13:03:41 +01001324 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001325 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001326
Denys Vlasenkofd883382012-03-09 13:03:41 +01001327 /* Do we want pids printed in our -o OUTFILE?
1328 * -ff: no (every pid has its own file); or
1329 * -f: yes (there can be more pids in the future); or
1330 * -p PID1,PID2: yes (there are already more than one pid)
1331 */
1332 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
1333
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334 if (trace() < 0)
1335 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001336
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001338 fflush(NULL);
1339 if (exit_code > 0xff) {
Dmitry V. Levin6c381562012-02-22 00:15:27 +00001340 /* Avoid potential core file clobbering. */
1341 struct rlimit rlim = {0, 0};
1342 setrlimit(RLIMIT_CORE, &rlim);
1343
Dmitry V. Levina6809652008-11-10 17:14:58 +00001344 /* Child was killed by a signal, mimic that. */
1345 exit_code &= 0xff;
1346 signal(exit_code, SIG_DFL);
1347 raise(exit_code);
1348 /* Paranoia - what if this signal is not fatal?
1349 Exit with 128 + signo then. */
1350 exit_code += 128;
1351 }
1352 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353}
1354
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001355static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001356expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001357{
1358 /* Allocate some more TCBs and expand the table.
1359 We don't want to relocate the TCBs because our
1360 callers have pointers and it would be a pain.
1361 So tcbtab is a table of pointers. Since we never
1362 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001363 int i = tcbtabsize;
1364 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1365 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001366 if (!newtab || !newtcbs)
1367 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001368 tcbtabsize *= 2;
1369 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001370 while (i < tcbtabsize)
1371 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001372}
1373
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001375alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376{
1377 int i;
1378 struct tcb *tcp;
1379
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001380 if (nprocs == tcbtabsize)
1381 expand_tcbtab();
1382
Roland McGrathee9d4352002-12-18 04:16:10 +00001383 for (i = 0; i < tcbtabsize; i++) {
1384 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001386 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001387 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001388 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001390#if SUPPORTED_PERSONALITIES > 1
1391 tcp->currpers = current_personality;
1392#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001393 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001394 if (debug)
1395 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001396 if (command_options_parsed)
1397 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398 return tcp;
1399 }
1400 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001401 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001402}
1403
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001404static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001405pid2tcb(int pid)
1406{
1407 int i;
1408
1409 if (pid <= 0)
1410 return NULL;
1411
1412 for (i = 0; i < tcbtabsize; i++) {
1413 struct tcb *tcp = tcbtab[i];
1414 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1415 return tcp;
1416 }
1417
1418 return NULL;
1419}
1420
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421void
Denys Vlasenko12014262011-05-30 14:00:14 +02001422droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423{
1424 if (tcp->pid == 0)
1425 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001426
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001427 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001428 if (debug)
1429 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001430
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001431 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001432 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001433
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001434 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435}
1436
Roland McGrath0a463882007-07-05 18:43:16 +00001437/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001438 * Never call DETACH twice on the same process as both unattached and
1439 * attached-unstopped processes give the same ESRCH. For unattached process we
1440 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1441 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001443detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001445 int error;
1446 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447
1448 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001449 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 /*
1452 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001453 * before detaching. Arghh. We go through hoops
1454 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001456#if defined(SPARC)
1457#undef PTRACE_DETACH
1458#define PTRACE_DETACH PTRACE_SUNDETACH
1459#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001460
1461 sigstop_expected = 0;
1462 if (tcp->flags & TCB_ATTACHED) {
1463 /*
1464 * We attached but possibly didn't see the expected SIGSTOP.
1465 * We must catch exactly one as otherwise the detached process
1466 * would be left stopped (process state T).
1467 */
1468 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1469 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1470 if (error == 0) {
1471 /* On a clear day, you can see forever. */
1472 }
1473 else if (errno != ESRCH) {
1474 /* Shouldn't happen. */
1475 perror("detach: ptrace(PTRACE_DETACH, ...)");
1476 }
1477 else if (my_tkill(tcp->pid, 0) < 0) {
1478 if (errno != ESRCH)
1479 perror("detach: checking sanity");
1480 }
1481 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1482 if (errno != ESRCH)
1483 perror("detach: stopping child");
1484 }
1485 else
1486 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001487 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001488
1489 if (sigstop_expected) {
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
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001535 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 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 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001567 if (!(tcp->flags & TCB_STRACE_CHILD))
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 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002011 if (printing_tcp) {
2012 /* Do we have dangling line "syscall(param, param"?
2013 * Finish the line then.
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002014 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002015 printing_tcp->flags |= TCB_REPRINT;
2016 tprints(" <unfinished ...>\n");
2017 printing_tcp = NULL;
2018 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019 }
Denys Vlasenkof2025022012-03-09 15:29:45 +01002020 /* We assume that ptrace error was caused by process death.
2021 * We used to detach(tcp) here, but since we no longer
2022 * implement "detach before death" policy/hack,
2023 * we can let this process to report its death to us
2024 * normally, via WIFEXITED or WIFSIGNALED wait status.
2025 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002026 continue;
2027 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002028 restart_tracee_with_sig_0:
2029 sig = 0;
2030 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002031 /* Remember current print column before continuing. */
2032 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002033 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 cleanup();
2035 return -1;
2036 }
2037 }
2038 return 0;
2039}
2040
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002043{
2044 va_list args;
2045
Andreas Schwabe5355de2009-10-27 16:56:43 +01002046 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002047 if (outf) {
2048 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002049 if (n < 0) {
2050 if (outf != stderr)
2051 perror(outfname == NULL
2052 ? "<writing to pipe>" : outfname);
2053 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002054 curcol += n;
2055 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002057}
2058
2059void
2060tprints(const char *str)
2061{
2062 if (outf) {
2063 int n = fputs(str, outf);
2064 if (n >= 0) {
2065 curcol += strlen(str);
2066 return;
2067 }
2068 if (outf != stderr)
2069 perror(outfname == NULL
2070 ? "<writing to pipe>" : outfname);
2071 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002072}
2073
2074void
Denys Vlasenko12014262011-05-30 14:00:14 +02002075printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002076{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002077 if (printing_tcp) {
2078 if (printing_tcp->ptrace_errno) {
2079 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002080 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002081 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002082 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002083 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002084 printing_tcp->ptrace_errno = 0;
2085 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2086 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002087 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002088 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002089 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002090
2091 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 curcol = 0;
Denys Vlasenkofd883382012-03-09 13:03:41 +01002093
2094 if (print_pid_pfx)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 tprintf("%-5d ", tcp->pid);
2096 else if (nprocs > 1 && !outfname)
2097 tprintf("[pid %5u] ", tcp->pid);
Denys Vlasenkofd883382012-03-09 13:03:41 +01002098
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 if (tflag) {
2100 char str[sizeof("HH:MM:SS")];
2101 struct timeval tv, dtv;
2102 static struct timeval otv;
2103
2104 gettimeofday(&tv, NULL);
2105 if (rflag) {
2106 if (otv.tv_sec == 0)
2107 otv = tv;
2108 tv_sub(&dtv, &tv, &otv);
2109 tprintf("%6ld.%06ld ",
2110 (long) dtv.tv_sec, (long) dtv.tv_usec);
2111 otv = tv;
2112 }
2113 else if (tflag > 2) {
2114 tprintf("%ld.%06ld ",
2115 (long) tv.tv_sec, (long) tv.tv_usec);
2116 }
2117 else {
2118 time_t local = tv.tv_sec;
2119 strftime(str, sizeof(str), "%T", localtime(&local));
2120 if (tflag > 1)
2121 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2122 else
2123 tprintf("%s ", str);
2124 }
2125 }
2126 if (iflag)
2127 printcall(tcp);
2128}
2129
2130void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002131tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002132{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002133 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002134 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002135}