blob: 745294dd3a8341bf81da804f5dc5458d375d7888 [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;
235 vasprintf(&msg, fmt, p);
236 if (msg) {
237 if (err_no)
238 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
239 else
240 fprintf(stderr, "%s: %s\n", progname, msg);
241 free(msg);
242 } else {
243 /* malloc in vasprintf failed, try it without malloc */
244 fprintf(stderr, "%s: ", progname);
245 vfprintf(stderr, fmt, p);
246 if (err_no)
247 fprintf(stderr, ": %s\n", strerror(err_no));
248 else
249 putc('\n', stderr);
250 }
251 /* We don't switch stderr to buffered, thus fprintf(stderr)
252 * always flushes its output and this is not necessary: */
253 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200254}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200255
Denys Vlasenko75422762011-05-27 14:36:01 +0200256void error_msg(const char *fmt, ...)
257{
258 va_list p;
259 va_start(p, fmt);
260 verror_msg(0, fmt, p);
261 va_end(p);
262}
263
264void error_msg_and_die(const char *fmt, ...)
265{
266 va_list p;
267 va_start(p, fmt);
268 verror_msg(0, fmt, p);
269 die();
270}
271
272void perror_msg(const char *fmt, ...)
273{
274 va_list p;
275 va_start(p, fmt);
276 verror_msg(errno, fmt, p);
277 va_end(p);
278}
279
280void perror_msg_and_die(const char *fmt, ...)
281{
282 va_list p;
283 va_start(p, fmt);
284 verror_msg(errno, fmt, p);
285 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200286}
287
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200288void die_out_of_memory(void)
289{
290 static bool recursed = 0;
291 if (recursed)
292 exit(1);
293 recursed = 1;
294 error_msg_and_die("Out of memory");
295}
296
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000297#ifdef SVR4
298#ifdef MIPS
299void
300foobar()
301{
302}
303#endif /* MIPS */
304#endif /* SVR4 */
305
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400306/* Glue for systems without a MMU that cannot provide fork() */
307#ifdef HAVE_FORK
308# define strace_vforked 0
309#else
310# define strace_vforked 1
311# define fork() vfork()
312#endif
313
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200314static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000315set_cloexec_flag(int fd)
316{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200317 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000318
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200319 flags = fcntl(fd, F_GETFD);
320 if (flags < 0) {
321 /* Can happen only if fd is bad.
322 * Should never happen: if it does, we have a bug
323 * in the caller. Therefore we just abort
324 * instead of propagating the error.
325 */
326 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000327 }
328
329 newflags = flags | FD_CLOEXEC;
330 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200331 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000332
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200333 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000334}
335
336/*
337 * When strace is setuid executable, we have to swap uids
338 * before and after filesystem and process management operations.
339 */
340static void
341swap_uid(void)
342{
343#ifndef SVR4
344 int euid = geteuid(), uid = getuid();
345
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200346 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200347 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000348 }
349#endif
350}
351
Roland McGrath4bfa6262007-07-05 20:03:16 +0000352#if _LFS64_LARGEFILE
353# define fopen_for_output fopen64
354#else
355# define fopen_for_output fopen
356#endif
357
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000358static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200359strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360{
361 FILE *fp;
362
363 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200364 fp = fopen_for_output(path, "w");
365 if (!fp)
366 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000367 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200368 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000369 return fp;
370}
371
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200372static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000373
374#ifndef _PATH_BSHELL
375# define _PATH_BSHELL "/bin/sh"
376#endif
377
378/*
379 * We cannot use standard popen(3) here because we have to distinguish
380 * popen child process from other processes we trace, and standard popen(3)
381 * does not export its child's pid.
382 */
383static FILE *
384strace_popen(const char *command)
385{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200386 FILE *fp;
387 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000388
389 swap_uid();
390 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200391 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000392
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200393 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000394
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200395 popen_pid = vfork();
396 if (popen_pid == -1)
397 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000398
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200399 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400 /* child */
401 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200402 if (fds[0] != 0) {
403 if (dup2(fds[0], 0))
404 perror_msg_and_die("dup2");
405 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000406 }
407 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200408 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000409 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200410
411 /* parent */
412 close(fds[0]);
413 swap_uid();
414 fp = fdopen(fds[1], "w");
415 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200416 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200417 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000418}
419
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200420static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000421newoutf(struct tcb *tcp)
422{
423 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000424 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000425 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200426 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000427 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000428}
429
Roland McGrath02203312007-06-11 22:06:31 +0000430static void
431startup_attach(void)
432{
433 int tcbi;
434 struct tcb *tcp;
435
436 /*
437 * Block user interruptions as we would leave the traced
438 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200439 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200440 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000441 */
442 if (interactive)
443 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
444
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000445 if (daemonized_tracer) {
446 pid_t pid = fork();
447 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200448 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000449 }
450 if (pid) { /* parent */
451 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200452 * Wait for grandchild to attach to straced process
453 * (grandparent). Grandchild SIGKILLs us after it attached.
454 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000455 * it proceeds to exec the straced program.
456 */
457 pause();
458 _exit(0); /* paranoia */
459 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200460 /* grandchild */
461 /* We will be the tracer process. Remember our new pid: */
462 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000463 }
464
Roland McGrath02203312007-06-11 22:06:31 +0000465 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
466 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200467
Denys Vlasenkod116a732011-09-05 14:01:33 +0200468 /* Is this a process we should attach to, but not yet attached? */
469 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
470 continue; /* no */
471
472 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000473 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200474 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000475
476#ifdef USE_PROCFS
477 if (proc_open(tcp, 1) < 0) {
478 fprintf(stderr, "trouble opening proc file\n");
479 droptcb(tcp);
480 continue;
481 }
482#else /* !USE_PROCFS */
483# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000484 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000485 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000486 DIR *dir;
487
488 sprintf(procdir, "/proc/%d/task", tcp->pid);
489 dir = opendir(procdir);
490 if (dir != NULL) {
491 unsigned int ntid = 0, nerr = 0;
492 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200493
Roland McGrath02203312007-06-11 22:06:31 +0000494 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200495 struct tcb *cur_tcp;
496 int tid;
497
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000498 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000499 continue;
500 tid = atoi(de->d_name);
501 if (tid <= 0)
502 continue;
503 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200504 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000505 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200506 if (debug)
507 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200508 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200509 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200510 if (debug)
511 fprintf(stderr, "attach to pid %d succeeded\n", tid);
512 cur_tcp = tcp;
513 if (tid != tcp->pid)
514 cur_tcp = alloctcb(tid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200515 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrath02203312007-06-11 22:06:31 +0000516 }
517 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200518 if (interactive) {
519 sigprocmask(SIG_SETMASK, &empty_set, NULL);
520 if (interrupted)
521 goto ret;
522 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
523 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000524 ntid -= nerr;
525 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000526 perror("attach: ptrace(PTRACE_ATTACH, ...)");
527 droptcb(tcp);
528 continue;
529 }
530 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000531 fprintf(stderr, ntid > 1
532? "Process %u attached with %u threads - interrupt to quit\n"
533: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200534 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000535 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200536 if (!(tcp->flags & TCB_STARTUP)) {
537 /* -p PID, we failed to attach to PID itself
538 * but did attach to some of its sibling threads.
539 * Drop PID's tcp.
540 */
541 droptcb(tcp);
542 }
Roland McGrath02203312007-06-11 22:06:31 +0000543 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000544 } /* if (opendir worked) */
545 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200546# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000547 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
548 perror("attach: ptrace(PTRACE_ATTACH, ...)");
549 droptcb(tcp);
550 continue;
551 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200552 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200553 if (debug)
554 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000555
556 if (daemonized_tracer) {
557 /*
558 * It is our grandparent we trace, not a -p PID.
559 * Don't want to just detach on exit, so...
560 */
561 tcp->flags &= ~TCB_ATTACHED;
562 /*
563 * Make parent go away.
564 * Also makes grandparent's wait() unblock.
565 */
566 kill(getppid(), SIGKILL);
567 }
568
Roland McGrath02203312007-06-11 22:06:31 +0000569#endif /* !USE_PROCFS */
570 if (!qflag)
571 fprintf(stderr,
572 "Process %u attached - interrupt to quit\n",
573 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200574 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000575
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200576 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000577 if (interactive)
578 sigprocmask(SIG_SETMASK, &empty_set, NULL);
579}
580
581static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200582startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000583{
584 struct stat statbuf;
585 const char *filename;
586 char pathname[MAXPATHLEN];
587 int pid = 0;
588 struct tcb *tcp;
589
590 filename = argv[0];
591 if (strchr(filename, '/')) {
592 if (strlen(filename) > sizeof pathname - 1) {
593 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200594 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000595 }
596 strcpy(pathname, filename);
597 }
598#ifdef USE_DEBUGGING_EXEC
599 /*
600 * Debuggers customarily check the current directory
601 * first regardless of the path but doing that gives
602 * security geeks a panic attack.
603 */
604 else if (stat(filename, &statbuf) == 0)
605 strcpy(pathname, filename);
606#endif /* USE_DEBUGGING_EXEC */
607 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000608 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000609 int m, n, len;
610
611 for (path = getenv("PATH"); path && *path; path += m) {
612 if (strchr(path, ':')) {
613 n = strchr(path, ':') - path;
614 m = n + 1;
615 }
616 else
617 m = n = strlen(path);
618 if (n == 0) {
619 if (!getcwd(pathname, MAXPATHLEN))
620 continue;
621 len = strlen(pathname);
622 }
623 else if (n > sizeof pathname - 1)
624 continue;
625 else {
626 strncpy(pathname, path, n);
627 len = n;
628 }
629 if (len && pathname[len - 1] != '/')
630 pathname[len++] = '/';
631 strcpy(pathname + len, filename);
632 if (stat(pathname, &statbuf) == 0 &&
633 /* Accept only regular files
634 with some execute bits set.
635 XXX not perfect, might still fail */
636 S_ISREG(statbuf.st_mode) &&
637 (statbuf.st_mode & 0111))
638 break;
639 }
640 }
641 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200642 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000643 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000644 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000645 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200646 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000647 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200648 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
649 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000650 ) {
651 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200652 if (outf != stderr)
653 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000654#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200655# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000656 /* Kludge for SGI, see proc_open for details. */
657 sa.sa_handler = foobar;
658 sa.sa_flags = 0;
659 sigemptyset(&sa.sa_mask);
660 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200661# endif
662# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000663 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200664# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200665 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200666# endif
Roland McGrath02203312007-06-11 22:06:31 +0000667#else /* !USE_PROCFS */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000668 if (!daemonized_tracer) {
669 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200670 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000671 }
672 if (debug)
673 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000674 }
Roland McGrath02203312007-06-11 22:06:31 +0000675
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200676 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000677 uid_t run_euid = run_uid;
678 gid_t run_egid = run_gid;
679
680 if (statbuf.st_mode & S_ISUID)
681 run_euid = statbuf.st_uid;
682 if (statbuf.st_mode & S_ISGID)
683 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000684 /*
685 * It is important to set groups before we
686 * lose privileges on setuid.
687 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200688 if (initgroups(username, run_gid) < 0) {
689 perror_msg_and_die("initgroups");
690 }
691 if (setregid(run_gid, run_egid) < 0) {
692 perror_msg_and_die("setregid");
693 }
694 if (setreuid(run_uid, run_euid) < 0) {
695 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000696 }
697 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200698 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000699 setreuid(run_uid, run_uid);
700
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000701 if (!daemonized_tracer) {
702 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200703 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000704 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200705 * the immediately following execve syscall.
706 * Can't do this on NOMMU systems, we are after
707 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400709 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200710 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000711 } else {
712 struct sigaction sv_sigchld;
713 sigaction(SIGCHLD, NULL, &sv_sigchld);
714 /*
715 * Make sure it is not SIG_IGN, otherwise wait
716 * will not block.
717 */
718 signal(SIGCHLD, SIG_DFL);
719 /*
720 * Wait for grandchild to attach to us.
721 * It kills child after that, and wait() unblocks.
722 */
723 alarm(3);
724 wait(NULL);
725 alarm(0);
726 sigaction(SIGCHLD, &sv_sigchld, NULL);
727 }
Roland McGrath02203312007-06-11 22:06:31 +0000728#endif /* !USE_PROCFS */
729
730 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200731 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000732 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000733
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200734 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200735
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200736 if (!daemonized_tracer) {
737 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200738 if (!strace_vforked)
739 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
740 else
741 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200742 }
743 else {
744 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
745 strace_tracer_pid = getpid();
746 /* The tracee is our parent: */
747 pid = getppid();
748 tcp = alloctcb(pid);
749 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000750 tcp->flags |= TCB_ATTACHED;
751 }
Roland McGrath02203312007-06-11 22:06:31 +0000752#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000753 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200754 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000755 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200756#endif
Roland McGrath02203312007-06-11 22:06:31 +0000757}
758
Wang Chaob13c0de2010-11-12 17:25:19 +0800759#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000760static void kill_save_errno(pid_t pid, int sig)
761{
762 int saved_errno = errno;
763
764 (void) kill(pid, sig);
765 errno = saved_errno;
766}
767
Wang Chaob13c0de2010-11-12 17:25:19 +0800768/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000769 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800770 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000771 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800772 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000773static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200774test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800775{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000776 int pid, expected_grandchild = 0, found_grandchild = 0;
777 const unsigned int test_options = PTRACE_O_TRACECLONE |
778 PTRACE_O_TRACEFORK |
779 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800780
Denys Vlasenko5d645812011-08-20 12:48:18 +0200781 pid = fork();
782 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000783 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200784 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000785 pid = getpid();
786 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
787 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
788 __func__);
789 kill(pid, SIGSTOP);
790 if (fork() < 0)
791 perror_msg_and_die("fork");
792 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800793 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000794
795 while (1) {
796 int status, tracee_pid;
797
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000798 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000799 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000800 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000801 if (errno == EINTR)
802 continue;
803 else if (errno == ECHILD)
804 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000805 kill_save_errno(pid, SIGKILL);
806 perror_msg_and_die("%s: unexpected wait result %d",
807 __func__, tracee_pid);
808 }
809 if (WIFEXITED(status)) {
810 if (WEXITSTATUS(status)) {
811 if (tracee_pid != pid)
812 kill_save_errno(pid, SIGKILL);
813 error_msg_and_die("%s: unexpected exit status %u",
814 __func__, WEXITSTATUS(status));
815 }
816 continue;
817 }
818 if (WIFSIGNALED(status)) {
819 if (tracee_pid != pid)
820 kill_save_errno(pid, SIGKILL);
821 error_msg_and_die("%s: unexpected signal %u",
822 __func__, WTERMSIG(status));
823 }
824 if (!WIFSTOPPED(status)) {
825 if (tracee_pid != pid)
826 kill_save_errno(tracee_pid, SIGKILL);
827 kill(pid, SIGKILL);
828 error_msg_and_die("%s: unexpected wait status %x",
829 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000830 }
831 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000832 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000833 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
834 kill_save_errno(tracee_pid, SIGKILL);
835 kill_save_errno(pid, SIGKILL);
836 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800837 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000838 continue;
839 }
840 switch (WSTOPSIG(status)) {
841 case SIGSTOP:
842 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
843 && errno != EINVAL && errno != EIO)
844 perror_msg("PTRACE_SETOPTIONS");
845 break;
846 case SIGTRAP:
847 if (status >> 16 == PTRACE_EVENT_FORK) {
848 long msg = 0;
849
850 if (ptrace(PTRACE_GETEVENTMSG, pid,
851 NULL, (long) &msg) == 0)
852 expected_grandchild = msg;
853 }
854 break;
855 }
856 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
857 kill_save_errno(pid, SIGKILL);
858 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800859 }
860 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000861 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200862 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000863 if (debug)
864 fprintf(stderr, "ptrace_setoptions = %#x\n",
865 ptrace_setoptions);
866 return;
867 }
868 error_msg("Test for PTRACE_O_TRACECLONE failed, "
869 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800870}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200871
872/*
873 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
874 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
875 * and then see whether it will stop with (SIGTRAP | 0x80).
876 *
877 * Use of this option enables correct handling of user-generated SIGTRAPs,
878 * and SIGTRAPs generated by special instructions such as int3 on x86:
879 * _start: .globl _start
880 * int3
881 * movl $42, %ebx
882 * movl $1, %eax
883 * int $0x80
884 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
885 */
886static void
887test_ptrace_setoptions_for_all(void)
888{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000889 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
890 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200891 int pid;
892 int it_worked = 0;
893
894 pid = fork();
895 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200896 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200897
898 if (pid == 0) {
899 pid = getpid();
900 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200901 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000902 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
903 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200904 kill(pid, SIGSTOP);
905 _exit(0); /* parent should see entry into this syscall */
906 }
907
908 while (1) {
909 int status, tracee_pid;
910
911 errno = 0;
912 tracee_pid = wait(&status);
913 if (tracee_pid <= 0) {
914 if (errno == EINTR)
915 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000916 kill_save_errno(pid, SIGKILL);
917 perror_msg_and_die("%s: unexpected wait result %d",
918 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200919 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200920 if (WIFEXITED(status)) {
921 if (WEXITSTATUS(status) == 0)
922 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000923 error_msg_and_die("%s: unexpected exit status %u",
924 __func__, WEXITSTATUS(status));
925 }
926 if (WIFSIGNALED(status)) {
927 error_msg_and_die("%s: unexpected signal %u",
928 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200929 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200930 if (!WIFSTOPPED(status)) {
931 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000932 error_msg_and_die("%s: unexpected wait status %x",
933 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200934 }
935 if (WSTOPSIG(status) == SIGSTOP) {
936 /*
937 * We don't check "options aren't accepted" error.
938 * If it happens, we'll never get (SIGTRAP | 0x80),
939 * and thus will decide to not use the option.
940 * IOW: the outcome of the test will be correct.
941 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000942 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
943 && errno != EINVAL && errno != EIO)
944 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200945 }
946 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
947 it_worked = 1;
948 }
949 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000950 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200951 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200952 }
953 }
954
955 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200956 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200957 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200958 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200959 fprintf(stderr, "ptrace_setoptions = %#x\n",
960 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200961 return;
962 }
963
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000964 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
965 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200966}
Wang Chaob13c0de2010-11-12 17:25:19 +0800967#endif
968
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000970main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 struct tcb *tcp;
973 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000974 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 struct sigaction sa;
976
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000977 progname = argv[0] ? argv[0] : "strace";
978
Denys Vlasenko75422762011-05-27 14:36:01 +0200979 strace_tracer_pid = getpid();
980
Roland McGrathee9d4352002-12-18 04:16:10 +0000981 /* Allocate the initial tcbtab. */
982 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200983 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200984 if (!tcbtab)
985 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200986 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200987 if (!tcp)
988 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200989 for (c = 0; c < tcbtabsize; c++)
990 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000991
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +0000993 set_sortby(DEFAULT_SORTBY);
994 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995 qualify("trace=all");
996 qualify("abbrev=all");
997 qualify("verbose=all");
998 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001000 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001001#ifndef USE_PROCFS
1002 "D"
1003#endif
Grant Edwards8a082772011-04-07 20:25:40 +00001004 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 switch (c) {
1006 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001007 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001008 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001009 }
1010 cflag = CFLAG_ONLY_STATS;
1011 break;
1012 case 'C':
1013 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001014 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001015 }
1016 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 break;
1018 case 'd':
1019 debug++;
1020 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001021#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001022 case 'D':
1023 daemonized_tracer = 1;
1024 break;
1025#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001026 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001027 optF = 1;
1028 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 case 'f':
1030 followfork++;
1031 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 case 'h':
1033 usage(stdout, 0);
1034 break;
1035 case 'i':
1036 iflag++;
1037 break;
1038 case 'q':
1039 qflag++;
1040 break;
1041 case 'r':
1042 rflag++;
1043 tflag++;
1044 break;
1045 case 't':
1046 tflag++;
1047 break;
1048 case 'T':
1049 dtime++;
1050 break;
1051 case 'x':
1052 xflag++;
1053 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001054 case 'y':
1055 show_fd_path = 1;
1056 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 case 'v':
1058 qualify("abbrev=none");
1059 break;
1060 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001061 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 exit(0);
1063 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001064 case 'z':
1065 not_failing_only = 1;
1066 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001067 case 'a':
1068 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001069 if (acolumn < 0)
1070 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 break;
1072 case 'e':
1073 qualify(optarg);
1074 break;
1075 case 'o':
1076 outfname = strdup(optarg);
1077 break;
1078 case 'O':
1079 set_overhead(atoi(optarg));
1080 break;
1081 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001082 pid = atoi(optarg);
1083 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001084 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085 break;
1086 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001087 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001088 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001089 break;
1090 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001091 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092 tcp->flags |= TCB_ATTACHED;
1093 pflag_seen++;
1094 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001095 case 'P':
1096 tracing_paths = 1;
1097 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001098 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001099 }
1100 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101 case 's':
1102 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001103 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001104 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001105 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106 break;
1107 case 'S':
1108 set_sortby(optarg);
1109 break;
1110 case 'u':
1111 username = strdup(optarg);
1112 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001113 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001114 if (putenv(optarg) < 0)
1115 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001116 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 default:
1118 usage(stderr, 1);
1119 break;
1120 }
1121 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001122 argv += optind;
1123 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124
Denys Vlasenko102ec492011-08-25 01:27:59 +02001125 acolumn_spaces = malloc(acolumn + 1);
1126 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001127 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001128 memset(acolumn_spaces, ' ', acolumn);
1129 acolumn_spaces[acolumn] = '\0';
1130
Denys Vlasenko837399a2012-01-24 11:37:03 +01001131 /* Must have PROG [ARGS], or -p PID. Not both. */
1132 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001133 usage(stderr, 1);
1134
Wang Chaod322a4b2010-08-05 14:30:11 +08001135 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001136 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001137 }
1138
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001139 if (!followfork)
1140 followfork = optF;
1141
Roland McGrathcb9def62006-04-25 07:48:03 +00001142 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001143 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001144 }
1145
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 /* See if they want to run as another user. */
1147 if (username != NULL) {
1148 struct passwd *pent;
1149
1150 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001151 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001153 pent = getpwnam(username);
1154 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001155 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 }
1157 run_uid = pent->pw_uid;
1158 run_gid = pent->pw_gid;
1159 }
1160 else {
1161 run_uid = getuid();
1162 run_gid = getgid();
1163 }
1164
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001165#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001166 if (followfork)
1167 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001168 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001169#endif
1170
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171 /* Check if they want to redirect the output. */
1172 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001173 /* See if they want to pipe the output. */
1174 if (outfname[0] == '|' || outfname[0] == '!') {
1175 /*
1176 * We can't do the <outfname>.PID funny business
1177 * when using popen, so prohibit it.
1178 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001179 if (followfork > 1)
1180 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1181 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001182 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001183 else if (followfork <= 1)
1184 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 }
1186
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001187 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001188 char *buf = malloc(BUFSIZ);
1189 if (!buf)
1190 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001192 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001193 if (outfname && argv[0]) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001196 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001197
Roland McGrath54cc1c82007-11-03 23:34:11 +00001198 /* Valid states here:
Denys Vlasenko837399a2012-01-24 11:37:03 +01001199 argv[0] pflag_seen outfname interactive
1200 yes 0 0 1
1201 no 1 0 1
1202 yes 0 1 0
1203 no 1 1 1
Roland McGrath54cc1c82007-11-03 23:34:11 +00001204 */
1205
1206 /* STARTUP_CHILD must be called before the signal handlers get
1207 installed below as they are inherited into the spawned process.
1208 Also we do not need to be protected by them as during interruption
1209 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001210 if (argv[0])
1211 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213 sigemptyset(&empty_set);
1214 sigemptyset(&blocked_set);
1215 sa.sa_handler = SIG_IGN;
1216 sigemptyset(&sa.sa_mask);
1217 sa.sa_flags = 0;
1218 sigaction(SIGTTOU, &sa, NULL);
1219 sigaction(SIGTTIN, &sa, NULL);
Denys Vlasenko837399a2012-01-24 11:37:03 +01001220 /* In interactive mode (if no -o OUTFILE, or -p PID is used),
1221 * fatal signals are blocked across syscall waits, and acted on
1222 * in between. In non-interactive mode, signals are ignored.
1223 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 if (interactive) {
1225 sigaddset(&blocked_set, SIGHUP);
1226 sigaddset(&blocked_set, SIGINT);
1227 sigaddset(&blocked_set, SIGQUIT);
1228 sigaddset(&blocked_set, SIGPIPE);
1229 sigaddset(&blocked_set, SIGTERM);
1230 sa.sa_handler = interrupt;
1231#ifdef SUNOS4
1232 /* POSIX signals on sunos4.1 are a little broken. */
1233 sa.sa_flags = SA_INTERRUPT;
1234#endif /* SUNOS4 */
1235 }
1236 sigaction(SIGHUP, &sa, NULL);
1237 sigaction(SIGINT, &sa, NULL);
1238 sigaction(SIGQUIT, &sa, NULL);
1239 sigaction(SIGPIPE, &sa, NULL);
1240 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001241#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 sa.sa_handler = reaper;
1243 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001244#else
1245 /* Make sure SIGCHLD has the default action so that waitpid
1246 definitely works without losing track of children. The user
1247 should not have given us a bogus state to inherit, but he might
1248 have. Arguably we should detect SIG_IGN here and pass it on
1249 to children, but probably noone really needs that. */
1250 sa.sa_handler = SIG_DFL;
1251 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001252#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001254 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001255 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001256
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257 if (trace() < 0)
1258 exit(1);
1259 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001260 fflush(NULL);
1261 if (exit_code > 0xff) {
1262 /* Child was killed by a signal, mimic that. */
1263 exit_code &= 0xff;
1264 signal(exit_code, SIG_DFL);
1265 raise(exit_code);
1266 /* Paranoia - what if this signal is not fatal?
1267 Exit with 128 + signo then. */
1268 exit_code += 128;
1269 }
1270 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271}
1272
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001273static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001274expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001275{
1276 /* Allocate some more TCBs and expand the table.
1277 We don't want to relocate the TCBs because our
1278 callers have pointers and it would be a pain.
1279 So tcbtab is a table of pointers. Since we never
1280 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001281 int i = tcbtabsize;
1282 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1283 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001284 if (!newtab || !newtcbs)
1285 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001286 tcbtabsize *= 2;
1287 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001288 while (i < tcbtabsize)
1289 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001290}
1291
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001293alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294{
1295 int i;
1296 struct tcb *tcp;
1297
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001298 if (nprocs == tcbtabsize)
1299 expand_tcbtab();
1300
Roland McGrathee9d4352002-12-18 04:16:10 +00001301 for (i = 0; i < tcbtabsize; i++) {
1302 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001303 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001304 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001306 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001308#if SUPPORTED_PERSONALITIES > 1
1309 tcp->currpers = current_personality;
1310#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001311#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001312 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001313#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001315 if (debug)
1316 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001317 if (command_options_parsed)
1318 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 return tcp;
1320 }
1321 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001322 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323}
1324
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001325#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001327proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328{
1329 char proc[32];
1330 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001331#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001332 int i;
1333 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334 sigset_t signals;
1335 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001336#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337#ifndef HAVE_POLLABLE_PROCFS
1338 static int last_pfd;
1339#endif
1340
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001341#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001342 /* Open the process pseudo-files in /proc. */
1343 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001344 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1345 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346 perror("strace: open(\"/proc/...\", ...)");
1347 return -1;
1348 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001349 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001350 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001351 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1352 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001353 perror("strace: open(\"/proc/...\", ...)");
1354 return -1;
1355 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001356 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001357 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001358 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1359 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001360 perror("strace: open(\"/proc/...\", ...)");
1361 return -1;
1362 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001363 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001364#else
1365 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001366# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001367 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001368 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001369# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001370 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001371 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001372# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001373 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001374 perror("strace: open(\"/proc/...\", ...)");
1375 return -1;
1376 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001377 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001378#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001379#ifdef FREEBSD
1380 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001381 tcp->pfd_reg = open(proc, O_RDONLY);
1382 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001383 perror("strace: open(\"/proc/.../regs\", ...)");
1384 return -1;
1385 }
1386 if (cflag) {
1387 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001388 tcp->pfd_status = open(proc, O_RDONLY);
1389 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001390 perror("strace: open(\"/proc/.../status\", ...)");
1391 return -1;
1392 }
1393 } else
1394 tcp->pfd_status = -1;
1395#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001396 rebuild_pollv();
1397 if (!attaching) {
1398 /*
1399 * Wait for the child to pause. Because of a race
1400 * condition we have to poll for the event.
1401 */
1402 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001403 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001404 perror("strace: PIOCSTATUS");
1405 return -1;
1406 }
1407 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001408 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001409 }
1410 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001411#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001412 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001413 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001414 perror("strace: PIOCSTOP");
1415 return -1;
1416 }
Roland McGrath553a6092002-12-16 20:40:39 +00001417#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418#ifdef PIOCSET
1419 /* Set Run-on-Last-Close. */
1420 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001421 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 perror("PIOCSET PR_RLC");
1423 return -1;
1424 }
1425 /* Set or Reset Inherit-on-Fork. */
1426 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001427 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428 perror("PIOC{SET,RESET} PR_FORK");
1429 return -1;
1430 }
1431#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001432#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1434 perror("PIOCSRLC");
1435 return -1;
1436 }
1437 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1438 perror("PIOC{S,R}FORK");
1439 return -1;
1440 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001441#else /* FREEBSD */
1442 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1443 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1444 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001445 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001446 }
1447 arg &= ~PF_LINGER;
1448 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001449 perror("PIOCSFL");
1450 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001451 }
1452#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001453#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001454#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001455 /* Enable all syscall entries we care about. */
1456 premptyset(&syscalls);
1457 for (i = 1; i < MAX_QUALS; ++i) {
1458 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001459 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001460 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001461 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001462 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001463 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001464#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001465 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001466#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001467#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001468 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001469#endif
1470#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001471 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001472#endif
1473#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001474 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001475#endif
1476 }
1477 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001478 perror("PIOCSENTRY");
1479 return -1;
1480 }
John Hughes19e49982001-10-19 08:59:12 +00001481 /* Enable the syscall exits. */
1482 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 perror("PIOSEXIT");
1484 return -1;
1485 }
John Hughes19e49982001-10-19 08:59:12 +00001486 /* Enable signals we care about. */
1487 premptyset(&signals);
1488 for (i = 1; i < MAX_QUALS; ++i) {
1489 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001490 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001491 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001492 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493 perror("PIOCSTRACE");
1494 return -1;
1495 }
John Hughes19e49982001-10-19 08:59:12 +00001496 /* Enable faults we care about */
1497 premptyset(&faults);
1498 for (i = 1; i < MAX_QUALS; ++i) {
1499 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001500 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001501 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001502 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 perror("PIOCSFAULT");
1504 return -1;
1505 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001506#else /* FREEBSD */
1507 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001508 arg = S_SIG | S_SCE | S_SCX;
1509 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001510 perror("PIOCBIS");
1511 return -1;
1512 }
1513#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001514 if (!attaching) {
1515#ifdef MIPS
1516 /*
1517 * The SGI PRSABORT doesn't work for pause() so
1518 * we send it a caught signal to wake it up.
1519 */
1520 kill(tcp->pid, SIGINT);
1521#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001522#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001524 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001525 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526 perror("PIOCRUN");
1527 return -1;
1528 }
Roland McGrath553a6092002-12-16 20:40:39 +00001529#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001530#endif /* !MIPS*/
1531#ifdef FREEBSD
1532 /* wake up the child if it received the SIGSTOP */
1533 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001534#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535 for (;;) {
1536 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001537 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538 perror("PIOCWSTOP");
1539 return -1;
1540 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001541 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001542 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001543 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001544 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545 break;
1546 }
1547 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001548#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001549 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001550 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1551#else
1552 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1553#endif
1554 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555 perror("PIOCRUN");
1556 return -1;
1557 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001558#ifdef FREEBSD
1559 /* handle the case where we "opened" the child before
1560 it did the kill -STOP */
1561 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1562 tcp->status.PR_WHAT == SIGSTOP)
1563 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001564#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565 }
1566 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001567#ifdef FREEBSD
1568 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001569 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001570 /* We are attaching to an already running process.
1571 * Try to figure out the state of the process in syscalls,
1572 * to handle the first event well.
1573 * This is done by having a look at the "wchan" property of the
1574 * process, which tells where it is stopped (if it is). */
1575 FILE * status;
1576 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001577
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001578 sprintf(proc, "/proc/%d/status", tcp->pid);
1579 status = fopen(proc, "r");
1580 if (status &&
1581 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1582 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1583 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1584 strcmp(wchan, "stopevent")) {
1585 /* The process is asleep in the middle of a syscall.
1586 Fake the syscall entry event */
1587 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1588 tcp->status.PR_WHY = PR_SYSENTRY;
1589 trace_syscall(tcp);
1590 }
1591 if (status)
1592 fclose(status);
1593 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001594 }
1595#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596#ifndef HAVE_POLLABLE_PROCFS
1597 if (proc_poll_pipe[0] != -1)
1598 proc_poller(tcp->pfd);
1599 else if (nprocs > 1) {
1600 proc_poll_open();
1601 proc_poller(last_pfd);
1602 proc_poller(tcp->pfd);
1603 }
1604 last_pfd = tcp->pfd;
1605#endif /* !HAVE_POLLABLE_PROCFS */
1606 return 0;
1607}
1608
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001609#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001611struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001612pid2tcb(int pid)
1613{
1614 int i;
1615
1616 if (pid <= 0)
1617 return NULL;
1618
1619 for (i = 0; i < tcbtabsize; i++) {
1620 struct tcb *tcp = tcbtab[i];
1621 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1622 return tcp;
1623 }
1624
1625 return NULL;
1626}
1627
1628#ifdef USE_PROCFS
1629
1630static struct tcb *
1631first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632{
1633 int i;
1634 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001635 for (i = 0; i < tcbtabsize; i++) {
1636 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637 if (tcp->flags & TCB_INUSE)
1638 return tcp;
1639 }
1640 return NULL;
1641}
1642
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001644pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645{
1646 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647
Roland McGrathca16be82003-01-10 19:55:28 +00001648 for (i = 0; i < tcbtabsize; i++) {
1649 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650 if (tcp->pfd != pfd)
1651 continue;
1652 if (tcp->flags & TCB_INUSE)
1653 return tcp;
1654 }
1655 return NULL;
1656}
1657
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001658#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001659
1660void
Denys Vlasenko12014262011-05-30 14:00:14 +02001661droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662{
1663 if (tcp->pid == 0)
1664 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001665
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001667 if (debug)
1668 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001669
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001670#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671 if (tcp->pfd != -1) {
1672 close(tcp->pfd);
1673 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001674# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001675 if (tcp->pfd_reg != -1) {
1676 close(tcp->pfd_reg);
1677 tcp->pfd_reg = -1;
1678 }
1679 if (tcp->pfd_status != -1) {
1680 close(tcp->pfd_status);
1681 tcp->pfd_status = -1;
1682 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001683# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001684 tcp->flags = 0; /* rebuild_pollv needs it */
1685 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001687#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001688
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001689 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001691
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001692 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693}
1694
Roland McGrath0a463882007-07-05 18:43:16 +00001695/* detach traced process; continue with sig
1696 Never call DETACH twice on the same process as both unattached and
1697 attached-unstopped processes give the same ESRCH. For unattached process we
1698 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699
1700static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001701detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702{
1703 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001704#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001705 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001706#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707
1708 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001709 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710
1711#ifdef LINUX
1712 /*
1713 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001714 * before detaching. Arghh. We go through hoops
1715 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001717#if defined(SPARC)
1718#undef PTRACE_DETACH
1719#define PTRACE_DETACH PTRACE_SUNDETACH
1720#endif
Roland McGrath02203312007-06-11 22:06:31 +00001721 /*
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001722 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1723 * We must catch exactly one as otherwise the detached process
1724 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001725 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001726 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001727 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001728 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001730 }
1731 else if (errno != ESRCH) {
1732 /* Shouldn't happen. */
1733 perror("detach: ptrace(PTRACE_DETACH, ...)");
1734 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001735 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001736 if (errno != ESRCH)
1737 perror("detach: checking sanity");
1738 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001739 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001740 if (errno != ESRCH)
1741 perror("detach: stopping child");
1742 }
Roland McGrath02203312007-06-11 22:06:31 +00001743 else
1744 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001745 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001747#ifdef __WALL
1748 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1749 if (errno == ECHILD) /* Already gone. */
1750 break;
1751 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001752 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001753 break;
1754 }
1755#endif /* __WALL */
1756 /* No __WALL here. */
1757 if (waitpid(tcp->pid, &status, 0) < 0) {
1758 if (errno != ECHILD) {
1759 perror("detach: waiting");
1760 break;
1761 }
1762#ifdef __WCLONE
1763 /* If no processes, try clones. */
1764 if (wait4(tcp->pid, &status, __WCLONE,
1765 NULL) < 0) {
1766 if (errno != ECHILD)
1767 perror("detach: waiting");
1768 break;
1769 }
1770#endif /* __WCLONE */
1771 }
1772#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001773 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001774#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775 if (!WIFSTOPPED(status)) {
1776 /* Au revoir, mon ami. */
1777 break;
1778 }
1779 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001780 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 break;
1782 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001783 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001784 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001785 : WSTOPSIG(status));
1786 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001789 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001790#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791
1792#if defined(SUNOS4)
1793 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001794 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795#endif /* SUNOS4 */
1796
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 if (!qflag)
1798 fprintf(stderr, "Process %u detached\n", tcp->pid);
1799
1800 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001801
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802 return error;
1803}
1804
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001805#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001807static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808{
1809 int pid;
1810 int status;
1811
1812 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813 }
1814}
1815
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001816#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817
1818static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001819cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820{
1821 int i;
1822 struct tcb *tcp;
1823
Roland McGrathee9d4352002-12-18 04:16:10 +00001824 for (i = 0; i < tcbtabsize; i++) {
1825 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826 if (!(tcp->flags & TCB_INUSE))
1827 continue;
1828 if (debug)
1829 fprintf(stderr,
1830 "cleanup: looking at pid %u\n", tcp->pid);
1831 if (tcp_last &&
1832 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001833 tprints(" <unfinished ...>");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001834 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001835 }
1836 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001837 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838 else {
1839 kill(tcp->pid, SIGCONT);
1840 kill(tcp->pid, SIGTERM);
1841 }
1842 }
1843 if (cflag)
1844 call_summary(outf);
1845}
1846
1847static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001848interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849{
1850 interrupted = 1;
1851}
1852
1853#ifndef HAVE_STRERROR
1854
Roland McGrath6d2b3492002-12-30 00:51:30 +00001855#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856extern int sys_nerr;
1857extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001858#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859
1860const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001861strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001862{
1863 static char buf[64];
1864
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001865 if (err_no < 1 || err_no >= sys_nerr) {
1866 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001867 return buf;
1868 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001869 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870}
1871
1872#endif /* HAVE_STERRROR */
1873
1874#ifndef HAVE_STRSIGNAL
1875
Roland McGrath8f474e02003-01-14 07:53:33 +00001876#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001877extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001879#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1880extern char *_sys_siglist[];
1881#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001882
1883const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001884strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885{
1886 static char buf[64];
1887
1888 if (sig < 1 || sig >= NSIG) {
1889 sprintf(buf, "Unknown signal %d", sig);
1890 return buf;
1891 }
1892#ifdef HAVE__SYS_SIGLIST
1893 return _sys_siglist[sig];
1894#else
1895 return sys_siglist[sig];
1896#endif
1897}
1898
1899#endif /* HAVE_STRSIGNAL */
1900
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001901#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902
1903static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001904rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905{
1906 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001908 free(pollv);
1909 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001910 if (!pollv)
1911 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001912
Roland McGrathca16be82003-01-10 19:55:28 +00001913 for (i = j = 0; i < tcbtabsize; i++) {
1914 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001915 if (!(tcp->flags & TCB_INUSE))
1916 continue;
1917 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001918 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001919 j++;
1920 }
1921 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001922 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923 }
1924}
1925
1926#ifndef HAVE_POLLABLE_PROCFS
1927
1928static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001929proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001930{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931 int i;
1932
1933 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001934 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001935 }
1936 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001937 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 }
1939}
1940
1941static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001942proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001943{
1944 int i;
1945 int n;
1946 struct proc_pollfd pollinfo;
1947
Denys Vlasenko5d645812011-08-20 12:48:18 +02001948 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1949 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 return n;
1951 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001952 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953 }
1954 for (i = 0; i < nprocs; i++) {
1955 if (pollv[i].fd == pollinfo.fd)
1956 pollv[i].revents = pollinfo.revents;
1957 else
1958 pollv[i].revents = 0;
1959 }
1960 poller_pid = pollinfo.pid;
1961 return 1;
1962}
1963
1964static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001965wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966{
1967}
1968
1969static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001970proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971{
1972 struct proc_pollfd pollinfo;
1973 struct sigaction sa;
1974 sigset_t blocked_set, empty_set;
1975 int i;
1976 int n;
1977 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001978#ifdef FREEBSD
1979 struct procfs_status pfs;
1980#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981
1982 switch (fork()) {
1983 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001984 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001985 case 0:
1986 break;
1987 default:
1988 return;
1989 }
1990
1991 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1992 sa.sa_flags = 0;
1993 sigemptyset(&sa.sa_mask);
1994 sigaction(SIGHUP, &sa, NULL);
1995 sigaction(SIGINT, &sa, NULL);
1996 sigaction(SIGQUIT, &sa, NULL);
1997 sigaction(SIGPIPE, &sa, NULL);
1998 sigaction(SIGTERM, &sa, NULL);
1999 sa.sa_handler = wakeup_handler;
2000 sigaction(SIGUSR1, &sa, NULL);
2001 sigemptyset(&blocked_set);
2002 sigaddset(&blocked_set, SIGUSR1);
2003 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2004 sigemptyset(&empty_set);
2005
2006 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002007 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002008 }
2009 n = rl.rlim_cur;
2010 for (i = 0; i < n; i++) {
2011 if (i != pfd && i != proc_poll_pipe[1])
2012 close(i);
2013 }
2014
2015 pollinfo.fd = pfd;
2016 pollinfo.pid = getpid();
2017 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002018#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002019 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2020#else
2021 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2022#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002023 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 switch (errno) {
2025 case EINTR:
2026 continue;
2027 case EBADF:
2028 pollinfo.revents = POLLERR;
2029 break;
2030 case ENOENT:
2031 pollinfo.revents = POLLHUP;
2032 break;
2033 default:
2034 perror("proc_poller: PIOCWSTOP");
2035 }
2036 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2037 _exit(0);
2038 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002039 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2041 sigsuspend(&empty_set);
2042 }
2043}
2044
2045#endif /* !HAVE_POLLABLE_PROCFS */
2046
2047static int
2048choose_pfd()
2049{
2050 int i, j;
2051 struct tcb *tcp;
2052
2053 static int last;
2054
2055 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002056 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002057 /*
2058 * The previous process is ready to run again. We'll
2059 * let it do so if it is currently in a syscall. This
2060 * heuristic improves the readability of the trace.
2061 */
2062 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002063 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002064 return pollv[last].fd;
2065 }
2066
2067 for (i = 0; i < nprocs; i++) {
2068 /* Let competing children run round robin. */
2069 j = (i + last + 1) % nprocs;
2070 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2071 tcp = pfd2tcb(pollv[j].fd);
2072 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002073 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002074 }
2075 droptcb(tcp);
2076 return -1;
2077 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002078 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079 last = j;
2080 return pollv[j].fd;
2081 }
2082 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002083 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002084}
2085
2086static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002087trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002088{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002089#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002090 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002091#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 struct tcb *tcp;
2093 int pfd;
2094 int what;
2095 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002096 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002097
2098 for (;;) {
2099 if (interactive)
2100 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2101
2102 if (nprocs == 0)
2103 break;
2104
2105 switch (nprocs) {
2106 case 1:
2107#ifndef HAVE_POLLABLE_PROCFS
2108 if (proc_poll_pipe[0] == -1) {
2109#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002110 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002111 if (!tcp)
2112 continue;
2113 pfd = tcp->pfd;
2114 if (pfd == -1)
2115 continue;
2116 break;
2117#ifndef HAVE_POLLABLE_PROCFS
2118 }
2119 /* fall through ... */
2120#endif /* !HAVE_POLLABLE_PROCFS */
2121 default:
2122#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002123#ifdef POLL_HACK
2124 /* On some systems (e.g. UnixWare) we get too much ugly
2125 "unfinished..." stuff when multiple proceses are in
2126 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002127
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002128 if (in_syscall) {
2129 struct pollfd pv;
2130 tcp = in_syscall;
2131 in_syscall = NULL;
2132 pv.fd = tcp->pfd;
2133 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002134 what = poll(&pv, 1, 1);
2135 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002136 if (interrupted)
2137 return 0;
2138 continue;
2139 }
2140 else if (what == 1 && pv.revents & POLLWANT) {
2141 goto FOUND;
2142 }
2143 }
2144#endif
2145
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 if (poll(pollv, nprocs, INFTIM) < 0) {
2147 if (interrupted)
2148 return 0;
2149 continue;
2150 }
2151#else /* !HAVE_POLLABLE_PROCFS */
2152 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2153 if (interrupted)
2154 return 0;
2155 continue;
2156 }
2157#endif /* !HAVE_POLLABLE_PROCFS */
2158 pfd = choose_pfd();
2159 if (pfd == -1)
2160 continue;
2161 break;
2162 }
2163
2164 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002165 tcp = pfd2tcb(pfd);
2166 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002167 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002168 }
John Hughesb6643082002-05-23 11:02:22 +00002169#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002170 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002171#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002172 /* Get the status of the process. */
2173 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002174#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002175 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002176#else /* FREEBSD */
2177 /* Thanks to some scheduling mystery, the first poller
2178 sometimes waits for the already processed end of fork
2179 event. Doing a non blocking poll here solves the problem. */
2180 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002181 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002182 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002183 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002184#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002185 ioctl_errno = errno;
2186#ifndef HAVE_POLLABLE_PROCFS
2187 if (proc_poll_pipe[0] != -1) {
2188 if (ioctl_result < 0)
2189 kill(poller_pid, SIGKILL);
2190 else
2191 kill(poller_pid, SIGUSR1);
2192 }
2193#endif /* !HAVE_POLLABLE_PROCFS */
2194 }
2195 if (interrupted)
2196 return 0;
2197
2198 if (interactive)
2199 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2200
2201 if (ioctl_result < 0) {
2202 /* Find out what happened if it failed. */
2203 switch (ioctl_errno) {
2204 case EINTR:
2205 case EBADF:
2206 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002207#ifdef FREEBSD
2208 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002209#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002210 case ENOENT:
2211 droptcb(tcp);
2212 continue;
2213 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002214 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002215 }
2216 }
2217
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002218#ifdef FREEBSD
2219 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2220 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002221 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002222 continue;
2223 }
Roland McGrath553a6092002-12-16 20:40:39 +00002224#endif
2225
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002226 /* clear the just started flag */
2227 tcp->flags &= ~TCB_STARTUP;
2228
2229 /* set current output file */
2230 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002231 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002232
2233 if (cflag) {
2234 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002235#ifdef FREEBSD
2236 char buf[1024];
2237 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002238
Denys Vlasenko5d645812011-08-20 12:48:18 +02002239 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2240 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002241 buf[len] = '\0';
2242 sscanf(buf,
2243 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2244 &stime.tv_sec, &stime.tv_usec);
2245 } else
2246 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002247#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2249 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002250#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002251 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2252 tcp->stime = stime;
2253 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002254 what = tcp->status.PR_WHAT;
2255 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002256#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002258 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2259 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002260 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002261 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002262 }
2263 }
2264 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002265#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002267#ifdef POLL_HACK
2268 in_syscall = tcp;
2269#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002270 case PR_SYSEXIT:
2271 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002272 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002273 }
2274 break;
2275 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002276 if (cflag != CFLAG_ONLY_STATS
2277 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002278 printleader(tcp);
2279 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002280 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002281 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002282#ifdef PR_INFO
2283 if (tcp->status.PR_INFO.si_signo == what) {
2284 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002285 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002286 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002287 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002288 }
2289#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002290 }
2291 break;
2292 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002293 if (cflag != CFLAGS_ONLY_STATS
2294 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002295 printleader(tcp);
2296 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002297 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002298 }
2299 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002300#ifdef FREEBSD
2301 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002302 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002303#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002304 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002305 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002306 break;
2307 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002308 /* Remember current print column before continuing. */
2309 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002310 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002311#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002312 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002313#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002314 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002315#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002316 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002317 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002318 }
2319 }
2320 return 0;
2321}
2322
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002323#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324
Roland McGratheb9e2e82009-06-02 16:49:22 -07002325static int
2326trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002327{
2328 int pid;
2329 int wait_errno;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002330 int status, sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002331 struct tcb *tcp;
2332#ifdef LINUX
2333 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002334 struct rusage *rup = cflag ? &ru : NULL;
2335# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002336 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002337# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002338#endif /* LINUX */
2339
Roland McGratheb9e2e82009-06-02 16:49:22 -07002340 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002341 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002342 return 0;
2343 if (interactive)
2344 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002346# ifdef __WALL
2347 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002348 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002349 /* this kernel does not support __WALL */
2350 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002351 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002352 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002353 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002354 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002355 pid = wait4(-1, &status, __WCLONE, rup);
2356 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002357 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002358 }
2359 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002360# else
2361 pid = wait4(-1, &status, 0, rup);
2362# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363#endif /* LINUX */
2364#ifdef SUNOS4
2365 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002366#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002367 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002368 if (interactive)
2369 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002370
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002371 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002372 switch (wait_errno) {
2373 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002375 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002376 /*
2377 * We would like to verify this case
2378 * but sometimes a race in Solbourne's
2379 * version of SunOS sometimes reports
2380 * ECHILD before sending us SIGCHILD.
2381 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002382 return 0;
2383 default:
2384 errno = wait_errno;
2385 perror("strace: wait");
2386 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 }
2388 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002389 if (pid == popen_pid) {
2390 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002391 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002392 continue;
2393 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002394 if (debug) {
2395 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2396#ifdef LINUX
2397 unsigned ev = (unsigned)status >> 16;
2398 if (ev) {
2399 static const char *const event_names[] = {
2400 [PTRACE_EVENT_CLONE] = "CLONE",
2401 [PTRACE_EVENT_FORK] = "FORK",
2402 [PTRACE_EVENT_VFORK] = "VFORK",
2403 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2404 [PTRACE_EVENT_EXEC] = "EXEC",
2405 [PTRACE_EVENT_EXIT] = "EXIT",
2406 };
2407 const char *e;
2408 if (ev < ARRAY_SIZE(event_names))
2409 e = event_names[ev];
2410 else {
2411 sprintf(buf, "?? (%u)", ev);
2412 e = buf;
2413 }
2414 fprintf(stderr, " PTRACE_EVENT_%s", e);
2415 }
2416#endif
2417 strcpy(buf, "???");
2418 if (WIFSIGNALED(status))
2419#ifdef WCOREDUMP
2420 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2421 WCOREDUMP(status) ? "core," : "",
2422 signame(WTERMSIG(status)));
2423#else
2424 sprintf(buf, "WIFSIGNALED,sig=%s",
2425 signame(WTERMSIG(status)));
2426#endif
2427 if (WIFEXITED(status))
2428 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2429 if (WIFSTOPPED(status))
2430 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002431#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002432 if (WIFCONTINUED(status))
2433 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002434#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002435 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2436 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002437
2438 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002439 tcp = pid2tcb(pid);
2440 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002441#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002442 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002443 /* This is needed to go with the CLONE_PTRACE
2444 changes in process.c/util.c: we might see
2445 the child's initial trap before we see the
2446 parent return from the clone syscall.
2447 Leave the child suspended until the parent
2448 returns from its system call. Only then
2449 will we have the association of parent and
2450 child so that we know how to do clearbpt
2451 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002452 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002453 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002454 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002455 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002456 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002457 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002458 else
2459 /* This can happen if a clone call used
2460 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002461#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002462 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002463 if (WIFSTOPPED(status))
2464 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002465 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002466 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002467 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002468 /* set current output file */
2469 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002470 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002471#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002472 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002473 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2474 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002475 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002476#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002477
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002478 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002479 if (pid == strace_child)
2480 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002481 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002482 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2483 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002484#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002485 tprintf("+++ killed by %s %s+++",
2486 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002487 WCOREDUMP(status) ? "(core dumped) " : "");
2488#else
2489 tprintf("+++ killed by %s +++",
2490 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002491#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002492 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002493 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002494 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495 droptcb(tcp);
2496 continue;
2497 }
2498 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002499 if (pid == strace_child)
2500 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002501 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002502 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002503 tprintf(" <unfinished ... exit status %d>\n",
2504 WEXITSTATUS(status));
2505 tcp_last = NULL;
2506 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002507 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2508 printleader(tcp);
2509 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2510 printtrailer();
2511 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002512 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002513 droptcb(tcp);
2514 continue;
2515 }
2516 if (!WIFSTOPPED(status)) {
2517 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2518 droptcb(tcp);
2519 continue;
2520 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002521
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002522 /* Is this the very first time we see this tracee stopped? */
2523 if (tcp->flags & TCB_STARTUP) {
2524 if (debug)
2525 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002526 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002527 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002528 /*
2529 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002530 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002531 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002532 if (clearbpt(tcp) < 0) {
2533 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 droptcb(tcp);
2535 cleanup();
2536 return -1;
2537 }
2538 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002539#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002540 if (ptrace_setoptions) {
2541 if (debug)
2542 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2543 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2544 if (errno != ESRCH) {
2545 /* Should never happen, really */
2546 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002547 }
2548 }
2549 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002550#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002551 }
2552
2553 if (((unsigned)status >> 16) != 0) {
2554 /* Ptrace event (we ignore all of them for now) */
2555 goto restart_tracee_with_sig_0;
2556 }
2557
2558 sig = WSTOPSIG(status);
2559
2560 /* Is this post-attach SIGSTOP?
2561 * Interestingly, the process may stop
2562 * with STOPSIG equal to some other signal
2563 * than SIGSTOP if we happend to attach
2564 * just before the process takes a signal.
2565 */
2566 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2567 if (debug)
2568 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2569 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002570 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002571 }
2572
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002573 if (sig != syscall_trap_sig) {
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002574 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002575 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002576 siginfo_t si;
2577#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002578 long pc = 0;
2579 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002580
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002581 upeek(tcp, PT_CR_IPSR, &psr);
2582 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002583
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002584# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002585 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002586# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002587# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002588#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002589# define PC_FORMAT_STR ""
2590# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002591#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002592 printleader(tcp);
Dmitry V. Levin436d8922011-11-29 00:15:59 +00002593 if (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002594 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002595 printsiginfo(&si, verbose(tcp));
2596 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002597 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002598 PC_FORMAT_ARG);
2599 } else
2600 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002601 strsignal(sig),
2602 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002603 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002604 printtrailer();
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002605 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002606 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002607 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002608 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002609
2610 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002611 if (interrupted)
2612 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002613
2614 /* This should be syscall entry or exit.
2615 * (Or it still can be that pesky post-execve SIGTRAP!)
2616 * Handle it.
2617 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002618 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2619 /* ptrace() failed in trace_syscall() with ESRCH.
2620 * Likely a result of process disappearing mid-flight.
2621 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002622 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002623 */
2624 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002625 if (tcp_last) {
2626 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002627 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002628 */
2629 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002630 tprints(" <unfinished ...>");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002631 printtrailer();
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002632 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002633 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002634 /* We assume that ptrace error was caused by process death.
2635 * We used to detach(tcp) here, but since we no longer
2636 * implement "detach before death" policy/hack,
2637 * we can let this process to report its death to us
2638 * normally, via WIFEXITED or WIFSIGNALED wait status.
2639 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002640 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002641 /* It's our real child (and we also trace it) */
2642 /* my_tkill(pid, SIGKILL); - why? */
2643 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002644 }
2645 continue;
2646 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002647 restart_tracee_with_sig_0:
2648 sig = 0;
2649 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002650 /* Remember current print column before continuing. */
2651 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002652 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002653 cleanup();
2654 return -1;
2655 }
2656 }
2657 return 0;
2658}
2659
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002660#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002662void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002663tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002664{
2665 va_list args;
2666
Andreas Schwabe5355de2009-10-27 16:56:43 +01002667 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002668 if (outf) {
2669 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002670 if (n < 0) {
2671 if (outf != stderr)
2672 perror(outfname == NULL
2673 ? "<writing to pipe>" : outfname);
2674 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002675 curcol += n;
2676 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002677 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002678}
2679
2680void
2681tprints(const char *str)
2682{
2683 if (outf) {
2684 int n = fputs(str, outf);
2685 if (n >= 0) {
2686 curcol += strlen(str);
2687 return;
2688 }
2689 if (outf != stderr)
2690 perror(outfname == NULL
2691 ? "<writing to pipe>" : outfname);
2692 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002693}
2694
2695void
Denys Vlasenko12014262011-05-30 14:00:14 +02002696printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002697{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002698 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002699 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002700 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002701 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002702 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002703 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002704 tprints("= ? <unavailable>\n");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002705 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002706 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002707 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002708 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002709 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002710 }
2711 curcol = 0;
2712 if ((followfork == 1 || pflag_seen > 1) && outfname)
2713 tprintf("%-5d ", tcp->pid);
2714 else if (nprocs > 1 && !outfname)
2715 tprintf("[pid %5u] ", tcp->pid);
2716 if (tflag) {
2717 char str[sizeof("HH:MM:SS")];
2718 struct timeval tv, dtv;
2719 static struct timeval otv;
2720
2721 gettimeofday(&tv, NULL);
2722 if (rflag) {
2723 if (otv.tv_sec == 0)
2724 otv = tv;
2725 tv_sub(&dtv, &tv, &otv);
2726 tprintf("%6ld.%06ld ",
2727 (long) dtv.tv_sec, (long) dtv.tv_usec);
2728 otv = tv;
2729 }
2730 else if (tflag > 2) {
2731 tprintf("%ld.%06ld ",
2732 (long) tv.tv_sec, (long) tv.tv_usec);
2733 }
2734 else {
2735 time_t local = tv.tv_sec;
2736 strftime(str, sizeof(str), "%T", localtime(&local));
2737 if (tflag > 1)
2738 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2739 else
2740 tprintf("%s ", str);
2741 }
2742 }
2743 if (iflag)
2744 printcall(tcp);
2745}
2746
2747void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002748tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002749{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002750 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002751 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002752}
2753
2754void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002755printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002756{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002757 tprints("\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002758 tcp_last = NULL;
2759}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002760
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002761#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002762
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002763int
2764mp_ioctl(int fd, int cmd, void *arg, int size)
2765{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002766 struct iovec iov[2];
2767 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002768
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002769 iov[0].iov_base = &cmd;
2770 iov[0].iov_len = sizeof cmd;
2771 if (arg) {
2772 ++n;
2773 iov[1].iov_base = arg;
2774 iov[1].iov_len = size;
2775 }
Roland McGrath553a6092002-12-16 20:40:39 +00002776
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002777 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002778}
2779
2780#endif