blob: 20c02663f0ec8a8789bebdca6d4742cee38b64ee [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>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# 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
60#endif
61
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000062#if defined(IA64) && defined(LINUX)
63# include <asm/ptrace_offsets.h>
64#endif
65
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000066#ifdef USE_PROCFS
67#include <poll.h>
68#endif
69
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070#ifdef SVR4
71#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000072#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000073#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000074#include <sys/uio.h>
75#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000077#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000078extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000079extern int optind;
80extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082
Roland McGrath41c48222008-07-18 00:25:10 +000083int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020084unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020085/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020086static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000087int dtime = 0, xflag = 0, qflag = 0;
88cflag_t cflag = CFLAG_NONE;
Denys Vlasenkoaa6ec412012-01-24 11:35:38 +010089static int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
90static int interactive = 1;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000105/* Sometimes we want to print only succeeding syscalls. */
106int not_failing_only = 0;
107
Grant Edwards8a082772011-04-07 20:25:40 +0000108/* Show path associated with fd arguments */
109int show_fd_path = 0;
110
111/* are we filtering traces based on paths? */
112int tracing_paths = 0;
113
Dmitry V. Levina6809652008-11-10 17:14:58 +0000114static int exit_code = 0;
115static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200116static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700117
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000118static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200119static uid_t run_uid;
120static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200123static int acolumn = DEFAULT_ACOLUMN;
124static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000125static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200126static FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100127static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200128static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200129static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200130static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131
Denys Vlasenko4c196382012-01-04 15:11:09 +0100132static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100133static int trace(void);
134static void cleanup(void);
135static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136static sigset_t empty_set, blocked_set;
137
138#ifdef HAVE_SIG_ATOMIC_T
139static volatile sig_atomic_t interrupted;
140#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142#endif /* !HAVE_SIG_ATOMIC_T */
143
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000144#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145
Andreas Schwabe5355de2009-10-27 16:56:43 +0100146static struct tcb *pfd2tcb(int pfd);
147static void reaper(int sig);
148static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000149static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150
151#ifndef HAVE_POLLABLE_PROCFS
152
Andreas Schwabe5355de2009-10-27 16:56:43 +0100153static void proc_poll_open(void);
154static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155
156struct proc_pollfd {
157 int fd;
158 int revents;
159 int pid;
160};
161
162static int poller_pid;
163static int proc_poll_pipe[2] = { -1, -1 };
164
165#endif /* !HAVE_POLLABLE_PROCFS */
166
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000167#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000168#define POLLWANT POLLWRNORM
169#else
170#define POLLWANT POLLPRI
171#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000172#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000173
174static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200175usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176{
177 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000178usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000179 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000180 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200181 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000182 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200184-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185-f -- follow forks, -ff -- with output into separate files\n\
186-F -- attempt to follow vforks, -h -- print help message\n\
187-i -- print instruction pointer at time of syscall\n\
188-q -- suppress messages about attaching, detaching, etc.\n\
189-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
190-T -- print time spent in each syscall, -V -- print version\n\
191-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
192-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000193-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194-a column -- alignment COLUMN for printing syscall results (default %d)\n\
195-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
196 options: trace, abbrev, verbose, raw, signal, read, or write\n\
197-o file -- send trace output to FILE instead of stderr\n\
198-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
199-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000200-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
202-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
203-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000204-E var=val -- put var=val in the environment for command\n\
205-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000206-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000207" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000208-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000209 */
210, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211 exit(exitval);
212}
213
Denys Vlasenko75422762011-05-27 14:36:01 +0200214static void die(void) __attribute__ ((noreturn));
215static void die(void)
216{
217 if (strace_tracer_pid == getpid()) {
218 cflag = 0;
219 cleanup();
220 }
221 exit(1);
222}
223
224static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200225{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100226 char *msg;
227
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000228 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100229
230 /* We want to print entire message with single fprintf to ensure
231 * message integrity if stderr is shared with other programs.
232 * Thus we use vasprintf + single fprintf.
233 */
234 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100235 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100236 if (err_no)
237 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
238 else
239 fprintf(stderr, "%s: %s\n", progname, msg);
240 free(msg);
241 } else {
242 /* malloc in vasprintf failed, try it without malloc */
243 fprintf(stderr, "%s: ", progname);
244 vfprintf(stderr, fmt, p);
245 if (err_no)
246 fprintf(stderr, ": %s\n", strerror(err_no));
247 else
248 putc('\n', stderr);
249 }
250 /* We don't switch stderr to buffered, thus fprintf(stderr)
251 * always flushes its output and this is not necessary: */
252 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200253}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200254
Denys Vlasenko75422762011-05-27 14:36:01 +0200255void error_msg(const char *fmt, ...)
256{
257 va_list p;
258 va_start(p, fmt);
259 verror_msg(0, fmt, p);
260 va_end(p);
261}
262
263void error_msg_and_die(const char *fmt, ...)
264{
265 va_list p;
266 va_start(p, fmt);
267 verror_msg(0, fmt, p);
268 die();
269}
270
271void perror_msg(const char *fmt, ...)
272{
273 va_list p;
274 va_start(p, fmt);
275 verror_msg(errno, fmt, p);
276 va_end(p);
277}
278
279void perror_msg_and_die(const char *fmt, ...)
280{
281 va_list p;
282 va_start(p, fmt);
283 verror_msg(errno, fmt, p);
284 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200285}
286
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200287void die_out_of_memory(void)
288{
289 static bool recursed = 0;
290 if (recursed)
291 exit(1);
292 recursed = 1;
293 error_msg_and_die("Out of memory");
294}
295
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000296#ifdef SVR4
297#ifdef MIPS
298void
299foobar()
300{
301}
302#endif /* MIPS */
303#endif /* SVR4 */
304
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400305/* Glue for systems without a MMU that cannot provide fork() */
306#ifdef HAVE_FORK
307# define strace_vforked 0
308#else
309# define strace_vforked 1
310# define fork() vfork()
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{
342#ifndef SVR4
343 int euid = geteuid(), uid = getuid();
344
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200345 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200346 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000347 }
348#endif
349}
350
Roland McGrath4bfa6262007-07-05 20:03:16 +0000351#if _LFS64_LARGEFILE
352# define fopen_for_output fopen64
353#else
354# define fopen_for_output fopen
355#endif
356
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000357static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200358strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000359{
360 FILE *fp;
361
362 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200363 fp = fopen_for_output(path, "w");
364 if (!fp)
365 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000366 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200367 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000368 return fp;
369}
370
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200371static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000372
373#ifndef _PATH_BSHELL
374# define _PATH_BSHELL "/bin/sh"
375#endif
376
377/*
378 * We cannot use standard popen(3) here because we have to distinguish
379 * popen child process from other processes we trace, and standard popen(3)
380 * does not export its child's pid.
381 */
382static FILE *
383strace_popen(const char *command)
384{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200385 FILE *fp;
386 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000387
388 swap_uid();
389 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200390 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000391
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200392 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000393
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200394 popen_pid = vfork();
395 if (popen_pid == -1)
396 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200398 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000399 /* child */
400 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200401 if (fds[0] != 0) {
402 if (dup2(fds[0], 0))
403 perror_msg_and_die("dup2");
404 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000405 }
406 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200407 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000408 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200409
410 /* parent */
411 close(fds[0]);
412 swap_uid();
413 fp = fdopen(fds[1], "w");
414 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200415 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200416 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000417}
418
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200419static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000420newoutf(struct tcb *tcp)
421{
422 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000423 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000424 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200425 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000426 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000427}
428
Roland McGrath02203312007-06-11 22:06:31 +0000429static void
430startup_attach(void)
431{
432 int tcbi;
433 struct tcb *tcp;
434
435 /*
436 * Block user interruptions as we would leave the traced
437 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200438 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200439 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000440 */
441 if (interactive)
442 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
443
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000444 if (daemonized_tracer) {
445 pid_t pid = fork();
446 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200447 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000448 }
449 if (pid) { /* parent */
450 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200451 * Wait for grandchild to attach to straced process
452 * (grandparent). Grandchild SIGKILLs us after it attached.
453 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000454 * it proceeds to exec the straced program.
455 */
456 pause();
457 _exit(0); /* paranoia */
458 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200459 /* grandchild */
460 /* We will be the tracer process. Remember our new pid: */
461 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000462 }
463
Roland McGrath02203312007-06-11 22:06:31 +0000464 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
465 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200466
Denys Vlasenkod116a732011-09-05 14:01:33 +0200467 /* Is this a process we should attach to, but not yet attached? */
468 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
469 continue; /* no */
470
471 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000472 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200473 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000474
475#ifdef USE_PROCFS
476 if (proc_open(tcp, 1) < 0) {
477 fprintf(stderr, "trouble opening proc file\n");
478 droptcb(tcp);
479 continue;
480 }
481#else /* !USE_PROCFS */
482# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000483 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000484 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000485 DIR *dir;
486
487 sprintf(procdir, "/proc/%d/task", tcp->pid);
488 dir = opendir(procdir);
489 if (dir != NULL) {
490 unsigned int ntid = 0, nerr = 0;
491 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200492
Roland McGrath02203312007-06-11 22:06:31 +0000493 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200494 struct tcb *cur_tcp;
495 int tid;
496
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000497 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000498 continue;
499 tid = atoi(de->d_name);
500 if (tid <= 0)
501 continue;
502 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200503 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000504 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200505 if (debug)
506 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200507 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200508 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200509 if (debug)
510 fprintf(stderr, "attach to pid %d succeeded\n", tid);
511 cur_tcp = tcp;
512 if (tid != tcp->pid)
513 cur_tcp = alloctcb(tid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200514 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrath02203312007-06-11 22:06:31 +0000515 }
516 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200517 if (interactive) {
518 sigprocmask(SIG_SETMASK, &empty_set, NULL);
519 if (interrupted)
520 goto ret;
521 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
522 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000523 ntid -= nerr;
524 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000525 perror("attach: ptrace(PTRACE_ATTACH, ...)");
526 droptcb(tcp);
527 continue;
528 }
529 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000530 fprintf(stderr, ntid > 1
531? "Process %u attached with %u threads - interrupt to quit\n"
532: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200533 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000534 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200535 if (!(tcp->flags & TCB_STARTUP)) {
536 /* -p PID, we failed to attach to PID itself
537 * but did attach to some of its sibling threads.
538 * Drop PID's tcp.
539 */
540 droptcb(tcp);
541 }
Roland McGrath02203312007-06-11 22:06:31 +0000542 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000543 } /* if (opendir worked) */
544 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200545# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000546 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
547 perror("attach: ptrace(PTRACE_ATTACH, ...)");
548 droptcb(tcp);
549 continue;
550 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200551 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200552 if (debug)
553 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000554
555 if (daemonized_tracer) {
556 /*
557 * It is our grandparent we trace, not a -p PID.
558 * Don't want to just detach on exit, so...
559 */
560 tcp->flags &= ~TCB_ATTACHED;
561 /*
562 * Make parent go away.
563 * Also makes grandparent's wait() unblock.
564 */
565 kill(getppid(), SIGKILL);
566 }
567
Roland McGrath02203312007-06-11 22:06:31 +0000568#endif /* !USE_PROCFS */
569 if (!qflag)
570 fprintf(stderr,
571 "Process %u attached - interrupt to quit\n",
572 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200573 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000574
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200575 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000576 if (interactive)
577 sigprocmask(SIG_SETMASK, &empty_set, NULL);
578}
579
580static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200581startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000582{
583 struct stat statbuf;
584 const char *filename;
585 char pathname[MAXPATHLEN];
586 int pid = 0;
587 struct tcb *tcp;
588
589 filename = argv[0];
590 if (strchr(filename, '/')) {
591 if (strlen(filename) > sizeof pathname - 1) {
592 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200593 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000594 }
595 strcpy(pathname, filename);
596 }
597#ifdef USE_DEBUGGING_EXEC
598 /*
599 * Debuggers customarily check the current directory
600 * first regardless of the path but doing that gives
601 * security geeks a panic attack.
602 */
603 else if (stat(filename, &statbuf) == 0)
604 strcpy(pathname, filename);
605#endif /* USE_DEBUGGING_EXEC */
606 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000607 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000608 int m, n, len;
609
610 for (path = getenv("PATH"); path && *path; path += m) {
611 if (strchr(path, ':')) {
612 n = strchr(path, ':') - path;
613 m = n + 1;
614 }
615 else
616 m = n = strlen(path);
617 if (n == 0) {
618 if (!getcwd(pathname, MAXPATHLEN))
619 continue;
620 len = strlen(pathname);
621 }
622 else if (n > sizeof pathname - 1)
623 continue;
624 else {
625 strncpy(pathname, path, n);
626 len = n;
627 }
628 if (len && pathname[len - 1] != '/')
629 pathname[len++] = '/';
630 strcpy(pathname + len, filename);
631 if (stat(pathname, &statbuf) == 0 &&
632 /* Accept only regular files
633 with some execute bits set.
634 XXX not perfect, might still fail */
635 S_ISREG(statbuf.st_mode) &&
636 (statbuf.st_mode & 0111))
637 break;
638 }
639 }
640 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200641 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000642 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000643 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000644 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200645 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000646 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200647 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
648 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000649 ) {
650 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200651 if (outf != stderr)
652 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000653#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200654# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000655 /* Kludge for SGI, see proc_open for details. */
656 sa.sa_handler = foobar;
657 sa.sa_flags = 0;
658 sigemptyset(&sa.sa_mask);
659 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200660# endif
661# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000662 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200663# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200664 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200665# endif
Roland McGrath02203312007-06-11 22:06:31 +0000666#else /* !USE_PROCFS */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000667 if (!daemonized_tracer) {
668 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200669 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000670 }
671 if (debug)
672 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000673 }
Roland McGrath02203312007-06-11 22:06:31 +0000674
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200675 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000676 uid_t run_euid = run_uid;
677 gid_t run_egid = run_gid;
678
679 if (statbuf.st_mode & S_ISUID)
680 run_euid = statbuf.st_uid;
681 if (statbuf.st_mode & S_ISGID)
682 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000683 /*
684 * It is important to set groups before we
685 * lose privileges on setuid.
686 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200687 if (initgroups(username, run_gid) < 0) {
688 perror_msg_and_die("initgroups");
689 }
690 if (setregid(run_gid, run_egid) < 0) {
691 perror_msg_and_die("setregid");
692 }
693 if (setreuid(run_uid, run_euid) < 0) {
694 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000695 }
696 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200697 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000698 setreuid(run_uid, run_uid);
699
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000700 if (!daemonized_tracer) {
701 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200702 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000703 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200704 * the immediately following execve syscall.
705 * Can't do this on NOMMU systems, we are after
706 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000707 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400708 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200709 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000710 } else {
711 struct sigaction sv_sigchld;
712 sigaction(SIGCHLD, NULL, &sv_sigchld);
713 /*
714 * Make sure it is not SIG_IGN, otherwise wait
715 * will not block.
716 */
717 signal(SIGCHLD, SIG_DFL);
718 /*
719 * Wait for grandchild to attach to us.
720 * It kills child after that, and wait() unblocks.
721 */
722 alarm(3);
723 wait(NULL);
724 alarm(0);
725 sigaction(SIGCHLD, &sv_sigchld, NULL);
726 }
Roland McGrath02203312007-06-11 22:06:31 +0000727#endif /* !USE_PROCFS */
728
729 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200730 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000731 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000732
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200733 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200734
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200735 if (!daemonized_tracer) {
736 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200737 if (!strace_vforked)
738 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
739 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#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000752 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200753 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000754 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200755#endif
Roland McGrath02203312007-06-11 22:06:31 +0000756}
757
Wang Chaob13c0de2010-11-12 17:25:19 +0800758#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000759static void kill_save_errno(pid_t pid, int sig)
760{
761 int saved_errno = errno;
762
763 (void) kill(pid, sig);
764 errno = saved_errno;
765}
766
Wang Chaob13c0de2010-11-12 17:25:19 +0800767/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000768 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800769 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000770 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800771 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000772static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200773test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800774{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000775 int pid, expected_grandchild = 0, found_grandchild = 0;
776 const unsigned int test_options = PTRACE_O_TRACECLONE |
777 PTRACE_O_TRACEFORK |
778 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800779
Denys Vlasenko5d645812011-08-20 12:48:18 +0200780 pid = fork();
781 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000782 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200783 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000784 pid = getpid();
785 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
786 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
787 __func__);
788 kill(pid, SIGSTOP);
789 if (fork() < 0)
790 perror_msg_and_die("fork");
791 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800792 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000793
794 while (1) {
795 int status, tracee_pid;
796
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000797 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000798 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000799 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000800 if (errno == EINTR)
801 continue;
802 else if (errno == ECHILD)
803 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000804 kill_save_errno(pid, SIGKILL);
805 perror_msg_and_die("%s: unexpected wait result %d",
806 __func__, tracee_pid);
807 }
808 if (WIFEXITED(status)) {
809 if (WEXITSTATUS(status)) {
810 if (tracee_pid != pid)
811 kill_save_errno(pid, SIGKILL);
812 error_msg_and_die("%s: unexpected exit status %u",
813 __func__, WEXITSTATUS(status));
814 }
815 continue;
816 }
817 if (WIFSIGNALED(status)) {
818 if (tracee_pid != pid)
819 kill_save_errno(pid, SIGKILL);
820 error_msg_and_die("%s: unexpected signal %u",
821 __func__, WTERMSIG(status));
822 }
823 if (!WIFSTOPPED(status)) {
824 if (tracee_pid != pid)
825 kill_save_errno(tracee_pid, SIGKILL);
826 kill(pid, SIGKILL);
827 error_msg_and_die("%s: unexpected wait status %x",
828 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000829 }
830 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000831 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000832 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
833 kill_save_errno(tracee_pid, SIGKILL);
834 kill_save_errno(pid, SIGKILL);
835 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800836 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000837 continue;
838 }
839 switch (WSTOPSIG(status)) {
840 case SIGSTOP:
841 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
842 && errno != EINVAL && errno != EIO)
843 perror_msg("PTRACE_SETOPTIONS");
844 break;
845 case SIGTRAP:
846 if (status >> 16 == PTRACE_EVENT_FORK) {
847 long msg = 0;
848
849 if (ptrace(PTRACE_GETEVENTMSG, pid,
850 NULL, (long) &msg) == 0)
851 expected_grandchild = msg;
852 }
853 break;
854 }
855 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
856 kill_save_errno(pid, SIGKILL);
857 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800858 }
859 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000860 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200861 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000862 if (debug)
863 fprintf(stderr, "ptrace_setoptions = %#x\n",
864 ptrace_setoptions);
865 return;
866 }
867 error_msg("Test for PTRACE_O_TRACECLONE failed, "
868 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800869}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200870
871/*
872 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
873 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
874 * and then see whether it will stop with (SIGTRAP | 0x80).
875 *
876 * Use of this option enables correct handling of user-generated SIGTRAPs,
877 * and SIGTRAPs generated by special instructions such as int3 on x86:
878 * _start: .globl _start
879 * int3
880 * movl $42, %ebx
881 * movl $1, %eax
882 * int $0x80
883 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
884 */
885static void
886test_ptrace_setoptions_for_all(void)
887{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000888 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
889 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200890 int pid;
891 int it_worked = 0;
892
893 pid = fork();
894 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200895 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200896
897 if (pid == 0) {
898 pid = getpid();
899 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200900 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000901 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
902 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200903 kill(pid, SIGSTOP);
904 _exit(0); /* parent should see entry into this syscall */
905 }
906
907 while (1) {
908 int status, tracee_pid;
909
910 errno = 0;
911 tracee_pid = wait(&status);
912 if (tracee_pid <= 0) {
913 if (errno == EINTR)
914 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000915 kill_save_errno(pid, SIGKILL);
916 perror_msg_and_die("%s: unexpected wait result %d",
917 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200918 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200919 if (WIFEXITED(status)) {
920 if (WEXITSTATUS(status) == 0)
921 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000922 error_msg_and_die("%s: unexpected exit status %u",
923 __func__, WEXITSTATUS(status));
924 }
925 if (WIFSIGNALED(status)) {
926 error_msg_and_die("%s: unexpected signal %u",
927 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200928 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200929 if (!WIFSTOPPED(status)) {
930 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000931 error_msg_and_die("%s: unexpected wait status %x",
932 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200933 }
934 if (WSTOPSIG(status) == SIGSTOP) {
935 /*
936 * We don't check "options aren't accepted" error.
937 * If it happens, we'll never get (SIGTRAP | 0x80),
938 * and thus will decide to not use the option.
939 * IOW: the outcome of the test will be correct.
940 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000941 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
942 && errno != EINVAL && errno != EIO)
943 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200944 }
945 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
946 it_worked = 1;
947 }
948 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000949 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200950 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200951 }
952 }
953
954 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200955 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200956 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200957 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200958 fprintf(stderr, "ptrace_setoptions = %#x\n",
959 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200960 return;
961 }
962
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000963 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
964 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200965}
Wang Chaob13c0de2010-11-12 17:25:19 +0800966#endif
967
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000969main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 struct tcb *tcp;
972 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000973 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974 struct sigaction sa;
975
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000976 progname = argv[0] ? argv[0] : "strace";
977
Denys Vlasenko75422762011-05-27 14:36:01 +0200978 strace_tracer_pid = getpid();
979
Roland McGrathee9d4352002-12-18 04:16:10 +0000980 /* Allocate the initial tcbtab. */
981 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200982 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200983 if (!tcbtab)
984 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200985 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200986 if (!tcp)
987 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200988 for (c = 0; c < tcbtabsize; c++)
989 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000990
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +0000992 set_sortby(DEFAULT_SORTBY);
993 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 qualify("trace=all");
995 qualify("abbrev=all");
996 qualify("verbose=all");
997 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000999 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001000#ifndef USE_PROCFS
1001 "D"
1002#endif
Grant Edwards8a082772011-04-07 20:25:40 +00001003 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004 switch (c) {
1005 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001006 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001007 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001008 }
1009 cflag = CFLAG_ONLY_STATS;
1010 break;
1011 case 'C':
1012 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001013 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001014 }
1015 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001016 break;
1017 case 'd':
1018 debug++;
1019 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001020#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001021 case 'D':
1022 daemonized_tracer = 1;
1023 break;
1024#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001025 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001026 optF = 1;
1027 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 case 'f':
1029 followfork++;
1030 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 case 'h':
1032 usage(stdout, 0);
1033 break;
1034 case 'i':
1035 iflag++;
1036 break;
1037 case 'q':
1038 qflag++;
1039 break;
1040 case 'r':
1041 rflag++;
1042 tflag++;
1043 break;
1044 case 't':
1045 tflag++;
1046 break;
1047 case 'T':
1048 dtime++;
1049 break;
1050 case 'x':
1051 xflag++;
1052 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001053 case 'y':
1054 show_fd_path = 1;
1055 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 case 'v':
1057 qualify("abbrev=none");
1058 break;
1059 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001060 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001061 exit(0);
1062 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001063 case 'z':
1064 not_failing_only = 1;
1065 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 case 'a':
1067 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001068 if (acolumn < 0)
1069 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 break;
1071 case 'e':
1072 qualify(optarg);
1073 break;
1074 case 'o':
1075 outfname = strdup(optarg);
1076 break;
1077 case 'O':
1078 set_overhead(atoi(optarg));
1079 break;
1080 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001081 pid = atoi(optarg);
1082 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001083 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 break;
1085 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001086 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001087 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 break;
1089 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001090 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 tcp->flags |= TCB_ATTACHED;
1092 pflag_seen++;
1093 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001094 case 'P':
1095 tracing_paths = 1;
1096 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001097 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001098 }
1099 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 case 's':
1101 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001102 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001103 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001104 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 break;
1106 case 'S':
1107 set_sortby(optarg);
1108 break;
1109 case 'u':
1110 username = strdup(optarg);
1111 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001112 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001113 if (putenv(optarg) < 0)
1114 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001115 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001116 default:
1117 usage(stderr, 1);
1118 break;
1119 }
1120 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001121 argv += optind;
1122 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123
Denys Vlasenko102ec492011-08-25 01:27:59 +02001124 acolumn_spaces = malloc(acolumn + 1);
1125 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001126 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001127 memset(acolumn_spaces, ' ', acolumn);
1128 acolumn_spaces[acolumn] = '\0';
1129
Denys Vlasenko837399a2012-01-24 11:37:03 +01001130 /* Must have PROG [ARGS], or -p PID. Not both. */
1131 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001132 usage(stderr, 1);
1133
Wang Chaod322a4b2010-08-05 14:30:11 +08001134 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001135 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001136 }
1137
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001138 if (!followfork)
1139 followfork = optF;
1140
Roland McGrathcb9def62006-04-25 07:48:03 +00001141 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001142 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001143 }
1144
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145 /* See if they want to run as another user. */
1146 if (username != NULL) {
1147 struct passwd *pent;
1148
1149 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001150 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001152 pent = getpwnam(username);
1153 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001154 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 }
1156 run_uid = pent->pw_uid;
1157 run_gid = pent->pw_gid;
1158 }
1159 else {
1160 run_uid = getuid();
1161 run_gid = getgid();
1162 }
1163
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001164#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001165 if (followfork)
1166 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001167 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001168#endif
1169
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 /* Check if they want to redirect the output. */
1171 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001172 /* See if they want to pipe the output. */
1173 if (outfname[0] == '|' || outfname[0] == '!') {
1174 /*
1175 * We can't do the <outfname>.PID funny business
1176 * when using popen, so prohibit it.
1177 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001178 if (followfork > 1)
1179 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1180 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001181 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001182 else if (followfork <= 1)
1183 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184 }
1185
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001186 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001187 char *buf = malloc(BUFSIZ);
1188 if (!buf)
1189 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001191 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001192 if (outfname && argv[0]) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001195 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001196
Roland McGrath54cc1c82007-11-03 23:34:11 +00001197 /* Valid states here:
Denys Vlasenko837399a2012-01-24 11:37:03 +01001198 argv[0] pflag_seen outfname interactive
1199 yes 0 0 1
1200 no 1 0 1
1201 yes 0 1 0
1202 no 1 1 1
Roland McGrath54cc1c82007-11-03 23:34:11 +00001203 */
1204
1205 /* STARTUP_CHILD must be called before the signal handlers get
1206 installed below as they are inherited into the spawned process.
1207 Also we do not need to be protected by them as during interruption
1208 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001209 if (argv[0])
1210 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 sigemptyset(&empty_set);
1213 sigemptyset(&blocked_set);
1214 sa.sa_handler = SIG_IGN;
1215 sigemptyset(&sa.sa_mask);
1216 sa.sa_flags = 0;
1217 sigaction(SIGTTOU, &sa, NULL);
1218 sigaction(SIGTTIN, &sa, NULL);
Denys Vlasenko837399a2012-01-24 11:37:03 +01001219 /* In interactive mode (if no -o OUTFILE, or -p PID is used),
1220 * fatal signals are blocked across syscall waits, and acted on
1221 * in between. In non-interactive mode, signals are ignored.
1222 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223 if (interactive) {
1224 sigaddset(&blocked_set, SIGHUP);
1225 sigaddset(&blocked_set, SIGINT);
1226 sigaddset(&blocked_set, SIGQUIT);
1227 sigaddset(&blocked_set, SIGPIPE);
1228 sigaddset(&blocked_set, SIGTERM);
1229 sa.sa_handler = interrupt;
1230#ifdef SUNOS4
1231 /* POSIX signals on sunos4.1 are a little broken. */
1232 sa.sa_flags = SA_INTERRUPT;
1233#endif /* SUNOS4 */
1234 }
1235 sigaction(SIGHUP, &sa, NULL);
1236 sigaction(SIGINT, &sa, NULL);
1237 sigaction(SIGQUIT, &sa, NULL);
1238 sigaction(SIGPIPE, &sa, NULL);
1239 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001240#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 sa.sa_handler = reaper;
1242 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001243#else
1244 /* Make sure SIGCHLD has the default action so that waitpid
1245 definitely works without losing track of children. The user
1246 should not have given us a bogus state to inherit, but he might
1247 have. Arguably we should detect SIG_IGN here and pass it on
1248 to children, but probably noone really needs that. */
1249 sa.sa_handler = SIG_DFL;
1250 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001251#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001253 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001254 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001255
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001256 if (trace() < 0)
1257 exit(1);
1258 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001259 fflush(NULL);
1260 if (exit_code > 0xff) {
1261 /* Child was killed by a signal, mimic that. */
1262 exit_code &= 0xff;
1263 signal(exit_code, SIG_DFL);
1264 raise(exit_code);
1265 /* Paranoia - what if this signal is not fatal?
1266 Exit with 128 + signo then. */
1267 exit_code += 128;
1268 }
1269 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270}
1271
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001272static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001273expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001274{
1275 /* Allocate some more TCBs and expand the table.
1276 We don't want to relocate the TCBs because our
1277 callers have pointers and it would be a pain.
1278 So tcbtab is a table of pointers. Since we never
1279 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001280 int i = tcbtabsize;
1281 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1282 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001283 if (!newtab || !newtcbs)
1284 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001285 tcbtabsize *= 2;
1286 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001287 while (i < tcbtabsize)
1288 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001289}
1290
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001291struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001292alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293{
1294 int i;
1295 struct tcb *tcp;
1296
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001297 if (nprocs == tcbtabsize)
1298 expand_tcbtab();
1299
Roland McGrathee9d4352002-12-18 04:16:10 +00001300 for (i = 0; i < tcbtabsize; i++) {
1301 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001303 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001305 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001307#if SUPPORTED_PERSONALITIES > 1
1308 tcp->currpers = current_personality;
1309#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001310#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001312#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001314 if (debug)
1315 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001316 if (command_options_parsed)
1317 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318 return tcp;
1319 }
1320 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001321 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001322}
1323
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001324#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001326proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001327{
1328 char proc[32];
1329 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001330#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001331 int i;
1332 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333 sigset_t signals;
1334 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001335#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336#ifndef HAVE_POLLABLE_PROCFS
1337 static int last_pfd;
1338#endif
1339
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001340#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001341 /* Open the process pseudo-files in /proc. */
1342 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001343 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1344 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345 perror("strace: open(\"/proc/...\", ...)");
1346 return -1;
1347 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001348 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001349 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001350 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1351 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001352 perror("strace: open(\"/proc/...\", ...)");
1353 return -1;
1354 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001355 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001356 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001357 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1358 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001359 perror("strace: open(\"/proc/...\", ...)");
1360 return -1;
1361 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001362 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001363#else
1364 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001365# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001366 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001367 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001368# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001369 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001370 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001371# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001372 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001373 perror("strace: open(\"/proc/...\", ...)");
1374 return -1;
1375 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001376 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001377#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001378#ifdef FREEBSD
1379 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001380 tcp->pfd_reg = open(proc, O_RDONLY);
1381 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001382 perror("strace: open(\"/proc/.../regs\", ...)");
1383 return -1;
1384 }
1385 if (cflag) {
1386 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001387 tcp->pfd_status = open(proc, O_RDONLY);
1388 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001389 perror("strace: open(\"/proc/.../status\", ...)");
1390 return -1;
1391 }
1392 } else
1393 tcp->pfd_status = -1;
1394#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001395 rebuild_pollv();
1396 if (!attaching) {
1397 /*
1398 * Wait for the child to pause. Because of a race
1399 * condition we have to poll for the event.
1400 */
1401 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001402 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001403 perror("strace: PIOCSTATUS");
1404 return -1;
1405 }
1406 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001407 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001408 }
1409 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001410#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001411 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001412 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001413 perror("strace: PIOCSTOP");
1414 return -1;
1415 }
Roland McGrath553a6092002-12-16 20:40:39 +00001416#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417#ifdef PIOCSET
1418 /* Set Run-on-Last-Close. */
1419 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001420 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421 perror("PIOCSET PR_RLC");
1422 return -1;
1423 }
1424 /* Set or Reset Inherit-on-Fork. */
1425 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001426 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001427 perror("PIOC{SET,RESET} PR_FORK");
1428 return -1;
1429 }
1430#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001431#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001432 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1433 perror("PIOCSRLC");
1434 return -1;
1435 }
1436 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1437 perror("PIOC{S,R}FORK");
1438 return -1;
1439 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001440#else /* FREEBSD */
1441 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1442 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1443 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001444 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001445 }
1446 arg &= ~PF_LINGER;
1447 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001448 perror("PIOCSFL");
1449 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001450 }
1451#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001452#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001453#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001454 /* Enable all syscall entries we care about. */
1455 premptyset(&syscalls);
1456 for (i = 1; i < MAX_QUALS; ++i) {
1457 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001458 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001459 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001460 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001461 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001462 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001463#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001464 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001465#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001466#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001467 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001468#endif
1469#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001470 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001471#endif
1472#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001473 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001474#endif
1475 }
1476 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477 perror("PIOCSENTRY");
1478 return -1;
1479 }
John Hughes19e49982001-10-19 08:59:12 +00001480 /* Enable the syscall exits. */
1481 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 perror("PIOSEXIT");
1483 return -1;
1484 }
John Hughes19e49982001-10-19 08:59:12 +00001485 /* Enable signals we care about. */
1486 premptyset(&signals);
1487 for (i = 1; i < MAX_QUALS; ++i) {
1488 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001489 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001490 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001491 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 perror("PIOCSTRACE");
1493 return -1;
1494 }
John Hughes19e49982001-10-19 08:59:12 +00001495 /* Enable faults we care about */
1496 premptyset(&faults);
1497 for (i = 1; i < MAX_QUALS; ++i) {
1498 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001499 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001500 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001501 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 perror("PIOCSFAULT");
1503 return -1;
1504 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001505#else /* FREEBSD */
1506 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001507 arg = S_SIG | S_SCE | S_SCX;
1508 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001509 perror("PIOCBIS");
1510 return -1;
1511 }
1512#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 if (!attaching) {
1514#ifdef MIPS
1515 /*
1516 * The SGI PRSABORT doesn't work for pause() so
1517 * we send it a caught signal to wake it up.
1518 */
1519 kill(tcp->pid, SIGINT);
1520#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001521#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001523 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001524 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525 perror("PIOCRUN");
1526 return -1;
1527 }
Roland McGrath553a6092002-12-16 20:40:39 +00001528#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001529#endif /* !MIPS*/
1530#ifdef FREEBSD
1531 /* wake up the child if it received the SIGSTOP */
1532 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001533#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534 for (;;) {
1535 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001536 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537 perror("PIOCWSTOP");
1538 return -1;
1539 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001540 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001541 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001542 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001543 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544 break;
1545 }
1546 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001547#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001548 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001549 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1550#else
1551 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1552#endif
1553 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554 perror("PIOCRUN");
1555 return -1;
1556 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001557#ifdef FREEBSD
1558 /* handle the case where we "opened" the child before
1559 it did the kill -STOP */
1560 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1561 tcp->status.PR_WHAT == SIGSTOP)
1562 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001563#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 }
1565 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001566#ifdef FREEBSD
1567 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001568 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001569 /* We are attaching to an already running process.
1570 * Try to figure out the state of the process in syscalls,
1571 * to handle the first event well.
1572 * This is done by having a look at the "wchan" property of the
1573 * process, which tells where it is stopped (if it is). */
1574 FILE * status;
1575 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001576
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001577 sprintf(proc, "/proc/%d/status", tcp->pid);
1578 status = fopen(proc, "r");
1579 if (status &&
1580 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1581 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1582 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1583 strcmp(wchan, "stopevent")) {
1584 /* The process is asleep in the middle of a syscall.
1585 Fake the syscall entry event */
1586 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1587 tcp->status.PR_WHY = PR_SYSENTRY;
1588 trace_syscall(tcp);
1589 }
1590 if (status)
1591 fclose(status);
1592 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001593 }
1594#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001595#ifndef HAVE_POLLABLE_PROCFS
1596 if (proc_poll_pipe[0] != -1)
1597 proc_poller(tcp->pfd);
1598 else if (nprocs > 1) {
1599 proc_poll_open();
1600 proc_poller(last_pfd);
1601 proc_poller(tcp->pfd);
1602 }
1603 last_pfd = tcp->pfd;
1604#endif /* !HAVE_POLLABLE_PROCFS */
1605 return 0;
1606}
1607
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001608#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001610struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001611pid2tcb(int pid)
1612{
1613 int i;
1614
1615 if (pid <= 0)
1616 return NULL;
1617
1618 for (i = 0; i < tcbtabsize; i++) {
1619 struct tcb *tcp = tcbtab[i];
1620 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1621 return tcp;
1622 }
1623
1624 return NULL;
1625}
1626
1627#ifdef USE_PROCFS
1628
1629static struct tcb *
1630first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631{
1632 int i;
1633 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001634 for (i = 0; i < tcbtabsize; i++) {
1635 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636 if (tcp->flags & TCB_INUSE)
1637 return tcp;
1638 }
1639 return NULL;
1640}
1641
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001643pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644{
1645 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646
Roland McGrathca16be82003-01-10 19:55:28 +00001647 for (i = 0; i < tcbtabsize; i++) {
1648 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649 if (tcp->pfd != pfd)
1650 continue;
1651 if (tcp->flags & TCB_INUSE)
1652 return tcp;
1653 }
1654 return NULL;
1655}
1656
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001657#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658
1659void
Denys Vlasenko12014262011-05-30 14:00:14 +02001660droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661{
1662 if (tcp->pid == 0)
1663 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001664
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001666 if (debug)
1667 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001668
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001669#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670 if (tcp->pfd != -1) {
1671 close(tcp->pfd);
1672 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001673# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001674 if (tcp->pfd_reg != -1) {
1675 close(tcp->pfd_reg);
1676 tcp->pfd_reg = -1;
1677 }
1678 if (tcp->pfd_status != -1) {
1679 close(tcp->pfd_status);
1680 tcp->pfd_status = -1;
1681 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001682# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001683 tcp->flags = 0; /* rebuild_pollv needs it */
1684 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001686#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001687
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001688 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001690
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001691 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692}
1693
Roland McGrath0a463882007-07-05 18:43:16 +00001694/* detach traced process; continue with sig
1695 Never call DETACH twice on the same process as both unattached and
1696 attached-unstopped processes give the same ESRCH. For unattached process we
1697 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698
1699static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001700detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701{
1702 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001703#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001704 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001705#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706
1707 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001708 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709
1710#ifdef LINUX
1711 /*
1712 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001713 * before detaching. Arghh. We go through hoops
1714 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001716#if defined(SPARC)
1717#undef PTRACE_DETACH
1718#define PTRACE_DETACH PTRACE_SUNDETACH
1719#endif
Roland McGrath02203312007-06-11 22:06:31 +00001720 /*
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001721 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1722 * We must catch exactly one as otherwise the detached process
1723 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001724 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001725 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001726 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001727 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001728 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001729 }
1730 else if (errno != ESRCH) {
1731 /* Shouldn't happen. */
1732 perror("detach: ptrace(PTRACE_DETACH, ...)");
1733 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001734 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001735 if (errno != ESRCH)
1736 perror("detach: checking sanity");
1737 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001738 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001739 if (errno != ESRCH)
1740 perror("detach: stopping child");
1741 }
Roland McGrath02203312007-06-11 22:06:31 +00001742 else
1743 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001744 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001746#ifdef __WALL
1747 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1748 if (errno == ECHILD) /* Already gone. */
1749 break;
1750 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001751 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001752 break;
1753 }
1754#endif /* __WALL */
1755 /* No __WALL here. */
1756 if (waitpid(tcp->pid, &status, 0) < 0) {
1757 if (errno != ECHILD) {
1758 perror("detach: waiting");
1759 break;
1760 }
1761#ifdef __WCLONE
1762 /* If no processes, try clones. */
1763 if (wait4(tcp->pid, &status, __WCLONE,
1764 NULL) < 0) {
1765 if (errno != ECHILD)
1766 perror("detach: waiting");
1767 break;
1768 }
1769#endif /* __WCLONE */
1770 }
1771#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001772 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001773#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774 if (!WIFSTOPPED(status)) {
1775 /* Au revoir, mon ami. */
1776 break;
1777 }
1778 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001779 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780 break;
1781 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001782 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001783 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001784 : WSTOPSIG(status));
1785 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001788 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001789#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790
1791#if defined(SUNOS4)
1792 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001793 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794#endif /* SUNOS4 */
1795
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 if (!qflag)
1797 fprintf(stderr, "Process %u detached\n", tcp->pid);
1798
1799 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001800
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801 return error;
1802}
1803
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001804#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001806static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807{
1808 int pid;
1809 int status;
1810
1811 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812 }
1813}
1814
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001815#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001816
1817static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001818cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819{
1820 int i;
1821 struct tcb *tcp;
1822
Roland McGrathee9d4352002-12-18 04:16:10 +00001823 for (i = 0; i < tcbtabsize; i++) {
1824 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825 if (!(tcp->flags & TCB_INUSE))
1826 continue;
1827 if (debug)
1828 fprintf(stderr,
1829 "cleanup: looking at pid %u\n", tcp->pid);
1830 if (tcp_last &&
1831 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001832 tprints(" <unfinished ...>");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001833 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834 }
1835 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001836 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837 else {
1838 kill(tcp->pid, SIGCONT);
1839 kill(tcp->pid, SIGTERM);
1840 }
1841 }
1842 if (cflag)
1843 call_summary(outf);
1844}
1845
1846static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001847interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848{
1849 interrupted = 1;
1850}
1851
1852#ifndef HAVE_STRERROR
1853
Roland McGrath6d2b3492002-12-30 00:51:30 +00001854#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001855extern int sys_nerr;
1856extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001857#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001858
1859const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001860strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861{
1862 static char buf[64];
1863
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001864 if (err_no < 1 || err_no >= sys_nerr) {
1865 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866 return buf;
1867 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001868 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869}
1870
1871#endif /* HAVE_STERRROR */
1872
1873#ifndef HAVE_STRSIGNAL
1874
Roland McGrath8f474e02003-01-14 07:53:33 +00001875#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001876extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001878#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1879extern char *_sys_siglist[];
1880#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001881
1882const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001883strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001884{
1885 static char buf[64];
1886
1887 if (sig < 1 || sig >= NSIG) {
1888 sprintf(buf, "Unknown signal %d", sig);
1889 return buf;
1890 }
1891#ifdef HAVE__SYS_SIGLIST
1892 return _sys_siglist[sig];
1893#else
1894 return sys_siglist[sig];
1895#endif
1896}
1897
1898#endif /* HAVE_STRSIGNAL */
1899
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001900#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901
1902static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001903rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904{
1905 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001906
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001907 free(pollv);
1908 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001909 if (!pollv)
1910 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001911
Roland McGrathca16be82003-01-10 19:55:28 +00001912 for (i = j = 0; i < tcbtabsize; i++) {
1913 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914 if (!(tcp->flags & TCB_INUSE))
1915 continue;
1916 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001917 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001918 j++;
1919 }
1920 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001921 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922 }
1923}
1924
1925#ifndef HAVE_POLLABLE_PROCFS
1926
1927static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001928proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001929{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001930 int i;
1931
1932 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001933 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934 }
1935 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001936 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937 }
1938}
1939
1940static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001941proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001942{
1943 int i;
1944 int n;
1945 struct proc_pollfd pollinfo;
1946
Denys Vlasenko5d645812011-08-20 12:48:18 +02001947 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1948 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949 return n;
1950 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001951 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 }
1953 for (i = 0; i < nprocs; i++) {
1954 if (pollv[i].fd == pollinfo.fd)
1955 pollv[i].revents = pollinfo.revents;
1956 else
1957 pollv[i].revents = 0;
1958 }
1959 poller_pid = pollinfo.pid;
1960 return 1;
1961}
1962
1963static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001964wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965{
1966}
1967
1968static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001969proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001970{
1971 struct proc_pollfd pollinfo;
1972 struct sigaction sa;
1973 sigset_t blocked_set, empty_set;
1974 int i;
1975 int n;
1976 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001977#ifdef FREEBSD
1978 struct procfs_status pfs;
1979#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001980
1981 switch (fork()) {
1982 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001983 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984 case 0:
1985 break;
1986 default:
1987 return;
1988 }
1989
1990 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1991 sa.sa_flags = 0;
1992 sigemptyset(&sa.sa_mask);
1993 sigaction(SIGHUP, &sa, NULL);
1994 sigaction(SIGINT, &sa, NULL);
1995 sigaction(SIGQUIT, &sa, NULL);
1996 sigaction(SIGPIPE, &sa, NULL);
1997 sigaction(SIGTERM, &sa, NULL);
1998 sa.sa_handler = wakeup_handler;
1999 sigaction(SIGUSR1, &sa, NULL);
2000 sigemptyset(&blocked_set);
2001 sigaddset(&blocked_set, SIGUSR1);
2002 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2003 sigemptyset(&empty_set);
2004
2005 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002006 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002007 }
2008 n = rl.rlim_cur;
2009 for (i = 0; i < n; i++) {
2010 if (i != pfd && i != proc_poll_pipe[1])
2011 close(i);
2012 }
2013
2014 pollinfo.fd = pfd;
2015 pollinfo.pid = getpid();
2016 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002017#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002018 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2019#else
2020 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2021#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002022 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002023 switch (errno) {
2024 case EINTR:
2025 continue;
2026 case EBADF:
2027 pollinfo.revents = POLLERR;
2028 break;
2029 case ENOENT:
2030 pollinfo.revents = POLLHUP;
2031 break;
2032 default:
2033 perror("proc_poller: PIOCWSTOP");
2034 }
2035 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2036 _exit(0);
2037 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002038 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002039 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2040 sigsuspend(&empty_set);
2041 }
2042}
2043
2044#endif /* !HAVE_POLLABLE_PROCFS */
2045
2046static int
2047choose_pfd()
2048{
2049 int i, j;
2050 struct tcb *tcp;
2051
2052 static int last;
2053
2054 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002055 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 /*
2057 * The previous process is ready to run again. We'll
2058 * let it do so if it is currently in a syscall. This
2059 * heuristic improves the readability of the trace.
2060 */
2061 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002062 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002063 return pollv[last].fd;
2064 }
2065
2066 for (i = 0; i < nprocs; i++) {
2067 /* Let competing children run round robin. */
2068 j = (i + last + 1) % nprocs;
2069 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2070 tcp = pfd2tcb(pollv[j].fd);
2071 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002072 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002073 }
2074 droptcb(tcp);
2075 return -1;
2076 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002077 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 last = j;
2079 return pollv[j].fd;
2080 }
2081 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002082 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083}
2084
2085static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002086trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002087{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002088#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002089 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002090#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091 struct tcb *tcp;
2092 int pfd;
2093 int what;
2094 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002095 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002096
2097 for (;;) {
2098 if (interactive)
2099 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2100
2101 if (nprocs == 0)
2102 break;
2103
2104 switch (nprocs) {
2105 case 1:
2106#ifndef HAVE_POLLABLE_PROCFS
2107 if (proc_poll_pipe[0] == -1) {
2108#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002109 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 if (!tcp)
2111 continue;
2112 pfd = tcp->pfd;
2113 if (pfd == -1)
2114 continue;
2115 break;
2116#ifndef HAVE_POLLABLE_PROCFS
2117 }
2118 /* fall through ... */
2119#endif /* !HAVE_POLLABLE_PROCFS */
2120 default:
2121#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002122#ifdef POLL_HACK
2123 /* On some systems (e.g. UnixWare) we get too much ugly
2124 "unfinished..." stuff when multiple proceses are in
2125 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002126
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002127 if (in_syscall) {
2128 struct pollfd pv;
2129 tcp = in_syscall;
2130 in_syscall = NULL;
2131 pv.fd = tcp->pfd;
2132 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002133 what = poll(&pv, 1, 1);
2134 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002135 if (interrupted)
2136 return 0;
2137 continue;
2138 }
2139 else if (what == 1 && pv.revents & POLLWANT) {
2140 goto FOUND;
2141 }
2142 }
2143#endif
2144
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002145 if (poll(pollv, nprocs, INFTIM) < 0) {
2146 if (interrupted)
2147 return 0;
2148 continue;
2149 }
2150#else /* !HAVE_POLLABLE_PROCFS */
2151 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2152 if (interrupted)
2153 return 0;
2154 continue;
2155 }
2156#endif /* !HAVE_POLLABLE_PROCFS */
2157 pfd = choose_pfd();
2158 if (pfd == -1)
2159 continue;
2160 break;
2161 }
2162
2163 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002164 tcp = pfd2tcb(pfd);
2165 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002166 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002167 }
John Hughesb6643082002-05-23 11:02:22 +00002168#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002169 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002170#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 /* Get the status of the process. */
2172 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002173#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002174 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002175#else /* FREEBSD */
2176 /* Thanks to some scheduling mystery, the first poller
2177 sometimes waits for the already processed end of fork
2178 event. Doing a non blocking poll here solves the problem. */
2179 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002180 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002181 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002182 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002183#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 ioctl_errno = errno;
2185#ifndef HAVE_POLLABLE_PROCFS
2186 if (proc_poll_pipe[0] != -1) {
2187 if (ioctl_result < 0)
2188 kill(poller_pid, SIGKILL);
2189 else
2190 kill(poller_pid, SIGUSR1);
2191 }
2192#endif /* !HAVE_POLLABLE_PROCFS */
2193 }
2194 if (interrupted)
2195 return 0;
2196
2197 if (interactive)
2198 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2199
2200 if (ioctl_result < 0) {
2201 /* Find out what happened if it failed. */
2202 switch (ioctl_errno) {
2203 case EINTR:
2204 case EBADF:
2205 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002206#ifdef FREEBSD
2207 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002208#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209 case ENOENT:
2210 droptcb(tcp);
2211 continue;
2212 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002213 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002214 }
2215 }
2216
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002217#ifdef FREEBSD
2218 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2219 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002220 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002221 continue;
2222 }
Roland McGrath553a6092002-12-16 20:40:39 +00002223#endif
2224
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002225 /* clear the just started flag */
2226 tcp->flags &= ~TCB_STARTUP;
2227
2228 /* set current output file */
2229 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002230 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231
2232 if (cflag) {
2233 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002234#ifdef FREEBSD
2235 char buf[1024];
2236 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002237
Denys Vlasenko5d645812011-08-20 12:48:18 +02002238 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2239 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002240 buf[len] = '\0';
2241 sscanf(buf,
2242 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2243 &stime.tv_sec, &stime.tv_usec);
2244 } else
2245 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002246#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002247 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2248 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002249#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002250 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2251 tcp->stime = stime;
2252 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002253 what = tcp->status.PR_WHAT;
2254 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002255#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002256 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002257 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2258 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002259 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002260 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002261 }
2262 }
2263 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002264#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002266#ifdef POLL_HACK
2267 in_syscall = tcp;
2268#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002269 case PR_SYSEXIT:
2270 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002271 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002272 }
2273 break;
2274 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002275 if (cflag != CFLAG_ONLY_STATS
2276 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002277 printleader(tcp);
2278 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002279 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002280 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002281#ifdef PR_INFO
2282 if (tcp->status.PR_INFO.si_signo == what) {
2283 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002284 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002285 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002286 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002287 }
2288#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002289 }
2290 break;
2291 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002292 if (cflag != CFLAGS_ONLY_STATS
2293 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294 printleader(tcp);
2295 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002296 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002297 }
2298 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002299#ifdef FREEBSD
2300 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002301 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002302#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002303 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002304 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305 break;
2306 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002307 /* Remember current print column before continuing. */
2308 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002309 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002310#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002311 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002312#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002313 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002314#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002315 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002316 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002317 }
2318 }
2319 return 0;
2320}
2321
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002322#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002323
Roland McGratheb9e2e82009-06-02 16:49:22 -07002324static int
2325trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002326{
2327 int pid;
2328 int wait_errno;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002329 int status, sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330 struct tcb *tcp;
2331#ifdef LINUX
2332 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002333 struct rusage *rup = cflag ? &ru : NULL;
2334# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002335 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002336# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337#endif /* LINUX */
2338
Roland McGratheb9e2e82009-06-02 16:49:22 -07002339 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002340 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002341 return 0;
2342 if (interactive)
2343 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002344#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002345# ifdef __WALL
2346 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002347 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002348 /* this kernel does not support __WALL */
2349 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002350 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002351 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002352 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002353 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002354 pid = wait4(-1, &status, __WCLONE, rup);
2355 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002356 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002357 }
2358 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002359# else
2360 pid = wait4(-1, &status, 0, rup);
2361# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002362#endif /* LINUX */
2363#ifdef SUNOS4
2364 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002365#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002366 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002367 if (interactive)
2368 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002369
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002370 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002371 switch (wait_errno) {
2372 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002373 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002374 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002375 /*
2376 * We would like to verify this case
2377 * but sometimes a race in Solbourne's
2378 * version of SunOS sometimes reports
2379 * ECHILD before sending us SIGCHILD.
2380 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002381 return 0;
2382 default:
2383 errno = wait_errno;
2384 perror("strace: wait");
2385 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386 }
2387 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002388 if (pid == popen_pid) {
2389 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002390 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002391 continue;
2392 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002393 if (debug) {
2394 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2395#ifdef LINUX
2396 unsigned ev = (unsigned)status >> 16;
2397 if (ev) {
2398 static const char *const event_names[] = {
2399 [PTRACE_EVENT_CLONE] = "CLONE",
2400 [PTRACE_EVENT_FORK] = "FORK",
2401 [PTRACE_EVENT_VFORK] = "VFORK",
2402 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2403 [PTRACE_EVENT_EXEC] = "EXEC",
2404 [PTRACE_EVENT_EXIT] = "EXIT",
2405 };
2406 const char *e;
2407 if (ev < ARRAY_SIZE(event_names))
2408 e = event_names[ev];
2409 else {
2410 sprintf(buf, "?? (%u)", ev);
2411 e = buf;
2412 }
2413 fprintf(stderr, " PTRACE_EVENT_%s", e);
2414 }
2415#endif
2416 strcpy(buf, "???");
2417 if (WIFSIGNALED(status))
2418#ifdef WCOREDUMP
2419 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2420 WCOREDUMP(status) ? "core," : "",
2421 signame(WTERMSIG(status)));
2422#else
2423 sprintf(buf, "WIFSIGNALED,sig=%s",
2424 signame(WTERMSIG(status)));
2425#endif
2426 if (WIFEXITED(status))
2427 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2428 if (WIFSTOPPED(status))
2429 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002430#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002431 if (WIFCONTINUED(status))
2432 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002433#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002434 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2435 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002436
2437 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002438 tcp = pid2tcb(pid);
2439 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002440#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002441 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002442 /* This is needed to go with the CLONE_PTRACE
2443 changes in process.c/util.c: we might see
2444 the child's initial trap before we see the
2445 parent return from the clone syscall.
2446 Leave the child suspended until the parent
2447 returns from its system call. Only then
2448 will we have the association of parent and
2449 child so that we know how to do clearbpt
2450 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002451 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002452 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002453 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002454 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002455 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002456 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002457 else
2458 /* This can happen if a clone call used
2459 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002460#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002461 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002462 if (WIFSTOPPED(status))
2463 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002464 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002465 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002466 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002467 /* set current output file */
2468 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002469 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002470#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002471 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2473 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002474 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002475#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002476
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002477 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002478 if (pid == strace_child)
2479 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002480 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002481 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2482 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002483#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002484 tprintf("+++ killed by %s %s+++",
2485 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002486 WCOREDUMP(status) ? "(core dumped) " : "");
2487#else
2488 tprintf("+++ killed by %s +++",
2489 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002490#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002491 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002492 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002493 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002494 droptcb(tcp);
2495 continue;
2496 }
2497 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002498 if (pid == strace_child)
2499 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002500 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002501 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002502 tprintf(" <unfinished ... exit status %d>\n",
2503 WEXITSTATUS(status));
2504 tcp_last = NULL;
2505 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002506 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2507 printleader(tcp);
2508 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2509 printtrailer();
2510 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002511 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002512 droptcb(tcp);
2513 continue;
2514 }
2515 if (!WIFSTOPPED(status)) {
2516 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2517 droptcb(tcp);
2518 continue;
2519 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002520
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002521 /* Is this the very first time we see this tracee stopped? */
2522 if (tcp->flags & TCB_STARTUP) {
2523 if (debug)
2524 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002525 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002526 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002527 /*
2528 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002529 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002530 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002531 if (clearbpt(tcp) < 0) {
2532 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002533 droptcb(tcp);
2534 cleanup();
2535 return -1;
2536 }
2537 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002538#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002539 if (ptrace_setoptions) {
2540 if (debug)
2541 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2542 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2543 if (errno != ESRCH) {
2544 /* Should never happen, really */
2545 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002546 }
2547 }
2548 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002549#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002550 }
2551
2552 if (((unsigned)status >> 16) != 0) {
2553 /* Ptrace event (we ignore all of them for now) */
2554 goto restart_tracee_with_sig_0;
2555 }
2556
2557 sig = WSTOPSIG(status);
2558
2559 /* Is this post-attach SIGSTOP?
2560 * Interestingly, the process may stop
2561 * with STOPSIG equal to some other signal
2562 * than SIGSTOP if we happend to attach
2563 * just before the process takes a signal.
2564 */
2565 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2566 if (debug)
2567 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2568 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002569 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002570 }
2571
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002572 if (sig != syscall_trap_sig) {
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002573 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002574 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002575 siginfo_t si;
2576#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002577 long pc = 0;
2578 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002579
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002580 upeek(tcp, PT_CR_IPSR, &psr);
2581 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002582
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002583# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002584 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002585# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002586# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002587#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002588# define PC_FORMAT_STR ""
2589# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002590#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002591 printleader(tcp);
Dmitry V. Levin436d8922011-11-29 00:15:59 +00002592 if (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002593 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002594 printsiginfo(&si, verbose(tcp));
2595 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002596 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002597 PC_FORMAT_ARG);
2598 } else
2599 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002600 strsignal(sig),
2601 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002602 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002603 printtrailer();
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002604 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002606 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002607 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002608
2609 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002610 if (interrupted)
2611 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002612
2613 /* This should be syscall entry or exit.
2614 * (Or it still can be that pesky post-execve SIGTRAP!)
2615 * Handle it.
2616 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002617 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2618 /* ptrace() failed in trace_syscall() with ESRCH.
2619 * Likely a result of process disappearing mid-flight.
2620 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002621 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002622 */
2623 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002624 if (tcp_last) {
2625 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002626 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002627 */
2628 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002629 tprints(" <unfinished ...>");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002630 printtrailer();
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002631 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002632 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002633 /* We assume that ptrace error was caused by process death.
2634 * We used to detach(tcp) here, but since we no longer
2635 * implement "detach before death" policy/hack,
2636 * we can let this process to report its death to us
2637 * normally, via WIFEXITED or WIFSIGNALED wait status.
2638 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002639 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002640 /* It's our real child (and we also trace it) */
2641 /* my_tkill(pid, SIGKILL); - why? */
2642 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002643 }
2644 continue;
2645 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002646 restart_tracee_with_sig_0:
2647 sig = 0;
2648 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002649 /* Remember current print column before continuing. */
2650 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002651 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002652 cleanup();
2653 return -1;
2654 }
2655 }
2656 return 0;
2657}
2658
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002659#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002660
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002662tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002663{
2664 va_list args;
2665
Andreas Schwabe5355de2009-10-27 16:56:43 +01002666 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002667 if (outf) {
2668 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002669 if (n < 0) {
2670 if (outf != stderr)
2671 perror(outfname == NULL
2672 ? "<writing to pipe>" : outfname);
2673 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002674 curcol += n;
2675 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002676 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002677}
2678
2679void
2680tprints(const char *str)
2681{
2682 if (outf) {
2683 int n = fputs(str, outf);
2684 if (n >= 0) {
2685 curcol += strlen(str);
2686 return;
2687 }
2688 if (outf != stderr)
2689 perror(outfname == NULL
2690 ? "<writing to pipe>" : outfname);
2691 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002692}
2693
2694void
Denys Vlasenko12014262011-05-30 14:00:14 +02002695printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002696{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002697 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002698 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002699 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002700 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002701 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002702 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002703 tprints("= ? <unavailable>\n");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002704 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002705 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002706 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002707 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002708 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002709 }
2710 curcol = 0;
2711 if ((followfork == 1 || pflag_seen > 1) && outfname)
2712 tprintf("%-5d ", tcp->pid);
2713 else if (nprocs > 1 && !outfname)
2714 tprintf("[pid %5u] ", tcp->pid);
2715 if (tflag) {
2716 char str[sizeof("HH:MM:SS")];
2717 struct timeval tv, dtv;
2718 static struct timeval otv;
2719
2720 gettimeofday(&tv, NULL);
2721 if (rflag) {
2722 if (otv.tv_sec == 0)
2723 otv = tv;
2724 tv_sub(&dtv, &tv, &otv);
2725 tprintf("%6ld.%06ld ",
2726 (long) dtv.tv_sec, (long) dtv.tv_usec);
2727 otv = tv;
2728 }
2729 else if (tflag > 2) {
2730 tprintf("%ld.%06ld ",
2731 (long) tv.tv_sec, (long) tv.tv_usec);
2732 }
2733 else {
2734 time_t local = tv.tv_sec;
2735 strftime(str, sizeof(str), "%T", localtime(&local));
2736 if (tflag > 1)
2737 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2738 else
2739 tprintf("%s ", str);
2740 }
2741 }
2742 if (iflag)
2743 printcall(tcp);
2744}
2745
2746void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002747tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002748{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002749 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002750 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002751}
2752
2753void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002754printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002755{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002756 tprints("\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002757 tcp_last = NULL;
2758}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002759
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002760#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002761
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002762int
2763mp_ioctl(int fd, int cmd, void *arg, int size)
2764{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002765 struct iovec iov[2];
2766 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002767
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002768 iov[0].iov_base = &cmd;
2769 iov[0].iov_len = sizeof cmd;
2770 if (arg) {
2771 ++n;
2772 iov[1].iov_base = arg;
2773 iov[1].iov_len = size;
2774 }
Roland McGrath553a6092002-12-16 20:40:39 +00002775
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002776 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002777}
2778
2779#endif