blob: d774611cb4c1081939c714e91875a29928732e70 [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
Roland McGrath02203312007-06-11 22:06:31 +0000423static void
424startup_attach(void)
425{
426 int tcbi;
427 struct tcb *tcp;
428
429 /*
430 * Block user interruptions as we would leave the traced
431 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200432 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200433 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000434 */
435 if (interactive)
436 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
437
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000438 if (daemonized_tracer) {
439 pid_t pid = fork();
440 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200441 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000442 }
443 if (pid) { /* parent */
444 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200445 * Wait for grandchild to attach to straced process
446 * (grandparent). Grandchild SIGKILLs us after it attached.
447 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000448 * it proceeds to exec the straced program.
449 */
450 pause();
451 _exit(0); /* paranoia */
452 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200453 /* grandchild */
454 /* We will be the tracer process. Remember our new pid: */
455 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000456 }
457
Roland McGrath02203312007-06-11 22:06:31 +0000458 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
459 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200460
Denys Vlasenkod116a732011-09-05 14:01:33 +0200461 /* Is this a process we should attach to, but not yet attached? */
462 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
463 continue; /* no */
464
465 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000466 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200467 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000468
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000469 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000470 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000471 DIR *dir;
472
473 sprintf(procdir, "/proc/%d/task", tcp->pid);
474 dir = opendir(procdir);
475 if (dir != NULL) {
476 unsigned int ntid = 0, nerr = 0;
477 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200478
Roland McGrath02203312007-06-11 22:06:31 +0000479 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200480 struct tcb *cur_tcp;
481 int tid;
482
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000483 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000484 continue;
485 tid = atoi(de->d_name);
486 if (tid <= 0)
487 continue;
488 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100489 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000490 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200491 if (debug)
492 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200493 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200494 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200495 if (debug)
496 fprintf(stderr, "attach to pid %d succeeded\n", tid);
497 cur_tcp = tcp;
498 if (tid != tcp->pid)
499 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100500 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000501 }
502 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200503 if (interactive) {
504 sigprocmask(SIG_SETMASK, &empty_set, NULL);
505 if (interrupted)
506 goto ret;
507 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
508 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000509 ntid -= nerr;
510 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000511 perror("attach: ptrace(PTRACE_ATTACH, ...)");
512 droptcb(tcp);
513 continue;
514 }
515 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000516 fprintf(stderr, ntid > 1
517? "Process %u attached with %u threads - interrupt to quit\n"
518: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200519 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000520 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200521 if (!(tcp->flags & TCB_STARTUP)) {
522 /* -p PID, we failed to attach to PID itself
523 * but did attach to some of its sibling threads.
524 * Drop PID's tcp.
525 */
526 droptcb(tcp);
527 }
Roland McGrath02203312007-06-11 22:06:31 +0000528 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000529 } /* if (opendir worked) */
530 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100531 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000532 perror("attach: ptrace(PTRACE_ATTACH, ...)");
533 droptcb(tcp);
534 continue;
535 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100536 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200537 if (debug)
538 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000539
540 if (daemonized_tracer) {
541 /*
542 * It is our grandparent we trace, not a -p PID.
543 * Don't want to just detach on exit, so...
544 */
545 tcp->flags &= ~TCB_ATTACHED;
546 /*
547 * Make parent go away.
548 * Also makes grandparent's wait() unblock.
549 */
550 kill(getppid(), SIGKILL);
551 }
552
Roland McGrath02203312007-06-11 22:06:31 +0000553 if (!qflag)
554 fprintf(stderr,
555 "Process %u attached - interrupt to quit\n",
556 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200557 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000558
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200559 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000560 if (interactive)
561 sigprocmask(SIG_SETMASK, &empty_set, NULL);
562}
563
564static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200565startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000566{
567 struct stat statbuf;
568 const char *filename;
569 char pathname[MAXPATHLEN];
570 int pid = 0;
571 struct tcb *tcp;
572
573 filename = argv[0];
574 if (strchr(filename, '/')) {
575 if (strlen(filename) > sizeof pathname - 1) {
576 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200577 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000578 }
579 strcpy(pathname, filename);
580 }
581#ifdef USE_DEBUGGING_EXEC
582 /*
583 * Debuggers customarily check the current directory
584 * first regardless of the path but doing that gives
585 * security geeks a panic attack.
586 */
587 else if (stat(filename, &statbuf) == 0)
588 strcpy(pathname, filename);
589#endif /* USE_DEBUGGING_EXEC */
590 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000591 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000592 int m, n, len;
593
594 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100595 const char *colon = strchr(path, ':');
596 if (colon) {
597 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000598 m = n + 1;
599 }
600 else
601 m = n = strlen(path);
602 if (n == 0) {
603 if (!getcwd(pathname, MAXPATHLEN))
604 continue;
605 len = strlen(pathname);
606 }
607 else if (n > sizeof pathname - 1)
608 continue;
609 else {
610 strncpy(pathname, path, n);
611 len = n;
612 }
613 if (len && pathname[len - 1] != '/')
614 pathname[len++] = '/';
615 strcpy(pathname + len, filename);
616 if (stat(pathname, &statbuf) == 0 &&
617 /* Accept only regular files
618 with some execute bits set.
619 XXX not perfect, might still fail */
620 S_ISREG(statbuf.st_mode) &&
621 (statbuf.st_mode & 0111))
622 break;
623 }
624 }
625 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200626 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000627 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000628 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000629 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200630 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000631 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200632 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
633 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000634 ) {
635 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200636 if (outf != stderr)
637 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100638 if (!daemonized_tracer && !use_seize) {
639 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200640 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000641 }
Roland McGrath02203312007-06-11 22:06:31 +0000642 }
Roland McGrath02203312007-06-11 22:06:31 +0000643
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200644 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000645 uid_t run_euid = run_uid;
646 gid_t run_egid = run_gid;
647
648 if (statbuf.st_mode & S_ISUID)
649 run_euid = statbuf.st_uid;
650 if (statbuf.st_mode & S_ISGID)
651 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000652 /*
653 * It is important to set groups before we
654 * lose privileges on setuid.
655 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200656 if (initgroups(username, run_gid) < 0) {
657 perror_msg_and_die("initgroups");
658 }
659 if (setregid(run_gid, run_egid) < 0) {
660 perror_msg_and_die("setregid");
661 }
662 if (setreuid(run_uid, run_euid) < 0) {
663 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000664 }
665 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200666 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000667 setreuid(run_uid, run_uid);
668
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000669 if (!daemonized_tracer) {
670 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200671 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000672 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200673 * the immediately following execve syscall.
674 * Can't do this on NOMMU systems, we are after
675 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400677 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200678 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000679 } else {
680 struct sigaction sv_sigchld;
681 sigaction(SIGCHLD, NULL, &sv_sigchld);
682 /*
683 * Make sure it is not SIG_IGN, otherwise wait
684 * will not block.
685 */
686 signal(SIGCHLD, SIG_DFL);
687 /*
688 * Wait for grandchild to attach to us.
689 * It kills child after that, and wait() unblocks.
690 */
691 alarm(3);
692 wait(NULL);
693 alarm(0);
694 sigaction(SIGCHLD, &sv_sigchld, NULL);
695 }
Roland McGrath02203312007-06-11 22:06:31 +0000696
697 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200698 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000699 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000700
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200701 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200702
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200703 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100704 if (!use_seize) {
705 /* child did PTRACE_TRACEME, nothing to do in parent */
706 } else {
707 if (!strace_vforked) {
708 /* Wait until child stopped itself */
709 int status;
710 while (waitpid(pid, &status, WSTOPPED) < 0) {
711 if (errno == EINTR)
712 continue;
713 perror_msg_and_die("waitpid");
714 }
715 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
716 kill(pid, SIGKILL);
717 perror_msg_and_die("Unexpected wait status %x", status);
718 }
719 }
720 /* Else: vforked case, we have no way to sync.
721 * Just attach to it as soon as possible.
722 * This means that we may miss a few first syscalls...
723 */
724
725 if (ptrace_attach_or_seize(pid)) {
726 kill(pid, SIGKILL);
727 perror_msg_and_die("Can't attach to %d", pid);
728 }
729 if (!strace_vforked)
730 kill(pid, SIGCONT);
731 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200732 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200733 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100734 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200735 else
736 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200737 }
738 else {
739 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
740 strace_tracer_pid = getpid();
741 /* The tracee is our parent: */
742 pid = getppid();
743 tcp = alloctcb(pid);
744 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000745 tcp->flags |= TCB_ATTACHED;
746 }
Roland McGrath02203312007-06-11 22:06:31 +0000747}
748
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000749static void kill_save_errno(pid_t pid, int sig)
750{
751 int saved_errno = errno;
752
753 (void) kill(pid, sig);
754 errno = saved_errno;
755}
756
Wang Chaob13c0de2010-11-12 17:25:19 +0800757/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000758 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800759 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000760 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800761 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000762static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200763test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800764{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000765 int pid, expected_grandchild = 0, found_grandchild = 0;
766 const unsigned int test_options = PTRACE_O_TRACECLONE |
767 PTRACE_O_TRACEFORK |
768 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800769
Denys Vlasenko5d645812011-08-20 12:48:18 +0200770 pid = fork();
771 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000772 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200773 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000774 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100775 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000776 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
777 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100778 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000779 if (fork() < 0)
780 perror_msg_and_die("fork");
781 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800782 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000783
784 while (1) {
785 int status, tracee_pid;
786
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000787 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000788 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000789 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000790 if (errno == EINTR)
791 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100792 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000793 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000794 kill_save_errno(pid, SIGKILL);
795 perror_msg_and_die("%s: unexpected wait result %d",
796 __func__, tracee_pid);
797 }
798 if (WIFEXITED(status)) {
799 if (WEXITSTATUS(status)) {
800 if (tracee_pid != pid)
801 kill_save_errno(pid, SIGKILL);
802 error_msg_and_die("%s: unexpected exit status %u",
803 __func__, WEXITSTATUS(status));
804 }
805 continue;
806 }
807 if (WIFSIGNALED(status)) {
808 if (tracee_pid != pid)
809 kill_save_errno(pid, SIGKILL);
810 error_msg_and_die("%s: unexpected signal %u",
811 __func__, WTERMSIG(status));
812 }
813 if (!WIFSTOPPED(status)) {
814 if (tracee_pid != pid)
815 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100816 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000817 error_msg_and_die("%s: unexpected wait status %x",
818 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000819 }
820 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000821 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000822 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
823 kill_save_errno(tracee_pid, SIGKILL);
824 kill_save_errno(pid, SIGKILL);
825 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800826 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000827 continue;
828 }
829 switch (WSTOPSIG(status)) {
830 case SIGSTOP:
831 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
832 && errno != EINVAL && errno != EIO)
833 perror_msg("PTRACE_SETOPTIONS");
834 break;
835 case SIGTRAP:
836 if (status >> 16 == PTRACE_EVENT_FORK) {
837 long msg = 0;
838
839 if (ptrace(PTRACE_GETEVENTMSG, pid,
840 NULL, (long) &msg) == 0)
841 expected_grandchild = msg;
842 }
843 break;
844 }
845 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
846 kill_save_errno(pid, SIGKILL);
847 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800848 }
849 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000850 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200851 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000852 if (debug)
853 fprintf(stderr, "ptrace_setoptions = %#x\n",
854 ptrace_setoptions);
855 return;
856 }
857 error_msg("Test for PTRACE_O_TRACECLONE failed, "
858 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800859}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200860
861/*
862 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
863 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
864 * and then see whether it will stop with (SIGTRAP | 0x80).
865 *
866 * Use of this option enables correct handling of user-generated SIGTRAPs,
867 * and SIGTRAPs generated by special instructions such as int3 on x86:
868 * _start: .globl _start
869 * int3
870 * movl $42, %ebx
871 * movl $1, %eax
872 * int $0x80
873 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
874 */
875static void
876test_ptrace_setoptions_for_all(void)
877{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000878 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
879 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200880 int pid;
881 int it_worked = 0;
882
883 pid = fork();
884 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200885 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200886
887 if (pid == 0) {
888 pid = getpid();
889 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200890 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000891 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
892 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200893 kill(pid, SIGSTOP);
894 _exit(0); /* parent should see entry into this syscall */
895 }
896
897 while (1) {
898 int status, tracee_pid;
899
900 errno = 0;
901 tracee_pid = wait(&status);
902 if (tracee_pid <= 0) {
903 if (errno == EINTR)
904 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000905 kill_save_errno(pid, SIGKILL);
906 perror_msg_and_die("%s: unexpected wait result %d",
907 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200908 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200909 if (WIFEXITED(status)) {
910 if (WEXITSTATUS(status) == 0)
911 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000912 error_msg_and_die("%s: unexpected exit status %u",
913 __func__, WEXITSTATUS(status));
914 }
915 if (WIFSIGNALED(status)) {
916 error_msg_and_die("%s: unexpected signal %u",
917 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200918 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200919 if (!WIFSTOPPED(status)) {
920 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000921 error_msg_and_die("%s: unexpected wait status %x",
922 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200923 }
924 if (WSTOPSIG(status) == SIGSTOP) {
925 /*
926 * We don't check "options aren't accepted" error.
927 * If it happens, we'll never get (SIGTRAP | 0x80),
928 * and thus will decide to not use the option.
929 * IOW: the outcome of the test will be correct.
930 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000931 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
932 && errno != EINVAL && errno != EIO)
933 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200934 }
935 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
936 it_worked = 1;
937 }
938 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000939 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200940 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200941 }
942 }
943
944 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200945 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200946 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200947 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200948 fprintf(stderr, "ptrace_setoptions = %#x\n",
949 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200950 return;
951 }
952
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000953 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
954 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200955}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100956
957# ifdef USE_SEIZE
958static void
959test_ptrace_seize(void)
960{
961 int pid;
962
963 pid = fork();
964 if (pid < 0)
965 perror_msg_and_die("fork");
966
967 if (pid == 0) {
968 pause();
969 _exit(0);
970 }
971
972 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
973 * attaching tracee continues to run unless a trap condition occurs.
974 * PTRACE_SEIZE doesn't affect signal or group stop state.
975 */
976 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
977 post_attach_sigstop = 0; /* this sets use_seize to 1 */
978 } else if (debug) {
979 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
980 }
981
982 kill(pid, SIGKILL);
983
984 while (1) {
985 int status, tracee_pid;
986
987 errno = 0;
988 tracee_pid = waitpid(pid, &status, 0);
989 if (tracee_pid <= 0) {
990 if (errno == EINTR)
991 continue;
992 perror_msg_and_die("%s: unexpected wait result %d",
993 __func__, tracee_pid);
994 }
995 if (WIFSIGNALED(status)) {
996 return;
997 }
998 error_msg_and_die("%s: unexpected wait status %x",
999 __func__, status);
1000 }
1001}
1002# else /* !USE_SEIZE */
1003# define test_ptrace_seize() ((void)0)
1004# endif
1005
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001006/* Noinline: don't want main to have struct utsname permanently on stack */
1007static void __attribute__ ((noinline))
1008get_os_release(void)
1009{
1010 struct utsname u;
1011 if (uname(&u) < 0)
1012 perror_msg_and_die("uname");
1013 os_release = strdup(u.release);
1014 if (!os_release)
1015 die_out_of_memory();
1016}
1017
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001019main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001020{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 struct tcb *tcp;
1022 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001023 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024 struct sigaction sa;
1025
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001026 progname = argv[0] ? argv[0] : "strace";
1027
Denys Vlasenko75422762011-05-27 14:36:01 +02001028 strace_tracer_pid = getpid();
1029
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001030 get_os_release();
1031
Roland McGrathee9d4352002-12-18 04:16:10 +00001032 /* Allocate the initial tcbtab. */
1033 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001034 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001035 if (!tcbtab)
1036 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001037 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001038 if (!tcp)
1039 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001040 for (c = 0; c < tcbtabsize; c++)
1041 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001042
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001044 set_sortby(DEFAULT_SORTBY);
1045 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 qualify("trace=all");
1047 qualify("abbrev=all");
1048 qualify("verbose=all");
1049 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001051 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001052 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001053 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 switch (c) {
1055 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001056 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001057 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001058 }
1059 cflag = CFLAG_ONLY_STATS;
1060 break;
1061 case 'C':
1062 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001063 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001064 }
1065 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 break;
1067 case 'd':
1068 debug++;
1069 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001070 case 'D':
1071 daemonized_tracer = 1;
1072 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001073 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001074 optF = 1;
1075 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 case 'f':
1077 followfork++;
1078 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 case 'h':
1080 usage(stdout, 0);
1081 break;
1082 case 'i':
1083 iflag++;
1084 break;
1085 case 'q':
1086 qflag++;
1087 break;
1088 case 'r':
1089 rflag++;
1090 tflag++;
1091 break;
1092 case 't':
1093 tflag++;
1094 break;
1095 case 'T':
1096 dtime++;
1097 break;
1098 case 'x':
1099 xflag++;
1100 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001101 case 'y':
1102 show_fd_path = 1;
1103 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 case 'v':
1105 qualify("abbrev=none");
1106 break;
1107 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001108 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109 exit(0);
1110 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001111 case 'z':
1112 not_failing_only = 1;
1113 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001114 case 'a':
1115 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001116 if (acolumn < 0)
1117 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 break;
1119 case 'e':
1120 qualify(optarg);
1121 break;
1122 case 'o':
1123 outfname = strdup(optarg);
1124 break;
1125 case 'O':
1126 set_overhead(atoi(optarg));
1127 break;
1128 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001129 pid = atoi(optarg);
1130 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001131 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 break;
1133 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001134 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001135 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 break;
1137 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001138 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 tcp->flags |= TCB_ATTACHED;
1140 pflag_seen++;
1141 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001142 case 'P':
1143 tracing_paths = 1;
1144 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001145 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001146 }
1147 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 case 's':
1149 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001150 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001151 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001152 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 break;
1154 case 'S':
1155 set_sortby(optarg);
1156 break;
1157 case 'u':
1158 username = strdup(optarg);
1159 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001160 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001161 if (putenv(optarg) < 0)
1162 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001163 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001164 case 'I':
1165 opt_intr = atoi(optarg);
1166 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1167 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1168 }
1169 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 default:
1171 usage(stderr, 1);
1172 break;
1173 }
1174 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001175 argv += optind;
1176 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177
Denys Vlasenko102ec492011-08-25 01:27:59 +02001178 acolumn_spaces = malloc(acolumn + 1);
1179 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001180 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001181 memset(acolumn_spaces, ' ', acolumn);
1182 acolumn_spaces[acolumn] = '\0';
1183
Denys Vlasenko837399a2012-01-24 11:37:03 +01001184 /* Must have PROG [ARGS], or -p PID. Not both. */
1185 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001186 usage(stderr, 1);
1187
Wang Chaod322a4b2010-08-05 14:30:11 +08001188 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001189 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001190 }
1191
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001192 if (!followfork)
1193 followfork = optF;
1194
Roland McGrathcb9def62006-04-25 07:48:03 +00001195 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001196 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001197 }
1198
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 /* See if they want to run as another user. */
1200 if (username != NULL) {
1201 struct passwd *pent;
1202
1203 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001204 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001206 pent = getpwnam(username);
1207 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001208 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 }
1210 run_uid = pent->pw_uid;
1211 run_gid = pent->pw_gid;
1212 }
1213 else {
1214 run_uid = getuid();
1215 run_gid = getgid();
1216 }
1217
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001218 if (followfork)
1219 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001220 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001221 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001222
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223 /* Check if they want to redirect the output. */
1224 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001225 /* See if they want to pipe the output. */
1226 if (outfname[0] == '|' || outfname[0] == '!') {
1227 /*
1228 * We can't do the <outfname>.PID funny business
1229 * when using popen, so prohibit it.
1230 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001231 if (followfork > 1)
1232 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1233 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001234 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001235 else if (followfork <= 1)
1236 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237 }
1238
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001239 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001240 char *buf = malloc(BUFSIZ);
1241 if (!buf)
1242 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001243 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001244 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001245 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001246 if (!opt_intr)
1247 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001249 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001250 if (!opt_intr)
1251 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001252
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001253 /* argv[0] -pPID -oFILE Default interactive setting
1254 * yes 0 0 INTR_WHILE_WAIT
1255 * no 1 0 INTR_WHILE_WAIT
1256 * yes 0 1 INTR_NEVER
1257 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001258 */
1259
1260 /* STARTUP_CHILD must be called before the signal handlers get
1261 installed below as they are inherited into the spawned process.
1262 Also we do not need to be protected by them as during interruption
1263 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001264 if (argv[0])
1265 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267 sigemptyset(&empty_set);
1268 sigemptyset(&blocked_set);
1269 sa.sa_handler = SIG_IGN;
1270 sigemptyset(&sa.sa_mask);
1271 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001272 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1273 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1274 if (opt_intr != INTR_ANYWHERE) {
1275 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1276 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1277 /*
1278 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1279 * fatal signals are blocked while syscall stop is processed,
1280 * and acted on in between, when waiting for new syscall stops.
1281 * In non-interactive mode, signals are ignored.
1282 */
1283 if (opt_intr == INTR_WHILE_WAIT) {
1284 sigaddset(&blocked_set, SIGHUP);
1285 sigaddset(&blocked_set, SIGINT);
1286 sigaddset(&blocked_set, SIGQUIT);
1287 sigaddset(&blocked_set, SIGPIPE);
1288 sigaddset(&blocked_set, SIGTERM);
1289 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001290 }
1291 /* SIG_IGN, or set handler for these */
1292 sigaction(SIGHUP, &sa, NULL);
1293 sigaction(SIGINT, &sa, NULL);
1294 sigaction(SIGQUIT, &sa, NULL);
1295 sigaction(SIGPIPE, &sa, NULL);
1296 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001297 }
Roland McGrath553a6092002-12-16 20:40:39 +00001298 /* Make sure SIGCHLD has the default action so that waitpid
1299 definitely works without losing track of children. The user
1300 should not have given us a bogus state to inherit, but he might
1301 have. Arguably we should detect SIG_IGN here and pass it on
1302 to children, but probably noone really needs that. */
1303 sa.sa_handler = SIG_DFL;
1304 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001306 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001307 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001308
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309 if (trace() < 0)
1310 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001311
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001312 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001313 fflush(NULL);
1314 if (exit_code > 0xff) {
Dmitry V. Levin6c381562012-02-22 00:15:27 +00001315 /* Avoid potential core file clobbering. */
1316 struct rlimit rlim = {0, 0};
1317 setrlimit(RLIMIT_CORE, &rlim);
1318
Dmitry V. Levina6809652008-11-10 17:14:58 +00001319 /* Child was killed by a signal, mimic that. */
1320 exit_code &= 0xff;
1321 signal(exit_code, SIG_DFL);
1322 raise(exit_code);
1323 /* Paranoia - what if this signal is not fatal?
1324 Exit with 128 + signo then. */
1325 exit_code += 128;
1326 }
1327 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328}
1329
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001330static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001331expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001332{
1333 /* Allocate some more TCBs and expand the table.
1334 We don't want to relocate the TCBs because our
1335 callers have pointers and it would be a pain.
1336 So tcbtab is a table of pointers. Since we never
1337 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001338 int i = tcbtabsize;
1339 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1340 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001341 if (!newtab || !newtcbs)
1342 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001343 tcbtabsize *= 2;
1344 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001345 while (i < tcbtabsize)
1346 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001347}
1348
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001349struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001350alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001351{
1352 int i;
1353 struct tcb *tcp;
1354
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001355 if (nprocs == tcbtabsize)
1356 expand_tcbtab();
1357
Roland McGrathee9d4352002-12-18 04:16:10 +00001358 for (i = 0; i < tcbtabsize; i++) {
1359 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001361 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001362 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001363 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001364 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001365#if SUPPORTED_PERSONALITIES > 1
1366 tcp->currpers = current_personality;
1367#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001368 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001369 if (debug)
1370 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001371 if (command_options_parsed)
1372 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001373 return tcp;
1374 }
1375 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001376 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377}
1378
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001379static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001380pid2tcb(int pid)
1381{
1382 int i;
1383
1384 if (pid <= 0)
1385 return NULL;
1386
1387 for (i = 0; i < tcbtabsize; i++) {
1388 struct tcb *tcp = tcbtab[i];
1389 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1390 return tcp;
1391 }
1392
1393 return NULL;
1394}
1395
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396void
Denys Vlasenko12014262011-05-30 14:00:14 +02001397droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398{
1399 if (tcp->pid == 0)
1400 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001401
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001402 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001403 if (debug)
1404 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001405
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001406 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001408
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001409 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410}
1411
Roland McGrath0a463882007-07-05 18:43:16 +00001412/* detach traced process; continue with sig
1413 Never call DETACH twice on the same process as both unattached and
1414 attached-unstopped processes give the same ESRCH. For unattached process we
1415 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416
1417static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001418detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001419{
1420 int error = 0;
Roland McGrath1bfd3102007-08-03 10:02:00 +00001421 int status, catch_sigstop;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422
1423 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001424 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001425
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426 /*
1427 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001428 * before detaching. Arghh. We go through hoops
1429 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001431#if defined(SPARC)
1432#undef PTRACE_DETACH
1433#define PTRACE_DETACH PTRACE_SUNDETACH
1434#endif
Roland McGrath02203312007-06-11 22:06:31 +00001435 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001436 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001437 * We must catch exactly one as otherwise the detached process
1438 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001439 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001440 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001441 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001442 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001444 }
1445 else if (errno != ESRCH) {
1446 /* Shouldn't happen. */
1447 perror("detach: ptrace(PTRACE_DETACH, ...)");
1448 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001449 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001450 if (errno != ESRCH)
1451 perror("detach: checking sanity");
1452 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001453 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001454 if (errno != ESRCH)
1455 perror("detach: stopping child");
1456 }
Roland McGrath02203312007-06-11 22:06:31 +00001457 else
1458 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001459 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001461#ifdef __WALL
1462 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1463 if (errno == ECHILD) /* Already gone. */
1464 break;
1465 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001466 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001467 break;
1468 }
1469#endif /* __WALL */
1470 /* No __WALL here. */
1471 if (waitpid(tcp->pid, &status, 0) < 0) {
1472 if (errno != ECHILD) {
1473 perror("detach: waiting");
1474 break;
1475 }
1476#ifdef __WCLONE
1477 /* If no processes, try clones. */
1478 if (wait4(tcp->pid, &status, __WCLONE,
1479 NULL) < 0) {
1480 if (errno != ECHILD)
1481 perror("detach: waiting");
1482 break;
1483 }
1484#endif /* __WCLONE */
1485 }
1486#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001487 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001488#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489 if (!WIFSTOPPED(status)) {
1490 /* Au revoir, mon ami. */
1491 break;
1492 }
1493 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001494 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495 break;
1496 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001497 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001498 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001499 : WSTOPSIG(status));
1500 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001503 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505 if (!qflag)
1506 fprintf(stderr, "Process %u detached\n", tcp->pid);
1507
1508 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001509
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510 return error;
1511}
1512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001514cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515{
1516 int i;
1517 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001518 int fatal_sig;
1519
1520 /* 'interrupted' is a volatile object, fetch it only once */
1521 fatal_sig = interrupted;
1522 if (!fatal_sig)
1523 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524
Roland McGrathee9d4352002-12-18 04:16:10 +00001525 for (i = 0; i < tcbtabsize; i++) {
1526 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527 if (!(tcp->flags & TCB_INUSE))
1528 continue;
1529 if (debug)
1530 fprintf(stderr,
1531 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001532 if (printing_tcp &&
1533 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1534 tprints(" <unfinished ...>\n");
1535 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 }
1537 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001538 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539 else {
1540 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001541 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542 }
1543 }
1544 if (cflag)
1545 call_summary(outf);
1546}
1547
1548static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001549interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001551 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552}
1553
1554#ifndef HAVE_STRERROR
1555
Roland McGrath6d2b3492002-12-30 00:51:30 +00001556#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557extern int sys_nerr;
1558extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001559#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001560
1561const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001562strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001564 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001566 if (err_no < 1 || err_no >= sys_nerr) {
1567 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568 return buf;
1569 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001570 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001571}
1572
1573#endif /* HAVE_STERRROR */
1574
1575#ifndef HAVE_STRSIGNAL
1576
Roland McGrath8f474e02003-01-14 07:53:33 +00001577#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001578extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001580#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1581extern char *_sys_siglist[];
1582#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583
1584const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001585strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001587 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588
1589 if (sig < 1 || sig >= NSIG) {
1590 sprintf(buf, "Unknown signal %d", sig);
1591 return buf;
1592 }
1593#ifdef HAVE__SYS_SIGLIST
1594 return _sys_siglist[sig];
1595#else
1596 return sys_siglist[sig];
1597#endif
1598}
1599
1600#endif /* HAVE_STRSIGNAL */
1601
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001602static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001603trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001606 struct rusage *rup = cflag ? &ru : NULL;
1607# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001608 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001609# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610
Roland McGratheb9e2e82009-06-02 16:49:22 -07001611 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001612 int pid;
1613 int wait_errno;
1614 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001615 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001616 struct tcb *tcp;
1617 unsigned event;
1618
Denys Vlasenko222713a2009-03-17 14:29:59 +00001619 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001620 return 0;
1621 if (interactive)
1622 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001623# ifdef __WALL
1624 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001625 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001626 /* this kernel does not support __WALL */
1627 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001628 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001629 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001630 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001631 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001632 pid = wait4(-1, &status, __WCLONE, rup);
1633 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001634 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001635 }
1636 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001637# else
1638 pid = wait4(-1, &status, 0, rup);
1639# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001641 if (interactive)
1642 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001644 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001645 switch (wait_errno) {
1646 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001648 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649 /*
1650 * We would like to verify this case
1651 * but sometimes a race in Solbourne's
1652 * version of SunOS sometimes reports
1653 * ECHILD before sending us SIGCHILD.
1654 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001655 return 0;
1656 default:
1657 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001658 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001659 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660 }
1661 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001662 if (pid == popen_pid) {
1663 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001664 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001665 continue;
1666 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001667
1668 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001669 if (debug) {
1670 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001671 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001672 static const char *const event_names[] = {
1673 [PTRACE_EVENT_CLONE] = "CLONE",
1674 [PTRACE_EVENT_FORK] = "FORK",
1675 [PTRACE_EVENT_VFORK] = "VFORK",
1676 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1677 [PTRACE_EVENT_EXEC] = "EXEC",
1678 [PTRACE_EVENT_EXIT] = "EXIT",
1679 };
1680 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001681 if (event < ARRAY_SIZE(event_names))
1682 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001683 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001684 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001685 e = buf;
1686 }
1687 fprintf(stderr, " PTRACE_EVENT_%s", e);
1688 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001689 strcpy(buf, "???");
1690 if (WIFSIGNALED(status))
1691#ifdef WCOREDUMP
1692 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1693 WCOREDUMP(status) ? "core," : "",
1694 signame(WTERMSIG(status)));
1695#else
1696 sprintf(buf, "WIFSIGNALED,sig=%s",
1697 signame(WTERMSIG(status)));
1698#endif
1699 if (WIFEXITED(status))
1700 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1701 if (WIFSTOPPED(status))
1702 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001703#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001704 if (WIFCONTINUED(status))
1705 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001706#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001707 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1708 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001710 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001711 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001712
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001713 /* Under Linux, execve changes pid to thread leader's pid,
1714 * and we see this changed pid on EVENT_EXEC and later,
1715 * execve sysexit. Leader "disappears" without exit
1716 * notification. Let user know that, drop leader's tcb,
1717 * and fix up pid in execve thread's tcb.
1718 * Effectively, execve thread's tcb replaces leader's tcb.
1719 *
1720 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1721 * on exit syscall) in multithreaded programs exactly
1722 * in order to handle this case.
1723 *
1724 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1725 * On 2.6 and earlier, it can return garbage.
1726 */
1727 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1728 long old_pid = 0;
1729 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1730 && old_pid > 0
1731 && old_pid != pid
1732 ) {
1733 struct tcb *execve_thread = pid2tcb(old_pid);
1734 if (tcp) {
1735 outf = tcp->outf;
1736 curcol = tcp->curcol;
1737 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001738 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001739 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001740 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001741 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1742 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001743 fflush(outf);
1744 }
1745 if (execve_thread) {
1746 /* swap output FILEs (needed for -ff) */
1747 tcp->outf = execve_thread->outf;
1748 execve_thread->outf = outf;
1749 }
1750 droptcb(tcp);
1751 }
1752 tcp = execve_thread;
1753 if (tcp) {
1754 tcp->pid = pid;
1755 tcp->flags |= TCB_REPRINT;
1756 }
1757 }
1758 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001759
Denys Vlasenko5d645812011-08-20 12:48:18 +02001760 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001761 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001762 /* This is needed to go with the CLONE_PTRACE
1763 changes in process.c/util.c: we might see
1764 the child's initial trap before we see the
1765 parent return from the clone syscall.
1766 Leave the child suspended until the parent
1767 returns from its system call. Only then
1768 will we have the association of parent and
1769 child so that we know how to do clearbpt
1770 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001771 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001772 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001773 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001774 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001775 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001776 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001777 else
1778 /* This can happen if a clone call used
1779 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001780 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001781 if (WIFSTOPPED(status))
1782 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001783 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001784 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001786 /* set current output file */
1787 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001788 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001789 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1791 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001793
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001795 if (pid == strace_child)
1796 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001797 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1799 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001800#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001801 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001802 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001803 WCOREDUMP(status) ? "(core dumped) " : "");
1804#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001805 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001806 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001807#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001808 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001810 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001811 droptcb(tcp);
1812 continue;
1813 }
1814 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001815 if (pid == strace_child)
1816 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001817 if (tcp == printing_tcp) {
1818 tprints(" <unfinished ...>\n");
1819 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001820 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001821 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1822 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001823 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1824 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001825 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001826 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001827 droptcb(tcp);
1828 continue;
1829 }
1830 if (!WIFSTOPPED(status)) {
1831 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1832 droptcb(tcp);
1833 continue;
1834 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001835
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001836 /* Is this the very first time we see this tracee stopped? */
1837 if (tcp->flags & TCB_STARTUP) {
1838 if (debug)
1839 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001840 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001842 /*
1843 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001844 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001845 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001846 if (clearbpt(tcp) < 0) {
1847 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848 droptcb(tcp);
1849 cleanup();
1850 return -1;
1851 }
1852 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001853 if (ptrace_setoptions) {
1854 if (debug)
1855 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1856 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1857 if (errno != ESRCH) {
1858 /* Should never happen, really */
1859 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001860 }
1861 }
1862 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001863 }
1864
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001865 sig = WSTOPSIG(status);
1866
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001867 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001868 /* Ptrace event */
1869#ifdef USE_SEIZE
1870 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001871 /*
1872 * PTRACE_INTERRUPT-stop or group-stop.
1873 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1874 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001875 if (sig == SIGSTOP
1876 || sig == SIGTSTP
1877 || sig == SIGTTIN
1878 || sig == SIGTTOU
1879 ) {
1880 stopped = 1;
1881 goto show_stopsig;
1882 }
1883 }
1884#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001885 goto restart_tracee_with_sig_0;
1886 }
1887
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001888 /* Is this post-attach SIGSTOP?
1889 * Interestingly, the process may stop
1890 * with STOPSIG equal to some other signal
1891 * than SIGSTOP if we happend to attach
1892 * just before the process takes a signal.
1893 */
1894 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
1895 if (debug)
1896 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
1897 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001898 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 }
1900
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001901 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001902 siginfo_t si;
1903
1904 /* Nonzero (true) if tracee is stopped by signal
1905 * (as opposed to "tracee received signal").
1906 */
1907 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01001908#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001909 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01001910#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001911 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001912 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00001913#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001914 long pc = 0;
1915 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001916
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001917 upeek(tcp, PT_CR_IPSR, &psr);
1918 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001919
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001920# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001921 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001922# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001923# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001924#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001925# define PC_FORMAT_STR ""
1926# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001927#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001928 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001929 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001930 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001931 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01001932 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001933 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001934 PC_FORMAT_ARG);
1935 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001936 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001937 strsignal(sig),
1938 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001939 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001940 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001941 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001942 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001943
1944 if (!stopped)
1945 /* It's signal-delivery-stop. Inject the signal */
1946 goto restart_tracee;
1947
1948 /* It's group-stop */
1949#ifdef USE_SEIZE
1950 if (use_seize) {
1951 /*
1952 * This ends ptrace-stop, but does *not* end group-stop.
1953 * This makes stopping signals work properly on straced process
1954 * (that is, process really stops. It used to continue to run).
1955 */
1956 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
1957 cleanup();
1958 return -1;
1959 }
1960 continue;
1961 }
1962 /* We don't have PTRACE_LISTEN support... */
1963#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001964 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001966
1967 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00001968 if (interrupted)
1969 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001970
1971 /* This should be syscall entry or exit.
1972 * (Or it still can be that pesky post-execve SIGTRAP!)
1973 * Handle it.
1974 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001975 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
1976 /* ptrace() failed in trace_syscall() with ESRCH.
1977 * Likely a result of process disappearing mid-flight.
1978 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01001979 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001980 */
1981 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001982 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001983 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02001984 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001985 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01001986 printing_tcp->flags |= TCB_REPRINT;
1987 tprints(" <unfinished ...>\n");
1988 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001989 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001990 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01001991 /* We assume that ptrace error was caused by process death.
1992 * We used to detach(tcp) here, but since we no longer
1993 * implement "detach before death" policy/hack,
1994 * we can let this process to report its death to us
1995 * normally, via WIFEXITED or WIFSIGNALED wait status.
1996 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001997 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01001998 /* It's our real child (and we also trace it) */
1999 /* my_tkill(pid, SIGKILL); - why? */
2000 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 }
2002 continue;
2003 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002004 restart_tracee_with_sig_0:
2005 sig = 0;
2006 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002007 /* Remember current print column before continuing. */
2008 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002009 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010 cleanup();
2011 return -1;
2012 }
2013 }
2014 return 0;
2015}
2016
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002018tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019{
2020 va_list args;
2021
Andreas Schwabe5355de2009-10-27 16:56:43 +01002022 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002023 if (outf) {
2024 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002025 if (n < 0) {
2026 if (outf != stderr)
2027 perror(outfname == NULL
2028 ? "<writing to pipe>" : outfname);
2029 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002030 curcol += n;
2031 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002032 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002033}
2034
2035void
2036tprints(const char *str)
2037{
2038 if (outf) {
2039 int n = fputs(str, outf);
2040 if (n >= 0) {
2041 curcol += strlen(str);
2042 return;
2043 }
2044 if (outf != stderr)
2045 perror(outfname == NULL
2046 ? "<writing to pipe>" : outfname);
2047 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048}
2049
2050void
Denys Vlasenko12014262011-05-30 14:00:14 +02002051printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002053 if (printing_tcp) {
2054 if (printing_tcp->ptrace_errno) {
2055 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002056 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002057 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002058 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002059 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002060 printing_tcp->ptrace_errno = 0;
2061 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2062 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002063 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002064 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002066
2067 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068 curcol = 0;
2069 if ((followfork == 1 || pflag_seen > 1) && outfname)
2070 tprintf("%-5d ", tcp->pid);
2071 else if (nprocs > 1 && !outfname)
2072 tprintf("[pid %5u] ", tcp->pid);
2073 if (tflag) {
2074 char str[sizeof("HH:MM:SS")];
2075 struct timeval tv, dtv;
2076 static struct timeval otv;
2077
2078 gettimeofday(&tv, NULL);
2079 if (rflag) {
2080 if (otv.tv_sec == 0)
2081 otv = tv;
2082 tv_sub(&dtv, &tv, &otv);
2083 tprintf("%6ld.%06ld ",
2084 (long) dtv.tv_sec, (long) dtv.tv_usec);
2085 otv = tv;
2086 }
2087 else if (tflag > 2) {
2088 tprintf("%ld.%06ld ",
2089 (long) tv.tv_sec, (long) tv.tv_usec);
2090 }
2091 else {
2092 time_t local = tv.tv_sec;
2093 strftime(str, sizeof(str), "%T", localtime(&local));
2094 if (tflag > 1)
2095 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2096 else
2097 tprintf("%s ", str);
2098 }
2099 }
2100 if (iflag)
2101 printcall(tcp);
2102}
2103
2104void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002105tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002107 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002108 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002109}