blob: 5e2f9c6c27a6494b1b4edf116e0b0e20a577cf4d [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 Vlasenkoaa6ec412012-01-24 11:35:38 +010075static int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010076
77/* -I n */
78enum {
79 INTR_NOT_SET = 0,
80 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
81 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
82 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
83 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
84 NUM_INTR_OPTS
85};
86static int opt_intr;
87/* We play with signal mask only if this mode is active: */
88#define interactive (opt_intr == INTR_WHILE_WAIT)
89
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000090/*
91 * daemonized_tracer supports -D option.
92 * With this option, strace forks twice.
93 * Unlike normal case, with -D *grandparent* process exec's,
94 * becoming a traced process. Child exits (this prevents traced process
95 * from having children it doesn't expect to have), and grandchild
96 * attaches to grandparent similarly to strace -p PID.
97 * This allows for more transparent interaction in cases
98 * when process and its parent are communicating via signals,
99 * wait() etc. Without -D, strace process gets lodged in between,
100 * disrupting parent<->child link.
101 */
102static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100104#ifdef USE_SEIZE
105static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
106# define use_seize (post_attach_sigstop == 0)
107#else
108# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
109# define use_seize 0
110#endif
111
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000112/* Sometimes we want to print only succeeding syscalls. */
113int not_failing_only = 0;
114
Grant Edwards8a082772011-04-07 20:25:40 +0000115/* Show path associated with fd arguments */
116int show_fd_path = 0;
117
118/* are we filtering traces based on paths? */
119int tracing_paths = 0;
120
Dmitry V. Levina6809652008-11-10 17:14:58 +0000121static int exit_code = 0;
122static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200123static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700124
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000125static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200126static uid_t run_uid;
127static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200130static int acolumn = DEFAULT_ACOLUMN;
131static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000132static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200133static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100134struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100135static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200136static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200137static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200138static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100140static char *os_release; /* from uname() */
141
Denys Vlasenko4c196382012-01-04 15:11:09 +0100142static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100143static int trace(void);
144static void cleanup(void);
145static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146static sigset_t empty_set, blocked_set;
147
148#ifdef HAVE_SIG_ATOMIC_T
149static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100150#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100152#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200155usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156{
157 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100158usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
159 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100160 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100161 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100162 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200164-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100165-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100167-F -- attempt to follow vforks\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100169-I interruptible\n\
170 1: no signals are blocked\n\
171 2: fatal signals are blocked while decoding syscall (default)\n\
172 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
173 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
174 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175-q -- suppress messages about attaching, detaching, etc.\n\
176-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100177-T -- print time spent in each syscall\n\
178-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000179-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000180-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100181-h -- print help message\n\
182-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183-a column -- alignment COLUMN for printing syscall results (default %d)\n\
184-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
185 options: trace, abbrev, verbose, raw, signal, read, or write\n\
186-o file -- send trace output to FILE instead of stderr\n\
187-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
188-p pid -- trace process with process id PID, may be repeated\n\
189-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
190-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
191-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000192-E var=val -- put var=val in the environment for command\n\
193-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000194-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000195" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000196-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000197 */
198, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199 exit(exitval);
200}
201
Denys Vlasenko75422762011-05-27 14:36:01 +0200202static void die(void) __attribute__ ((noreturn));
203static void die(void)
204{
205 if (strace_tracer_pid == getpid()) {
206 cflag = 0;
207 cleanup();
208 }
209 exit(1);
210}
211
212static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200213{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100214 char *msg;
215
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000216 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100217
218 /* We want to print entire message with single fprintf to ensure
219 * message integrity if stderr is shared with other programs.
220 * Thus we use vasprintf + single fprintf.
221 */
222 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100223 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100224 if (err_no)
225 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
226 else
227 fprintf(stderr, "%s: %s\n", progname, msg);
228 free(msg);
229 } else {
230 /* malloc in vasprintf failed, try it without malloc */
231 fprintf(stderr, "%s: ", progname);
232 vfprintf(stderr, fmt, p);
233 if (err_no)
234 fprintf(stderr, ": %s\n", strerror(err_no));
235 else
236 putc('\n', stderr);
237 }
238 /* We don't switch stderr to buffered, thus fprintf(stderr)
239 * always flushes its output and this is not necessary: */
240 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200241}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200242
Denys Vlasenko75422762011-05-27 14:36:01 +0200243void error_msg(const char *fmt, ...)
244{
245 va_list p;
246 va_start(p, fmt);
247 verror_msg(0, fmt, p);
248 va_end(p);
249}
250
251void error_msg_and_die(const char *fmt, ...)
252{
253 va_list p;
254 va_start(p, fmt);
255 verror_msg(0, fmt, p);
256 die();
257}
258
259void perror_msg(const char *fmt, ...)
260{
261 va_list p;
262 va_start(p, fmt);
263 verror_msg(errno, fmt, p);
264 va_end(p);
265}
266
267void perror_msg_and_die(const char *fmt, ...)
268{
269 va_list p;
270 va_start(p, fmt);
271 verror_msg(errno, fmt, p);
272 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200273}
274
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200275void die_out_of_memory(void)
276{
277 static bool recursed = 0;
278 if (recursed)
279 exit(1);
280 recursed = 1;
281 error_msg_and_die("Out of memory");
282}
283
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400284/* Glue for systems without a MMU that cannot provide fork() */
285#ifdef HAVE_FORK
286# define strace_vforked 0
287#else
288# define strace_vforked 1
289# define fork() vfork()
290#endif
291
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100292#ifdef USE_SEIZE
293static int
294ptrace_attach_or_seize(int pid)
295{
296 int r;
297 if (!use_seize)
298 return ptrace(PTRACE_ATTACH, pid, 0, 0);
299 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
300 if (r)
301 return r;
302 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
303 return r;
304}
305#else
306# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
307#endif
308
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200309static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000310set_cloexec_flag(int fd)
311{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200312 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000313
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200314 flags = fcntl(fd, F_GETFD);
315 if (flags < 0) {
316 /* Can happen only if fd is bad.
317 * Should never happen: if it does, we have a bug
318 * in the caller. Therefore we just abort
319 * instead of propagating the error.
320 */
321 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000322 }
323
324 newflags = flags | FD_CLOEXEC;
325 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200326 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000327
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200328 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000329}
330
331/*
332 * When strace is setuid executable, we have to swap uids
333 * before and after filesystem and process management operations.
334 */
335static void
336swap_uid(void)
337{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000338 int euid = geteuid(), uid = getuid();
339
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200340 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200341 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000342 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343}
344
Roland McGrath4bfa6262007-07-05 20:03:16 +0000345#if _LFS64_LARGEFILE
346# define fopen_for_output fopen64
347#else
348# define fopen_for_output fopen
349#endif
350
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000351static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200352strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000353{
354 FILE *fp;
355
356 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200357 fp = fopen_for_output(path, "w");
358 if (!fp)
359 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200361 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362 return fp;
363}
364
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200365static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000366
367#ifndef _PATH_BSHELL
368# define _PATH_BSHELL "/bin/sh"
369#endif
370
371/*
372 * We cannot use standard popen(3) here because we have to distinguish
373 * popen child process from other processes we trace, and standard popen(3)
374 * does not export its child's pid.
375 */
376static FILE *
377strace_popen(const char *command)
378{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200379 FILE *fp;
380 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000381
382 swap_uid();
383 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200384 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000385
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200386 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000387
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200388 popen_pid = vfork();
389 if (popen_pid == -1)
390 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000391
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200392 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000393 /* child */
394 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200395 if (fds[0] != 0) {
396 if (dup2(fds[0], 0))
397 perror_msg_and_die("dup2");
398 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000399 }
400 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200401 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000402 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200403
404 /* parent */
405 close(fds[0]);
406 swap_uid();
407 fp = fdopen(fds[1], "w");
408 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200409 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200410 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000411}
412
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200413static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000414newoutf(struct tcb *tcp)
415{
416 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000417 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000418 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200419 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000420 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000421}
422
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100423static void process_opt_p_list(char *opt)
424{
425 while (*opt) {
426 /*
427 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
428 * pidof uses space as delim, pgrep uses newline. :(
429 */
430 int pid;
431 struct tcb *tcp;
432 char *delim = opt + strcspn(opt, ", \n\t");
433 char c = *delim;
434
435 *delim = '\0';
436 pid = atoi(opt); /* TODO: stricter parsing of the number? */
437 if (pid <= 0) {
438 error_msg("Invalid process id: '%s'", opt);
439 *delim = c;
440 return;
441 }
442 if (pid == strace_tracer_pid) {
443 error_msg("I'm sorry, I can't let you do that, Dave.");
444 *delim = c;
445 return;
446 }
447 *delim = c;
448 tcp = alloc_tcb(pid, 0);
449 tcp->flags |= TCB_ATTACHED;
450 /*
451 * pflag_seen says how many PIDs we handled,
452 * not how many -p opts there were.
453 * Used to decide whether to print pid prefix in logs.
454 */
455 pflag_seen++;
456 if (c == '\0')
457 break;
458 opt = delim + 1;
459 }
460}
461
Roland McGrath02203312007-06-11 22:06:31 +0000462static void
463startup_attach(void)
464{
465 int tcbi;
466 struct tcb *tcp;
467
468 /*
469 * Block user interruptions as we would leave the traced
470 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200471 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200472 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000473 */
474 if (interactive)
475 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
476
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000477 if (daemonized_tracer) {
478 pid_t pid = fork();
479 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200480 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000481 }
482 if (pid) { /* parent */
483 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200484 * Wait for grandchild to attach to straced process
485 * (grandparent). Grandchild SIGKILLs us after it attached.
486 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000487 * it proceeds to exec the straced program.
488 */
489 pause();
490 _exit(0); /* paranoia */
491 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200492 /* grandchild */
493 /* We will be the tracer process. Remember our new pid: */
494 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000495 }
496
Roland McGrath02203312007-06-11 22:06:31 +0000497 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
498 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200499
Denys Vlasenkod116a732011-09-05 14:01:33 +0200500 /* Is this a process we should attach to, but not yet attached? */
501 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
502 continue; /* no */
503
504 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000505 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200506 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000507
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000508 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000509 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000510 DIR *dir;
511
512 sprintf(procdir, "/proc/%d/task", tcp->pid);
513 dir = opendir(procdir);
514 if (dir != NULL) {
515 unsigned int ntid = 0, nerr = 0;
516 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200517
Roland McGrath02203312007-06-11 22:06:31 +0000518 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200519 struct tcb *cur_tcp;
520 int tid;
521
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000522 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000523 continue;
524 tid = atoi(de->d_name);
525 if (tid <= 0)
526 continue;
527 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100528 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000529 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200530 if (debug)
531 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200532 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200533 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200534 if (debug)
535 fprintf(stderr, "attach to pid %d succeeded\n", tid);
536 cur_tcp = tcp;
537 if (tid != tcp->pid)
538 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100539 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000540 }
541 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200542 if (interactive) {
543 sigprocmask(SIG_SETMASK, &empty_set, NULL);
544 if (interrupted)
545 goto ret;
546 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
547 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000548 ntid -= nerr;
549 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000550 perror("attach: ptrace(PTRACE_ATTACH, ...)");
551 droptcb(tcp);
552 continue;
553 }
554 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000555 fprintf(stderr, ntid > 1
556? "Process %u attached with %u threads - interrupt to quit\n"
557: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200558 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000559 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200560 if (!(tcp->flags & TCB_STARTUP)) {
561 /* -p PID, we failed to attach to PID itself
562 * but did attach to some of its sibling threads.
563 * Drop PID's tcp.
564 */
565 droptcb(tcp);
566 }
Roland McGrath02203312007-06-11 22:06:31 +0000567 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000568 } /* if (opendir worked) */
569 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100570 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000571 perror("attach: ptrace(PTRACE_ATTACH, ...)");
572 droptcb(tcp);
573 continue;
574 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100575 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200576 if (debug)
577 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000578
579 if (daemonized_tracer) {
580 /*
581 * It is our grandparent we trace, not a -p PID.
582 * Don't want to just detach on exit, so...
583 */
584 tcp->flags &= ~TCB_ATTACHED;
585 /*
586 * Make parent go away.
587 * Also makes grandparent's wait() unblock.
588 */
589 kill(getppid(), SIGKILL);
590 }
591
Roland McGrath02203312007-06-11 22:06:31 +0000592 if (!qflag)
593 fprintf(stderr,
594 "Process %u attached - interrupt to quit\n",
595 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200596 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000597
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200598 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000599 if (interactive)
600 sigprocmask(SIG_SETMASK, &empty_set, NULL);
601}
602
603static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200604startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000605{
606 struct stat statbuf;
607 const char *filename;
608 char pathname[MAXPATHLEN];
609 int pid = 0;
610 struct tcb *tcp;
611
612 filename = argv[0];
613 if (strchr(filename, '/')) {
614 if (strlen(filename) > sizeof pathname - 1) {
615 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200616 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000617 }
618 strcpy(pathname, filename);
619 }
620#ifdef USE_DEBUGGING_EXEC
621 /*
622 * Debuggers customarily check the current directory
623 * first regardless of the path but doing that gives
624 * security geeks a panic attack.
625 */
626 else if (stat(filename, &statbuf) == 0)
627 strcpy(pathname, filename);
628#endif /* USE_DEBUGGING_EXEC */
629 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000630 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000631 int m, n, len;
632
633 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100634 const char *colon = strchr(path, ':');
635 if (colon) {
636 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000637 m = n + 1;
638 }
639 else
640 m = n = strlen(path);
641 if (n == 0) {
642 if (!getcwd(pathname, MAXPATHLEN))
643 continue;
644 len = strlen(pathname);
645 }
646 else if (n > sizeof pathname - 1)
647 continue;
648 else {
649 strncpy(pathname, path, n);
650 len = n;
651 }
652 if (len && pathname[len - 1] != '/')
653 pathname[len++] = '/';
654 strcpy(pathname + len, filename);
655 if (stat(pathname, &statbuf) == 0 &&
656 /* Accept only regular files
657 with some execute bits set.
658 XXX not perfect, might still fail */
659 S_ISREG(statbuf.st_mode) &&
660 (statbuf.st_mode & 0111))
661 break;
662 }
663 }
664 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200665 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000666 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000667 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000668 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200669 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000670 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200671 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
672 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000673 ) {
674 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200675 if (outf != stderr)
676 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100677 if (!daemonized_tracer && !use_seize) {
678 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200679 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000680 }
Roland McGrath02203312007-06-11 22:06:31 +0000681 }
Roland McGrath02203312007-06-11 22:06:31 +0000682
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200683 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000684 uid_t run_euid = run_uid;
685 gid_t run_egid = run_gid;
686
687 if (statbuf.st_mode & S_ISUID)
688 run_euid = statbuf.st_uid;
689 if (statbuf.st_mode & S_ISGID)
690 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000691 /*
692 * It is important to set groups before we
693 * lose privileges on setuid.
694 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200695 if (initgroups(username, run_gid) < 0) {
696 perror_msg_and_die("initgroups");
697 }
698 if (setregid(run_gid, run_egid) < 0) {
699 perror_msg_and_die("setregid");
700 }
701 if (setreuid(run_uid, run_euid) < 0) {
702 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000703 }
704 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200705 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000706 setreuid(run_uid, run_uid);
707
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708 if (!daemonized_tracer) {
709 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200710 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000711 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200712 * the immediately following execve syscall.
713 * Can't do this on NOMMU systems, we are after
714 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000715 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400716 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200717 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000718 } else {
719 struct sigaction sv_sigchld;
720 sigaction(SIGCHLD, NULL, &sv_sigchld);
721 /*
722 * Make sure it is not SIG_IGN, otherwise wait
723 * will not block.
724 */
725 signal(SIGCHLD, SIG_DFL);
726 /*
727 * Wait for grandchild to attach to us.
728 * It kills child after that, and wait() unblocks.
729 */
730 alarm(3);
731 wait(NULL);
732 alarm(0);
733 sigaction(SIGCHLD, &sv_sigchld, NULL);
734 }
Roland McGrath02203312007-06-11 22:06:31 +0000735
736 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200737 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000738 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000739
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200740 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200741
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200742 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100743 if (!use_seize) {
744 /* child did PTRACE_TRACEME, nothing to do in parent */
745 } else {
746 if (!strace_vforked) {
747 /* Wait until child stopped itself */
748 int status;
749 while (waitpid(pid, &status, WSTOPPED) < 0) {
750 if (errno == EINTR)
751 continue;
752 perror_msg_and_die("waitpid");
753 }
754 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
755 kill(pid, SIGKILL);
756 perror_msg_and_die("Unexpected wait status %x", status);
757 }
758 }
759 /* Else: vforked case, we have no way to sync.
760 * Just attach to it as soon as possible.
761 * This means that we may miss a few first syscalls...
762 */
763
764 if (ptrace_attach_or_seize(pid)) {
765 kill(pid, SIGKILL);
766 perror_msg_and_die("Can't attach to %d", pid);
767 }
768 if (!strace_vforked)
769 kill(pid, SIGCONT);
770 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200771 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200772 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100773 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200774 else
775 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200776 }
777 else {
778 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
779 strace_tracer_pid = getpid();
780 /* The tracee is our parent: */
781 pid = getppid();
782 tcp = alloctcb(pid);
783 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000784 tcp->flags |= TCB_ATTACHED;
785 }
Roland McGrath02203312007-06-11 22:06:31 +0000786}
787
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000788static void kill_save_errno(pid_t pid, int sig)
789{
790 int saved_errno = errno;
791
792 (void) kill(pid, sig);
793 errno = saved_errno;
794}
795
Wang Chaob13c0de2010-11-12 17:25:19 +0800796/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000797 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800798 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000799 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800800 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000801static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200802test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800803{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000804 int pid, expected_grandchild = 0, found_grandchild = 0;
805 const unsigned int test_options = PTRACE_O_TRACECLONE |
806 PTRACE_O_TRACEFORK |
807 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800808
Denys Vlasenko5d645812011-08-20 12:48:18 +0200809 pid = fork();
810 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000811 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200812 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000813 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100814 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000815 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
816 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100817 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000818 if (fork() < 0)
819 perror_msg_and_die("fork");
820 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800821 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000822
823 while (1) {
824 int status, tracee_pid;
825
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000826 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000827 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000828 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000829 if (errno == EINTR)
830 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100831 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000832 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000833 kill_save_errno(pid, SIGKILL);
834 perror_msg_and_die("%s: unexpected wait result %d",
835 __func__, tracee_pid);
836 }
837 if (WIFEXITED(status)) {
838 if (WEXITSTATUS(status)) {
839 if (tracee_pid != pid)
840 kill_save_errno(pid, SIGKILL);
841 error_msg_and_die("%s: unexpected exit status %u",
842 __func__, WEXITSTATUS(status));
843 }
844 continue;
845 }
846 if (WIFSIGNALED(status)) {
847 if (tracee_pid != pid)
848 kill_save_errno(pid, SIGKILL);
849 error_msg_and_die("%s: unexpected signal %u",
850 __func__, WTERMSIG(status));
851 }
852 if (!WIFSTOPPED(status)) {
853 if (tracee_pid != pid)
854 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100855 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000856 error_msg_and_die("%s: unexpected wait status %x",
857 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000858 }
859 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000860 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000861 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
862 kill_save_errno(tracee_pid, SIGKILL);
863 kill_save_errno(pid, SIGKILL);
864 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800865 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000866 continue;
867 }
868 switch (WSTOPSIG(status)) {
869 case SIGSTOP:
870 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
871 && errno != EINVAL && errno != EIO)
872 perror_msg("PTRACE_SETOPTIONS");
873 break;
874 case SIGTRAP:
875 if (status >> 16 == PTRACE_EVENT_FORK) {
876 long msg = 0;
877
878 if (ptrace(PTRACE_GETEVENTMSG, pid,
879 NULL, (long) &msg) == 0)
880 expected_grandchild = msg;
881 }
882 break;
883 }
884 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
885 kill_save_errno(pid, SIGKILL);
886 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800887 }
888 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000889 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200890 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000891 if (debug)
892 fprintf(stderr, "ptrace_setoptions = %#x\n",
893 ptrace_setoptions);
894 return;
895 }
896 error_msg("Test for PTRACE_O_TRACECLONE failed, "
897 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800898}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200899
900/*
901 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
902 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
903 * and then see whether it will stop with (SIGTRAP | 0x80).
904 *
905 * Use of this option enables correct handling of user-generated SIGTRAPs,
906 * and SIGTRAPs generated by special instructions such as int3 on x86:
907 * _start: .globl _start
908 * int3
909 * movl $42, %ebx
910 * movl $1, %eax
911 * int $0x80
912 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
913 */
914static void
915test_ptrace_setoptions_for_all(void)
916{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000917 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
918 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200919 int pid;
920 int it_worked = 0;
921
922 pid = fork();
923 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200924 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200925
926 if (pid == 0) {
927 pid = getpid();
928 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200929 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000930 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
931 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200932 kill(pid, SIGSTOP);
933 _exit(0); /* parent should see entry into this syscall */
934 }
935
936 while (1) {
937 int status, tracee_pid;
938
939 errno = 0;
940 tracee_pid = wait(&status);
941 if (tracee_pid <= 0) {
942 if (errno == EINTR)
943 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000944 kill_save_errno(pid, SIGKILL);
945 perror_msg_and_die("%s: unexpected wait result %d",
946 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200947 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200948 if (WIFEXITED(status)) {
949 if (WEXITSTATUS(status) == 0)
950 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000951 error_msg_and_die("%s: unexpected exit status %u",
952 __func__, WEXITSTATUS(status));
953 }
954 if (WIFSIGNALED(status)) {
955 error_msg_and_die("%s: unexpected signal %u",
956 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200957 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200958 if (!WIFSTOPPED(status)) {
959 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000960 error_msg_and_die("%s: unexpected wait status %x",
961 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200962 }
963 if (WSTOPSIG(status) == SIGSTOP) {
964 /*
965 * We don't check "options aren't accepted" error.
966 * If it happens, we'll never get (SIGTRAP | 0x80),
967 * and thus will decide to not use the option.
968 * IOW: the outcome of the test will be correct.
969 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000970 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
971 && errno != EINVAL && errno != EIO)
972 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200973 }
974 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
975 it_worked = 1;
976 }
977 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000978 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200979 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200980 }
981 }
982
983 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200984 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200985 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200986 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200987 fprintf(stderr, "ptrace_setoptions = %#x\n",
988 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200989 return;
990 }
991
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000992 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
993 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200994}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100995
996# ifdef USE_SEIZE
997static void
998test_ptrace_seize(void)
999{
1000 int pid;
1001
1002 pid = fork();
1003 if (pid < 0)
1004 perror_msg_and_die("fork");
1005
1006 if (pid == 0) {
1007 pause();
1008 _exit(0);
1009 }
1010
1011 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1012 * attaching tracee continues to run unless a trap condition occurs.
1013 * PTRACE_SEIZE doesn't affect signal or group stop state.
1014 */
1015 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1016 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1017 } else if (debug) {
1018 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1019 }
1020
1021 kill(pid, SIGKILL);
1022
1023 while (1) {
1024 int status, tracee_pid;
1025
1026 errno = 0;
1027 tracee_pid = waitpid(pid, &status, 0);
1028 if (tracee_pid <= 0) {
1029 if (errno == EINTR)
1030 continue;
1031 perror_msg_and_die("%s: unexpected wait result %d",
1032 __func__, tracee_pid);
1033 }
1034 if (WIFSIGNALED(status)) {
1035 return;
1036 }
1037 error_msg_and_die("%s: unexpected wait status %x",
1038 __func__, status);
1039 }
1040}
1041# else /* !USE_SEIZE */
1042# define test_ptrace_seize() ((void)0)
1043# endif
1044
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001045/* Noinline: don't want main to have struct utsname permanently on stack */
1046static void __attribute__ ((noinline))
1047get_os_release(void)
1048{
1049 struct utsname u;
1050 if (uname(&u) < 0)
1051 perror_msg_and_die("uname");
1052 os_release = strdup(u.release);
1053 if (!os_release)
1054 die_out_of_memory();
1055}
1056
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001058main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001061 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001062 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001063 struct sigaction sa;
1064
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001065 progname = argv[0] ? argv[0] : "strace";
1066
Denys Vlasenko75422762011-05-27 14:36:01 +02001067 strace_tracer_pid = getpid();
1068
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001069 get_os_release();
1070
Roland McGrathee9d4352002-12-18 04:16:10 +00001071 /* Allocate the initial tcbtab. */
1072 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001073 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001074 if (!tcbtab)
1075 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001076 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001077 if (!tcp)
1078 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001079 for (c = 0; c < tcbtabsize; c++)
1080 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001081
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001083 set_sortby(DEFAULT_SORTBY);
1084 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085 qualify("trace=all");
1086 qualify("abbrev=all");
1087 qualify("verbose=all");
1088 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001089 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001090 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001091 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001092 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093 switch (c) {
1094 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001095 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001096 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001097 }
1098 cflag = CFLAG_ONLY_STATS;
1099 break;
1100 case 'C':
1101 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001102 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001103 }
1104 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 break;
1106 case 'd':
1107 debug++;
1108 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001109 case 'D':
1110 daemonized_tracer = 1;
1111 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001112 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001113 optF = 1;
1114 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001115 case 'f':
1116 followfork++;
1117 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 case 'h':
1119 usage(stdout, 0);
1120 break;
1121 case 'i':
1122 iflag++;
1123 break;
1124 case 'q':
1125 qflag++;
1126 break;
1127 case 'r':
1128 rflag++;
1129 tflag++;
1130 break;
1131 case 't':
1132 tflag++;
1133 break;
1134 case 'T':
1135 dtime++;
1136 break;
1137 case 'x':
1138 xflag++;
1139 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001140 case 'y':
1141 show_fd_path = 1;
1142 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 case 'v':
1144 qualify("abbrev=none");
1145 break;
1146 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001147 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 exit(0);
1149 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001150 case 'z':
1151 not_failing_only = 1;
1152 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 case 'a':
1154 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001155 if (acolumn < 0)
1156 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 break;
1158 case 'e':
1159 qualify(optarg);
1160 break;
1161 case 'o':
1162 outfname = strdup(optarg);
1163 break;
1164 case 'O':
1165 set_overhead(atoi(optarg));
1166 break;
1167 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001168 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001170 case 'P':
1171 tracing_paths = 1;
1172 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001173 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001174 }
1175 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176 case 's':
1177 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001178 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001179 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001180 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181 break;
1182 case 'S':
1183 set_sortby(optarg);
1184 break;
1185 case 'u':
1186 username = strdup(optarg);
1187 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001188 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001189 if (putenv(optarg) < 0)
1190 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001191 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001192 case 'I':
1193 opt_intr = atoi(optarg);
1194 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1195 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1196 }
1197 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198 default:
1199 usage(stderr, 1);
1200 break;
1201 }
1202 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001203 argv += optind;
1204 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205
Denys Vlasenko102ec492011-08-25 01:27:59 +02001206 acolumn_spaces = malloc(acolumn + 1);
1207 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001208 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001209 memset(acolumn_spaces, ' ', acolumn);
1210 acolumn_spaces[acolumn] = '\0';
1211
Denys Vlasenko837399a2012-01-24 11:37:03 +01001212 /* Must have PROG [ARGS], or -p PID. Not both. */
1213 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001214 usage(stderr, 1);
1215
Wang Chaod322a4b2010-08-05 14:30:11 +08001216 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001217 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001218 }
1219
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001220 if (!followfork)
1221 followfork = optF;
1222
Roland McGrathcb9def62006-04-25 07:48:03 +00001223 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001224 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001225 }
1226
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227 /* See if they want to run as another user. */
1228 if (username != NULL) {
1229 struct passwd *pent;
1230
1231 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001232 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001234 pent = getpwnam(username);
1235 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001236 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237 }
1238 run_uid = pent->pw_uid;
1239 run_gid = pent->pw_gid;
1240 }
1241 else {
1242 run_uid = getuid();
1243 run_gid = getgid();
1244 }
1245
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001246 if (followfork)
1247 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001248 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001249 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001250
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251 /* Check if they want to redirect the output. */
1252 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001253 /* See if they want to pipe the output. */
1254 if (outfname[0] == '|' || outfname[0] == '!') {
1255 /*
1256 * We can't do the <outfname>.PID funny business
1257 * when using popen, so prohibit it.
1258 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001259 if (followfork > 1)
1260 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1261 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001262 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001263 else if (followfork <= 1)
1264 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265 }
1266
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001267 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001268 char *buf = malloc(BUFSIZ);
1269 if (!buf)
1270 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001272 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001273 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001274 if (!opt_intr)
1275 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001277 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001278 if (!opt_intr)
1279 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001280
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001281 /* argv[0] -pPID -oFILE Default interactive setting
1282 * yes 0 0 INTR_WHILE_WAIT
1283 * no 1 0 INTR_WHILE_WAIT
1284 * yes 0 1 INTR_NEVER
1285 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001286 */
1287
1288 /* STARTUP_CHILD must be called before the signal handlers get
1289 installed below as they are inherited into the spawned process.
1290 Also we do not need to be protected by them as during interruption
1291 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001292 if (argv[0])
1293 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295 sigemptyset(&empty_set);
1296 sigemptyset(&blocked_set);
1297 sa.sa_handler = SIG_IGN;
1298 sigemptyset(&sa.sa_mask);
1299 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001300 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1301 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1302 if (opt_intr != INTR_ANYWHERE) {
1303 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1304 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1305 /*
1306 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1307 * fatal signals are blocked while syscall stop is processed,
1308 * and acted on in between, when waiting for new syscall stops.
1309 * In non-interactive mode, signals are ignored.
1310 */
1311 if (opt_intr == INTR_WHILE_WAIT) {
1312 sigaddset(&blocked_set, SIGHUP);
1313 sigaddset(&blocked_set, SIGINT);
1314 sigaddset(&blocked_set, SIGQUIT);
1315 sigaddset(&blocked_set, SIGPIPE);
1316 sigaddset(&blocked_set, SIGTERM);
1317 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001318 }
1319 /* SIG_IGN, or set handler for these */
1320 sigaction(SIGHUP, &sa, NULL);
1321 sigaction(SIGINT, &sa, NULL);
1322 sigaction(SIGQUIT, &sa, NULL);
1323 sigaction(SIGPIPE, &sa, NULL);
1324 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325 }
Roland McGrath553a6092002-12-16 20:40:39 +00001326 /* Make sure SIGCHLD has the default action so that waitpid
1327 definitely works without losing track of children. The user
1328 should not have given us a bogus state to inherit, but he might
1329 have. Arguably we should detect SIG_IGN here and pass it on
1330 to children, but probably noone really needs that. */
1331 sa.sa_handler = SIG_DFL;
1332 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001334 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001335 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001336
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337 if (trace() < 0)
1338 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001339
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001340 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001341 fflush(NULL);
1342 if (exit_code > 0xff) {
Dmitry V. Levin6c381562012-02-22 00:15:27 +00001343 /* Avoid potential core file clobbering. */
1344 struct rlimit rlim = {0, 0};
1345 setrlimit(RLIMIT_CORE, &rlim);
1346
Dmitry V. Levina6809652008-11-10 17:14:58 +00001347 /* Child was killed by a signal, mimic that. */
1348 exit_code &= 0xff;
1349 signal(exit_code, SIG_DFL);
1350 raise(exit_code);
1351 /* Paranoia - what if this signal is not fatal?
1352 Exit with 128 + signo then. */
1353 exit_code += 128;
1354 }
1355 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356}
1357
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001358static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001359expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001360{
1361 /* Allocate some more TCBs and expand the table.
1362 We don't want to relocate the TCBs because our
1363 callers have pointers and it would be a pain.
1364 So tcbtab is a table of pointers. Since we never
1365 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001366 int i = tcbtabsize;
1367 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1368 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001369 if (!newtab || !newtcbs)
1370 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001371 tcbtabsize *= 2;
1372 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001373 while (i < tcbtabsize)
1374 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001375}
1376
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001378alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001379{
1380 int i;
1381 struct tcb *tcp;
1382
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001383 if (nprocs == tcbtabsize)
1384 expand_tcbtab();
1385
Roland McGrathee9d4352002-12-18 04:16:10 +00001386 for (i = 0; i < tcbtabsize; i++) {
1387 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001388 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001389 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001390 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001391 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001393#if SUPPORTED_PERSONALITIES > 1
1394 tcp->currpers = current_personality;
1395#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001397 if (debug)
1398 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001399 if (command_options_parsed)
1400 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001401 return tcp;
1402 }
1403 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001404 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405}
1406
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001407static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001408pid2tcb(int pid)
1409{
1410 int i;
1411
1412 if (pid <= 0)
1413 return NULL;
1414
1415 for (i = 0; i < tcbtabsize; i++) {
1416 struct tcb *tcp = tcbtab[i];
1417 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1418 return tcp;
1419 }
1420
1421 return NULL;
1422}
1423
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424void
Denys Vlasenko12014262011-05-30 14:00:14 +02001425droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426{
1427 if (tcp->pid == 0)
1428 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001429
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001431 if (debug)
1432 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001433
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001434 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001436
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001437 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438}
1439
Roland McGrath0a463882007-07-05 18:43:16 +00001440/* detach traced process; continue with sig
1441 Never call DETACH twice on the same process as both unattached and
1442 attached-unstopped processes give the same ESRCH. For unattached process we
1443 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444
1445static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001446detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447{
1448 int error = 0;
Roland McGrath1bfd3102007-08-03 10:02:00 +00001449 int status, catch_sigstop;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450
1451 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001452 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001453
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454 /*
1455 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001456 * before detaching. Arghh. We go through hoops
1457 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001459#if defined(SPARC)
1460#undef PTRACE_DETACH
1461#define PTRACE_DETACH PTRACE_SUNDETACH
1462#endif
Roland McGrath02203312007-06-11 22:06:31 +00001463 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001464 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001465 * We must catch exactly one as otherwise the detached process
1466 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001467 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001468 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001469 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001470 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001472 }
1473 else if (errno != ESRCH) {
1474 /* Shouldn't happen. */
1475 perror("detach: ptrace(PTRACE_DETACH, ...)");
1476 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001477 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001478 if (errno != ESRCH)
1479 perror("detach: checking sanity");
1480 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001481 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001482 if (errno != ESRCH)
1483 perror("detach: stopping child");
1484 }
Roland McGrath02203312007-06-11 22:06:31 +00001485 else
1486 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001487 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001489#ifdef __WALL
1490 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1491 if (errno == ECHILD) /* Already gone. */
1492 break;
1493 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001494 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001495 break;
1496 }
1497#endif /* __WALL */
1498 /* No __WALL here. */
1499 if (waitpid(tcp->pid, &status, 0) < 0) {
1500 if (errno != ECHILD) {
1501 perror("detach: waiting");
1502 break;
1503 }
1504#ifdef __WCLONE
1505 /* If no processes, try clones. */
1506 if (wait4(tcp->pid, &status, __WCLONE,
1507 NULL) < 0) {
1508 if (errno != ECHILD)
1509 perror("detach: waiting");
1510 break;
1511 }
1512#endif /* __WCLONE */
1513 }
1514#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001515 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001516#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517 if (!WIFSTOPPED(status)) {
1518 /* Au revoir, mon ami. */
1519 break;
1520 }
1521 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001522 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 break;
1524 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001525 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001526 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001527 : WSTOPSIG(status));
1528 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001531 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533 if (!qflag)
1534 fprintf(stderr, "Process %u detached\n", tcp->pid);
1535
1536 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001537
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538 return error;
1539}
1540
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001542cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543{
1544 int i;
1545 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001546 int fatal_sig;
1547
1548 /* 'interrupted' is a volatile object, fetch it only once */
1549 fatal_sig = interrupted;
1550 if (!fatal_sig)
1551 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552
Roland McGrathee9d4352002-12-18 04:16:10 +00001553 for (i = 0; i < tcbtabsize; i++) {
1554 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555 if (!(tcp->flags & TCB_INUSE))
1556 continue;
1557 if (debug)
1558 fprintf(stderr,
1559 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001560 if (printing_tcp &&
1561 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1562 tprints(" <unfinished ...>\n");
1563 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 }
1565 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001566 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567 else {
1568 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001569 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570 }
1571 }
1572 if (cflag)
1573 call_summary(outf);
1574}
1575
1576static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001577interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001579 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580}
1581
1582#ifndef HAVE_STRERROR
1583
Roland McGrath6d2b3492002-12-30 00:51:30 +00001584#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585extern int sys_nerr;
1586extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001587#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588
1589const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001590strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001591{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001592 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001594 if (err_no < 1 || err_no >= sys_nerr) {
1595 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596 return buf;
1597 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001598 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599}
1600
1601#endif /* HAVE_STERRROR */
1602
1603#ifndef HAVE_STRSIGNAL
1604
Roland McGrath8f474e02003-01-14 07:53:33 +00001605#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001606extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001608#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1609extern char *_sys_siglist[];
1610#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001611
1612const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001613strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001615 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616
1617 if (sig < 1 || sig >= NSIG) {
1618 sprintf(buf, "Unknown signal %d", sig);
1619 return buf;
1620 }
1621#ifdef HAVE__SYS_SIGLIST
1622 return _sys_siglist[sig];
1623#else
1624 return sys_siglist[sig];
1625#endif
1626}
1627
1628#endif /* HAVE_STRSIGNAL */
1629
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001631trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001634 struct rusage *rup = cflag ? &ru : NULL;
1635# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001636 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001637# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638
Roland McGratheb9e2e82009-06-02 16:49:22 -07001639 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001640 int pid;
1641 int wait_errno;
1642 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001643 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001644 struct tcb *tcp;
1645 unsigned event;
1646
Denys Vlasenko222713a2009-03-17 14:29:59 +00001647 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001648 return 0;
1649 if (interactive)
1650 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001651# ifdef __WALL
1652 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001653 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001654 /* this kernel does not support __WALL */
1655 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001656 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001657 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001658 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001659 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001660 pid = wait4(-1, &status, __WCLONE, rup);
1661 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001662 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001663 }
1664 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001665# else
1666 pid = wait4(-1, &status, 0, rup);
1667# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001669 if (interactive)
1670 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001672 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001673 switch (wait_errno) {
1674 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001676 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 /*
1678 * We would like to verify this case
1679 * but sometimes a race in Solbourne's
1680 * version of SunOS sometimes reports
1681 * ECHILD before sending us SIGCHILD.
1682 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001683 return 0;
1684 default:
1685 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001686 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001687 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688 }
1689 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001690 if (pid == popen_pid) {
1691 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001692 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001693 continue;
1694 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001695
1696 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001697 if (debug) {
1698 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001699 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001700 static const char *const event_names[] = {
1701 [PTRACE_EVENT_CLONE] = "CLONE",
1702 [PTRACE_EVENT_FORK] = "FORK",
1703 [PTRACE_EVENT_VFORK] = "VFORK",
1704 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1705 [PTRACE_EVENT_EXEC] = "EXEC",
1706 [PTRACE_EVENT_EXIT] = "EXIT",
1707 };
1708 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001709 if (event < ARRAY_SIZE(event_names))
1710 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001711 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001712 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001713 e = buf;
1714 }
1715 fprintf(stderr, " PTRACE_EVENT_%s", e);
1716 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001717 strcpy(buf, "???");
1718 if (WIFSIGNALED(status))
1719#ifdef WCOREDUMP
1720 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1721 WCOREDUMP(status) ? "core," : "",
1722 signame(WTERMSIG(status)));
1723#else
1724 sprintf(buf, "WIFSIGNALED,sig=%s",
1725 signame(WTERMSIG(status)));
1726#endif
1727 if (WIFEXITED(status))
1728 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1729 if (WIFSTOPPED(status))
1730 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001731#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001732 if (WIFCONTINUED(status))
1733 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001734#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001735 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1736 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001738 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001739 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001740
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001741 /* Under Linux, execve changes pid to thread leader's pid,
1742 * and we see this changed pid on EVENT_EXEC and later,
1743 * execve sysexit. Leader "disappears" without exit
1744 * notification. Let user know that, drop leader's tcb,
1745 * and fix up pid in execve thread's tcb.
1746 * Effectively, execve thread's tcb replaces leader's tcb.
1747 *
1748 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1749 * on exit syscall) in multithreaded programs exactly
1750 * in order to handle this case.
1751 *
1752 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1753 * On 2.6 and earlier, it can return garbage.
1754 */
1755 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1756 long old_pid = 0;
1757 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1758 && old_pid > 0
1759 && old_pid != pid
1760 ) {
1761 struct tcb *execve_thread = pid2tcb(old_pid);
1762 if (tcp) {
1763 outf = tcp->outf;
1764 curcol = tcp->curcol;
1765 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001766 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001767 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001768 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001769 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1770 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001771 fflush(outf);
1772 }
1773 if (execve_thread) {
1774 /* swap output FILEs (needed for -ff) */
1775 tcp->outf = execve_thread->outf;
1776 execve_thread->outf = outf;
1777 }
1778 droptcb(tcp);
1779 }
1780 tcp = execve_thread;
1781 if (tcp) {
1782 tcp->pid = pid;
1783 tcp->flags |= TCB_REPRINT;
1784 }
1785 }
1786 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001787
Denys Vlasenko5d645812011-08-20 12:48:18 +02001788 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001789 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001790 /* This is needed to go with the CLONE_PTRACE
1791 changes in process.c/util.c: we might see
1792 the child's initial trap before we see the
1793 parent return from the clone syscall.
1794 Leave the child suspended until the parent
1795 returns from its system call. Only then
1796 will we have the association of parent and
1797 child so that we know how to do clearbpt
1798 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001799 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001800 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001801 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001802 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001803 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001804 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001805 else
1806 /* This can happen if a clone call used
1807 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001808 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001809 if (WIFSTOPPED(status))
1810 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001811 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001812 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001814 /* set current output file */
1815 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001816 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001817 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1819 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001821
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001823 if (pid == strace_child)
1824 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001825 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1827 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001828#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001829 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001830 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001831 WCOREDUMP(status) ? "(core dumped) " : "");
1832#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001833 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001834 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001835#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001836 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001838 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839 droptcb(tcp);
1840 continue;
1841 }
1842 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001843 if (pid == strace_child)
1844 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001845 if (tcp == printing_tcp) {
1846 tprints(" <unfinished ...>\n");
1847 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001848 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001849 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1850 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001851 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1852 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001853 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001854 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001855 droptcb(tcp);
1856 continue;
1857 }
1858 if (!WIFSTOPPED(status)) {
1859 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1860 droptcb(tcp);
1861 continue;
1862 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001863
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001864 /* Is this the very first time we see this tracee stopped? */
1865 if (tcp->flags & TCB_STARTUP) {
1866 if (debug)
1867 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001870 /*
1871 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001872 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001873 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001874 if (clearbpt(tcp) < 0) {
1875 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876 droptcb(tcp);
1877 cleanup();
1878 return -1;
1879 }
1880 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001881 if (ptrace_setoptions) {
1882 if (debug)
1883 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1884 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1885 if (errno != ESRCH) {
1886 /* Should never happen, really */
1887 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001888 }
1889 }
1890 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001891 }
1892
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001893 sig = WSTOPSIG(status);
1894
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001895 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001896 /* Ptrace event */
1897#ifdef USE_SEIZE
1898 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001899 /*
1900 * PTRACE_INTERRUPT-stop or group-stop.
1901 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1902 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001903 if (sig == SIGSTOP
1904 || sig == SIGTSTP
1905 || sig == SIGTTIN
1906 || sig == SIGTTOU
1907 ) {
1908 stopped = 1;
1909 goto show_stopsig;
1910 }
1911 }
1912#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001913 goto restart_tracee_with_sig_0;
1914 }
1915
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001916 /* Is this post-attach SIGSTOP?
1917 * Interestingly, the process may stop
1918 * with STOPSIG equal to some other signal
1919 * than SIGSTOP if we happend to attach
1920 * just before the process takes a signal.
1921 */
1922 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
1923 if (debug)
1924 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
1925 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001926 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927 }
1928
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001929 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001930 siginfo_t si;
1931
1932 /* Nonzero (true) if tracee is stopped by signal
1933 * (as opposed to "tracee received signal").
1934 */
1935 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01001936#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001937 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01001938#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001939 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001940 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00001941#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001942 long pc = 0;
1943 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001944
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001945 upeek(tcp, PT_CR_IPSR, &psr);
1946 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001947
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001948# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001949 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001950# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001951# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001952#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001953# define PC_FORMAT_STR ""
1954# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001955#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001956 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001957 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001958 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001959 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01001960 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001961 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001962 PC_FORMAT_ARG);
1963 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001964 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001965 strsignal(sig),
1966 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001967 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001968 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001969 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001970 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001971
1972 if (!stopped)
1973 /* It's signal-delivery-stop. Inject the signal */
1974 goto restart_tracee;
1975
1976 /* It's group-stop */
1977#ifdef USE_SEIZE
1978 if (use_seize) {
1979 /*
1980 * This ends ptrace-stop, but does *not* end group-stop.
1981 * This makes stopping signals work properly on straced process
1982 * (that is, process really stops. It used to continue to run).
1983 */
1984 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
1985 cleanup();
1986 return -1;
1987 }
1988 continue;
1989 }
1990 /* We don't have PTRACE_LISTEN support... */
1991#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001992 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001993 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001994
1995 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00001996 if (interrupted)
1997 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001998
1999 /* This should be syscall entry or exit.
2000 * (Or it still can be that pesky post-execve SIGTRAP!)
2001 * Handle it.
2002 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002003 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2004 /* ptrace() failed in trace_syscall() with ESRCH.
2005 * Likely a result of process disappearing mid-flight.
2006 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002007 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002008 */
2009 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002010 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002011 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002012 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002013 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002014 printing_tcp->flags |= TCB_REPRINT;
2015 tprints(" <unfinished ...>\n");
2016 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002017 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002018 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002019 /* We assume that ptrace error was caused by process death.
2020 * We used to detach(tcp) here, but since we no longer
2021 * implement "detach before death" policy/hack,
2022 * we can let this process to report its death to us
2023 * normally, via WIFEXITED or WIFSIGNALED wait status.
2024 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002025 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002026 /* It's our real child (and we also trace it) */
2027 /* my_tkill(pid, SIGKILL); - why? */
2028 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029 }
2030 continue;
2031 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002032 restart_tracee_with_sig_0:
2033 sig = 0;
2034 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002035 /* Remember current print column before continuing. */
2036 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002037 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038 cleanup();
2039 return -1;
2040 }
2041 }
2042 return 0;
2043}
2044
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002046tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047{
2048 va_list args;
2049
Andreas Schwabe5355de2009-10-27 16:56:43 +01002050 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002051 if (outf) {
2052 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002053 if (n < 0) {
2054 if (outf != stderr)
2055 perror(outfname == NULL
2056 ? "<writing to pipe>" : outfname);
2057 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002058 curcol += n;
2059 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002060 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002061}
2062
2063void
2064tprints(const char *str)
2065{
2066 if (outf) {
2067 int n = fputs(str, outf);
2068 if (n >= 0) {
2069 curcol += strlen(str);
2070 return;
2071 }
2072 if (outf != stderr)
2073 perror(outfname == NULL
2074 ? "<writing to pipe>" : outfname);
2075 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002076}
2077
2078void
Denys Vlasenko12014262011-05-30 14:00:14 +02002079printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002080{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002081 if (printing_tcp) {
2082 if (printing_tcp->ptrace_errno) {
2083 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002084 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002085 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002086 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002087 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002088 printing_tcp->ptrace_errno = 0;
2089 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2090 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002091 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002092 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002093 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002094
2095 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002096 curcol = 0;
2097 if ((followfork == 1 || pflag_seen > 1) && outfname)
2098 tprintf("%-5d ", tcp->pid);
2099 else if (nprocs > 1 && !outfname)
2100 tprintf("[pid %5u] ", tcp->pid);
2101 if (tflag) {
2102 char str[sizeof("HH:MM:SS")];
2103 struct timeval tv, dtv;
2104 static struct timeval otv;
2105
2106 gettimeofday(&tv, NULL);
2107 if (rflag) {
2108 if (otv.tv_sec == 0)
2109 otv = tv;
2110 tv_sub(&dtv, &tv, &otv);
2111 tprintf("%6ld.%06ld ",
2112 (long) dtv.tv_sec, (long) dtv.tv_usec);
2113 otv = tv;
2114 }
2115 else if (tflag > 2) {
2116 tprintf("%ld.%06ld ",
2117 (long) tv.tv_sec, (long) tv.tv_usec);
2118 }
2119 else {
2120 time_t local = tv.tv_sec;
2121 strftime(str, sizeof(str), "%T", localtime(&local));
2122 if (tflag > 1)
2123 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2124 else
2125 tprintf("%s ", str);
2126 }
2127 }
2128 if (iflag)
2129 printcall(tcp);
2130}
2131
2132void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002133tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002135 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002136 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002137}