blob: 66dee5f817687f39c1d3db7312fead67c560b930 [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
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000065
Denys Vlasenko96d5a762008-12-29 19:13:27 +000066extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000067extern int optind;
68extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000069
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070
Roland McGrath41c48222008-07-18 00:25:10 +000071int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020072unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020073/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020074static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000075int dtime = 0, xflag = 0, qflag = 0;
76cflag_t cflag = CFLAG_NONE;
Denys Vlasenkoaa6ec412012-01-24 11:35:38 +010077static int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010078
79/* -I n */
80enum {
81 INTR_NOT_SET = 0,
82 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
83 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
84 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
85 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
86 NUM_INTR_OPTS
87};
88static int opt_intr;
89/* We play with signal mask only if this mode is active: */
90#define interactive (opt_intr == INTR_WHILE_WAIT)
91
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000092/*
93 * daemonized_tracer supports -D option.
94 * With this option, strace forks twice.
95 * Unlike normal case, with -D *grandparent* process exec's,
96 * becoming a traced process. Child exits (this prevents traced process
97 * from having children it doesn't expect to have), and grandchild
98 * attaches to grandparent similarly to strace -p PID.
99 * This allows for more transparent interaction in cases
100 * when process and its parent are communicating via signals,
101 * wait() etc. Without -D, strace process gets lodged in between,
102 * disrupting parent<->child link.
103 */
104static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100106#ifdef USE_SEIZE
107static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
108# define use_seize (post_attach_sigstop == 0)
109#else
110# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
111# define use_seize 0
112#endif
113
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000114/* Sometimes we want to print only succeeding syscalls. */
115int not_failing_only = 0;
116
Grant Edwards8a082772011-04-07 20:25:40 +0000117/* Show path associated with fd arguments */
118int show_fd_path = 0;
119
120/* are we filtering traces based on paths? */
121int tracing_paths = 0;
122
Dmitry V. Levina6809652008-11-10 17:14:58 +0000123static int exit_code = 0;
124static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200125static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700126
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000127static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200128static uid_t run_uid;
129static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200132static int acolumn = DEFAULT_ACOLUMN;
133static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000134static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200135static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100136struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100137static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200138static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200139static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200140static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100142static char *os_release; /* from uname() */
143
Denys Vlasenko4c196382012-01-04 15:11:09 +0100144static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100145static int trace(void);
146static void cleanup(void);
147static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148static sigset_t empty_set, blocked_set;
149
150#ifdef HAVE_SIG_ATOMIC_T
151static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100152#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100154#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156
157static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200158usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159{
160 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100161usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
162 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100163 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100164 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100165 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200167-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100168-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100170-F -- attempt to follow vforks\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000171-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100172-I interruptible\n\
173 1: no signals are blocked\n\
174 2: fatal signals are blocked while decoding syscall (default)\n\
175 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
176 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
177 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178-q -- suppress messages about attaching, detaching, etc.\n\
179-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100180-T -- print time spent in each syscall\n\
181-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000183-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100184-h -- print help message\n\
185-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186-a column -- alignment COLUMN for printing syscall results (default %d)\n\
187-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
188 options: trace, abbrev, verbose, raw, signal, read, or write\n\
189-o file -- send trace output to FILE instead of stderr\n\
190-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
191-p pid -- trace process with process id PID, may be repeated\n\
192-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
193-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
194-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000195-E var=val -- put var=val in the environment for command\n\
196-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000197-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000198" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000199-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000200 */
201, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202 exit(exitval);
203}
204
Denys Vlasenko75422762011-05-27 14:36:01 +0200205static void die(void) __attribute__ ((noreturn));
206static void die(void)
207{
208 if (strace_tracer_pid == getpid()) {
209 cflag = 0;
210 cleanup();
211 }
212 exit(1);
213}
214
215static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200216{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100217 char *msg;
218
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000219 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100220
221 /* We want to print entire message with single fprintf to ensure
222 * message integrity if stderr is shared with other programs.
223 * Thus we use vasprintf + single fprintf.
224 */
225 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100226 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100227 if (err_no)
228 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
229 else
230 fprintf(stderr, "%s: %s\n", progname, msg);
231 free(msg);
232 } else {
233 /* malloc in vasprintf failed, try it without malloc */
234 fprintf(stderr, "%s: ", progname);
235 vfprintf(stderr, fmt, p);
236 if (err_no)
237 fprintf(stderr, ": %s\n", strerror(err_no));
238 else
239 putc('\n', stderr);
240 }
241 /* We don't switch stderr to buffered, thus fprintf(stderr)
242 * always flushes its output and this is not necessary: */
243 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200244}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200245
Denys Vlasenko75422762011-05-27 14:36:01 +0200246void error_msg(const char *fmt, ...)
247{
248 va_list p;
249 va_start(p, fmt);
250 verror_msg(0, fmt, p);
251 va_end(p);
252}
253
254void error_msg_and_die(const char *fmt, ...)
255{
256 va_list p;
257 va_start(p, fmt);
258 verror_msg(0, fmt, p);
259 die();
260}
261
262void perror_msg(const char *fmt, ...)
263{
264 va_list p;
265 va_start(p, fmt);
266 verror_msg(errno, fmt, p);
267 va_end(p);
268}
269
270void perror_msg_and_die(const char *fmt, ...)
271{
272 va_list p;
273 va_start(p, fmt);
274 verror_msg(errno, fmt, p);
275 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200276}
277
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200278void die_out_of_memory(void)
279{
280 static bool recursed = 0;
281 if (recursed)
282 exit(1);
283 recursed = 1;
284 error_msg_and_die("Out of memory");
285}
286
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400288/* Glue for systems without a MMU that cannot provide fork() */
289#ifdef HAVE_FORK
290# define strace_vforked 0
291#else
292# define strace_vforked 1
293# define fork() vfork()
294#endif
295
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100296#ifdef USE_SEIZE
297static int
298ptrace_attach_or_seize(int pid)
299{
300 int r;
301 if (!use_seize)
302 return ptrace(PTRACE_ATTACH, pid, 0, 0);
303 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
304 if (r)
305 return r;
306 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
307 return r;
308}
309#else
310# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
311#endif
312
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200313static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000314set_cloexec_flag(int fd)
315{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200316 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000317
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200318 flags = fcntl(fd, F_GETFD);
319 if (flags < 0) {
320 /* Can happen only if fd is bad.
321 * Should never happen: if it does, we have a bug
322 * in the caller. Therefore we just abort
323 * instead of propagating the error.
324 */
325 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000326 }
327
328 newflags = flags | FD_CLOEXEC;
329 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200330 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000331
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200332 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000333}
334
335/*
336 * When strace is setuid executable, we have to swap uids
337 * before and after filesystem and process management operations.
338 */
339static void
340swap_uid(void)
341{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000342 int euid = geteuid(), uid = getuid();
343
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200344 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200345 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000346 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000347}
348
Roland McGrath4bfa6262007-07-05 20:03:16 +0000349#if _LFS64_LARGEFILE
350# define fopen_for_output fopen64
351#else
352# define fopen_for_output fopen
353#endif
354
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000355static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200356strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000357{
358 FILE *fp;
359
360 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200361 fp = fopen_for_output(path, "w");
362 if (!fp)
363 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200365 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000366 return fp;
367}
368
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200369static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000370
371#ifndef _PATH_BSHELL
372# define _PATH_BSHELL "/bin/sh"
373#endif
374
375/*
376 * We cannot use standard popen(3) here because we have to distinguish
377 * popen child process from other processes we trace, and standard popen(3)
378 * does not export its child's pid.
379 */
380static FILE *
381strace_popen(const char *command)
382{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200383 FILE *fp;
384 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000385
386 swap_uid();
387 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200388 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000389
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200390 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000391
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200392 popen_pid = vfork();
393 if (popen_pid == -1)
394 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000395
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200396 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397 /* child */
398 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200399 if (fds[0] != 0) {
400 if (dup2(fds[0], 0))
401 perror_msg_and_die("dup2");
402 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000403 }
404 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200405 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000406 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200407
408 /* parent */
409 close(fds[0]);
410 swap_uid();
411 fp = fdopen(fds[1], "w");
412 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200413 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200414 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000415}
416
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200417static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000418newoutf(struct tcb *tcp)
419{
420 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000421 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000422 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200423 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000424 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000425}
426
Roland McGrath02203312007-06-11 22:06:31 +0000427static void
428startup_attach(void)
429{
430 int tcbi;
431 struct tcb *tcp;
432
433 /*
434 * Block user interruptions as we would leave the traced
435 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200436 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200437 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000438 */
439 if (interactive)
440 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
441
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000442 if (daemonized_tracer) {
443 pid_t pid = fork();
444 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200445 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000446 }
447 if (pid) { /* parent */
448 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200449 * Wait for grandchild to attach to straced process
450 * (grandparent). Grandchild SIGKILLs us after it attached.
451 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000452 * it proceeds to exec the straced program.
453 */
454 pause();
455 _exit(0); /* paranoia */
456 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200457 /* grandchild */
458 /* We will be the tracer process. Remember our new pid: */
459 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000460 }
461
Roland McGrath02203312007-06-11 22:06:31 +0000462 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
463 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200464
Denys Vlasenkod116a732011-09-05 14:01:33 +0200465 /* Is this a process we should attach to, but not yet attached? */
466 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
467 continue; /* no */
468
469 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000470 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200471 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000472
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000473 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000474 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000475 DIR *dir;
476
477 sprintf(procdir, "/proc/%d/task", tcp->pid);
478 dir = opendir(procdir);
479 if (dir != NULL) {
480 unsigned int ntid = 0, nerr = 0;
481 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200482
Roland McGrath02203312007-06-11 22:06:31 +0000483 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200484 struct tcb *cur_tcp;
485 int tid;
486
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000487 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000488 continue;
489 tid = atoi(de->d_name);
490 if (tid <= 0)
491 continue;
492 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100493 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000494 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200495 if (debug)
496 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200497 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200498 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200499 if (debug)
500 fprintf(stderr, "attach to pid %d succeeded\n", tid);
501 cur_tcp = tcp;
502 if (tid != tcp->pid)
503 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100504 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000505 }
506 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200507 if (interactive) {
508 sigprocmask(SIG_SETMASK, &empty_set, NULL);
509 if (interrupted)
510 goto ret;
511 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
512 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000513 ntid -= nerr;
514 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000515 perror("attach: ptrace(PTRACE_ATTACH, ...)");
516 droptcb(tcp);
517 continue;
518 }
519 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000520 fprintf(stderr, ntid > 1
521? "Process %u attached with %u threads - interrupt to quit\n"
522: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200523 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000524 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200525 if (!(tcp->flags & TCB_STARTUP)) {
526 /* -p PID, we failed to attach to PID itself
527 * but did attach to some of its sibling threads.
528 * Drop PID's tcp.
529 */
530 droptcb(tcp);
531 }
Roland McGrath02203312007-06-11 22:06:31 +0000532 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000533 } /* if (opendir worked) */
534 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100535 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000536 perror("attach: ptrace(PTRACE_ATTACH, ...)");
537 droptcb(tcp);
538 continue;
539 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100540 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200541 if (debug)
542 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000543
544 if (daemonized_tracer) {
545 /*
546 * It is our grandparent we trace, not a -p PID.
547 * Don't want to just detach on exit, so...
548 */
549 tcp->flags &= ~TCB_ATTACHED;
550 /*
551 * Make parent go away.
552 * Also makes grandparent's wait() unblock.
553 */
554 kill(getppid(), SIGKILL);
555 }
556
Roland McGrath02203312007-06-11 22:06:31 +0000557 if (!qflag)
558 fprintf(stderr,
559 "Process %u attached - interrupt to quit\n",
560 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200561 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000562
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200563 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000564 if (interactive)
565 sigprocmask(SIG_SETMASK, &empty_set, NULL);
566}
567
568static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200569startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000570{
571 struct stat statbuf;
572 const char *filename;
573 char pathname[MAXPATHLEN];
574 int pid = 0;
575 struct tcb *tcp;
576
577 filename = argv[0];
578 if (strchr(filename, '/')) {
579 if (strlen(filename) > sizeof pathname - 1) {
580 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200581 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000582 }
583 strcpy(pathname, filename);
584 }
585#ifdef USE_DEBUGGING_EXEC
586 /*
587 * Debuggers customarily check the current directory
588 * first regardless of the path but doing that gives
589 * security geeks a panic attack.
590 */
591 else if (stat(filename, &statbuf) == 0)
592 strcpy(pathname, filename);
593#endif /* USE_DEBUGGING_EXEC */
594 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000595 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000596 int m, n, len;
597
598 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100599 const char *colon = strchr(path, ':');
600 if (colon) {
601 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000602 m = n + 1;
603 }
604 else
605 m = n = strlen(path);
606 if (n == 0) {
607 if (!getcwd(pathname, MAXPATHLEN))
608 continue;
609 len = strlen(pathname);
610 }
611 else if (n > sizeof pathname - 1)
612 continue;
613 else {
614 strncpy(pathname, path, n);
615 len = n;
616 }
617 if (len && pathname[len - 1] != '/')
618 pathname[len++] = '/';
619 strcpy(pathname + len, filename);
620 if (stat(pathname, &statbuf) == 0 &&
621 /* Accept only regular files
622 with some execute bits set.
623 XXX not perfect, might still fail */
624 S_ISREG(statbuf.st_mode) &&
625 (statbuf.st_mode & 0111))
626 break;
627 }
628 }
629 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200630 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000631 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000632 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000633 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200634 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000635 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200636 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
637 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000638 ) {
639 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200640 if (outf != stderr)
641 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100642 if (!daemonized_tracer && !use_seize) {
643 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200644 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000645 }
Roland McGrath02203312007-06-11 22:06:31 +0000646 }
Roland McGrath02203312007-06-11 22:06:31 +0000647
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200648 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000649 uid_t run_euid = run_uid;
650 gid_t run_egid = run_gid;
651
652 if (statbuf.st_mode & S_ISUID)
653 run_euid = statbuf.st_uid;
654 if (statbuf.st_mode & S_ISGID)
655 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000656 /*
657 * It is important to set groups before we
658 * lose privileges on setuid.
659 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200660 if (initgroups(username, run_gid) < 0) {
661 perror_msg_and_die("initgroups");
662 }
663 if (setregid(run_gid, run_egid) < 0) {
664 perror_msg_and_die("setregid");
665 }
666 if (setreuid(run_uid, run_euid) < 0) {
667 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000668 }
669 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200670 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000671 setreuid(run_uid, run_uid);
672
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000673 if (!daemonized_tracer) {
674 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200675 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200677 * the immediately following execve syscall.
678 * Can't do this on NOMMU systems, we are after
679 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000680 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400681 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200682 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 } else {
684 struct sigaction sv_sigchld;
685 sigaction(SIGCHLD, NULL, &sv_sigchld);
686 /*
687 * Make sure it is not SIG_IGN, otherwise wait
688 * will not block.
689 */
690 signal(SIGCHLD, SIG_DFL);
691 /*
692 * Wait for grandchild to attach to us.
693 * It kills child after that, and wait() unblocks.
694 */
695 alarm(3);
696 wait(NULL);
697 alarm(0);
698 sigaction(SIGCHLD, &sv_sigchld, NULL);
699 }
Roland McGrath02203312007-06-11 22:06:31 +0000700
701 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200702 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000703 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000704
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200705 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200706
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200707 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100708 if (!use_seize) {
709 /* child did PTRACE_TRACEME, nothing to do in parent */
710 } else {
711 if (!strace_vforked) {
712 /* Wait until child stopped itself */
713 int status;
714 while (waitpid(pid, &status, WSTOPPED) < 0) {
715 if (errno == EINTR)
716 continue;
717 perror_msg_and_die("waitpid");
718 }
719 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
720 kill(pid, SIGKILL);
721 perror_msg_and_die("Unexpected wait status %x", status);
722 }
723 }
724 /* Else: vforked case, we have no way to sync.
725 * Just attach to it as soon as possible.
726 * This means that we may miss a few first syscalls...
727 */
728
729 if (ptrace_attach_or_seize(pid)) {
730 kill(pid, SIGKILL);
731 perror_msg_and_die("Can't attach to %d", pid);
732 }
733 if (!strace_vforked)
734 kill(pid, SIGCONT);
735 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200736 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200737 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100738 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200739 else
740 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200741 }
742 else {
743 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
744 strace_tracer_pid = getpid();
745 /* The tracee is our parent: */
746 pid = getppid();
747 tcp = alloctcb(pid);
748 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000749 tcp->flags |= TCB_ATTACHED;
750 }
Roland McGrath02203312007-06-11 22:06:31 +0000751}
752
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000753static void kill_save_errno(pid_t pid, int sig)
754{
755 int saved_errno = errno;
756
757 (void) kill(pid, sig);
758 errno = saved_errno;
759}
760
Wang Chaob13c0de2010-11-12 17:25:19 +0800761/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000762 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800763 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000764 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800765 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000766static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200767test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800768{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000769 int pid, expected_grandchild = 0, found_grandchild = 0;
770 const unsigned int test_options = PTRACE_O_TRACECLONE |
771 PTRACE_O_TRACEFORK |
772 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800773
Denys Vlasenko5d645812011-08-20 12:48:18 +0200774 pid = fork();
775 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000776 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200777 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000778 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100779 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000780 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
781 __func__);
782 kill(pid, SIGSTOP);
783 if (fork() < 0)
784 perror_msg_and_die("fork");
785 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800786 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000787
788 while (1) {
789 int status, tracee_pid;
790
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000791 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000792 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000793 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000794 if (errno == EINTR)
795 continue;
796 else if (errno == ECHILD)
797 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000798 kill_save_errno(pid, SIGKILL);
799 perror_msg_and_die("%s: unexpected wait result %d",
800 __func__, tracee_pid);
801 }
802 if (WIFEXITED(status)) {
803 if (WEXITSTATUS(status)) {
804 if (tracee_pid != pid)
805 kill_save_errno(pid, SIGKILL);
806 error_msg_and_die("%s: unexpected exit status %u",
807 __func__, WEXITSTATUS(status));
808 }
809 continue;
810 }
811 if (WIFSIGNALED(status)) {
812 if (tracee_pid != pid)
813 kill_save_errno(pid, SIGKILL);
814 error_msg_and_die("%s: unexpected signal %u",
815 __func__, WTERMSIG(status));
816 }
817 if (!WIFSTOPPED(status)) {
818 if (tracee_pid != pid)
819 kill_save_errno(tracee_pid, SIGKILL);
820 kill(pid, SIGKILL);
821 error_msg_and_die("%s: unexpected wait status %x",
822 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000823 }
824 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000825 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000826 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
827 kill_save_errno(tracee_pid, SIGKILL);
828 kill_save_errno(pid, SIGKILL);
829 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800830 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000831 continue;
832 }
833 switch (WSTOPSIG(status)) {
834 case SIGSTOP:
835 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
836 && errno != EINVAL && errno != EIO)
837 perror_msg("PTRACE_SETOPTIONS");
838 break;
839 case SIGTRAP:
840 if (status >> 16 == PTRACE_EVENT_FORK) {
841 long msg = 0;
842
843 if (ptrace(PTRACE_GETEVENTMSG, pid,
844 NULL, (long) &msg) == 0)
845 expected_grandchild = msg;
846 }
847 break;
848 }
849 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
850 kill_save_errno(pid, SIGKILL);
851 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800852 }
853 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000854 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200855 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000856 if (debug)
857 fprintf(stderr, "ptrace_setoptions = %#x\n",
858 ptrace_setoptions);
859 return;
860 }
861 error_msg("Test for PTRACE_O_TRACECLONE failed, "
862 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800863}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200864
865/*
866 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
867 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
868 * and then see whether it will stop with (SIGTRAP | 0x80).
869 *
870 * Use of this option enables correct handling of user-generated SIGTRAPs,
871 * and SIGTRAPs generated by special instructions such as int3 on x86:
872 * _start: .globl _start
873 * int3
874 * movl $42, %ebx
875 * movl $1, %eax
876 * int $0x80
877 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
878 */
879static void
880test_ptrace_setoptions_for_all(void)
881{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000882 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
883 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200884 int pid;
885 int it_worked = 0;
886
887 pid = fork();
888 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200889 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200890
891 if (pid == 0) {
892 pid = getpid();
893 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200894 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000895 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
896 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200897 kill(pid, SIGSTOP);
898 _exit(0); /* parent should see entry into this syscall */
899 }
900
901 while (1) {
902 int status, tracee_pid;
903
904 errno = 0;
905 tracee_pid = wait(&status);
906 if (tracee_pid <= 0) {
907 if (errno == EINTR)
908 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000909 kill_save_errno(pid, SIGKILL);
910 perror_msg_and_die("%s: unexpected wait result %d",
911 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200912 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200913 if (WIFEXITED(status)) {
914 if (WEXITSTATUS(status) == 0)
915 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000916 error_msg_and_die("%s: unexpected exit status %u",
917 __func__, WEXITSTATUS(status));
918 }
919 if (WIFSIGNALED(status)) {
920 error_msg_and_die("%s: unexpected signal %u",
921 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200922 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200923 if (!WIFSTOPPED(status)) {
924 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000925 error_msg_and_die("%s: unexpected wait status %x",
926 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200927 }
928 if (WSTOPSIG(status) == SIGSTOP) {
929 /*
930 * We don't check "options aren't accepted" error.
931 * If it happens, we'll never get (SIGTRAP | 0x80),
932 * and thus will decide to not use the option.
933 * IOW: the outcome of the test will be correct.
934 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000935 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
936 && errno != EINVAL && errno != EIO)
937 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200938 }
939 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
940 it_worked = 1;
941 }
942 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000943 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200944 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200945 }
946 }
947
948 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200949 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200950 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200951 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200952 fprintf(stderr, "ptrace_setoptions = %#x\n",
953 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200954 return;
955 }
956
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000957 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
958 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200959}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100960
961# ifdef USE_SEIZE
962static void
963test_ptrace_seize(void)
964{
965 int pid;
966
967 pid = fork();
968 if (pid < 0)
969 perror_msg_and_die("fork");
970
971 if (pid == 0) {
972 pause();
973 _exit(0);
974 }
975
976 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
977 * attaching tracee continues to run unless a trap condition occurs.
978 * PTRACE_SEIZE doesn't affect signal or group stop state.
979 */
980 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
981 post_attach_sigstop = 0; /* this sets use_seize to 1 */
982 } else if (debug) {
983 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
984 }
985
986 kill(pid, SIGKILL);
987
988 while (1) {
989 int status, tracee_pid;
990
991 errno = 0;
992 tracee_pid = waitpid(pid, &status, 0);
993 if (tracee_pid <= 0) {
994 if (errno == EINTR)
995 continue;
996 perror_msg_and_die("%s: unexpected wait result %d",
997 __func__, tracee_pid);
998 }
999 if (WIFSIGNALED(status)) {
1000 return;
1001 }
1002 error_msg_and_die("%s: unexpected wait status %x",
1003 __func__, status);
1004 }
1005}
1006# else /* !USE_SEIZE */
1007# define test_ptrace_seize() ((void)0)
1008# endif
1009
Wang Chaob13c0de2010-11-12 17:25:19 +08001010
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001011/* Noinline: don't want main to have struct utsname permanently on stack */
1012static void __attribute__ ((noinline))
1013get_os_release(void)
1014{
1015 struct utsname u;
1016 if (uname(&u) < 0)
1017 perror_msg_and_die("uname");
1018 os_release = strdup(u.release);
1019 if (!os_release)
1020 die_out_of_memory();
1021}
1022
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001024main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 struct tcb *tcp;
1027 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001028 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 struct sigaction sa;
1030
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001031 progname = argv[0] ? argv[0] : "strace";
1032
Denys Vlasenko75422762011-05-27 14:36:01 +02001033 strace_tracer_pid = getpid();
1034
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001035 get_os_release();
1036
Roland McGrathee9d4352002-12-18 04:16:10 +00001037 /* Allocate the initial tcbtab. */
1038 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001039 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001040 if (!tcbtab)
1041 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001042 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001043 if (!tcp)
1044 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001045 for (c = 0; c < tcbtabsize; c++)
1046 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001047
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001049 set_sortby(DEFAULT_SORTBY);
1050 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 qualify("trace=all");
1052 qualify("abbrev=all");
1053 qualify("verbose=all");
1054 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001056 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001057 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001058 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 switch (c) {
1060 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001061 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001062 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001063 }
1064 cflag = CFLAG_ONLY_STATS;
1065 break;
1066 case 'C':
1067 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001068 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001069 }
1070 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 break;
1072 case 'd':
1073 debug++;
1074 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001075 case 'D':
1076 daemonized_tracer = 1;
1077 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001078 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001079 optF = 1;
1080 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081 case 'f':
1082 followfork++;
1083 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 case 'h':
1085 usage(stdout, 0);
1086 break;
1087 case 'i':
1088 iflag++;
1089 break;
1090 case 'q':
1091 qflag++;
1092 break;
1093 case 'r':
1094 rflag++;
1095 tflag++;
1096 break;
1097 case 't':
1098 tflag++;
1099 break;
1100 case 'T':
1101 dtime++;
1102 break;
1103 case 'x':
1104 xflag++;
1105 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001106 case 'y':
1107 show_fd_path = 1;
1108 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109 case 'v':
1110 qualify("abbrev=none");
1111 break;
1112 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001113 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001114 exit(0);
1115 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001116 case 'z':
1117 not_failing_only = 1;
1118 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119 case 'a':
1120 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001121 if (acolumn < 0)
1122 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 break;
1124 case 'e':
1125 qualify(optarg);
1126 break;
1127 case 'o':
1128 outfname = strdup(optarg);
1129 break;
1130 case 'O':
1131 set_overhead(atoi(optarg));
1132 break;
1133 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001134 pid = atoi(optarg);
1135 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001136 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137 break;
1138 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001139 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001140 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141 break;
1142 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001143 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 tcp->flags |= TCB_ATTACHED;
1145 pflag_seen++;
1146 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001147 case 'P':
1148 tracing_paths = 1;
1149 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001150 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001151 }
1152 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 case 's':
1154 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001155 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001156 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001157 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 break;
1159 case 'S':
1160 set_sortby(optarg);
1161 break;
1162 case 'u':
1163 username = strdup(optarg);
1164 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001165 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001166 if (putenv(optarg) < 0)
1167 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001168 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001169 case 'I':
1170 opt_intr = atoi(optarg);
1171 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1172 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1173 }
1174 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 default:
1176 usage(stderr, 1);
1177 break;
1178 }
1179 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001180 argv += optind;
1181 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182
Denys Vlasenko102ec492011-08-25 01:27:59 +02001183 acolumn_spaces = malloc(acolumn + 1);
1184 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001185 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001186 memset(acolumn_spaces, ' ', acolumn);
1187 acolumn_spaces[acolumn] = '\0';
1188
Denys Vlasenko837399a2012-01-24 11:37:03 +01001189 /* Must have PROG [ARGS], or -p PID. Not both. */
1190 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001191 usage(stderr, 1);
1192
Wang Chaod322a4b2010-08-05 14:30:11 +08001193 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001194 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001195 }
1196
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001197 if (!followfork)
1198 followfork = optF;
1199
Roland McGrathcb9def62006-04-25 07:48:03 +00001200 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001201 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001202 }
1203
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 /* See if they want to run as another user. */
1205 if (username != NULL) {
1206 struct passwd *pent;
1207
1208 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001209 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001211 pent = getpwnam(username);
1212 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001213 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214 }
1215 run_uid = pent->pw_uid;
1216 run_gid = pent->pw_gid;
1217 }
1218 else {
1219 run_uid = getuid();
1220 run_gid = getgid();
1221 }
1222
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001223 if (followfork)
1224 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001225 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001226 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001227
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228 /* Check if they want to redirect the output. */
1229 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001230 /* See if they want to pipe the output. */
1231 if (outfname[0] == '|' || outfname[0] == '!') {
1232 /*
1233 * We can't do the <outfname>.PID funny business
1234 * when using popen, so prohibit it.
1235 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001236 if (followfork > 1)
1237 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1238 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001239 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001240 else if (followfork <= 1)
1241 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 }
1243
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001244 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001245 char *buf = malloc(BUFSIZ);
1246 if (!buf)
1247 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001249 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001250 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001251 if (!opt_intr)
1252 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001254 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001255 if (!opt_intr)
1256 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001257
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001258 /* argv[0] -pPID -oFILE Default interactive setting
1259 * yes 0 0 INTR_WHILE_WAIT
1260 * no 1 0 INTR_WHILE_WAIT
1261 * yes 0 1 INTR_NEVER
1262 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001263 */
1264
1265 /* STARTUP_CHILD must be called before the signal handlers get
1266 installed below as they are inherited into the spawned process.
1267 Also we do not need to be protected by them as during interruption
1268 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001269 if (argv[0])
1270 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272 sigemptyset(&empty_set);
1273 sigemptyset(&blocked_set);
1274 sa.sa_handler = SIG_IGN;
1275 sigemptyset(&sa.sa_mask);
1276 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001277 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1278 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1279 if (opt_intr != INTR_ANYWHERE) {
1280 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1281 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1282 /*
1283 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1284 * fatal signals are blocked while syscall stop is processed,
1285 * and acted on in between, when waiting for new syscall stops.
1286 * In non-interactive mode, signals are ignored.
1287 */
1288 if (opt_intr == INTR_WHILE_WAIT) {
1289 sigaddset(&blocked_set, SIGHUP);
1290 sigaddset(&blocked_set, SIGINT);
1291 sigaddset(&blocked_set, SIGQUIT);
1292 sigaddset(&blocked_set, SIGPIPE);
1293 sigaddset(&blocked_set, SIGTERM);
1294 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001295 }
1296 /* SIG_IGN, or set handler for these */
1297 sigaction(SIGHUP, &sa, NULL);
1298 sigaction(SIGINT, &sa, NULL);
1299 sigaction(SIGQUIT, &sa, NULL);
1300 sigaction(SIGPIPE, &sa, NULL);
1301 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 }
Roland McGrath553a6092002-12-16 20:40:39 +00001303 /* Make sure SIGCHLD has the default action so that waitpid
1304 definitely works without losing track of children. The user
1305 should not have given us a bogus state to inherit, but he might
1306 have. Arguably we should detect SIG_IGN here and pass it on
1307 to children, but probably noone really needs that. */
1308 sa.sa_handler = SIG_DFL;
1309 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001310
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001311 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001312 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 if (trace() < 0)
1315 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001316
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001317 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001318 fflush(NULL);
1319 if (exit_code > 0xff) {
Dmitry V. Levin6c381562012-02-22 00:15:27 +00001320 /* Avoid potential core file clobbering. */
1321 struct rlimit rlim = {0, 0};
1322 setrlimit(RLIMIT_CORE, &rlim);
1323
Dmitry V. Levina6809652008-11-10 17:14:58 +00001324 /* Child was killed by a signal, mimic that. */
1325 exit_code &= 0xff;
1326 signal(exit_code, SIG_DFL);
1327 raise(exit_code);
1328 /* Paranoia - what if this signal is not fatal?
1329 Exit with 128 + signo then. */
1330 exit_code += 128;
1331 }
1332 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333}
1334
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001335static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001336expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001337{
1338 /* Allocate some more TCBs and expand the table.
1339 We don't want to relocate the TCBs because our
1340 callers have pointers and it would be a pain.
1341 So tcbtab is a table of pointers. Since we never
1342 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001343 int i = tcbtabsize;
1344 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1345 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001346 if (!newtab || !newtcbs)
1347 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001348 tcbtabsize *= 2;
1349 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001350 while (i < tcbtabsize)
1351 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001352}
1353
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001355alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356{
1357 int i;
1358 struct tcb *tcp;
1359
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001360 if (nprocs == tcbtabsize)
1361 expand_tcbtab();
1362
Roland McGrathee9d4352002-12-18 04:16:10 +00001363 for (i = 0; i < tcbtabsize; i++) {
1364 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001365 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001366 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001367 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001368 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001369 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001370#if SUPPORTED_PERSONALITIES > 1
1371 tcp->currpers = current_personality;
1372#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001373 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001374 if (debug)
1375 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001376 if (command_options_parsed)
1377 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378 return tcp;
1379 }
1380 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001381 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382}
1383
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001385static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001386pid2tcb(int pid)
1387{
1388 int i;
1389
1390 if (pid <= 0)
1391 return NULL;
1392
1393 for (i = 0; i < tcbtabsize; i++) {
1394 struct tcb *tcp = tcbtab[i];
1395 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1396 return tcp;
1397 }
1398
1399 return NULL;
1400}
1401
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001402
1403void
Denys Vlasenko12014262011-05-30 14:00:14 +02001404droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405{
1406 if (tcp->pid == 0)
1407 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001408
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001409 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001410 if (debug)
1411 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001412
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001413
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001414 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001416
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001417 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418}
1419
Roland McGrath0a463882007-07-05 18:43:16 +00001420/* detach traced process; continue with sig
1421 Never call DETACH twice on the same process as both unattached and
1422 attached-unstopped processes give the same ESRCH. For unattached process we
1423 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424
1425static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001426detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001427{
1428 int error = 0;
Roland McGrath1bfd3102007-08-03 10:02:00 +00001429 int status, catch_sigstop;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430
1431 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001432 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001434 /*
1435 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001436 * before detaching. Arghh. We go through hoops
1437 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001439#if defined(SPARC)
1440#undef PTRACE_DETACH
1441#define PTRACE_DETACH PTRACE_SUNDETACH
1442#endif
Roland McGrath02203312007-06-11 22:06:31 +00001443 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001444 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001445 * We must catch exactly one as otherwise the detached process
1446 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001447 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001448 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001449 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001450 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001452 }
1453 else if (errno != ESRCH) {
1454 /* Shouldn't happen. */
1455 perror("detach: ptrace(PTRACE_DETACH, ...)");
1456 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001457 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001458 if (errno != ESRCH)
1459 perror("detach: checking sanity");
1460 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001461 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001462 if (errno != ESRCH)
1463 perror("detach: stopping child");
1464 }
Roland McGrath02203312007-06-11 22:06:31 +00001465 else
1466 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001467 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001468 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001469#ifdef __WALL
1470 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1471 if (errno == ECHILD) /* Already gone. */
1472 break;
1473 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001474 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001475 break;
1476 }
1477#endif /* __WALL */
1478 /* No __WALL here. */
1479 if (waitpid(tcp->pid, &status, 0) < 0) {
1480 if (errno != ECHILD) {
1481 perror("detach: waiting");
1482 break;
1483 }
1484#ifdef __WCLONE
1485 /* If no processes, try clones. */
1486 if (wait4(tcp->pid, &status, __WCLONE,
1487 NULL) < 0) {
1488 if (errno != ECHILD)
1489 perror("detach: waiting");
1490 break;
1491 }
1492#endif /* __WCLONE */
1493 }
1494#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001495 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001496#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001497 if (!WIFSTOPPED(status)) {
1498 /* Au revoir, mon ami. */
1499 break;
1500 }
1501 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001502 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 break;
1504 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001505 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001506 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001507 : WSTOPSIG(status));
1508 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001511 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001514 if (!qflag)
1515 fprintf(stderr, "Process %u detached\n", tcp->pid);
1516
1517 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001518
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 return error;
1520}
1521
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522
1523static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001524cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525{
1526 int i;
1527 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001528 int fatal_sig;
1529
1530 /* 'interrupted' is a volatile object, fetch it only once */
1531 fatal_sig = interrupted;
1532 if (!fatal_sig)
1533 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534
Roland McGrathee9d4352002-12-18 04:16:10 +00001535 for (i = 0; i < tcbtabsize; i++) {
1536 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537 if (!(tcp->flags & TCB_INUSE))
1538 continue;
1539 if (debug)
1540 fprintf(stderr,
1541 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001542 if (printing_tcp &&
1543 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1544 tprints(" <unfinished ...>\n");
1545 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546 }
1547 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001548 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001549 else {
1550 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001551 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552 }
1553 }
1554 if (cflag)
1555 call_summary(outf);
1556}
1557
1558static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001559interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001560{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001561 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562}
1563
1564#ifndef HAVE_STRERROR
1565
Roland McGrath6d2b3492002-12-30 00:51:30 +00001566#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567extern int sys_nerr;
1568extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001569#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570
1571const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001572strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573{
1574 static char buf[64];
1575
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001576 if (err_no < 1 || err_no >= sys_nerr) {
1577 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578 return buf;
1579 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001580 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581}
1582
1583#endif /* HAVE_STERRROR */
1584
1585#ifndef HAVE_STRSIGNAL
1586
Roland McGrath8f474e02003-01-14 07:53:33 +00001587#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001588extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001590#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1591extern char *_sys_siglist[];
1592#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593
1594const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001595strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596{
1597 static char buf[64];
1598
1599 if (sig < 1 || sig >= NSIG) {
1600 sprintf(buf, "Unknown signal %d", sig);
1601 return buf;
1602 }
1603#ifdef HAVE__SYS_SIGLIST
1604 return _sys_siglist[sig];
1605#else
1606 return sys_siglist[sig];
1607#endif
1608}
1609
1610#endif /* HAVE_STRSIGNAL */
1611
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612
1613static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001614trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001617 struct rusage *rup = cflag ? &ru : NULL;
1618# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001619 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001620# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621
Roland McGratheb9e2e82009-06-02 16:49:22 -07001622 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001623 int pid;
1624 int wait_errno;
1625 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001626 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001627 struct tcb *tcp;
1628 unsigned event;
1629
Denys Vlasenko222713a2009-03-17 14:29:59 +00001630 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001631 return 0;
1632 if (interactive)
1633 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001634# ifdef __WALL
1635 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001636 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001637 /* this kernel does not support __WALL */
1638 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001639 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001640 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001641 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001642 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001643 pid = wait4(-1, &status, __WCLONE, rup);
1644 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001645 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001646 }
1647 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001648# else
1649 pid = wait4(-1, &status, 0, rup);
1650# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001652 if (interactive)
1653 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001655 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001656 switch (wait_errno) {
1657 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001659 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660 /*
1661 * We would like to verify this case
1662 * but sometimes a race in Solbourne's
1663 * version of SunOS sometimes reports
1664 * ECHILD before sending us SIGCHILD.
1665 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001666 return 0;
1667 default:
1668 errno = wait_errno;
1669 perror("strace: wait");
1670 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671 }
1672 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001673 if (pid == popen_pid) {
1674 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001675 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001676 continue;
1677 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001678
1679 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001680 if (debug) {
1681 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001682 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001683 static const char *const event_names[] = {
1684 [PTRACE_EVENT_CLONE] = "CLONE",
1685 [PTRACE_EVENT_FORK] = "FORK",
1686 [PTRACE_EVENT_VFORK] = "VFORK",
1687 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1688 [PTRACE_EVENT_EXEC] = "EXEC",
1689 [PTRACE_EVENT_EXIT] = "EXIT",
1690 };
1691 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001692 if (event < ARRAY_SIZE(event_names))
1693 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001694 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001695 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001696 e = buf;
1697 }
1698 fprintf(stderr, " PTRACE_EVENT_%s", e);
1699 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001700 strcpy(buf, "???");
1701 if (WIFSIGNALED(status))
1702#ifdef WCOREDUMP
1703 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1704 WCOREDUMP(status) ? "core," : "",
1705 signame(WTERMSIG(status)));
1706#else
1707 sprintf(buf, "WIFSIGNALED,sig=%s",
1708 signame(WTERMSIG(status)));
1709#endif
1710 if (WIFEXITED(status))
1711 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1712 if (WIFSTOPPED(status))
1713 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001714#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001715 if (WIFCONTINUED(status))
1716 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001717#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001718 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1719 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001721 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001722 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001723
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001724 /* Under Linux, execve changes pid to thread leader's pid,
1725 * and we see this changed pid on EVENT_EXEC and later,
1726 * execve sysexit. Leader "disappears" without exit
1727 * notification. Let user know that, drop leader's tcb,
1728 * and fix up pid in execve thread's tcb.
1729 * Effectively, execve thread's tcb replaces leader's tcb.
1730 *
1731 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1732 * on exit syscall) in multithreaded programs exactly
1733 * in order to handle this case.
1734 *
1735 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1736 * On 2.6 and earlier, it can return garbage.
1737 */
1738 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1739 long old_pid = 0;
1740 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1741 && old_pid > 0
1742 && old_pid != pid
1743 ) {
1744 struct tcb *execve_thread = pid2tcb(old_pid);
1745 if (tcp) {
1746 outf = tcp->outf;
1747 curcol = tcp->curcol;
1748 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001749 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001750 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001751 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001752 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1753 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001754 fflush(outf);
1755 }
1756 if (execve_thread) {
1757 /* swap output FILEs (needed for -ff) */
1758 tcp->outf = execve_thread->outf;
1759 execve_thread->outf = outf;
1760 }
1761 droptcb(tcp);
1762 }
1763 tcp = execve_thread;
1764 if (tcp) {
1765 tcp->pid = pid;
1766 tcp->flags |= TCB_REPRINT;
1767 }
1768 }
1769 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001770
Denys Vlasenko5d645812011-08-20 12:48:18 +02001771 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001772 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001773 /* This is needed to go with the CLONE_PTRACE
1774 changes in process.c/util.c: we might see
1775 the child's initial trap before we see the
1776 parent return from the clone syscall.
1777 Leave the child suspended until the parent
1778 returns from its system call. Only then
1779 will we have the association of parent and
1780 child so that we know how to do clearbpt
1781 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001782 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001783 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001784 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001785 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001786 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001787 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001788 else
1789 /* This can happen if a clone call used
1790 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001791 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001792 if (WIFSTOPPED(status))
1793 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001794 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001795 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001797 /* set current output file */
1798 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001799 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001800 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1802 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001804
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001806 if (pid == strace_child)
1807 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001808 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1810 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001811#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001812 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001813 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001814 WCOREDUMP(status) ? "(core dumped) " : "");
1815#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001816 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001817 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001818#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001819 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001821 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822 droptcb(tcp);
1823 continue;
1824 }
1825 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001826 if (pid == strace_child)
1827 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001828 if (tcp == printing_tcp) {
1829 tprints(" <unfinished ...>\n");
1830 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001831 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001832 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1833 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001834 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1835 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001836 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001837 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838 droptcb(tcp);
1839 continue;
1840 }
1841 if (!WIFSTOPPED(status)) {
1842 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1843 droptcb(tcp);
1844 continue;
1845 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001847 /* Is this the very first time we see this tracee stopped? */
1848 if (tcp->flags & TCB_STARTUP) {
1849 if (debug)
1850 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001853 /*
1854 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001855 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001856 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001857 if (clearbpt(tcp) < 0) {
1858 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859 droptcb(tcp);
1860 cleanup();
1861 return -1;
1862 }
1863 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001864 if (ptrace_setoptions) {
1865 if (debug)
1866 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1867 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1868 if (errno != ESRCH) {
1869 /* Should never happen, really */
1870 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001871 }
1872 }
1873 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001874 }
1875
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001876 sig = WSTOPSIG(status);
1877
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001878 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001879 /* Ptrace event */
1880#ifdef USE_SEIZE
1881 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001882 /*
1883 * PTRACE_INTERRUPT-stop or group-stop.
1884 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1885 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001886 if (sig == SIGSTOP
1887 || sig == SIGTSTP
1888 || sig == SIGTTIN
1889 || sig == SIGTTOU
1890 ) {
1891 stopped = 1;
1892 goto show_stopsig;
1893 }
1894 }
1895#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001896 goto restart_tracee_with_sig_0;
1897 }
1898
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001899 /* Is this post-attach SIGSTOP?
1900 * Interestingly, the process may stop
1901 * with STOPSIG equal to some other signal
1902 * than SIGSTOP if we happend to attach
1903 * just before the process takes a signal.
1904 */
1905 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
1906 if (debug)
1907 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
1908 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001909 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910 }
1911
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001912 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001913 siginfo_t si;
1914
1915 /* Nonzero (true) if tracee is stopped by signal
1916 * (as opposed to "tracee received signal").
1917 */
1918 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01001919#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001920 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01001921#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001922 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001923 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00001924#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001925 long pc = 0;
1926 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001927
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001928 upeek(tcp, PT_CR_IPSR, &psr);
1929 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001930
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001931# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001932 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001933# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001934# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001935#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001936# define PC_FORMAT_STR ""
1937# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001938#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001939 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001940 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001941 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001942 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01001943 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001944 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001945 PC_FORMAT_ARG);
1946 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001947 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001948 strsignal(sig),
1949 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001950 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001951 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001952 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001954
1955 if (!stopped)
1956 /* It's signal-delivery-stop. Inject the signal */
1957 goto restart_tracee;
1958
1959 /* It's group-stop */
1960#ifdef USE_SEIZE
1961 if (use_seize) {
1962 /*
1963 * This ends ptrace-stop, but does *not* end group-stop.
1964 * This makes stopping signals work properly on straced process
1965 * (that is, process really stops. It used to continue to run).
1966 */
1967 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
1968 cleanup();
1969 return -1;
1970 }
1971 continue;
1972 }
1973 /* We don't have PTRACE_LISTEN support... */
1974#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001975 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001977
1978 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00001979 if (interrupted)
1980 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001981
1982 /* This should be syscall entry or exit.
1983 * (Or it still can be that pesky post-execve SIGTRAP!)
1984 * Handle it.
1985 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001986 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
1987 /* ptrace() failed in trace_syscall() with ESRCH.
1988 * Likely a result of process disappearing mid-flight.
1989 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01001990 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001991 */
1992 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001993 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001994 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02001995 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001996 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01001997 printing_tcp->flags |= TCB_REPRINT;
1998 tprints(" <unfinished ...>\n");
1999 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002000 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002001 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002002 /* We assume that ptrace error was caused by process death.
2003 * We used to detach(tcp) here, but since we no longer
2004 * implement "detach before death" policy/hack,
2005 * we can let this process to report its death to us
2006 * normally, via WIFEXITED or WIFSIGNALED wait status.
2007 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002008 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002009 /* It's our real child (and we also trace it) */
2010 /* my_tkill(pid, SIGKILL); - why? */
2011 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012 }
2013 continue;
2014 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002015 restart_tracee_with_sig_0:
2016 sig = 0;
2017 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002018 /* Remember current print column before continuing. */
2019 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002020 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 cleanup();
2022 return -1;
2023 }
2024 }
2025 return 0;
2026}
2027
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002030tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031{
2032 va_list args;
2033
Andreas Schwabe5355de2009-10-27 16:56:43 +01002034 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002035 if (outf) {
2036 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002037 if (n < 0) {
2038 if (outf != stderr)
2039 perror(outfname == NULL
2040 ? "<writing to pipe>" : outfname);
2041 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002042 curcol += n;
2043 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002045}
2046
2047void
2048tprints(const char *str)
2049{
2050 if (outf) {
2051 int n = fputs(str, outf);
2052 if (n >= 0) {
2053 curcol += strlen(str);
2054 return;
2055 }
2056 if (outf != stderr)
2057 perror(outfname == NULL
2058 ? "<writing to pipe>" : outfname);
2059 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002060}
2061
2062void
Denys Vlasenko12014262011-05-30 14:00:14 +02002063printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002064{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002065 if (printing_tcp) {
2066 if (printing_tcp->ptrace_errno) {
2067 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002068 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002069 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002070 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002071 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002072 printing_tcp->ptrace_errno = 0;
2073 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2074 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002075 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002076 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002077 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002078
2079 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002080 curcol = 0;
2081 if ((followfork == 1 || pflag_seen > 1) && outfname)
2082 tprintf("%-5d ", tcp->pid);
2083 else if (nprocs > 1 && !outfname)
2084 tprintf("[pid %5u] ", tcp->pid);
2085 if (tflag) {
2086 char str[sizeof("HH:MM:SS")];
2087 struct timeval tv, dtv;
2088 static struct timeval otv;
2089
2090 gettimeofday(&tv, NULL);
2091 if (rflag) {
2092 if (otv.tv_sec == 0)
2093 otv = tv;
2094 tv_sub(&dtv, &tv, &otv);
2095 tprintf("%6ld.%06ld ",
2096 (long) dtv.tv_sec, (long) dtv.tv_usec);
2097 otv = tv;
2098 }
2099 else if (tflag > 2) {
2100 tprintf("%ld.%06ld ",
2101 (long) tv.tv_sec, (long) tv.tv_usec);
2102 }
2103 else {
2104 time_t local = tv.tv_sec;
2105 strftime(str, sizeof(str), "%T", localtime(&local));
2106 if (tflag > 1)
2107 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2108 else
2109 tprintf("%s ", str);
2110 }
2111 }
2112 if (iflag)
2113 printcall(tcp);
2114}
2115
2116void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002117tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002118{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002119 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002120 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121}
2122