blob: 472805482e02b2b9d422d4b21fc2855960e9e2ba [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>
John Hughes19e49982001-10-19 08:59:12 +000047#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000048#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
52# if defined __NR_tgkill
53# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
54# elif defined __NR_tkill
55# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
56# else
57 /* kill() may choose arbitrarily the target task of the process group
58 while we later wait on a that specific TID. PID process waits become
59 TID task specific waits for a process under ptrace(2). */
60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
62# endif
63#endif
64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000065#if defined(IA64) && defined(LINUX)
66# include <asm/ptrace_offsets.h>
67#endif
68
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000069#ifdef USE_PROCFS
70#include <poll.h>
71#endif
72
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#ifdef SVR4
74#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000075#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000076#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000077#include <sys/uio.h>
78#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000080#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000082extern int optind;
83extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000084
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085
Roland McGrath41c48222008-07-18 00:25:10 +000086int debug = 0, followfork = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020087unsigned int ptrace_setoptions_followfork = 0;
88static unsigned int ptrace_setoptions_for_all = 0;
89/* Which WSTOPSIG(status) value marks syscall traps? */
90static unsigned int SYSCALLTRAP = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000091int dtime = 0, xflag = 0, qflag = 0;
92cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000093static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000094/*
95 * daemonized_tracer supports -D option.
96 * With this option, strace forks twice.
97 * Unlike normal case, with -D *grandparent* process exec's,
98 * becoming a traced process. Child exits (this prevents traced process
99 * from having children it doesn't expect to have), and grandchild
100 * attaches to grandparent similarly to strace -p PID.
101 * This allows for more transparent interaction in cases
102 * when process and its parent are communicating via signals,
103 * wait() etc. Without -D, strace process gets lodged in between,
104 * disrupting parent<->child link.
105 */
106static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000108/* Sometimes we want to print only succeeding syscalls. */
109int not_failing_only = 0;
110
Grant Edwards8a082772011-04-07 20:25:40 +0000111/* Show path associated with fd arguments */
112int show_fd_path = 0;
113
114/* are we filtering traces based on paths? */
115int tracing_paths = 0;
116
Dmitry V. Levina6809652008-11-10 17:14:58 +0000117static int exit_code = 0;
118static int strace_child = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700119
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000120static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121uid_t run_uid;
122gid_t run_gid;
123
124int acolumn = DEFAULT_ACOLUMN;
125int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100128static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000129struct tcb **tcbtab;
130unsigned int nprocs, tcbtabsize;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000131const char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700132extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133
Andreas Schwabe5355de2009-10-27 16:56:43 +0100134static int detach(struct tcb *tcp, int sig);
135static int trace(void);
136static void cleanup(void);
137static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138static sigset_t empty_set, blocked_set;
139
140#ifdef HAVE_SIG_ATOMIC_T
141static volatile sig_atomic_t interrupted;
142#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144#endif /* !HAVE_SIG_ATOMIC_T */
145
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000146#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147
Andreas Schwabe5355de2009-10-27 16:56:43 +0100148static struct tcb *pfd2tcb(int pfd);
149static void reaper(int sig);
150static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000151static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152
153#ifndef HAVE_POLLABLE_PROCFS
154
Andreas Schwabe5355de2009-10-27 16:56:43 +0100155static void proc_poll_open(void);
156static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157
158struct proc_pollfd {
159 int fd;
160 int revents;
161 int pid;
162};
163
164static int poller_pid;
165static int proc_poll_pipe[2] = { -1, -1 };
166
167#endif /* !HAVE_POLLABLE_PROCFS */
168
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000169#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000170#define POLLWANT POLLWRNORM
171#else
172#define POLLWANT POLLPRI
173#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000174#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175
176static void
177usage(ofp, exitval)
178FILE *ofp;
179int exitval;
180{
181 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000182usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000183 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000184 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200185 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000186 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200188-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000189-f -- follow forks, -ff -- with output into separate files\n\
190-F -- attempt to follow vforks, -h -- print help message\n\
191-i -- print instruction pointer at time of syscall\n\
192-q -- suppress messages about attaching, detaching, etc.\n\
193-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
194-T -- print time spent in each syscall, -V -- print version\n\
195-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
196-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000197-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198-a column -- alignment COLUMN for printing syscall results (default %d)\n\
199-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
200 options: trace, abbrev, verbose, raw, signal, read, or write\n\
201-o file -- send trace output to FILE instead of stderr\n\
202-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
203-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000204-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
206-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
207-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000208-E var=val -- put var=val in the environment for command\n\
209-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000210-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000211" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000212-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000213 */
214, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215 exit(exitval);
216}
217
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200218static void error_msg_and_die(const char *fmt, ...)
219#if defined __GNUC__
220 __attribute__ ((noreturn, format(printf, 1, 2)))
221#endif
222;
223static void error_msg_and_die(const char *fmt, ...)
224{
225 char *msg;
226 va_list p;
227
228 va_start(p, fmt);
229 msg = NULL;
230 vasprintf(&msg, fmt, p);
231 if (msg) {
232 fprintf(stderr, "%s: %s\n", progname, msg);
233 free(msg);
234 }
235 va_end(p);
236
237 /* TODO? cflag = 0; -- or else cleanup() may print summary */
238 cleanup();
239 fflush(NULL);
240 _exit(1);
241}
242
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000243#ifdef SVR4
244#ifdef MIPS
245void
246foobar()
247{
248}
249#endif /* MIPS */
250#endif /* SVR4 */
251
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400252/* Glue for systems without a MMU that cannot provide fork() */
253#ifdef HAVE_FORK
254# define strace_vforked 0
255#else
256# define strace_vforked 1
257# define fork() vfork()
258#endif
259
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000260static int
261set_cloexec_flag(int fd)
262{
263 int flags, newflags;
264
265 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
266 {
267 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
268 progname, strerror(errno));
269 return -1;
270 }
271
272 newflags = flags | FD_CLOEXEC;
273 if (flags == newflags)
274 return 0;
275
276 if (fcntl(fd, F_SETFD, newflags) < 0)
277 {
278 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
279 progname, strerror(errno));
280 return -1;
281 }
282
283 return 0;
284}
285
286/*
287 * When strace is setuid executable, we have to swap uids
288 * before and after filesystem and process management operations.
289 */
290static void
291swap_uid(void)
292{
293#ifndef SVR4
294 int euid = geteuid(), uid = getuid();
295
296 if (euid != uid && setreuid(euid, uid) < 0)
297 {
298 fprintf(stderr, "%s: setreuid: %s\n",
299 progname, strerror(errno));
300 exit(1);
301 }
302#endif
303}
304
Roland McGrath4bfa6262007-07-05 20:03:16 +0000305#if _LFS64_LARGEFILE
306# define fopen_for_output fopen64
307#else
308# define fopen_for_output fopen
309#endif
310
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000311static FILE *
312strace_fopen(const char *path, const char *mode)
313{
314 FILE *fp;
315
316 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000317 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000318 fprintf(stderr, "%s: can't fopen '%s': %s\n",
319 progname, path, strerror(errno));
320 swap_uid();
321 if (fp && set_cloexec_flag(fileno(fp)) < 0)
322 {
323 fclose(fp);
324 fp = NULL;
325 }
326 return fp;
327}
328
329static int popen_pid = -1;
330
331#ifndef _PATH_BSHELL
332# define _PATH_BSHELL "/bin/sh"
333#endif
334
335/*
336 * We cannot use standard popen(3) here because we have to distinguish
337 * popen child process from other processes we trace, and standard popen(3)
338 * does not export its child's pid.
339 */
340static FILE *
341strace_popen(const char *command)
342{
343 int fds[2];
344
345 swap_uid();
346 if (pipe(fds) < 0)
347 {
348 fprintf(stderr, "%s: pipe: %s\n",
349 progname, strerror(errno));
350 swap_uid();
351 return NULL;
352 }
353
354 if (set_cloexec_flag(fds[1]) < 0)
355 {
356 close(fds[0]);
357 close(fds[1]);
358 swap_uid();
359 return NULL;
360 }
361
362 if ((popen_pid = fork()) == -1)
363 {
364 fprintf(stderr, "%s: fork: %s\n",
365 progname, strerror(errno));
366 close(fds[0]);
367 close(fds[1]);
368 swap_uid();
369 return NULL;
370 }
371
372 if (popen_pid)
373 {
374 /* parent */
375 close(fds[0]);
376 swap_uid();
377 return fdopen(fds[1], "w");
378 } else
379 {
380 /* child */
381 close(fds[1]);
382 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
383 {
384 fprintf(stderr, "%s: dup2: %s\n",
385 progname, strerror(errno));
386 _exit(1);
387 }
388 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
389 fprintf(stderr, "%s: execl: %s: %s\n",
390 progname, _PATH_BSHELL, strerror(errno));
391 _exit(1);
392 }
393}
394
395static int
396newoutf(struct tcb *tcp)
397{
398 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000399 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400 FILE *fp;
401
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000402 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000403 if ((fp = strace_fopen(name, "w")) == NULL)
404 return -1;
405 tcp->outf = fp;
406 }
407 return 0;
408}
409
Roland McGrath02203312007-06-11 22:06:31 +0000410static void
411startup_attach(void)
412{
413 int tcbi;
414 struct tcb *tcp;
415
416 /*
417 * Block user interruptions as we would leave the traced
418 * process stopped (process state T) if we would terminate in
419 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
420 * We rely on cleanup () from this point on.
421 */
422 if (interactive)
423 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
424
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000425 if (daemonized_tracer) {
426 pid_t pid = fork();
427 if (pid < 0) {
428 _exit(1);
429 }
430 if (pid) { /* parent */
431 /*
432 * Wait for child to attach to straced process
433 * (our parent). Child SIGKILLs us after it attached.
434 * Parent's wait() is unblocked by our death,
435 * it proceeds to exec the straced program.
436 */
437 pause();
438 _exit(0); /* paranoia */
439 }
440 }
441
Roland McGrath02203312007-06-11 22:06:31 +0000442 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
443 tcp = tcbtab[tcbi];
444 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
445 continue;
446#ifdef LINUX
447 if (tcp->flags & TCB_CLONE_THREAD)
448 continue;
449#endif
450 /* Reinitialize the output since it may have changed. */
451 tcp->outf = outf;
452 if (newoutf(tcp) < 0)
453 exit(1);
454
455#ifdef USE_PROCFS
456 if (proc_open(tcp, 1) < 0) {
457 fprintf(stderr, "trouble opening proc file\n");
458 droptcb(tcp);
459 continue;
460 }
461#else /* !USE_PROCFS */
462# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000463 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000464 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000465 DIR *dir;
466
467 sprintf(procdir, "/proc/%d/task", tcp->pid);
468 dir = opendir(procdir);
469 if (dir != NULL) {
470 unsigned int ntid = 0, nerr = 0;
471 struct dirent *de;
472 int tid;
473 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000474 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000475 continue;
476 tid = atoi(de->d_name);
477 if (tid <= 0)
478 continue;
479 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000480 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000481 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000482 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000483 tcp = alloctcb(tid);
Wang Chao21b8db42010-08-27 17:43:16 +0800484 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000485 tcbtab[tcbi]->nchildren++;
486 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000487 tcp->parent = tcbtab[tcbi];
488 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000489 if (interactive) {
490 sigprocmask(SIG_SETMASK, &empty_set, NULL);
491 if (interrupted)
492 return;
493 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
494 }
Roland McGrath02203312007-06-11 22:06:31 +0000495 }
496 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000497 ntid -= nerr;
498 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000499 perror("attach: ptrace(PTRACE_ATTACH, ...)");
500 droptcb(tcp);
501 continue;
502 }
503 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000504 fprintf(stderr, ntid > 1
505? "Process %u attached with %u threads - interrupt to quit\n"
506: "Process %u attached - interrupt to quit\n",
507 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000508 }
509 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000510 } /* if (opendir worked) */
511 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000512# endif
513 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
514 perror("attach: ptrace(PTRACE_ATTACH, ...)");
515 droptcb(tcp);
516 continue;
517 }
518 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000519
520 if (daemonized_tracer) {
521 /*
522 * It is our grandparent we trace, not a -p PID.
523 * Don't want to just detach on exit, so...
524 */
525 tcp->flags &= ~TCB_ATTACHED;
526 /*
527 * Make parent go away.
528 * Also makes grandparent's wait() unblock.
529 */
530 kill(getppid(), SIGKILL);
531 }
532
Roland McGrath02203312007-06-11 22:06:31 +0000533#endif /* !USE_PROCFS */
534 if (!qflag)
535 fprintf(stderr,
536 "Process %u attached - interrupt to quit\n",
537 tcp->pid);
538 }
539
540 if (interactive)
541 sigprocmask(SIG_SETMASK, &empty_set, NULL);
542}
543
544static void
545startup_child (char **argv)
546{
547 struct stat statbuf;
548 const char *filename;
549 char pathname[MAXPATHLEN];
550 int pid = 0;
551 struct tcb *tcp;
552
553 filename = argv[0];
554 if (strchr(filename, '/')) {
555 if (strlen(filename) > sizeof pathname - 1) {
556 errno = ENAMETOOLONG;
557 perror("strace: exec");
558 exit(1);
559 }
560 strcpy(pathname, filename);
561 }
562#ifdef USE_DEBUGGING_EXEC
563 /*
564 * Debuggers customarily check the current directory
565 * first regardless of the path but doing that gives
566 * security geeks a panic attack.
567 */
568 else if (stat(filename, &statbuf) == 0)
569 strcpy(pathname, filename);
570#endif /* USE_DEBUGGING_EXEC */
571 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000572 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000573 int m, n, len;
574
575 for (path = getenv("PATH"); path && *path; path += m) {
576 if (strchr(path, ':')) {
577 n = strchr(path, ':') - path;
578 m = n + 1;
579 }
580 else
581 m = n = strlen(path);
582 if (n == 0) {
583 if (!getcwd(pathname, MAXPATHLEN))
584 continue;
585 len = strlen(pathname);
586 }
587 else if (n > sizeof pathname - 1)
588 continue;
589 else {
590 strncpy(pathname, path, n);
591 len = n;
592 }
593 if (len && pathname[len - 1] != '/')
594 pathname[len++] = '/';
595 strcpy(pathname + len, filename);
596 if (stat(pathname, &statbuf) == 0 &&
597 /* Accept only regular files
598 with some execute bits set.
599 XXX not perfect, might still fail */
600 S_ISREG(statbuf.st_mode) &&
601 (statbuf.st_mode & 0111))
602 break;
603 }
604 }
605 if (stat(pathname, &statbuf) < 0) {
606 fprintf(stderr, "%s: %s: command not found\n",
607 progname, filename);
608 exit(1);
609 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000610 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000611 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000612 perror("strace: fork");
613 cleanup();
614 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000615 }
616 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
617 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
618 ) {
619 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000620#ifdef USE_PROCFS
621 if (outf != stderr) close (fileno (outf));
622#ifdef MIPS
623 /* Kludge for SGI, see proc_open for details. */
624 sa.sa_handler = foobar;
625 sa.sa_flags = 0;
626 sigemptyset(&sa.sa_mask);
627 sigaction(SIGINT, &sa, NULL);
628#endif /* MIPS */
629#ifndef FREEBSD
630 pause();
631#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000632 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000633#endif /* FREEBSD */
634#else /* !USE_PROCFS */
635 if (outf!=stderr)
636 close(fileno (outf));
637
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000638 if (!daemonized_tracer) {
639 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
640 perror("strace: ptrace(PTRACE_TRACEME, ...)");
641 exit(1);
642 }
643 if (debug)
644 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000645 }
Roland McGrath02203312007-06-11 22:06:31 +0000646
647 if (username != NULL || geteuid() == 0) {
648 uid_t run_euid = run_uid;
649 gid_t run_egid = run_gid;
650
651 if (statbuf.st_mode & S_ISUID)
652 run_euid = statbuf.st_uid;
653 if (statbuf.st_mode & S_ISGID)
654 run_egid = statbuf.st_gid;
655
656 /*
657 * It is important to set groups before we
658 * lose privileges on setuid.
659 */
660 if (username != NULL) {
661 if (initgroups(username, run_gid) < 0) {
662 perror("initgroups");
663 exit(1);
664 }
665 if (setregid(run_gid, run_egid) < 0) {
666 perror("setregid");
667 exit(1);
668 }
669 if (setreuid(run_uid, run_euid) < 0) {
670 perror("setreuid");
671 exit(1);
672 }
673 }
674 }
675 else
676 setreuid(run_uid, run_uid);
677
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000678 if (!daemonized_tracer) {
679 /*
680 * Induce an immediate stop so that the parent
681 * will resume us with PTRACE_SYSCALL and display
682 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400683 * Unless of course we're on a no-MMU system where
684 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000685 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400686 if (!strace_vforked)
687 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000688 } else {
689 struct sigaction sv_sigchld;
690 sigaction(SIGCHLD, NULL, &sv_sigchld);
691 /*
692 * Make sure it is not SIG_IGN, otherwise wait
693 * will not block.
694 */
695 signal(SIGCHLD, SIG_DFL);
696 /*
697 * Wait for grandchild to attach to us.
698 * It kills child after that, and wait() unblocks.
699 */
700 alarm(3);
701 wait(NULL);
702 alarm(0);
703 sigaction(SIGCHLD, &sv_sigchld, NULL);
704 }
Roland McGrath02203312007-06-11 22:06:31 +0000705#endif /* !USE_PROCFS */
706
707 execv(pathname, argv);
708 perror("strace: exec");
709 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000710 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000711
712 /* We are the tracer. */
713 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 if (daemonized_tracer) {
715 /* We want subsequent startup_attach() to attach to it. */
716 tcp->flags |= TCB_ATTACHED;
717 }
Roland McGrath02203312007-06-11 22:06:31 +0000718#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000719 if (proc_open(tcp, 0) < 0) {
720 fprintf(stderr, "trouble opening proc file\n");
721 cleanup();
722 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000723 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000724#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000725}
726
Wang Chaob13c0de2010-11-12 17:25:19 +0800727#ifdef LINUX
728/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000729 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800730 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000731 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800732 */
733static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200734test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800735{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000736 int pid, expected_grandchild = 0, found_grandchild = 0;
737 const unsigned int test_options = PTRACE_O_TRACECLONE |
738 PTRACE_O_TRACEFORK |
739 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800740
741 if ((pid = fork()) < 0)
742 return -1;
743 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000744 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800745 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800746 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000747 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800748 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000749
750 while (1) {
751 int status, tracee_pid;
752
753 tracee_pid = wait(&status);
754 if (tracee_pid == -1) {
755 if (errno == EINTR)
756 continue;
757 else if (errno == ECHILD)
758 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200759 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000760 return -1;
761 }
762 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000763 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000764 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
765 errno != ESRCH)
766 kill(tracee_pid, SIGKILL);
767 }
768 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000769 switch (WSTOPSIG(status)) {
770 case SIGSTOP:
771 if (ptrace(PTRACE_SETOPTIONS, pid,
772 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000773 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800774 return -1;
775 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000776 break;
777 case SIGTRAP:
778 if (status >> 16 == PTRACE_EVENT_FORK) {
779 long msg = 0;
780
781 if (ptrace(PTRACE_GETEVENTMSG, pid,
782 NULL, (long) &msg) == 0)
783 expected_grandchild = msg;
784 }
785 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800786 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000787 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
788 errno != ESRCH)
789 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800790 }
791 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000792 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200793 ptrace_setoptions_followfork |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800794 return 0;
795}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200796
797/*
798 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
799 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
800 * and then see whether it will stop with (SIGTRAP | 0x80).
801 *
802 * Use of this option enables correct handling of user-generated SIGTRAPs,
803 * and SIGTRAPs generated by special instructions such as int3 on x86:
804 * _start: .globl _start
805 * int3
806 * movl $42, %ebx
807 * movl $1, %eax
808 * int $0x80
809 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
810 */
811static void
812test_ptrace_setoptions_for_all(void)
813{
814 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
815 int pid;
816 int it_worked = 0;
817
818 pid = fork();
819 if (pid < 0)
820 error_msg_and_die("fork failed");
821
822 if (pid == 0) {
823 pid = getpid();
824 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
825 /* "parent, something is deeply wrong!" */
826 kill(pid, SIGKILL);
827 kill(pid, SIGSTOP);
828 _exit(0); /* parent should see entry into this syscall */
829 }
830
831 while (1) {
832 int status, tracee_pid;
833
834 errno = 0;
835 tracee_pid = wait(&status);
836 if (tracee_pid <= 0) {
837 if (errno == EINTR)
838 continue;
839 kill(pid, SIGKILL);
840 error_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
841 }
842 if (WIFEXITED(status))
843 break;
844 if (!WIFSTOPPED(status)) {
845 kill(pid, SIGKILL);
846 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
847 }
848 if (WSTOPSIG(status) == SIGSTOP) {
849 /*
850 * We don't check "options aren't accepted" error.
851 * If it happens, we'll never get (SIGTRAP | 0x80),
852 * and thus will decide to not use the option.
853 * IOW: the outcome of the test will be correct.
854 */
855 ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options);
856 }
857 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
858 it_worked = 1;
859 }
860 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
861 kill(pid, SIGKILL);
862 error_msg_and_die("PTRACE_SYSCALL doesn't work");
863 }
864 }
865
866 if (it_worked) {
867 SYSCALLTRAP = (SIGTRAP | 0x80);
868 ptrace_setoptions_for_all = test_options;
869 if (debug)
870 fprintf(stderr, "ptrace_setoptions_for_all = %#x\n",
871 ptrace_setoptions_for_all);
872 return;
873 }
874
875 fprintf(stderr,
876 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
877}
Wang Chaob13c0de2010-11-12 17:25:19 +0800878#endif
879
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000880int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000881main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883 struct tcb *tcp;
884 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000885 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886 struct sigaction sa;
887
888 static char buf[BUFSIZ];
889
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000890 progname = argv[0] ? argv[0] : "strace";
891
Roland McGrathee9d4352002-12-18 04:16:10 +0000892 /* Allocate the initial tcbtab. */
893 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000894 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000895 fprintf(stderr, "%s: out of memory\n", progname);
896 exit(1);
897 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000898 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000899 fprintf(stderr, "%s: out of memory\n", progname);
900 exit(1);
901 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000902 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
903 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
904
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905 outf = stderr;
906 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000907 set_sortby(DEFAULT_SORTBY);
908 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 qualify("trace=all");
910 qualify("abbrev=all");
911 qualify("verbose=all");
912 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000913 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000914 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000915#ifndef USE_PROCFS
916 "D"
917#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000918 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919 switch (c) {
920 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000921 if (cflag == CFLAG_BOTH) {
922 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
923 progname);
924 exit(1);
925 }
926 cflag = CFLAG_ONLY_STATS;
927 break;
928 case 'C':
929 if (cflag == CFLAG_ONLY_STATS) {
930 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
931 progname);
932 exit(1);
933 }
934 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000935 break;
936 case 'd':
937 debug++;
938 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000939#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000940 case 'D':
941 daemonized_tracer = 1;
942 break;
943#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000944 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000945 optF = 1;
946 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947 case 'f':
948 followfork++;
949 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000950 case 'h':
951 usage(stdout, 0);
952 break;
953 case 'i':
954 iflag++;
955 break;
956 case 'q':
957 qflag++;
958 break;
959 case 'r':
960 rflag++;
961 tflag++;
962 break;
963 case 't':
964 tflag++;
965 break;
966 case 'T':
967 dtime++;
968 break;
969 case 'x':
970 xflag++;
971 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000972 case 'y':
973 show_fd_path = 1;
974 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 case 'v':
976 qualify("abbrev=none");
977 break;
978 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000979 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980 exit(0);
981 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000982 case 'z':
983 not_failing_only = 1;
984 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985 case 'a':
986 acolumn = atoi(optarg);
987 break;
988 case 'e':
989 qualify(optarg);
990 break;
991 case 'o':
992 outfname = strdup(optarg);
993 break;
994 case 'O':
995 set_overhead(atoi(optarg));
996 break;
997 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000998 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 fprintf(stderr, "%s: Invalid process id: %s\n",
1000 progname, optarg);
1001 break;
1002 }
1003 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +00001004 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 break;
1006 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001007 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 tcp->flags |= TCB_ATTACHED;
1009 pflag_seen++;
1010 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001011 case 'P':
1012 tracing_paths = 1;
1013 if (pathtrace_select(optarg)) {
1014 fprintf(stderr,"%s : failed to select path '%s'\n", progname, optarg);
1015 exit(1);
1016 }
1017 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 case 's':
1019 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001020 if (max_strlen < 0) {
1021 fprintf(stderr,
1022 "%s: invalid -s argument: %s\n",
1023 progname, optarg);
1024 exit(1);
1025 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 break;
1027 case 'S':
1028 set_sortby(optarg);
1029 break;
1030 case 'u':
1031 username = strdup(optarg);
1032 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001033 case 'E':
1034 if (putenv(optarg) < 0) {
1035 fprintf(stderr, "%s: out of memory\n",
1036 progname);
1037 exit(1);
1038 }
1039 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040 default:
1041 usage(stderr, 1);
1042 break;
1043 }
1044 }
1045
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001046 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001047 usage(stderr, 1);
1048
Wang Chaod322a4b2010-08-05 14:30:11 +08001049 if (pflag_seen && daemonized_tracer) {
1050 fprintf(stderr,
1051 "%s: -D and -p are mutually exclusive options\n",
1052 progname);
1053 exit(1);
1054 }
1055
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001056 if (!followfork)
1057 followfork = optF;
1058
Roland McGrathcb9def62006-04-25 07:48:03 +00001059 if (followfork > 1 && cflag) {
1060 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001061 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +00001062 progname);
1063 exit(1);
1064 }
1065
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 /* See if they want to run as another user. */
1067 if (username != NULL) {
1068 struct passwd *pent;
1069
1070 if (getuid() != 0 || geteuid() != 0) {
1071 fprintf(stderr,
1072 "%s: you must be root to use the -u option\n",
1073 progname);
1074 exit(1);
1075 }
1076 if ((pent = getpwnam(username)) == NULL) {
1077 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +00001078 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 exit(1);
1080 }
1081 run_uid = pent->pw_uid;
1082 run_gid = pent->pw_gid;
1083 }
1084 else {
1085 run_uid = getuid();
1086 run_gid = getgid();
1087 }
1088
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001089#ifdef LINUX
1090 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001091 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001092 fprintf(stderr,
1093 "Test for options supported by PTRACE_SETOPTIONS "
1094 "failed, giving up using this feature.\n");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001095 ptrace_setoptions_followfork = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001096 }
1097 if (debug)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001098 fprintf(stderr, "ptrace_setoptions_followfork = %#x\n",
1099 ptrace_setoptions_followfork);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001100 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001101 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001102#endif
1103
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 /* Check if they want to redirect the output. */
1105 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001106 /* See if they want to pipe the output. */
1107 if (outfname[0] == '|' || outfname[0] == '!') {
1108 /*
1109 * We can't do the <outfname>.PID funny business
1110 * when using popen, so prohibit it.
1111 */
1112 if (followfork > 1) {
1113 fprintf(stderr, "\
1114%s: piping the output and -ff are mutually exclusive options\n",
1115 progname);
1116 exit(1);
1117 }
1118
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001119 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +00001120 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001121 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001122 else if (followfork <= 1 &&
1123 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125 }
1126
Roland McGrath37b9a662003-11-07 02:26:54 +00001127 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +00001129 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001132 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001133
Roland McGrath54cc1c82007-11-03 23:34:11 +00001134 /* Valid states here:
1135 optind < argc pflag_seen outfname interactive
1136 1 0 0 1
1137 0 1 0 1
1138 1 0 1 0
1139 0 1 1 1
1140 */
1141
1142 /* STARTUP_CHILD must be called before the signal handlers get
1143 installed below as they are inherited into the spawned process.
1144 Also we do not need to be protected by them as during interruption
1145 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1146 if (!pflag_seen)
1147 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149 sigemptyset(&empty_set);
1150 sigemptyset(&blocked_set);
1151 sa.sa_handler = SIG_IGN;
1152 sigemptyset(&sa.sa_mask);
1153 sa.sa_flags = 0;
1154 sigaction(SIGTTOU, &sa, NULL);
1155 sigaction(SIGTTIN, &sa, NULL);
1156 if (interactive) {
1157 sigaddset(&blocked_set, SIGHUP);
1158 sigaddset(&blocked_set, SIGINT);
1159 sigaddset(&blocked_set, SIGQUIT);
1160 sigaddset(&blocked_set, SIGPIPE);
1161 sigaddset(&blocked_set, SIGTERM);
1162 sa.sa_handler = interrupt;
1163#ifdef SUNOS4
1164 /* POSIX signals on sunos4.1 are a little broken. */
1165 sa.sa_flags = SA_INTERRUPT;
1166#endif /* SUNOS4 */
1167 }
1168 sigaction(SIGHUP, &sa, NULL);
1169 sigaction(SIGINT, &sa, NULL);
1170 sigaction(SIGQUIT, &sa, NULL);
1171 sigaction(SIGPIPE, &sa, NULL);
1172 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001173#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174 sa.sa_handler = reaper;
1175 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001176#else
1177 /* Make sure SIGCHLD has the default action so that waitpid
1178 definitely works without losing track of children. The user
1179 should not have given us a bogus state to inherit, but he might
1180 have. Arguably we should detect SIG_IGN here and pass it on
1181 to children, but probably noone really needs that. */
1182 sa.sa_handler = SIG_DFL;
1183 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001184#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001186 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001187 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001188
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 if (trace() < 0)
1190 exit(1);
1191 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001192 fflush(NULL);
1193 if (exit_code > 0xff) {
1194 /* Child was killed by a signal, mimic that. */
1195 exit_code &= 0xff;
1196 signal(exit_code, SIG_DFL);
1197 raise(exit_code);
1198 /* Paranoia - what if this signal is not fatal?
1199 Exit with 128 + signo then. */
1200 exit_code += 128;
1201 }
1202 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203}
1204
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001205void
1206expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001207{
1208 /* Allocate some more TCBs and expand the table.
1209 We don't want to relocate the TCBs because our
1210 callers have pointers and it would be a pain.
1211 So tcbtab is a table of pointers. Since we never
1212 free the TCBs, we allocate a single chunk of many. */
1213 struct tcb **newtab = (struct tcb **)
1214 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
1215 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
1216 sizeof *newtcbs);
1217 int i;
1218 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +00001219 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
1220 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001221 cleanup();
1222 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001223 }
1224 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1225 newtab[i] = &newtcbs[i - tcbtabsize];
1226 tcbtabsize *= 2;
1227 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001228}
1229
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001231alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232{
1233 int i;
1234 struct tcb *tcp;
1235
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001236 if (nprocs == tcbtabsize)
1237 expand_tcbtab();
1238
Roland McGrathee9d4352002-12-18 04:16:10 +00001239 for (i = 0; i < tcbtabsize; i++) {
1240 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 if ((tcp->flags & TCB_INUSE) == 0) {
1242 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001243 tcp->parent = NULL;
1244 tcp->nchildren = 0;
1245 tcp->nzombies = 0;
1246#ifdef TCB_CLONE_THREAD
Wang Chao21b8db42010-08-27 17:43:16 +08001247 tcp->nclone_threads = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001248 tcp->nclone_waiting = 0;
1249#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250 tcp->flags = TCB_INUSE | TCB_STARTUP;
1251 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001252 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001253 tcp->stime.tv_sec = 0;
1254 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255 tcp->pfd = -1;
1256 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001257 if (command_options_parsed)
1258 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001259 return tcp;
1260 }
1261 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001262 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1263 cleanup();
1264 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265}
1266
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001267#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001269proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270{
1271 char proc[32];
1272 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001273#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001274 int i;
1275 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 sigset_t signals;
1277 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001278#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279#ifndef HAVE_POLLABLE_PROCFS
1280 static int last_pfd;
1281#endif
1282
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001283#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001284 /* Open the process pseudo-files in /proc. */
1285 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1286 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287 perror("strace: open(\"/proc/...\", ...)");
1288 return -1;
1289 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001290 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001291 return -1;
1292 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001293 sprintf(proc, "/proc/%d/status", tcp->pid);
1294 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1295 perror("strace: open(\"/proc/...\", ...)");
1296 return -1;
1297 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001298 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001299 return -1;
1300 }
1301 sprintf(proc, "/proc/%d/as", tcp->pid);
1302 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1303 perror("strace: open(\"/proc/...\", ...)");
1304 return -1;
1305 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001306 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001307 return -1;
1308 }
1309#else
1310 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001311#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001312 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001313 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001314#else /* FREEBSD */
1315 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001316 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001318 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001319 perror("strace: open(\"/proc/...\", ...)");
1320 return -1;
1321 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001322 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001323 return -1;
1324 }
1325#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001326#ifdef FREEBSD
1327 sprintf(proc, "/proc/%d/regs", tcp->pid);
1328 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1329 perror("strace: open(\"/proc/.../regs\", ...)");
1330 return -1;
1331 }
1332 if (cflag) {
1333 sprintf(proc, "/proc/%d/status", tcp->pid);
1334 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1335 perror("strace: open(\"/proc/.../status\", ...)");
1336 return -1;
1337 }
1338 } else
1339 tcp->pfd_status = -1;
1340#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001341 rebuild_pollv();
1342 if (!attaching) {
1343 /*
1344 * Wait for the child to pause. Because of a race
1345 * condition we have to poll for the event.
1346 */
1347 for (;;) {
1348 if (IOCTL_STATUS (tcp) < 0) {
1349 perror("strace: PIOCSTATUS");
1350 return -1;
1351 }
1352 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001353 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001354 }
1355 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001356#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001357 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001358 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001359 perror("strace: PIOCSTOP");
1360 return -1;
1361 }
Roland McGrath553a6092002-12-16 20:40:39 +00001362#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363#ifdef PIOCSET
1364 /* Set Run-on-Last-Close. */
1365 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001366 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001367 perror("PIOCSET PR_RLC");
1368 return -1;
1369 }
1370 /* Set or Reset Inherit-on-Fork. */
1371 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001372 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001373 perror("PIOC{SET,RESET} PR_FORK");
1374 return -1;
1375 }
1376#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001377#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1379 perror("PIOCSRLC");
1380 return -1;
1381 }
1382 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1383 perror("PIOC{S,R}FORK");
1384 return -1;
1385 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001386#else /* FREEBSD */
1387 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1388 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1389 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001390 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001391 }
1392 arg &= ~PF_LINGER;
1393 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001394 perror("PIOCSFL");
1395 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001396 }
1397#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001399#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001400 /* Enable all syscall entries we care about. */
1401 premptyset(&syscalls);
1402 for (i = 1; i < MAX_QUALS; ++i) {
1403 if (i > (sizeof syscalls) * CHAR_BIT) break;
1404 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1405 }
1406 praddset (&syscalls, SYS_execve);
1407 if (followfork) {
1408 praddset (&syscalls, SYS_fork);
1409#ifdef SYS_forkall
1410 praddset (&syscalls, SYS_forkall);
1411#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001412#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001413 praddset (&syscalls, SYS_fork1);
1414#endif
1415#ifdef SYS_rfork1
1416 praddset (&syscalls, SYS_rfork1);
1417#endif
1418#ifdef SYS_rforkall
1419 praddset (&syscalls, SYS_rforkall);
1420#endif
1421 }
1422 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423 perror("PIOCSENTRY");
1424 return -1;
1425 }
John Hughes19e49982001-10-19 08:59:12 +00001426 /* Enable the syscall exits. */
1427 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428 perror("PIOSEXIT");
1429 return -1;
1430 }
John Hughes19e49982001-10-19 08:59:12 +00001431 /* Enable signals we care about. */
1432 premptyset(&signals);
1433 for (i = 1; i < MAX_QUALS; ++i) {
1434 if (i > (sizeof signals) * CHAR_BIT) break;
1435 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1436 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001437 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438 perror("PIOCSTRACE");
1439 return -1;
1440 }
John Hughes19e49982001-10-19 08:59:12 +00001441 /* Enable faults we care about */
1442 premptyset(&faults);
1443 for (i = 1; i < MAX_QUALS; ++i) {
1444 if (i > (sizeof faults) * CHAR_BIT) break;
1445 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1446 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001447 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448 perror("PIOCSFAULT");
1449 return -1;
1450 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001451#else /* FREEBSD */
1452 /* set events flags. */
1453 arg = S_SIG | S_SCE | S_SCX ;
1454 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1455 perror("PIOCBIS");
1456 return -1;
1457 }
1458#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 if (!attaching) {
1460#ifdef MIPS
1461 /*
1462 * The SGI PRSABORT doesn't work for pause() so
1463 * we send it a caught signal to wake it up.
1464 */
1465 kill(tcp->pid, SIGINT);
1466#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001467#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001468 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001469 arg = PRSABORT;
1470 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 perror("PIOCRUN");
1472 return -1;
1473 }
Roland McGrath553a6092002-12-16 20:40:39 +00001474#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001475#endif /* !MIPS*/
1476#ifdef FREEBSD
1477 /* wake up the child if it received the SIGSTOP */
1478 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001479#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480 for (;;) {
1481 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001482 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 perror("PIOCWSTOP");
1484 return -1;
1485 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001486 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001487 tcp->flags &= ~TCB_INSYSCALL;
1488 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001489 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490 break;
1491 }
1492 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001493#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001494 arg = 0;
1495 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001496#else /* FREEBSD */
1497 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001498#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 perror("PIOCRUN");
1500 return -1;
1501 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001502#ifdef FREEBSD
1503 /* handle the case where we "opened" the child before
1504 it did the kill -STOP */
1505 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1506 tcp->status.PR_WHAT == SIGSTOP)
1507 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001508#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001510#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001511 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001512#else /* FREEBSD */
1513 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001514 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001515 /* We are attaching to an already running process.
1516 * Try to figure out the state of the process in syscalls,
1517 * to handle the first event well.
1518 * This is done by having a look at the "wchan" property of the
1519 * process, which tells where it is stopped (if it is). */
1520 FILE * status;
1521 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001522
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001523 sprintf(proc, "/proc/%d/status", tcp->pid);
1524 status = fopen(proc, "r");
1525 if (status &&
1526 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1527 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1528 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1529 strcmp(wchan, "stopevent")) {
1530 /* The process is asleep in the middle of a syscall.
1531 Fake the syscall entry event */
1532 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1533 tcp->status.PR_WHY = PR_SYSENTRY;
1534 trace_syscall(tcp);
1535 }
1536 if (status)
1537 fclose(status);
1538 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001539 }
1540#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541#ifndef HAVE_POLLABLE_PROCFS
1542 if (proc_poll_pipe[0] != -1)
1543 proc_poller(tcp->pfd);
1544 else if (nprocs > 1) {
1545 proc_poll_open();
1546 proc_poller(last_pfd);
1547 proc_poller(tcp->pfd);
1548 }
1549 last_pfd = tcp->pfd;
1550#endif /* !HAVE_POLLABLE_PROCFS */
1551 return 0;
1552}
1553
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001554#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001556struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001557pid2tcb(int pid)
1558{
1559 int i;
1560
1561 if (pid <= 0)
1562 return NULL;
1563
1564 for (i = 0; i < tcbtabsize; i++) {
1565 struct tcb *tcp = tcbtab[i];
1566 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1567 return tcp;
1568 }
1569
1570 return NULL;
1571}
1572
1573#ifdef USE_PROCFS
1574
1575static struct tcb *
1576first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577{
1578 int i;
1579 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001580 for (i = 0; i < tcbtabsize; i++) {
1581 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 if (tcp->flags & TCB_INUSE)
1583 return tcp;
1584 }
1585 return NULL;
1586}
1587
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588static struct tcb *
1589pfd2tcb(pfd)
1590int pfd;
1591{
1592 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593
Roland McGrathca16be82003-01-10 19:55:28 +00001594 for (i = 0; i < tcbtabsize; i++) {
1595 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596 if (tcp->pfd != pfd)
1597 continue;
1598 if (tcp->flags & TCB_INUSE)
1599 return tcp;
1600 }
1601 return NULL;
1602}
1603
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001604#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605
1606void
1607droptcb(tcp)
1608struct tcb *tcp;
1609{
1610 if (tcp->pid == 0)
1611 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001612#ifdef TCB_CLONE_THREAD
1613 if (tcp->nclone_threads > 0) {
1614 /* There are other threads left in this process, but this
1615 is the one whose PID represents the whole process.
1616 We need to keep this record around as a zombie until
1617 all the threads die. */
1618 tcp->flags |= TCB_EXITING;
1619 return;
1620 }
1621#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 nprocs--;
1623 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001624
Roland McGrathe29341c2003-01-10 20:14:20 +00001625 if (tcp->parent != NULL) {
1626 tcp->parent->nchildren--;
1627#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001628 if (tcp->flags & TCB_CLONE_THREAD)
1629 tcp->parent->nclone_threads--;
1630#endif
Wang Chao21b8db42010-08-27 17:43:16 +08001631 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001632#ifdef LINUX
1633 /* Update `tcp->parent->parent->nchildren' and the other fields
1634 like NCLONE_DETACHED, only for zombie group leader that has
1635 already reported and been short-circuited at the top of this
1636 function. The same condition as at the top of DETACH. */
1637 if ((tcp->flags & TCB_CLONE_THREAD) &&
1638 tcp->parent->nclone_threads == 0 &&
1639 (tcp->parent->flags & TCB_EXITING))
1640 droptcb(tcp->parent);
1641#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001642 tcp->parent = NULL;
1643 }
1644
1645 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646 if (tcp->pfd != -1) {
1647 close(tcp->pfd);
1648 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001649#ifdef FREEBSD
1650 if (tcp->pfd_reg != -1) {
1651 close(tcp->pfd_reg);
1652 tcp->pfd_reg = -1;
1653 }
1654 if (tcp->pfd_status != -1) {
1655 close(tcp->pfd_status);
1656 tcp->pfd_status = -1;
1657 }
Roland McGrath553a6092002-12-16 20:40:39 +00001658#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001659#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001660 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661#endif
1662 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001663
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001664 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001666
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667 tcp->outf = 0;
1668}
1669
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001670#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671
1672static int
1673resume(tcp)
1674struct tcb *tcp;
1675{
1676 if (tcp == NULL)
1677 return -1;
1678
1679 if (!(tcp->flags & TCB_SUSPENDED)) {
1680 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1681 return -1;
1682 }
1683 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001684#ifdef TCB_CLONE_THREAD
1685 if (tcp->flags & TCB_CLONE_THREAD)
1686 tcp->parent->nclone_waiting--;
1687#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001689 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691
1692 if (!qflag)
1693 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1694 return 0;
1695}
1696
Roland McGrath1bfd3102007-08-03 10:02:00 +00001697static int
1698resume_from_tcp (struct tcb *tcp)
1699{
1700 int error = 0;
1701 int resumed = 0;
1702
1703 /* XXX This won't always be quite right (but it never was).
1704 A waiter with argument 0 or < -1 is waiting for any pid in
1705 a particular pgrp, which this child might or might not be
1706 in. The waiter will only wake up if it's argument is -1
1707 or if it's waiting for tcp->pid's pgrp. It makes a
1708 difference to wake up a waiter when there might be more
1709 traced children, because it could get a false ECHILD
1710 error. OTOH, if this was the last child in the pgrp, then
1711 it ought to wake up and get ECHILD. We would have to
1712 search the system for all pid's in the pgrp to be sure.
1713
1714 && (t->waitpid == -1 ||
1715 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1716 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1717 */
1718
1719 if (tcp->parent &&
1720 (tcp->parent->flags & TCB_SUSPENDED) &&
1721 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001722 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001723 ++resumed;
1724 }
1725#ifdef TCB_CLONE_THREAD
1726 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1727 /* Some other threads of our parent are waiting too. */
1728 unsigned int i;
1729
1730 /* Resume all the threads that were waiting for this PID. */
1731 for (i = 0; i < tcbtabsize; i++) {
1732 struct tcb *t = tcbtab[i];
1733 if (t->parent == tcp->parent && t != tcp
1734 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1735 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1736 && t->waitpid == tcp->pid) {
1737 error |= resume (t);
1738 ++resumed;
1739 }
1740 }
1741 if (resumed == 0)
1742 /* Noone was waiting for this PID in particular,
1743 so now we might need to resume some wildcarders. */
1744 for (i = 0; i < tcbtabsize; i++) {
1745 struct tcb *t = tcbtab[i];
1746 if (t->parent == tcp->parent && t != tcp
1747 && ((t->flags
1748 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1749 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1750 && t->waitpid <= 0
1751 ) {
1752 error |= resume (t);
1753 break;
1754 }
1755 }
1756 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001757#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001758
1759 return error;
1760}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001761
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001762#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763
Roland McGrath0a463882007-07-05 18:43:16 +00001764/* detach traced process; continue with sig
1765 Never call DETACH twice on the same process as both unattached and
1766 attached-unstopped processes give the same ESRCH. For unattached process we
1767 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768
1769static int
1770detach(tcp, sig)
1771struct tcb *tcp;
1772int sig;
1773{
1774 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001775#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001776 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001777 struct tcb *zombie = NULL;
1778
1779 /* If the group leader is lingering only because of this other
1780 thread now dying, then detach the leader as well. */
1781 if ((tcp->flags & TCB_CLONE_THREAD) &&
1782 tcp->parent->nclone_threads == 1 &&
1783 (tcp->parent->flags & TCB_EXITING))
1784 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001785#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786
1787 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001788 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789
1790#ifdef LINUX
1791 /*
1792 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001793 * before detaching. Arghh. We go through hoops
1794 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001796#if defined(SPARC)
1797#undef PTRACE_DETACH
1798#define PTRACE_DETACH PTRACE_SUNDETACH
1799#endif
Roland McGrath02203312007-06-11 22:06:31 +00001800 /*
1801 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1802 * expected SIGSTOP. We must catch exactly one as otherwise the
1803 * detached process would be left stopped (process state T).
1804 */
1805 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1807 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001808 }
1809 else if (errno != ESRCH) {
1810 /* Shouldn't happen. */
1811 perror("detach: ptrace(PTRACE_DETACH, ...)");
1812 }
Roland McGrath134813a2007-06-02 00:07:33 +00001813 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1814 : tcp->pid),
1815 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001816 if (errno != ESRCH)
1817 perror("detach: checking sanity");
1818 }
Roland McGrath02203312007-06-11 22:06:31 +00001819 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1820 ? tcp->parent->pid : tcp->pid),
1821 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001822 if (errno != ESRCH)
1823 perror("detach: stopping child");
1824 }
Roland McGrath02203312007-06-11 22:06:31 +00001825 else
1826 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001827 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001829#ifdef __WALL
1830 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1831 if (errno == ECHILD) /* Already gone. */
1832 break;
1833 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001834 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001835 break;
1836 }
1837#endif /* __WALL */
1838 /* No __WALL here. */
1839 if (waitpid(tcp->pid, &status, 0) < 0) {
1840 if (errno != ECHILD) {
1841 perror("detach: waiting");
1842 break;
1843 }
1844#ifdef __WCLONE
1845 /* If no processes, try clones. */
1846 if (wait4(tcp->pid, &status, __WCLONE,
1847 NULL) < 0) {
1848 if (errno != ECHILD)
1849 perror("detach: waiting");
1850 break;
1851 }
1852#endif /* __WCLONE */
1853 }
1854#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001855 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001856#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 if (!WIFSTOPPED(status)) {
1858 /* Au revoir, mon ami. */
1859 break;
1860 }
1861 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001862 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001863 break;
1864 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001865 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001866 WSTOPSIG(status) == SYSCALLTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001867 : WSTOPSIG(status));
1868 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001871 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001872#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873
1874#if defined(SUNOS4)
1875 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1876 if (sig && kill(tcp->pid, sig) < 0)
1877 perror("detach: kill");
1878 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001879 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880#endif /* SUNOS4 */
1881
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001882#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001883 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001884#endif
1885
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886 if (!qflag)
1887 fprintf(stderr, "Process %u detached\n", tcp->pid);
1888
1889 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001890
1891#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001892 if (zombie != NULL) {
1893 /* TCP no longer exists therefore you must not detach () it. */
1894 droptcb(zombie);
1895 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001896#endif
1897
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898 return error;
1899}
1900
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001901#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001903static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904{
1905 int pid;
1906 int status;
1907
1908 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909 }
1910}
1911
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001912#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001913
1914static void
1915cleanup()
1916{
1917 int i;
1918 struct tcb *tcp;
1919
Roland McGrathee9d4352002-12-18 04:16:10 +00001920 for (i = 0; i < tcbtabsize; i++) {
1921 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922 if (!(tcp->flags & TCB_INUSE))
1923 continue;
1924 if (debug)
1925 fprintf(stderr,
1926 "cleanup: looking at pid %u\n", tcp->pid);
1927 if (tcp_last &&
1928 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001929 tprintf(" <unfinished ...>");
1930 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931 }
1932 if (tcp->flags & TCB_ATTACHED)
1933 detach(tcp, 0);
1934 else {
1935 kill(tcp->pid, SIGCONT);
1936 kill(tcp->pid, SIGTERM);
1937 }
1938 }
1939 if (cflag)
1940 call_summary(outf);
1941}
1942
1943static void
1944interrupt(sig)
1945int sig;
1946{
1947 interrupted = 1;
1948}
1949
1950#ifndef HAVE_STRERROR
1951
Roland McGrath6d2b3492002-12-30 00:51:30 +00001952#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953extern int sys_nerr;
1954extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001955#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001956
1957const char *
1958strerror(errno)
1959int errno;
1960{
1961 static char buf[64];
1962
1963 if (errno < 1 || errno >= sys_nerr) {
1964 sprintf(buf, "Unknown error %d", errno);
1965 return buf;
1966 }
1967 return sys_errlist[errno];
1968}
1969
1970#endif /* HAVE_STERRROR */
1971
1972#ifndef HAVE_STRSIGNAL
1973
Roland McGrath8f474e02003-01-14 07:53:33 +00001974#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001975extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001977#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1978extern char *_sys_siglist[];
1979#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001980
1981const char *
1982strsignal(sig)
1983int sig;
1984{
1985 static char buf[64];
1986
1987 if (sig < 1 || sig >= NSIG) {
1988 sprintf(buf, "Unknown signal %d", sig);
1989 return buf;
1990 }
1991#ifdef HAVE__SYS_SIGLIST
1992 return _sys_siglist[sig];
1993#else
1994 return sys_siglist[sig];
1995#endif
1996}
1997
1998#endif /* HAVE_STRSIGNAL */
1999
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002000#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001
2002static void
2003rebuild_pollv()
2004{
2005 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002006
Roland McGrathee9d4352002-12-18 04:16:10 +00002007 if (pollv != NULL)
2008 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00002009 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00002010 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002011 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00002012 exit(1);
2013 }
2014
Roland McGrathca16be82003-01-10 19:55:28 +00002015 for (i = j = 0; i < tcbtabsize; i++) {
2016 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017 if (!(tcp->flags & TCB_INUSE))
2018 continue;
2019 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002020 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 j++;
2022 }
2023 if (j != nprocs) {
2024 fprintf(stderr, "strace: proc miscount\n");
2025 exit(1);
2026 }
2027}
2028
2029#ifndef HAVE_POLLABLE_PROCFS
2030
2031static void
2032proc_poll_open()
2033{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 int i;
2035
2036 if (pipe(proc_poll_pipe) < 0) {
2037 perror("pipe");
2038 exit(1);
2039 }
2040 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002041 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042 exit(1);
2043 }
2044 }
2045}
2046
2047static int
2048proc_poll(pollv, nfds, timeout)
2049struct pollfd *pollv;
2050int nfds;
2051int timeout;
2052{
2053 int i;
2054 int n;
2055 struct proc_pollfd pollinfo;
2056
2057 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
2058 return n;
2059 if (n != sizeof(struct proc_pollfd)) {
2060 fprintf(stderr, "panic: short read: %d\n", n);
2061 exit(1);
2062 }
2063 for (i = 0; i < nprocs; i++) {
2064 if (pollv[i].fd == pollinfo.fd)
2065 pollv[i].revents = pollinfo.revents;
2066 else
2067 pollv[i].revents = 0;
2068 }
2069 poller_pid = pollinfo.pid;
2070 return 1;
2071}
2072
2073static void
2074wakeup_handler(sig)
2075int sig;
2076{
2077}
2078
2079static void
2080proc_poller(pfd)
2081int pfd;
2082{
2083 struct proc_pollfd pollinfo;
2084 struct sigaction sa;
2085 sigset_t blocked_set, empty_set;
2086 int i;
2087 int n;
2088 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002089#ifdef FREEBSD
2090 struct procfs_status pfs;
2091#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092
2093 switch (fork()) {
2094 case -1:
2095 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00002096 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002097 case 0:
2098 break;
2099 default:
2100 return;
2101 }
2102
2103 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2104 sa.sa_flags = 0;
2105 sigemptyset(&sa.sa_mask);
2106 sigaction(SIGHUP, &sa, NULL);
2107 sigaction(SIGINT, &sa, NULL);
2108 sigaction(SIGQUIT, &sa, NULL);
2109 sigaction(SIGPIPE, &sa, NULL);
2110 sigaction(SIGTERM, &sa, NULL);
2111 sa.sa_handler = wakeup_handler;
2112 sigaction(SIGUSR1, &sa, NULL);
2113 sigemptyset(&blocked_set);
2114 sigaddset(&blocked_set, SIGUSR1);
2115 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2116 sigemptyset(&empty_set);
2117
2118 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
2119 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00002120 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121 }
2122 n = rl.rlim_cur;
2123 for (i = 0; i < n; i++) {
2124 if (i != pfd && i != proc_poll_pipe[1])
2125 close(i);
2126 }
2127
2128 pollinfo.fd = pfd;
2129 pollinfo.pid = getpid();
2130 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002131#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002132 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2133#else
2134 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2135#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002136 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002137 switch (errno) {
2138 case EINTR:
2139 continue;
2140 case EBADF:
2141 pollinfo.revents = POLLERR;
2142 break;
2143 case ENOENT:
2144 pollinfo.revents = POLLHUP;
2145 break;
2146 default:
2147 perror("proc_poller: PIOCWSTOP");
2148 }
2149 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2150 _exit(0);
2151 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002152 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2154 sigsuspend(&empty_set);
2155 }
2156}
2157
2158#endif /* !HAVE_POLLABLE_PROCFS */
2159
2160static int
2161choose_pfd()
2162{
2163 int i, j;
2164 struct tcb *tcp;
2165
2166 static int last;
2167
2168 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002169 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 /*
2171 * The previous process is ready to run again. We'll
2172 * let it do so if it is currently in a syscall. This
2173 * heuristic improves the readability of the trace.
2174 */
2175 tcp = pfd2tcb(pollv[last].fd);
2176 if (tcp && (tcp->flags & TCB_INSYSCALL))
2177 return pollv[last].fd;
2178 }
2179
2180 for (i = 0; i < nprocs; i++) {
2181 /* Let competing children run round robin. */
2182 j = (i + last + 1) % nprocs;
2183 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2184 tcp = pfd2tcb(pollv[j].fd);
2185 if (!tcp) {
2186 fprintf(stderr, "strace: lost proc\n");
2187 exit(1);
2188 }
2189 droptcb(tcp);
2190 return -1;
2191 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002192 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002193 last = j;
2194 return pollv[j].fd;
2195 }
2196 }
2197 fprintf(stderr, "strace: nothing ready\n");
2198 exit(1);
2199}
2200
2201static int
2202trace()
2203{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002204#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002205 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002206#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207 struct tcb *tcp;
2208 int pfd;
2209 int what;
2210 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002211 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212
2213 for (;;) {
2214 if (interactive)
2215 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2216
2217 if (nprocs == 0)
2218 break;
2219
2220 switch (nprocs) {
2221 case 1:
2222#ifndef HAVE_POLLABLE_PROCFS
2223 if (proc_poll_pipe[0] == -1) {
2224#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002225 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002226 if (!tcp)
2227 continue;
2228 pfd = tcp->pfd;
2229 if (pfd == -1)
2230 continue;
2231 break;
2232#ifndef HAVE_POLLABLE_PROCFS
2233 }
2234 /* fall through ... */
2235#endif /* !HAVE_POLLABLE_PROCFS */
2236 default:
2237#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002238#ifdef POLL_HACK
2239 /* On some systems (e.g. UnixWare) we get too much ugly
2240 "unfinished..." stuff when multiple proceses are in
2241 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002242
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002243 if (in_syscall) {
2244 struct pollfd pv;
2245 tcp = in_syscall;
2246 in_syscall = NULL;
2247 pv.fd = tcp->pfd;
2248 pv.events = POLLWANT;
2249 if ((what = poll (&pv, 1, 1)) < 0) {
2250 if (interrupted)
2251 return 0;
2252 continue;
2253 }
2254 else if (what == 1 && pv.revents & POLLWANT) {
2255 goto FOUND;
2256 }
2257 }
2258#endif
2259
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002260 if (poll(pollv, nprocs, INFTIM) < 0) {
2261 if (interrupted)
2262 return 0;
2263 continue;
2264 }
2265#else /* !HAVE_POLLABLE_PROCFS */
2266 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2267 if (interrupted)
2268 return 0;
2269 continue;
2270 }
2271#endif /* !HAVE_POLLABLE_PROCFS */
2272 pfd = choose_pfd();
2273 if (pfd == -1)
2274 continue;
2275 break;
2276 }
2277
2278 /* Look up `pfd' in our table. */
2279 if ((tcp = pfd2tcb(pfd)) == NULL) {
2280 fprintf(stderr, "unknown pfd: %u\n", pfd);
2281 exit(1);
2282 }
John Hughesb6643082002-05-23 11:02:22 +00002283#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002284 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002285#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002286 /* Get the status of the process. */
2287 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002288#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002289 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002290#else /* FREEBSD */
2291 /* Thanks to some scheduling mystery, the first poller
2292 sometimes waits for the already processed end of fork
2293 event. Doing a non blocking poll here solves the problem. */
2294 if (proc_poll_pipe[0] != -1)
2295 ioctl_result = IOCTL_STATUS (tcp);
2296 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002297 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002298#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002299 ioctl_errno = errno;
2300#ifndef HAVE_POLLABLE_PROCFS
2301 if (proc_poll_pipe[0] != -1) {
2302 if (ioctl_result < 0)
2303 kill(poller_pid, SIGKILL);
2304 else
2305 kill(poller_pid, SIGUSR1);
2306 }
2307#endif /* !HAVE_POLLABLE_PROCFS */
2308 }
2309 if (interrupted)
2310 return 0;
2311
2312 if (interactive)
2313 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2314
2315 if (ioctl_result < 0) {
2316 /* Find out what happened if it failed. */
2317 switch (ioctl_errno) {
2318 case EINTR:
2319 case EBADF:
2320 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002321#ifdef FREEBSD
2322 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002323#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324 case ENOENT:
2325 droptcb(tcp);
2326 continue;
2327 default:
2328 perror("PIOCWSTOP");
2329 exit(1);
2330 }
2331 }
2332
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002333#ifdef FREEBSD
2334 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2335 /* discard first event for a syscall we never entered */
2336 IOCTL (tcp->pfd, PIOCRUN, 0);
2337 continue;
2338 }
Roland McGrath553a6092002-12-16 20:40:39 +00002339#endif
2340
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341 /* clear the just started flag */
2342 tcp->flags &= ~TCB_STARTUP;
2343
2344 /* set current output file */
2345 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002346 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347
2348 if (cflag) {
2349 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002350#ifdef FREEBSD
2351 char buf[1024];
2352 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002353
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002354 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2355 buf[len] = '\0';
2356 sscanf(buf,
2357 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2358 &stime.tv_sec, &stime.tv_usec);
2359 } else
2360 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002361#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002362 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2363 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002364#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002365 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2366 tcp->stime = stime;
2367 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002368 what = tcp->status.PR_WHAT;
2369 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002370#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002371 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002372 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2373 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374 if (trace_syscall(tcp) < 0) {
2375 fprintf(stderr, "syscall trouble\n");
2376 exit(1);
2377 }
2378 }
2379 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002380#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002381 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002382#ifdef POLL_HACK
2383 in_syscall = tcp;
2384#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 case PR_SYSEXIT:
2386 if (trace_syscall(tcp) < 0) {
2387 fprintf(stderr, "syscall trouble\n");
2388 exit(1);
2389 }
2390 break;
2391 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002392 if (cflag != CFLAG_ONLY_STATS
2393 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 printleader(tcp);
2395 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002396 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002397 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002398#ifdef PR_INFO
2399 if (tcp->status.PR_INFO.si_signo == what) {
2400 printleader(tcp);
2401 tprintf(" siginfo=");
2402 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002403 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002404 }
2405#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002406 }
2407 break;
2408 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002409 if (cflag != CFLAGS_ONLY_STATS
2410 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411 printleader(tcp);
2412 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002413 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002414 }
2415 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002416#ifdef FREEBSD
2417 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002418 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002419#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002421 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002422 exit(1);
2423 break;
2424 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002425 /* Remember current print column before continuing. */
2426 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002427 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002428#ifndef FREEBSD
Andreas Schwab372cc842010-07-09 11:49:27 +02002429 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002430#else
Andreas Schwab372cc842010-07-09 11:49:27 +02002431 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002432#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002433 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 perror("PIOCRUN");
2435 exit(1);
2436 }
2437 }
2438 return 0;
2439}
2440
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002441#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002443#ifdef TCB_GROUP_EXITING
2444/* Handle an exit detach or death signal that is taking all the
2445 related clone threads with it. This is called in three circumstances:
2446 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2447 SIG == 0 Continuing TCP will perform an exit_group syscall.
2448 SIG == other Continuing TCP with SIG will kill the process.
2449*/
2450static int
2451handle_group_exit(struct tcb *tcp, int sig)
2452{
2453 /* We need to locate our records of all the clone threads
2454 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002455 struct tcb *leader = NULL;
2456
2457 if (tcp->flags & TCB_CLONE_THREAD)
2458 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002459
2460 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002461 if (leader != NULL && leader != tcp
2462 && !(leader->flags & TCB_GROUP_EXITING)
2463 && !(tcp->flags & TCB_STARTUP)
2464 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002465 fprintf(stderr,
2466 "PANIC: handle_group_exit: %d leader %d\n",
2467 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002468 }
2469 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002470#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002471 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002472#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002473 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002474 }
2475 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002476 /* Mark that we are taking the process down. */
2477 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002478 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002479 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002480 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002481 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002482 } else {
2483 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2484 cleanup();
2485 return -1;
2486 }
2487 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002488 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002489 if (leader != tcp)
2490 droptcb(tcp);
2491 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002492 /* The leader will report to us as parent now,
2493 and then we'll get to the SIG==-1 case. */
2494 return 0;
2495 }
2496 }
2497
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002498 return 0;
2499}
2500#endif
2501
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002502#ifdef LINUX
2503static int
2504handle_ptrace_event(int status, struct tcb *tcp)
2505{
2506 if (status >> 16 == PTRACE_EVENT_VFORK ||
2507 status >> 16 == PTRACE_EVENT_CLONE ||
2508 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002509 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002510
2511 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2512 if (errno != ESRCH) {
2513 fprintf(stderr, "\
2514%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2515 progname);
2516 cleanup();
2517 exit(1);
2518 }
2519 return -1;
2520 }
2521 return handle_new_child(tcp, childpid, 0);
2522 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002523 if (status >> 16 == PTRACE_EVENT_EXEC) {
2524 if (debug)
2525 fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
2526 return 0;
2527 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002528 return 1;
2529}
2530#endif
2531
Roland McGratheb9e2e82009-06-02 16:49:22 -07002532static int
2533trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534{
2535 int pid;
2536 int wait_errno;
2537 int status;
2538 struct tcb *tcp;
2539#ifdef LINUX
2540 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002541#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002542 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002543#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544#endif /* LINUX */
2545
Roland McGratheb9e2e82009-06-02 16:49:22 -07002546 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002547 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002548 return 0;
2549 if (interactive)
2550 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002552#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002553 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002554 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002555 /* this kernel does not support __WALL */
2556 wait4_options &= ~__WALL;
2557 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002558 pid = wait4(-1, &status, wait4_options,
2559 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002560 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002561 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002562 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002563 pid = wait4(-1, &status, __WCLONE,
2564 cflag ? &ru : NULL);
2565 if (pid == -1) {
2566 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002567 "failed: %s\n", strerror(errno));
2568 }
2569 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002570#else
2571 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2572#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002573#endif /* LINUX */
2574#ifdef SUNOS4
2575 pid = wait(&status);
2576#endif /* SUNOS4 */
2577 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002578 if (interactive)
2579 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002580
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002581 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002582 switch (wait_errno) {
2583 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002585 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002586 /*
2587 * We would like to verify this case
2588 * but sometimes a race in Solbourne's
2589 * version of SunOS sometimes reports
2590 * ECHILD before sending us SIGCHILD.
2591 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002592 return 0;
2593 default:
2594 errno = wait_errno;
2595 perror("strace: wait");
2596 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002597 }
2598 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002599 if (pid == popen_pid) {
2600 if (WIFEXITED(status) || WIFSIGNALED(status))
2601 popen_pid = -1;
2602 continue;
2603 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002604 if (debug)
2605 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2606
2607 /* Look up `pid' in our table. */
2608 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002609#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002610 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002611 /* This is needed to go with the CLONE_PTRACE
2612 changes in process.c/util.c: we might see
2613 the child's initial trap before we see the
2614 parent return from the clone syscall.
2615 Leave the child suspended until the parent
2616 returns from its system call. Only then
2617 will we have the association of parent and
2618 child so that we know how to do clearbpt
2619 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002620 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002621 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002622 if (!qflag)
2623 fprintf(stderr, "\
2624Process %d attached (waiting for parent)\n",
2625 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002626 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002627 else
2628 /* This can happen if a clone call used
2629 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002630#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002631 {
2632 fprintf(stderr, "unknown pid: %u\n", pid);
2633 if (WIFSTOPPED(status))
2634 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2635 exit(1);
2636 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002637 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002638 /* set current output file */
2639 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002640 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002641 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002642#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002643 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2644 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002645#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002646 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002647
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002648 if (tcp->flags & TCB_SUSPENDED) {
2649 /*
2650 * Apparently, doing any ptrace() call on a stopped
2651 * process, provokes the kernel to report the process
2652 * status again on a subsequent wait(), even if the
2653 * process has not been actually restarted.
2654 * Since we have inspected the arguments of suspended
2655 * processes we end up here testing for this case.
2656 */
2657 continue;
2658 }
2659 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002660 if (pid == strace_child)
2661 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002662 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002663 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2664 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002665 tprintf("+++ killed by %s %s+++",
2666 signame(WTERMSIG(status)),
2667#ifdef WCOREDUMP
2668 WCOREDUMP(status) ? "(core dumped) " :
2669#endif
2670 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002671 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002672 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002673#ifdef TCB_GROUP_EXITING
2674 handle_group_exit(tcp, -1);
2675#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002676 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002677#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002678 continue;
2679 }
2680 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002681 if (pid == strace_child)
2682 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002683 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002684 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2685 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002686#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002687 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002688 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002689#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002690 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002691 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002692 "PANIC: attached pid %u exited with %d\n",
2693 pid, WEXITSTATUS(status));
2694 }
Roland McGrath0a396902003-06-10 03:05:53 +00002695 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002696 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002697 tprintf(" <unfinished ... exit status %d>\n",
2698 WEXITSTATUS(status));
2699 tcp_last = NULL;
2700 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002701#ifdef TCB_GROUP_EXITING
2702 handle_group_exit(tcp, -1);
2703#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002704 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002705#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002706 continue;
2707 }
2708 if (!WIFSTOPPED(status)) {
2709 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2710 droptcb(tcp);
2711 continue;
2712 }
2713 if (debug)
2714 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002715 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002716
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002717 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002718 if (handle_ptrace_event(status, tcp) != 1)
2719 goto tracing;
2720 }
2721
Roland McGrath02203312007-06-11 22:06:31 +00002722 /*
2723 * Interestingly, the process may stop
2724 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002725 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002726 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002727 * A no-MMU vforked child won't send up a signal,
2728 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002729 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002730 if ((tcp->flags & TCB_STARTUP) &&
2731 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002732 /*
2733 * This flag is there to keep us in sync.
2734 * Next time this process stops it should
2735 * really be entering a system call.
2736 */
2737 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002738 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002739 /*
2740 * One example is a breakpoint inherited from
2741 * parent through fork ().
2742 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002743 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2744 droptcb(tcp);
2745 cleanup();
2746 return -1;
2747 }
2748 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002749#ifdef LINUX
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002750 int options = ptrace_setoptions_for_all;
2751 if (followfork && (tcp->parent == NULL))
2752 options |= ptrace_setoptions_followfork;
2753 if (options) {
2754 if (debug)
2755 fprintf(stderr, "setting opts %x on pid %d\n", options, tcp->pid);
2756 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, options) < 0) {
2757 if (errno != ESRCH) {
2758 /* Should never happen, really */
2759 error_msg_and_die("PTRACE_SETOPTIONS");
2760 }
2761 }
2762 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002763#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002764 goto tracing;
2765 }
2766
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002767 if (WSTOPSIG(status) != SYSCALLTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002768 if (WSTOPSIG(status) == SIGSTOP &&
2769 (tcp->flags & TCB_SIGTRAPPED)) {
2770 /*
2771 * Trapped attempt to block SIGTRAP
2772 * Hope we are back in control now.
2773 */
2774 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002775 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002776 cleanup();
2777 return -1;
2778 }
2779 continue;
2780 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002781 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002782 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002783 siginfo_t si;
2784#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002785 long pc = 0;
2786 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002787
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002788 upeek(tcp, PT_CR_IPSR, &psr);
2789 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002790
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002791# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002792 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002793# define PC_FORMAT_STR " @ %lx"
2794# define PC_FORMAT_ARG pc
2795#else
2796# define PC_FORMAT_STR "%s"
2797# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002798#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002799 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002800 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2801 tprintf("--- ");
2802 printsiginfo(&si, verbose(tcp));
2803 tprintf(" (%s)" PC_FORMAT_STR " ---",
2804 strsignal(WSTOPSIG(status)),
2805 PC_FORMAT_ARG);
2806 } else
2807 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2808 strsignal(WSTOPSIG(status)),
2809 signame(WSTOPSIG(status)),
2810 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002811 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002812 }
Roland McGrath05690952004-10-20 01:00:27 +00002813 if (((tcp->flags & TCB_ATTACHED) ||
2814 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002815 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002816#ifdef TCB_GROUP_EXITING
2817 handle_group_exit(tcp, WSTOPSIG(status));
2818#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002819 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002820#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002821 continue;
2822 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002823 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002824 cleanup();
2825 return -1;
2826 }
2827 tcp->flags &= ~TCB_SUSPENDED;
2828 continue;
2829 }
Roland McGrath02203312007-06-11 22:06:31 +00002830 /* we handled the STATUS, we are permitted to interrupt now. */
2831 if (interrupted)
2832 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002833 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2834 /* ptrace() failed in trace_syscall() with ESRCH.
2835 * Likely a result of process disappearing mid-flight.
2836 * Observed case: exit_group() terminating
2837 * all processes in thread group. In this case, threads
2838 * "disappear" in an unpredictable moment without any
2839 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002840 */
2841 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002842 if (tcp_last) {
2843 /* Do we have dangling line "syscall(param, param"?
2844 * Finish the line then. We cannot
2845 */
2846 tcp_last->flags |= TCB_REPRINT;
2847 tprintf(" <unfinished ...>");
2848 printtrailer();
2849 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002850 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002851 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002852 ptrace(PTRACE_KILL,
2853 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002854 droptcb(tcp);
2855 }
2856 continue;
2857 }
2858 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002859#ifdef TCB_GROUP_EXITING
2860 if (tcp->flags & TCB_GROUP_EXITING) {
2861 if (handle_group_exit(tcp, 0) < 0)
2862 return -1;
2863 continue;
2864 }
2865#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002866 if (tcp->flags & TCB_ATTACHED)
2867 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002868 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002869 cleanup();
2870 return -1;
2871 }
2872 continue;
2873 }
2874 if (tcp->flags & TCB_SUSPENDED) {
2875 if (!qflag)
2876 fprintf(stderr, "Process %u suspended\n", pid);
2877 continue;
2878 }
2879 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002880 /* Remember current print column before continuing. */
2881 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002882 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002883 cleanup();
2884 return -1;
2885 }
2886 }
2887 return 0;
2888}
2889
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002890#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002891
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002892#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002893
2894void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002895tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002896{
2897 va_list args;
2898
Andreas Schwabe5355de2009-10-27 16:56:43 +01002899 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002900 if (outf) {
2901 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002902 if (n < 0) {
2903 if (outf != stderr)
2904 perror(outfname == NULL
2905 ? "<writing to pipe>" : outfname);
2906 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002907 curcol += n;
2908 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002909 va_end(args);
2910 return;
2911}
2912
2913void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002914printleader(tcp)
2915struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002916{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002917 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002918 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002919 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002920 tprintf(" <unavailable>)");
2921 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002922 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002923 tprintf("= ? <unavailable>\n");
2924 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002925 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002926 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002927 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002928 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002929 }
2930 curcol = 0;
2931 if ((followfork == 1 || pflag_seen > 1) && outfname)
2932 tprintf("%-5d ", tcp->pid);
2933 else if (nprocs > 1 && !outfname)
2934 tprintf("[pid %5u] ", tcp->pid);
2935 if (tflag) {
2936 char str[sizeof("HH:MM:SS")];
2937 struct timeval tv, dtv;
2938 static struct timeval otv;
2939
2940 gettimeofday(&tv, NULL);
2941 if (rflag) {
2942 if (otv.tv_sec == 0)
2943 otv = tv;
2944 tv_sub(&dtv, &tv, &otv);
2945 tprintf("%6ld.%06ld ",
2946 (long) dtv.tv_sec, (long) dtv.tv_usec);
2947 otv = tv;
2948 }
2949 else if (tflag > 2) {
2950 tprintf("%ld.%06ld ",
2951 (long) tv.tv_sec, (long) tv.tv_usec);
2952 }
2953 else {
2954 time_t local = tv.tv_sec;
2955 strftime(str, sizeof(str), "%T", localtime(&local));
2956 if (tflag > 1)
2957 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2958 else
2959 tprintf("%s ", str);
2960 }
2961 }
2962 if (iflag)
2963 printcall(tcp);
2964}
2965
2966void
2967tabto(col)
2968int col;
2969{
2970 if (curcol < col)
2971 tprintf("%*s", col - curcol, "");
2972}
2973
2974void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002975printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002976{
2977 tprintf("\n");
2978 tcp_last = NULL;
2979}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002980
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002981#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002982
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002983int
2984mp_ioctl(int fd, int cmd, void *arg, int size)
2985{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002986 struct iovec iov[2];
2987 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002988
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002989 iov[0].iov_base = &cmd;
2990 iov[0].iov_len = sizeof cmd;
2991 if (arg) {
2992 ++n;
2993 iov[1].iov_base = arg;
2994 iov[1].iov_len = size;
2995 }
Roland McGrath553a6092002-12-16 20:40:39 +00002996
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002997 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002998}
2999
3000#endif