blob: 23c3650fd6c869e99e58ead720a16b86fdc9fa05 [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>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <signal.h>
37#include <errno.h>
38#include <sys/param.h>
39#include <fcntl.h>
40#include <sys/resource.h>
41#include <sys/wait.h>
42#include <sys/stat.h>
43#include <pwd.h>
44#include <grp.h>
45#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000046#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# include <asm/unistd.h>
51# if defined __NR_tgkill
52# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53# elif defined __NR_tkill
54# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55# else
56 /* kill() may choose arbitrarily the target task of the process group
57 while we later wait on a that specific TID. PID process waits become
58 TID task specific waits for a process under ptrace(2). */
59# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61# endif
62#endif
63
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000064#if defined(IA64) && defined(LINUX)
65# include <asm/ptrace_offsets.h>
66#endif
67
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000068#ifdef USE_PROCFS
69#include <poll.h>
70#endif
71
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000072#ifdef SVR4
73#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000074#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000075#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000076#include <sys/uio.h>
77#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000079#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000080extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000081extern int optind;
82extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000083
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
Roland McGrath41c48222008-07-18 00:25:10 +000085int debug = 0, followfork = 0;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000086int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
87static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000088/*
89 * daemonized_tracer supports -D option.
90 * With this option, strace forks twice.
91 * Unlike normal case, with -D *grandparent* process exec's,
92 * becoming a traced process. Child exits (this prevents traced process
93 * from having children it doesn't expect to have), and grandchild
94 * attaches to grandparent similarly to strace -p PID.
95 * This allows for more transparent interaction in cases
96 * when process and its parent are communicating via signals,
97 * wait() etc. Without -D, strace process gets lodged in between,
98 * disrupting parent<->child link.
99 */
100static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000102/* Sometimes we want to print only succeeding syscalls. */
103int not_failing_only = 0;
104
Dmitry V. Levina6809652008-11-10 17:14:58 +0000105static int exit_code = 0;
106static int strace_child = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700107
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000108static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109uid_t run_uid;
110gid_t run_gid;
111
112int acolumn = DEFAULT_ACOLUMN;
113int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000114static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100116static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000117struct tcb **tcbtab;
118unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119char *progname;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700120extern char **environ;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
Andreas Schwabe5355de2009-10-27 16:56:43 +0100122static int detach(struct tcb *tcp, int sig);
123static int trace(void);
124static void cleanup(void);
125static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126static sigset_t empty_set, blocked_set;
127
128#ifdef HAVE_SIG_ATOMIC_T
129static volatile sig_atomic_t interrupted;
130#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132#endif /* !HAVE_SIG_ATOMIC_T */
133
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000134#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135
Andreas Schwabe5355de2009-10-27 16:56:43 +0100136static struct tcb *pfd2tcb(int pfd);
137static void reaper(int sig);
138static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000139static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140
141#ifndef HAVE_POLLABLE_PROCFS
142
Andreas Schwabe5355de2009-10-27 16:56:43 +0100143static void proc_poll_open(void);
144static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145
146struct proc_pollfd {
147 int fd;
148 int revents;
149 int pid;
150};
151
152static int poller_pid;
153static int proc_poll_pipe[2] = { -1, -1 };
154
155#endif /* !HAVE_POLLABLE_PROCFS */
156
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000157#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000158#define POLLWANT POLLWRNORM
159#else
160#define POLLWANT POLLPRI
161#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000162#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163
164static void
165usage(ofp, exitval)
166FILE *ofp;
167int exitval;
168{
169 fprintf(ofp, "\
170usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000171 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
172 [command [arg ...]]\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000173 or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000174 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175-c -- count time, calls, and errors for each syscall and report summary\n\
176-f -- follow forks, -ff -- with output into separate files\n\
177-F -- attempt to follow vforks, -h -- print help message\n\
178-i -- print instruction pointer at time of syscall\n\
179-q -- suppress messages about attaching, detaching, etc.\n\
180-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
181-T -- print time spent in each syscall, -V -- print version\n\
182-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
183-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
184-a column -- alignment COLUMN for printing syscall results (default %d)\n\
185-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
186 options: trace, abbrev, verbose, raw, signal, read, or write\n\
187-o file -- send trace output to FILE instead of stderr\n\
188-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
189-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000190-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000191-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
192-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
193-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000194-E var=val -- put var=val in the environment for command\n\
195-E var -- remove var from the environment for command\n\
196" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000197-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000198 */
199, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 exit(exitval);
201}
202
203#ifdef SVR4
204#ifdef MIPS
205void
206foobar()
207{
208}
209#endif /* MIPS */
210#endif /* SVR4 */
211
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400212/* Glue for systems without a MMU that cannot provide fork() */
213#ifdef HAVE_FORK
214# define strace_vforked 0
215#else
216# define strace_vforked 1
217# define fork() vfork()
218#endif
219
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000220static int
221set_cloexec_flag(int fd)
222{
223 int flags, newflags;
224
225 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
226 {
227 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
228 progname, strerror(errno));
229 return -1;
230 }
231
232 newflags = flags | FD_CLOEXEC;
233 if (flags == newflags)
234 return 0;
235
236 if (fcntl(fd, F_SETFD, newflags) < 0)
237 {
238 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
239 progname, strerror(errno));
240 return -1;
241 }
242
243 return 0;
244}
245
246/*
247 * When strace is setuid executable, we have to swap uids
248 * before and after filesystem and process management operations.
249 */
250static void
251swap_uid(void)
252{
253#ifndef SVR4
254 int euid = geteuid(), uid = getuid();
255
256 if (euid != uid && setreuid(euid, uid) < 0)
257 {
258 fprintf(stderr, "%s: setreuid: %s\n",
259 progname, strerror(errno));
260 exit(1);
261 }
262#endif
263}
264
Roland McGrath4bfa6262007-07-05 20:03:16 +0000265#if _LFS64_LARGEFILE
266# define fopen_for_output fopen64
267#else
268# define fopen_for_output fopen
269#endif
270
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000271static FILE *
272strace_fopen(const char *path, const char *mode)
273{
274 FILE *fp;
275
276 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000277 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000278 fprintf(stderr, "%s: can't fopen '%s': %s\n",
279 progname, path, strerror(errno));
280 swap_uid();
281 if (fp && set_cloexec_flag(fileno(fp)) < 0)
282 {
283 fclose(fp);
284 fp = NULL;
285 }
286 return fp;
287}
288
289static int popen_pid = -1;
290
291#ifndef _PATH_BSHELL
292# define _PATH_BSHELL "/bin/sh"
293#endif
294
295/*
296 * We cannot use standard popen(3) here because we have to distinguish
297 * popen child process from other processes we trace, and standard popen(3)
298 * does not export its child's pid.
299 */
300static FILE *
301strace_popen(const char *command)
302{
303 int fds[2];
304
305 swap_uid();
306 if (pipe(fds) < 0)
307 {
308 fprintf(stderr, "%s: pipe: %s\n",
309 progname, strerror(errno));
310 swap_uid();
311 return NULL;
312 }
313
314 if (set_cloexec_flag(fds[1]) < 0)
315 {
316 close(fds[0]);
317 close(fds[1]);
318 swap_uid();
319 return NULL;
320 }
321
322 if ((popen_pid = fork()) == -1)
323 {
324 fprintf(stderr, "%s: fork: %s\n",
325 progname, strerror(errno));
326 close(fds[0]);
327 close(fds[1]);
328 swap_uid();
329 return NULL;
330 }
331
332 if (popen_pid)
333 {
334 /* parent */
335 close(fds[0]);
336 swap_uid();
337 return fdopen(fds[1], "w");
338 } else
339 {
340 /* child */
341 close(fds[1]);
342 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
343 {
344 fprintf(stderr, "%s: dup2: %s\n",
345 progname, strerror(errno));
346 _exit(1);
347 }
348 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
349 fprintf(stderr, "%s: execl: %s: %s\n",
350 progname, _PATH_BSHELL, strerror(errno));
351 _exit(1);
352 }
353}
354
355static int
356newoutf(struct tcb *tcp)
357{
358 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000359 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360 FILE *fp;
361
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000362 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000363 if ((fp = strace_fopen(name, "w")) == NULL)
364 return -1;
365 tcp->outf = fp;
366 }
367 return 0;
368}
369
Roland McGrath02203312007-06-11 22:06:31 +0000370static void
371startup_attach(void)
372{
373 int tcbi;
374 struct tcb *tcp;
375
376 /*
377 * Block user interruptions as we would leave the traced
378 * process stopped (process state T) if we would terminate in
379 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
380 * We rely on cleanup () from this point on.
381 */
382 if (interactive)
383 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
384
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000385 if (daemonized_tracer) {
386 pid_t pid = fork();
387 if (pid < 0) {
388 _exit(1);
389 }
390 if (pid) { /* parent */
391 /*
392 * Wait for child to attach to straced process
393 * (our parent). Child SIGKILLs us after it attached.
394 * Parent's wait() is unblocked by our death,
395 * it proceeds to exec the straced program.
396 */
397 pause();
398 _exit(0); /* paranoia */
399 }
400 }
401
Roland McGrath02203312007-06-11 22:06:31 +0000402 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
403 tcp = tcbtab[tcbi];
404 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
405 continue;
406#ifdef LINUX
407 if (tcp->flags & TCB_CLONE_THREAD)
408 continue;
409#endif
410 /* Reinitialize the output since it may have changed. */
411 tcp->outf = outf;
412 if (newoutf(tcp) < 0)
413 exit(1);
414
415#ifdef USE_PROCFS
416 if (proc_open(tcp, 1) < 0) {
417 fprintf(stderr, "trouble opening proc file\n");
418 droptcb(tcp);
419 continue;
420 }
421#else /* !USE_PROCFS */
422# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000423 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000424 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000425 DIR *dir;
426
427 sprintf(procdir, "/proc/%d/task", tcp->pid);
428 dir = opendir(procdir);
429 if (dir != NULL) {
430 unsigned int ntid = 0, nerr = 0;
431 struct dirent *de;
432 int tid;
433 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000434 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000435 continue;
436 tid = atoi(de->d_name);
437 if (tid <= 0)
438 continue;
439 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000440 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000441 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000442 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000443 tcp = alloctcb(tid);
Roland McGratheb9e2e82009-06-02 16:49:22 -0700444 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000445 tcbtab[tcbi]->nchildren++;
446 tcbtab[tcbi]->nclone_threads++;
447 tcbtab[tcbi]->nclone_detached++;
448 tcp->parent = tcbtab[tcbi];
449 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000450 if (interactive) {
451 sigprocmask(SIG_SETMASK, &empty_set, NULL);
452 if (interrupted)
453 return;
454 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
455 }
Roland McGrath02203312007-06-11 22:06:31 +0000456 }
457 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000458 ntid -= nerr;
459 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000460 perror("attach: ptrace(PTRACE_ATTACH, ...)");
461 droptcb(tcp);
462 continue;
463 }
464 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000465 fprintf(stderr, ntid > 1
466? "Process %u attached with %u threads - interrupt to quit\n"
467: "Process %u attached - interrupt to quit\n",
468 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000469 }
470 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000471 } /* if (opendir worked) */
472 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000473# endif
474 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
475 perror("attach: ptrace(PTRACE_ATTACH, ...)");
476 droptcb(tcp);
477 continue;
478 }
479 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000480
481 if (daemonized_tracer) {
482 /*
483 * It is our grandparent we trace, not a -p PID.
484 * Don't want to just detach on exit, so...
485 */
486 tcp->flags &= ~TCB_ATTACHED;
487 /*
488 * Make parent go away.
489 * Also makes grandparent's wait() unblock.
490 */
491 kill(getppid(), SIGKILL);
492 }
493
Roland McGrath02203312007-06-11 22:06:31 +0000494#endif /* !USE_PROCFS */
495 if (!qflag)
496 fprintf(stderr,
497 "Process %u attached - interrupt to quit\n",
498 tcp->pid);
499 }
500
501 if (interactive)
502 sigprocmask(SIG_SETMASK, &empty_set, NULL);
503}
504
505static void
506startup_child (char **argv)
507{
508 struct stat statbuf;
509 const char *filename;
510 char pathname[MAXPATHLEN];
511 int pid = 0;
512 struct tcb *tcp;
513
514 filename = argv[0];
515 if (strchr(filename, '/')) {
516 if (strlen(filename) > sizeof pathname - 1) {
517 errno = ENAMETOOLONG;
518 perror("strace: exec");
519 exit(1);
520 }
521 strcpy(pathname, filename);
522 }
523#ifdef USE_DEBUGGING_EXEC
524 /*
525 * Debuggers customarily check the current directory
526 * first regardless of the path but doing that gives
527 * security geeks a panic attack.
528 */
529 else if (stat(filename, &statbuf) == 0)
530 strcpy(pathname, filename);
531#endif /* USE_DEBUGGING_EXEC */
532 else {
533 char *path;
534 int m, n, len;
535
536 for (path = getenv("PATH"); path && *path; path += m) {
537 if (strchr(path, ':')) {
538 n = strchr(path, ':') - path;
539 m = n + 1;
540 }
541 else
542 m = n = strlen(path);
543 if (n == 0) {
544 if (!getcwd(pathname, MAXPATHLEN))
545 continue;
546 len = strlen(pathname);
547 }
548 else if (n > sizeof pathname - 1)
549 continue;
550 else {
551 strncpy(pathname, path, n);
552 len = n;
553 }
554 if (len && pathname[len - 1] != '/')
555 pathname[len++] = '/';
556 strcpy(pathname + len, filename);
557 if (stat(pathname, &statbuf) == 0 &&
558 /* Accept only regular files
559 with some execute bits set.
560 XXX not perfect, might still fail */
561 S_ISREG(statbuf.st_mode) &&
562 (statbuf.st_mode & 0111))
563 break;
564 }
565 }
566 if (stat(pathname, &statbuf) < 0) {
567 fprintf(stderr, "%s: %s: command not found\n",
568 progname, filename);
569 exit(1);
570 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000571 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000572 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000573 perror("strace: fork");
574 cleanup();
575 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000576 }
577 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
578 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
579 ) {
580 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000581#ifdef USE_PROCFS
582 if (outf != stderr) close (fileno (outf));
583#ifdef MIPS
584 /* Kludge for SGI, see proc_open for details. */
585 sa.sa_handler = foobar;
586 sa.sa_flags = 0;
587 sigemptyset(&sa.sa_mask);
588 sigaction(SIGINT, &sa, NULL);
589#endif /* MIPS */
590#ifndef FREEBSD
591 pause();
592#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000593 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000594#endif /* FREEBSD */
595#else /* !USE_PROCFS */
596 if (outf!=stderr)
597 close(fileno (outf));
598
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000599 if (!daemonized_tracer) {
600 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
601 perror("strace: ptrace(PTRACE_TRACEME, ...)");
602 exit(1);
603 }
604 if (debug)
605 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000606 }
Roland McGrath02203312007-06-11 22:06:31 +0000607
608 if (username != NULL || geteuid() == 0) {
609 uid_t run_euid = run_uid;
610 gid_t run_egid = run_gid;
611
612 if (statbuf.st_mode & S_ISUID)
613 run_euid = statbuf.st_uid;
614 if (statbuf.st_mode & S_ISGID)
615 run_egid = statbuf.st_gid;
616
617 /*
618 * It is important to set groups before we
619 * lose privileges on setuid.
620 */
621 if (username != NULL) {
622 if (initgroups(username, run_gid) < 0) {
623 perror("initgroups");
624 exit(1);
625 }
626 if (setregid(run_gid, run_egid) < 0) {
627 perror("setregid");
628 exit(1);
629 }
630 if (setreuid(run_uid, run_euid) < 0) {
631 perror("setreuid");
632 exit(1);
633 }
634 }
635 }
636 else
637 setreuid(run_uid, run_uid);
638
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000639 if (!daemonized_tracer) {
640 /*
641 * Induce an immediate stop so that the parent
642 * will resume us with PTRACE_SYSCALL and display
643 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400644 * Unless of course we're on a no-MMU system where
645 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000646 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400647 if (!strace_vforked)
648 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000649 } else {
650 struct sigaction sv_sigchld;
651 sigaction(SIGCHLD, NULL, &sv_sigchld);
652 /*
653 * Make sure it is not SIG_IGN, otherwise wait
654 * will not block.
655 */
656 signal(SIGCHLD, SIG_DFL);
657 /*
658 * Wait for grandchild to attach to us.
659 * It kills child after that, and wait() unblocks.
660 */
661 alarm(3);
662 wait(NULL);
663 alarm(0);
664 sigaction(SIGCHLD, &sv_sigchld, NULL);
665 }
Roland McGrath02203312007-06-11 22:06:31 +0000666#endif /* !USE_PROCFS */
667
668 execv(pathname, argv);
669 perror("strace: exec");
670 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000671 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000672
673 /* We are the tracer. */
674 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000675 if (daemonized_tracer) {
676 /* We want subsequent startup_attach() to attach to it. */
677 tcp->flags |= TCB_ATTACHED;
678 }
Roland McGrath02203312007-06-11 22:06:31 +0000679#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000680 if (proc_open(tcp, 0) < 0) {
681 fprintf(stderr, "trouble opening proc file\n");
682 cleanup();
683 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000684 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000685#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000686}
687
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000689main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000691 struct tcb *tcp;
692 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000693 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694 struct sigaction sa;
695
696 static char buf[BUFSIZ];
697
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000698 progname = argv[0] ? argv[0] : "strace";
699
Roland McGrathee9d4352002-12-18 04:16:10 +0000700 /* Allocate the initial tcbtab. */
701 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000702 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000703 fprintf(stderr, "%s: out of memory\n", progname);
704 exit(1);
705 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000706 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000707 fprintf(stderr, "%s: out of memory\n", progname);
708 exit(1);
709 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000710 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
711 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
712
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000713 outf = stderr;
714 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000715 set_sortby(DEFAULT_SORTBY);
716 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000717 qualify("trace=all");
718 qualify("abbrev=all");
719 qualify("verbose=all");
720 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000721 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000722 "+cdfFhiqrtTvVxz"
723#ifndef USE_PROCFS
724 "D"
725#endif
726 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000727 switch (c) {
728 case 'c':
729 cflag++;
730 dtime++;
731 break;
732 case 'd':
733 debug++;
734 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000735#ifndef USE_PROCFS
736 /* Experimental, not documented in manpage yet. */
737 case 'D':
738 daemonized_tracer = 1;
739 break;
740#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000741 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000742 optF = 1;
743 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000744 case 'f':
745 followfork++;
746 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000747 case 'h':
748 usage(stdout, 0);
749 break;
750 case 'i':
751 iflag++;
752 break;
753 case 'q':
754 qflag++;
755 break;
756 case 'r':
757 rflag++;
758 tflag++;
759 break;
760 case 't':
761 tflag++;
762 break;
763 case 'T':
764 dtime++;
765 break;
766 case 'x':
767 xflag++;
768 break;
769 case 'v':
770 qualify("abbrev=none");
771 break;
772 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000773 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000774 exit(0);
775 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000776 case 'z':
777 not_failing_only = 1;
778 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779 case 'a':
780 acolumn = atoi(optarg);
781 break;
782 case 'e':
783 qualify(optarg);
784 break;
785 case 'o':
786 outfname = strdup(optarg);
787 break;
788 case 'O':
789 set_overhead(atoi(optarg));
790 break;
791 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000792 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000793 fprintf(stderr, "%s: Invalid process id: %s\n",
794 progname, optarg);
795 break;
796 }
797 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000798 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000799 break;
800 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000801 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802 tcp->flags |= TCB_ATTACHED;
803 pflag_seen++;
804 break;
805 case 's':
806 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000807 if (max_strlen < 0) {
808 fprintf(stderr,
809 "%s: invalid -s argument: %s\n",
810 progname, optarg);
811 exit(1);
812 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813 break;
814 case 'S':
815 set_sortby(optarg);
816 break;
817 case 'u':
818 username = strdup(optarg);
819 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000820 case 'E':
821 if (putenv(optarg) < 0) {
822 fprintf(stderr, "%s: out of memory\n",
823 progname);
824 exit(1);
825 }
826 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000827 default:
828 usage(stderr, 1);
829 break;
830 }
831 }
832
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000833 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000834 usage(stderr, 1);
835
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000836 if (!followfork)
837 followfork = optF;
838
Roland McGrathcb9def62006-04-25 07:48:03 +0000839 if (followfork > 1 && cflag) {
840 fprintf(stderr,
841 "%s: -c and -ff are mutually exclusive options\n",
842 progname);
843 exit(1);
844 }
845
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000846 /* See if they want to run as another user. */
847 if (username != NULL) {
848 struct passwd *pent;
849
850 if (getuid() != 0 || geteuid() != 0) {
851 fprintf(stderr,
852 "%s: you must be root to use the -u option\n",
853 progname);
854 exit(1);
855 }
856 if ((pent = getpwnam(username)) == NULL) {
857 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000858 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000859 exit(1);
860 }
861 run_uid = pent->pw_uid;
862 run_gid = pent->pw_gid;
863 }
864 else {
865 run_uid = getuid();
866 run_gid = getgid();
867 }
868
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000869 /* Check if they want to redirect the output. */
870 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000871 /* See if they want to pipe the output. */
872 if (outfname[0] == '|' || outfname[0] == '!') {
873 /*
874 * We can't do the <outfname>.PID funny business
875 * when using popen, so prohibit it.
876 */
877 if (followfork > 1) {
878 fprintf(stderr, "\
879%s: piping the output and -ff are mutually exclusive options\n",
880 progname);
881 exit(1);
882 }
883
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000884 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000885 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000886 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000887 else if (followfork <= 1 &&
888 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 }
891
Roland McGrath37b9a662003-11-07 02:26:54 +0000892 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000894 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000896 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000897 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000898 /* Valid states here:
899 optind < argc pflag_seen outfname interactive
900 1 0 0 1
901 0 1 0 1
902 1 0 1 0
903 0 1 1 1
904 */
905
906 /* STARTUP_CHILD must be called before the signal handlers get
907 installed below as they are inherited into the spawned process.
908 Also we do not need to be protected by them as during interruption
909 in the STARTUP_CHILD mode we kill the spawned process anyway. */
910 if (!pflag_seen)
911 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000913 sigemptyset(&empty_set);
914 sigemptyset(&blocked_set);
915 sa.sa_handler = SIG_IGN;
916 sigemptyset(&sa.sa_mask);
917 sa.sa_flags = 0;
918 sigaction(SIGTTOU, &sa, NULL);
919 sigaction(SIGTTIN, &sa, NULL);
920 if (interactive) {
921 sigaddset(&blocked_set, SIGHUP);
922 sigaddset(&blocked_set, SIGINT);
923 sigaddset(&blocked_set, SIGQUIT);
924 sigaddset(&blocked_set, SIGPIPE);
925 sigaddset(&blocked_set, SIGTERM);
926 sa.sa_handler = interrupt;
927#ifdef SUNOS4
928 /* POSIX signals on sunos4.1 are a little broken. */
929 sa.sa_flags = SA_INTERRUPT;
930#endif /* SUNOS4 */
931 }
932 sigaction(SIGHUP, &sa, NULL);
933 sigaction(SIGINT, &sa, NULL);
934 sigaction(SIGQUIT, &sa, NULL);
935 sigaction(SIGPIPE, &sa, NULL);
936 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000937#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000938 sa.sa_handler = reaper;
939 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000940#else
941 /* Make sure SIGCHLD has the default action so that waitpid
942 definitely works without losing track of children. The user
943 should not have given us a bogus state to inherit, but he might
944 have. Arguably we should detect SIG_IGN here and pass it on
945 to children, but probably noone really needs that. */
946 sa.sa_handler = SIG_DFL;
947 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000948#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000950 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000951 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000952
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 if (trace() < 0)
954 exit(1);
955 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000956 fflush(NULL);
957 if (exit_code > 0xff) {
958 /* Child was killed by a signal, mimic that. */
959 exit_code &= 0xff;
960 signal(exit_code, SIG_DFL);
961 raise(exit_code);
962 /* Paranoia - what if this signal is not fatal?
963 Exit with 128 + signo then. */
964 exit_code += 128;
965 }
966 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967}
968
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000969void
970expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000971{
972 /* Allocate some more TCBs and expand the table.
973 We don't want to relocate the TCBs because our
974 callers have pointers and it would be a pain.
975 So tcbtab is a table of pointers. Since we never
976 free the TCBs, we allocate a single chunk of many. */
977 struct tcb **newtab = (struct tcb **)
978 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
979 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
980 sizeof *newtcbs);
981 int i;
982 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000983 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
984 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000985 cleanup();
986 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000987 }
988 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
989 newtab[i] = &newtcbs[i - tcbtabsize];
990 tcbtabsize *= 2;
991 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000992}
993
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000995alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996{
997 int i;
998 struct tcb *tcp;
999
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001000 if (nprocs == tcbtabsize)
1001 expand_tcbtab();
1002
Roland McGrathee9d4352002-12-18 04:16:10 +00001003 for (i = 0; i < tcbtabsize; i++) {
1004 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 if ((tcp->flags & TCB_INUSE) == 0) {
1006 tcp->pid = pid;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001007 tcp->parent = NULL;
1008 tcp->nchildren = 0;
1009 tcp->nzombies = 0;
1010#ifdef TCB_CLONE_THREAD
1011 tcp->nclone_threads = tcp->nclone_detached = 0;
1012 tcp->nclone_waiting = 0;
1013#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 tcp->flags = TCB_INUSE | TCB_STARTUP;
1015 tcp->outf = outf; /* Initialise to current out file */
Andreas Schwabccdff482009-10-27 16:27:13 +01001016 tcp->curcol = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001017 tcp->stime.tv_sec = 0;
1018 tcp->stime.tv_usec = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 tcp->pfd = -1;
1020 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001021 if (command_options_parsed)
1022 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023 return tcp;
1024 }
1025 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001026 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1027 cleanup();
1028 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029}
1030
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001031#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001033proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034{
1035 char proc[32];
1036 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001037#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001038 int i;
1039 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040 sigset_t signals;
1041 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001042#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043#ifndef HAVE_POLLABLE_PROCFS
1044 static int last_pfd;
1045#endif
1046
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001047#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001048 /* Open the process pseudo-files in /proc. */
1049 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1050 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 perror("strace: open(\"/proc/...\", ...)");
1052 return -1;
1053 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001054 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 return -1;
1056 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001057 sprintf(proc, "/proc/%d/status", tcp->pid);
1058 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1059 perror("strace: open(\"/proc/...\", ...)");
1060 return -1;
1061 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001062 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001063 return -1;
1064 }
1065 sprintf(proc, "/proc/%d/as", tcp->pid);
1066 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1067 perror("strace: open(\"/proc/...\", ...)");
1068 return -1;
1069 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001070 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001071 return -1;
1072 }
1073#else
1074 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001075#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001076 sprintf(proc, "/proc/%d", tcp->pid);
1077 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001078#else /* FREEBSD */
1079 sprintf(proc, "/proc/%d/mem", tcp->pid);
1080 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1081#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001082 perror("strace: open(\"/proc/...\", ...)");
1083 return -1;
1084 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001085 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001086 return -1;
1087 }
1088#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001089#ifdef FREEBSD
1090 sprintf(proc, "/proc/%d/regs", tcp->pid);
1091 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1092 perror("strace: open(\"/proc/.../regs\", ...)");
1093 return -1;
1094 }
1095 if (cflag) {
1096 sprintf(proc, "/proc/%d/status", tcp->pid);
1097 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1098 perror("strace: open(\"/proc/.../status\", ...)");
1099 return -1;
1100 }
1101 } else
1102 tcp->pfd_status = -1;
1103#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001104 rebuild_pollv();
1105 if (!attaching) {
1106 /*
1107 * Wait for the child to pause. Because of a race
1108 * condition we have to poll for the event.
1109 */
1110 for (;;) {
1111 if (IOCTL_STATUS (tcp) < 0) {
1112 perror("strace: PIOCSTATUS");
1113 return -1;
1114 }
1115 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001116 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001117 }
1118 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001119#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001120 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001121 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001122 perror("strace: PIOCSTOP");
1123 return -1;
1124 }
Roland McGrath553a6092002-12-16 20:40:39 +00001125#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001126#ifdef PIOCSET
1127 /* Set Run-on-Last-Close. */
1128 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001129 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130 perror("PIOCSET PR_RLC");
1131 return -1;
1132 }
1133 /* Set or Reset Inherit-on-Fork. */
1134 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001135 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 perror("PIOC{SET,RESET} PR_FORK");
1137 return -1;
1138 }
1139#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001140#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1142 perror("PIOCSRLC");
1143 return -1;
1144 }
1145 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1146 perror("PIOC{S,R}FORK");
1147 return -1;
1148 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001149#else /* FREEBSD */
1150 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1151 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1152 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001153 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001154 }
1155 arg &= ~PF_LINGER;
1156 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001157 perror("PIOCSFL");
1158 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001159 }
1160#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001162#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001163 /* Enable all syscall entries we care about. */
1164 premptyset(&syscalls);
1165 for (i = 1; i < MAX_QUALS; ++i) {
1166 if (i > (sizeof syscalls) * CHAR_BIT) break;
1167 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1168 }
1169 praddset (&syscalls, SYS_execve);
1170 if (followfork) {
1171 praddset (&syscalls, SYS_fork);
1172#ifdef SYS_forkall
1173 praddset (&syscalls, SYS_forkall);
1174#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001175#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001176 praddset (&syscalls, SYS_fork1);
1177#endif
1178#ifdef SYS_rfork1
1179 praddset (&syscalls, SYS_rfork1);
1180#endif
1181#ifdef SYS_rforkall
1182 praddset (&syscalls, SYS_rforkall);
1183#endif
1184 }
1185 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186 perror("PIOCSENTRY");
1187 return -1;
1188 }
John Hughes19e49982001-10-19 08:59:12 +00001189 /* Enable the syscall exits. */
1190 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 perror("PIOSEXIT");
1192 return -1;
1193 }
John Hughes19e49982001-10-19 08:59:12 +00001194 /* Enable signals we care about. */
1195 premptyset(&signals);
1196 for (i = 1; i < MAX_QUALS; ++i) {
1197 if (i > (sizeof signals) * CHAR_BIT) break;
1198 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1199 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001200 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 perror("PIOCSTRACE");
1202 return -1;
1203 }
John Hughes19e49982001-10-19 08:59:12 +00001204 /* Enable faults we care about */
1205 premptyset(&faults);
1206 for (i = 1; i < MAX_QUALS; ++i) {
1207 if (i > (sizeof faults) * CHAR_BIT) break;
1208 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1209 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001210 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 perror("PIOCSFAULT");
1212 return -1;
1213 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001214#else /* FREEBSD */
1215 /* set events flags. */
1216 arg = S_SIG | S_SCE | S_SCX ;
1217 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1218 perror("PIOCBIS");
1219 return -1;
1220 }
1221#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 if (!attaching) {
1223#ifdef MIPS
1224 /*
1225 * The SGI PRSABORT doesn't work for pause() so
1226 * we send it a caught signal to wake it up.
1227 */
1228 kill(tcp->pid, SIGINT);
1229#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001230#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001232 arg = PRSABORT;
1233 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234 perror("PIOCRUN");
1235 return -1;
1236 }
Roland McGrath553a6092002-12-16 20:40:39 +00001237#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001238#endif /* !MIPS*/
1239#ifdef FREEBSD
1240 /* wake up the child if it received the SIGSTOP */
1241 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001242#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001243 for (;;) {
1244 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001245 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001246 perror("PIOCWSTOP");
1247 return -1;
1248 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001249 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001250 tcp->flags &= ~TCB_INSYSCALL;
1251 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001252 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 break;
1254 }
1255 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001256#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001257 arg = 0;
1258 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001259#else /* FREEBSD */
1260 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001261#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 perror("PIOCRUN");
1263 return -1;
1264 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001265#ifdef FREEBSD
1266 /* handle the case where we "opened" the child before
1267 it did the kill -STOP */
1268 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1269 tcp->status.PR_WHAT == SIGSTOP)
1270 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001271#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001273#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001275#else /* FREEBSD */
1276 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001277 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001278 /* We are attaching to an already running process.
1279 * Try to figure out the state of the process in syscalls,
1280 * to handle the first event well.
1281 * This is done by having a look at the "wchan" property of the
1282 * process, which tells where it is stopped (if it is). */
1283 FILE * status;
1284 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001285
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001286 sprintf(proc, "/proc/%d/status", tcp->pid);
1287 status = fopen(proc, "r");
1288 if (status &&
1289 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1290 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1291 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1292 strcmp(wchan, "stopevent")) {
1293 /* The process is asleep in the middle of a syscall.
1294 Fake the syscall entry event */
1295 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1296 tcp->status.PR_WHY = PR_SYSENTRY;
1297 trace_syscall(tcp);
1298 }
1299 if (status)
1300 fclose(status);
1301 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001302 }
1303#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304#ifndef HAVE_POLLABLE_PROCFS
1305 if (proc_poll_pipe[0] != -1)
1306 proc_poller(tcp->pfd);
1307 else if (nprocs > 1) {
1308 proc_poll_open();
1309 proc_poller(last_pfd);
1310 proc_poller(tcp->pfd);
1311 }
1312 last_pfd = tcp->pfd;
1313#endif /* !HAVE_POLLABLE_PROCFS */
1314 return 0;
1315}
1316
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001319struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320pid2tcb(pid)
1321int pid;
1322{
1323 int i;
1324 struct tcb *tcp;
1325
Roland McGrathee9d4352002-12-18 04:16:10 +00001326 for (i = 0; i < tcbtabsize; i++) {
1327 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328 if (pid && tcp->pid != pid)
1329 continue;
1330 if (tcp->flags & TCB_INUSE)
1331 return tcp;
1332 }
1333 return NULL;
1334}
1335
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001336#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337
1338static struct tcb *
1339pfd2tcb(pfd)
1340int pfd;
1341{
1342 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001343
Roland McGrathca16be82003-01-10 19:55:28 +00001344 for (i = 0; i < tcbtabsize; i++) {
1345 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346 if (tcp->pfd != pfd)
1347 continue;
1348 if (tcp->flags & TCB_INUSE)
1349 return tcp;
1350 }
1351 return NULL;
1352}
1353
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001354#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001355
1356void
1357droptcb(tcp)
1358struct tcb *tcp;
1359{
1360 if (tcp->pid == 0)
1361 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001362#ifdef TCB_CLONE_THREAD
1363 if (tcp->nclone_threads > 0) {
1364 /* There are other threads left in this process, but this
1365 is the one whose PID represents the whole process.
1366 We need to keep this record around as a zombie until
1367 all the threads die. */
1368 tcp->flags |= TCB_EXITING;
1369 return;
1370 }
1371#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001372 nprocs--;
1373 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001374
Roland McGrathe29341c2003-01-10 20:14:20 +00001375 if (tcp->parent != NULL) {
1376 tcp->parent->nchildren--;
1377#ifdef TCB_CLONE_THREAD
1378 if (tcp->flags & TCB_CLONE_DETACHED)
1379 tcp->parent->nclone_detached--;
1380 if (tcp->flags & TCB_CLONE_THREAD)
1381 tcp->parent->nclone_threads--;
1382#endif
Roland McGrath09623452003-05-23 02:27:13 +00001383#ifdef TCB_CLONE_DETACHED
1384 if (!(tcp->flags & TCB_CLONE_DETACHED))
1385#endif
1386 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001387#ifdef LINUX
1388 /* Update `tcp->parent->parent->nchildren' and the other fields
1389 like NCLONE_DETACHED, only for zombie group leader that has
1390 already reported and been short-circuited at the top of this
1391 function. The same condition as at the top of DETACH. */
1392 if ((tcp->flags & TCB_CLONE_THREAD) &&
1393 tcp->parent->nclone_threads == 0 &&
1394 (tcp->parent->flags & TCB_EXITING))
1395 droptcb(tcp->parent);
1396#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001397 tcp->parent = NULL;
1398 }
1399
1400 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001401 if (tcp->pfd != -1) {
1402 close(tcp->pfd);
1403 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001404#ifdef FREEBSD
1405 if (tcp->pfd_reg != -1) {
1406 close(tcp->pfd_reg);
1407 tcp->pfd_reg = -1;
1408 }
1409 if (tcp->pfd_status != -1) {
1410 close(tcp->pfd_status);
1411 tcp->pfd_status = -1;
1412 }
Roland McGrath553a6092002-12-16 20:40:39 +00001413#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001414#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001415 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416#endif
1417 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001418
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001419 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001420 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001421
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 tcp->outf = 0;
1423}
1424
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001425#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426
1427static int
1428resume(tcp)
1429struct tcb *tcp;
1430{
1431 if (tcp == NULL)
1432 return -1;
1433
1434 if (!(tcp->flags & TCB_SUSPENDED)) {
1435 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1436 return -1;
1437 }
1438 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001439#ifdef TCB_CLONE_THREAD
1440 if (tcp->flags & TCB_CLONE_THREAD)
1441 tcp->parent->nclone_waiting--;
1442#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001444 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446
1447 if (!qflag)
1448 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1449 return 0;
1450}
1451
Roland McGrath1bfd3102007-08-03 10:02:00 +00001452static int
1453resume_from_tcp (struct tcb *tcp)
1454{
1455 int error = 0;
1456 int resumed = 0;
1457
1458 /* XXX This won't always be quite right (but it never was).
1459 A waiter with argument 0 or < -1 is waiting for any pid in
1460 a particular pgrp, which this child might or might not be
1461 in. The waiter will only wake up if it's argument is -1
1462 or if it's waiting for tcp->pid's pgrp. It makes a
1463 difference to wake up a waiter when there might be more
1464 traced children, because it could get a false ECHILD
1465 error. OTOH, if this was the last child in the pgrp, then
1466 it ought to wake up and get ECHILD. We would have to
1467 search the system for all pid's in the pgrp to be sure.
1468
1469 && (t->waitpid == -1 ||
1470 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1471 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1472 */
1473
1474 if (tcp->parent &&
1475 (tcp->parent->flags & TCB_SUSPENDED) &&
1476 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001477 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001478 ++resumed;
1479 }
1480#ifdef TCB_CLONE_THREAD
1481 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1482 /* Some other threads of our parent are waiting too. */
1483 unsigned int i;
1484
1485 /* Resume all the threads that were waiting for this PID. */
1486 for (i = 0; i < tcbtabsize; i++) {
1487 struct tcb *t = tcbtab[i];
1488 if (t->parent == tcp->parent && t != tcp
1489 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1490 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1491 && t->waitpid == tcp->pid) {
1492 error |= resume (t);
1493 ++resumed;
1494 }
1495 }
1496 if (resumed == 0)
1497 /* Noone was waiting for this PID in particular,
1498 so now we might need to resume some wildcarders. */
1499 for (i = 0; i < tcbtabsize; i++) {
1500 struct tcb *t = tcbtab[i];
1501 if (t->parent == tcp->parent && t != tcp
1502 && ((t->flags
1503 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1504 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1505 && t->waitpid <= 0
1506 ) {
1507 error |= resume (t);
1508 break;
1509 }
1510 }
1511 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001512#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001513
1514 return error;
1515}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001516
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001517#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518
Roland McGrath0a463882007-07-05 18:43:16 +00001519/* detach traced process; continue with sig
1520 Never call DETACH twice on the same process as both unattached and
1521 attached-unstopped processes give the same ESRCH. For unattached process we
1522 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523
1524static int
1525detach(tcp, sig)
1526struct tcb *tcp;
1527int sig;
1528{
1529 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001530#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001531 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001532 struct tcb *zombie = NULL;
1533
1534 /* If the group leader is lingering only because of this other
1535 thread now dying, then detach the leader as well. */
1536 if ((tcp->flags & TCB_CLONE_THREAD) &&
1537 tcp->parent->nclone_threads == 1 &&
1538 (tcp->parent->flags & TCB_EXITING))
1539 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001540#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541
1542 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001543 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544
1545#ifdef LINUX
1546 /*
1547 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001548 * before detaching. Arghh. We go through hoops
1549 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001551#if defined(SPARC)
1552#undef PTRACE_DETACH
1553#define PTRACE_DETACH PTRACE_SUNDETACH
1554#endif
Roland McGrath02203312007-06-11 22:06:31 +00001555 /*
1556 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1557 * expected SIGSTOP. We must catch exactly one as otherwise the
1558 * detached process would be left stopped (process state T).
1559 */
1560 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1562 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001563 }
1564 else if (errno != ESRCH) {
1565 /* Shouldn't happen. */
1566 perror("detach: ptrace(PTRACE_DETACH, ...)");
1567 }
Roland McGrath134813a2007-06-02 00:07:33 +00001568 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1569 : tcp->pid),
1570 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001571 if (errno != ESRCH)
1572 perror("detach: checking sanity");
1573 }
Roland McGrath02203312007-06-11 22:06:31 +00001574 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1575 ? tcp->parent->pid : tcp->pid),
1576 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001577 if (errno != ESRCH)
1578 perror("detach: stopping child");
1579 }
Roland McGrath02203312007-06-11 22:06:31 +00001580 else
1581 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001582 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001584#ifdef __WALL
1585 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1586 if (errno == ECHILD) /* Already gone. */
1587 break;
1588 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001589 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001590 break;
1591 }
1592#endif /* __WALL */
1593 /* No __WALL here. */
1594 if (waitpid(tcp->pid, &status, 0) < 0) {
1595 if (errno != ECHILD) {
1596 perror("detach: waiting");
1597 break;
1598 }
1599#ifdef __WCLONE
1600 /* If no processes, try clones. */
1601 if (wait4(tcp->pid, &status, __WCLONE,
1602 NULL) < 0) {
1603 if (errno != ECHILD)
1604 perror("detach: waiting");
1605 break;
1606 }
1607#endif /* __WCLONE */
1608 }
1609#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001610 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001611#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612 if (!WIFSTOPPED(status)) {
1613 /* Au revoir, mon ami. */
1614 break;
1615 }
1616 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001617 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618 break;
1619 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001620 error = ptrace_restart(PTRACE_CONT, tcp,
Roland McGratheb9e2e82009-06-02 16:49:22 -07001621 WSTOPSIG(status) == SIGTRAP ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001622 : WSTOPSIG(status));
1623 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001626 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001627#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001628
1629#if defined(SUNOS4)
1630 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1631 if (sig && kill(tcp->pid, sig) < 0)
1632 perror("detach: kill");
1633 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001634 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635#endif /* SUNOS4 */
1636
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001637#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001638 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001639#endif
1640
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001641 if (!qflag)
1642 fprintf(stderr, "Process %u detached\n", tcp->pid);
1643
1644 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001645
1646#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001647 if (zombie != NULL) {
1648 /* TCP no longer exists therefore you must not detach () it. */
1649 droptcb(zombie);
1650 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001651#endif
1652
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653 return error;
1654}
1655
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001656#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657
1658static void
1659reaper(sig)
1660int sig;
1661{
1662 int pid;
1663 int status;
1664
1665 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1666#if 0
1667 struct tcb *tcp;
1668
1669 tcp = pid2tcb(pid);
1670 if (tcp)
1671 droptcb(tcp);
1672#endif
1673 }
1674}
1675
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001676#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677
1678static void
1679cleanup()
1680{
1681 int i;
1682 struct tcb *tcp;
1683
Roland McGrathee9d4352002-12-18 04:16:10 +00001684 for (i = 0; i < tcbtabsize; i++) {
1685 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686 if (!(tcp->flags & TCB_INUSE))
1687 continue;
1688 if (debug)
1689 fprintf(stderr,
1690 "cleanup: looking at pid %u\n", tcp->pid);
1691 if (tcp_last &&
1692 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001693 tprintf(" <unfinished ...>");
1694 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001695 }
1696 if (tcp->flags & TCB_ATTACHED)
1697 detach(tcp, 0);
1698 else {
1699 kill(tcp->pid, SIGCONT);
1700 kill(tcp->pid, SIGTERM);
1701 }
1702 }
1703 if (cflag)
1704 call_summary(outf);
1705}
1706
1707static void
1708interrupt(sig)
1709int sig;
1710{
1711 interrupted = 1;
1712}
1713
1714#ifndef HAVE_STRERROR
1715
Roland McGrath6d2b3492002-12-30 00:51:30 +00001716#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717extern int sys_nerr;
1718extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001719#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720
1721const char *
1722strerror(errno)
1723int errno;
1724{
1725 static char buf[64];
1726
1727 if (errno < 1 || errno >= sys_nerr) {
1728 sprintf(buf, "Unknown error %d", errno);
1729 return buf;
1730 }
1731 return sys_errlist[errno];
1732}
1733
1734#endif /* HAVE_STERRROR */
1735
1736#ifndef HAVE_STRSIGNAL
1737
Roland McGrath8f474e02003-01-14 07:53:33 +00001738#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001739extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001740#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001741#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1742extern char *_sys_siglist[];
1743#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744
1745const char *
1746strsignal(sig)
1747int sig;
1748{
1749 static char buf[64];
1750
1751 if (sig < 1 || sig >= NSIG) {
1752 sprintf(buf, "Unknown signal %d", sig);
1753 return buf;
1754 }
1755#ifdef HAVE__SYS_SIGLIST
1756 return _sys_siglist[sig];
1757#else
1758 return sys_siglist[sig];
1759#endif
1760}
1761
1762#endif /* HAVE_STRSIGNAL */
1763
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001764#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765
1766static void
1767rebuild_pollv()
1768{
1769 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770
Roland McGrathee9d4352002-12-18 04:16:10 +00001771 if (pollv != NULL)
1772 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001773 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001774 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001775 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001776 exit(1);
1777 }
1778
Roland McGrathca16be82003-01-10 19:55:28 +00001779 for (i = j = 0; i < tcbtabsize; i++) {
1780 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 if (!(tcp->flags & TCB_INUSE))
1782 continue;
1783 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001784 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 j++;
1786 }
1787 if (j != nprocs) {
1788 fprintf(stderr, "strace: proc miscount\n");
1789 exit(1);
1790 }
1791}
1792
1793#ifndef HAVE_POLLABLE_PROCFS
1794
1795static void
1796proc_poll_open()
1797{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798 int i;
1799
1800 if (pipe(proc_poll_pipe) < 0) {
1801 perror("pipe");
1802 exit(1);
1803 }
1804 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001805 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806 exit(1);
1807 }
1808 }
1809}
1810
1811static int
1812proc_poll(pollv, nfds, timeout)
1813struct pollfd *pollv;
1814int nfds;
1815int timeout;
1816{
1817 int i;
1818 int n;
1819 struct proc_pollfd pollinfo;
1820
1821 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1822 return n;
1823 if (n != sizeof(struct proc_pollfd)) {
1824 fprintf(stderr, "panic: short read: %d\n", n);
1825 exit(1);
1826 }
1827 for (i = 0; i < nprocs; i++) {
1828 if (pollv[i].fd == pollinfo.fd)
1829 pollv[i].revents = pollinfo.revents;
1830 else
1831 pollv[i].revents = 0;
1832 }
1833 poller_pid = pollinfo.pid;
1834 return 1;
1835}
1836
1837static void
1838wakeup_handler(sig)
1839int sig;
1840{
1841}
1842
1843static void
1844proc_poller(pfd)
1845int pfd;
1846{
1847 struct proc_pollfd pollinfo;
1848 struct sigaction sa;
1849 sigset_t blocked_set, empty_set;
1850 int i;
1851 int n;
1852 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001853#ifdef FREEBSD
1854 struct procfs_status pfs;
1855#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856
1857 switch (fork()) {
1858 case -1:
1859 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001860 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861 case 0:
1862 break;
1863 default:
1864 return;
1865 }
1866
1867 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1868 sa.sa_flags = 0;
1869 sigemptyset(&sa.sa_mask);
1870 sigaction(SIGHUP, &sa, NULL);
1871 sigaction(SIGINT, &sa, NULL);
1872 sigaction(SIGQUIT, &sa, NULL);
1873 sigaction(SIGPIPE, &sa, NULL);
1874 sigaction(SIGTERM, &sa, NULL);
1875 sa.sa_handler = wakeup_handler;
1876 sigaction(SIGUSR1, &sa, NULL);
1877 sigemptyset(&blocked_set);
1878 sigaddset(&blocked_set, SIGUSR1);
1879 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1880 sigemptyset(&empty_set);
1881
1882 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1883 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001884 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885 }
1886 n = rl.rlim_cur;
1887 for (i = 0; i < n; i++) {
1888 if (i != pfd && i != proc_poll_pipe[1])
1889 close(i);
1890 }
1891
1892 pollinfo.fd = pfd;
1893 pollinfo.pid = getpid();
1894 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001895#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001896 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1897#else
1898 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1899#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001900 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901 switch (errno) {
1902 case EINTR:
1903 continue;
1904 case EBADF:
1905 pollinfo.revents = POLLERR;
1906 break;
1907 case ENOENT:
1908 pollinfo.revents = POLLHUP;
1909 break;
1910 default:
1911 perror("proc_poller: PIOCWSTOP");
1912 }
1913 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1914 _exit(0);
1915 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001916 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1918 sigsuspend(&empty_set);
1919 }
1920}
1921
1922#endif /* !HAVE_POLLABLE_PROCFS */
1923
1924static int
1925choose_pfd()
1926{
1927 int i, j;
1928 struct tcb *tcp;
1929
1930 static int last;
1931
1932 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001933 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934 /*
1935 * The previous process is ready to run again. We'll
1936 * let it do so if it is currently in a syscall. This
1937 * heuristic improves the readability of the trace.
1938 */
1939 tcp = pfd2tcb(pollv[last].fd);
1940 if (tcp && (tcp->flags & TCB_INSYSCALL))
1941 return pollv[last].fd;
1942 }
1943
1944 for (i = 0; i < nprocs; i++) {
1945 /* Let competing children run round robin. */
1946 j = (i + last + 1) % nprocs;
1947 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1948 tcp = pfd2tcb(pollv[j].fd);
1949 if (!tcp) {
1950 fprintf(stderr, "strace: lost proc\n");
1951 exit(1);
1952 }
1953 droptcb(tcp);
1954 return -1;
1955 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001956 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 last = j;
1958 return pollv[j].fd;
1959 }
1960 }
1961 fprintf(stderr, "strace: nothing ready\n");
1962 exit(1);
1963}
1964
1965static int
1966trace()
1967{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001968#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001969 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001970#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971 struct tcb *tcp;
1972 int pfd;
1973 int what;
1974 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001975 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976
1977 for (;;) {
1978 if (interactive)
1979 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1980
1981 if (nprocs == 0)
1982 break;
1983
1984 switch (nprocs) {
1985 case 1:
1986#ifndef HAVE_POLLABLE_PROCFS
1987 if (proc_poll_pipe[0] == -1) {
1988#endif
1989 tcp = pid2tcb(0);
1990 if (!tcp)
1991 continue;
1992 pfd = tcp->pfd;
1993 if (pfd == -1)
1994 continue;
1995 break;
1996#ifndef HAVE_POLLABLE_PROCFS
1997 }
1998 /* fall through ... */
1999#endif /* !HAVE_POLLABLE_PROCFS */
2000 default:
2001#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002002#ifdef POLL_HACK
2003 /* On some systems (e.g. UnixWare) we get too much ugly
2004 "unfinished..." stuff when multiple proceses are in
2005 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002006
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002007 if (in_syscall) {
2008 struct pollfd pv;
2009 tcp = in_syscall;
2010 in_syscall = NULL;
2011 pv.fd = tcp->pfd;
2012 pv.events = POLLWANT;
2013 if ((what = poll (&pv, 1, 1)) < 0) {
2014 if (interrupted)
2015 return 0;
2016 continue;
2017 }
2018 else if (what == 1 && pv.revents & POLLWANT) {
2019 goto FOUND;
2020 }
2021 }
2022#endif
2023
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 if (poll(pollv, nprocs, INFTIM) < 0) {
2025 if (interrupted)
2026 return 0;
2027 continue;
2028 }
2029#else /* !HAVE_POLLABLE_PROCFS */
2030 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2031 if (interrupted)
2032 return 0;
2033 continue;
2034 }
2035#endif /* !HAVE_POLLABLE_PROCFS */
2036 pfd = choose_pfd();
2037 if (pfd == -1)
2038 continue;
2039 break;
2040 }
2041
2042 /* Look up `pfd' in our table. */
2043 if ((tcp = pfd2tcb(pfd)) == NULL) {
2044 fprintf(stderr, "unknown pfd: %u\n", pfd);
2045 exit(1);
2046 }
John Hughesb6643082002-05-23 11:02:22 +00002047#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002048 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002049#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002050 /* Get the status of the process. */
2051 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002052#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002053 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002054#else /* FREEBSD */
2055 /* Thanks to some scheduling mystery, the first poller
2056 sometimes waits for the already processed end of fork
2057 event. Doing a non blocking poll here solves the problem. */
2058 if (proc_poll_pipe[0] != -1)
2059 ioctl_result = IOCTL_STATUS (tcp);
2060 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002061 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002062#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002063 ioctl_errno = errno;
2064#ifndef HAVE_POLLABLE_PROCFS
2065 if (proc_poll_pipe[0] != -1) {
2066 if (ioctl_result < 0)
2067 kill(poller_pid, SIGKILL);
2068 else
2069 kill(poller_pid, SIGUSR1);
2070 }
2071#endif /* !HAVE_POLLABLE_PROCFS */
2072 }
2073 if (interrupted)
2074 return 0;
2075
2076 if (interactive)
2077 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2078
2079 if (ioctl_result < 0) {
2080 /* Find out what happened if it failed. */
2081 switch (ioctl_errno) {
2082 case EINTR:
2083 case EBADF:
2084 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002085#ifdef FREEBSD
2086 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002087#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002088 case ENOENT:
2089 droptcb(tcp);
2090 continue;
2091 default:
2092 perror("PIOCWSTOP");
2093 exit(1);
2094 }
2095 }
2096
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002097#ifdef FREEBSD
2098 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2099 /* discard first event for a syscall we never entered */
2100 IOCTL (tcp->pfd, PIOCRUN, 0);
2101 continue;
2102 }
Roland McGrath553a6092002-12-16 20:40:39 +00002103#endif
2104
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002105 /* clear the just started flag */
2106 tcp->flags &= ~TCB_STARTUP;
2107
2108 /* set current output file */
2109 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002110 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002111
2112 if (cflag) {
2113 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002114#ifdef FREEBSD
2115 char buf[1024];
2116 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002117
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002118 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2119 buf[len] = '\0';
2120 sscanf(buf,
2121 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2122 &stime.tv_sec, &stime.tv_usec);
2123 } else
2124 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002125#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002126 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2127 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002128#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2130 tcp->stime = stime;
2131 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002132 what = tcp->status.PR_WHAT;
2133 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002134#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002135 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002136 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2137 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 if (trace_syscall(tcp) < 0) {
2139 fprintf(stderr, "syscall trouble\n");
2140 exit(1);
2141 }
2142 }
2143 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002144#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002145 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002146#ifdef POLL_HACK
2147 in_syscall = tcp;
2148#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002149 case PR_SYSEXIT:
2150 if (trace_syscall(tcp) < 0) {
2151 fprintf(stderr, "syscall trouble\n");
2152 exit(1);
2153 }
2154 break;
2155 case PR_SIGNALLED:
2156 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2157 printleader(tcp);
2158 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002159 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002160 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002161#ifdef PR_INFO
2162 if (tcp->status.PR_INFO.si_signo == what) {
2163 printleader(tcp);
2164 tprintf(" siginfo=");
2165 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002166 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002167 }
2168#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002169 }
2170 break;
2171 case PR_FAULTED:
2172 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2173 printleader(tcp);
2174 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002175 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002176 }
2177 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002178#ifdef FREEBSD
2179 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002180 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002183 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 exit(1);
2185 break;
2186 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002187 /* Remember current print column before continuing. */
2188 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002189 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002190#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002191 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002192#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002193 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002194#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195 perror("PIOCRUN");
2196 exit(1);
2197 }
2198 }
2199 return 0;
2200}
2201
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002202#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002204#ifdef TCB_GROUP_EXITING
2205/* Handle an exit detach or death signal that is taking all the
2206 related clone threads with it. This is called in three circumstances:
2207 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2208 SIG == 0 Continuing TCP will perform an exit_group syscall.
2209 SIG == other Continuing TCP with SIG will kill the process.
2210*/
2211static int
2212handle_group_exit(struct tcb *tcp, int sig)
2213{
2214 /* We need to locate our records of all the clone threads
2215 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002216 struct tcb *leader = NULL;
2217
2218 if (tcp->flags & TCB_CLONE_THREAD)
2219 leader = tcp->parent;
2220 else if (tcp->nclone_detached > 0)
2221 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002222
2223 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002224 if (leader != NULL && leader != tcp
2225 && !(leader->flags & TCB_GROUP_EXITING)
2226 && !(tcp->flags & TCB_STARTUP)
2227 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002228 fprintf(stderr,
2229 "PANIC: handle_group_exit: %d leader %d\n",
2230 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002231 }
2232 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002233#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002234 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002235#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002236 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002237 }
2238 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002239 /* Mark that we are taking the process down. */
2240 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002241 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002242 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002243 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002244 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002245 } else {
2246 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2247 cleanup();
2248 return -1;
2249 }
2250 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002251 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002252 if (leader != tcp)
2253 droptcb(tcp);
2254 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002255 /* The leader will report to us as parent now,
2256 and then we'll get to the SIG==-1 case. */
2257 return 0;
2258 }
2259 }
2260
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002261 return 0;
2262}
2263#endif
2264
Roland McGratheb9e2e82009-06-02 16:49:22 -07002265static int
2266trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002267{
2268 int pid;
2269 int wait_errno;
2270 int status;
2271 struct tcb *tcp;
2272#ifdef LINUX
2273 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002274#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002275 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002276#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002277#endif /* LINUX */
2278
Roland McGratheb9e2e82009-06-02 16:49:22 -07002279 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002280 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002281 return 0;
2282 if (interactive)
2283 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002284#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002285#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002286 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002287 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002288 /* this kernel does not support __WALL */
2289 wait4_options &= ~__WALL;
2290 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002291 pid = wait4(-1, &status, wait4_options,
2292 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002293 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002294 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002295 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002296 pid = wait4(-1, &status, __WCLONE,
2297 cflag ? &ru : NULL);
2298 if (pid == -1) {
2299 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002300 "failed: %s\n", strerror(errno));
2301 }
2302 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002303#else
2304 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2305#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002306#endif /* LINUX */
2307#ifdef SUNOS4
2308 pid = wait(&status);
2309#endif /* SUNOS4 */
2310 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002311 if (interactive)
2312 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002314 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002315 switch (wait_errno) {
2316 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002317 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002318 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002319 /*
2320 * We would like to verify this case
2321 * but sometimes a race in Solbourne's
2322 * version of SunOS sometimes reports
2323 * ECHILD before sending us SIGCHILD.
2324 */
2325#if 0
Roland McGratheb9e2e82009-06-02 16:49:22 -07002326 if (nprocs == 0)
2327 return 0;
2328 fprintf(stderr, "strace: proc miscount\n");
2329 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002331 return 0;
2332 default:
2333 errno = wait_errno;
2334 perror("strace: wait");
2335 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002336 }
2337 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002338 if (pid == popen_pid) {
2339 if (WIFEXITED(status) || WIFSIGNALED(status))
2340 popen_pid = -1;
2341 continue;
2342 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343 if (debug)
2344 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2345
2346 /* Look up `pid' in our table. */
2347 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002348#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002349 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002350 /* This is needed to go with the CLONE_PTRACE
2351 changes in process.c/util.c: we might see
2352 the child's initial trap before we see the
2353 parent return from the clone syscall.
2354 Leave the child suspended until the parent
2355 returns from its system call. Only then
2356 will we have the association of parent and
2357 child so that we know how to do clearbpt
2358 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002359 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002360 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002361 if (!qflag)
2362 fprintf(stderr, "\
2363Process %d attached (waiting for parent)\n",
2364 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002365 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002366 else
2367 /* This can happen if a clone call used
2368 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002369#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002370 {
2371 fprintf(stderr, "unknown pid: %u\n", pid);
2372 if (WIFSTOPPED(status))
2373 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2374 exit(1);
2375 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002376 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002377 /* set current output file */
2378 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002379 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002380 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002381#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002382 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2383 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002384#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002386
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 if (tcp->flags & TCB_SUSPENDED) {
2388 /*
2389 * Apparently, doing any ptrace() call on a stopped
2390 * process, provokes the kernel to report the process
2391 * status again on a subsequent wait(), even if the
2392 * process has not been actually restarted.
2393 * Since we have inspected the arguments of suspended
2394 * processes we end up here testing for this case.
2395 */
2396 continue;
2397 }
2398 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002399 if (pid == strace_child)
2400 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002401 if (!cflag
2402 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2403 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002404 tprintf("+++ killed by %s %s+++",
2405 signame(WTERMSIG(status)),
2406#ifdef WCOREDUMP
2407 WCOREDUMP(status) ? "(core dumped) " :
2408#endif
2409 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002410 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002412#ifdef TCB_GROUP_EXITING
2413 handle_group_exit(tcp, -1);
2414#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002416#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002417 continue;
2418 }
2419 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002420 if (pid == strace_child)
2421 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002422 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002423 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2424 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002425#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002426 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002427 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002428#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002429 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002430 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002431 "PANIC: attached pid %u exited with %d\n",
2432 pid, WEXITSTATUS(status));
2433 }
Roland McGrath0a396902003-06-10 03:05:53 +00002434 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002435 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002436 tprintf(" <unfinished ... exit status %d>\n",
2437 WEXITSTATUS(status));
2438 tcp_last = NULL;
2439 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002440#ifdef TCB_GROUP_EXITING
2441 handle_group_exit(tcp, -1);
2442#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002444#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 continue;
2446 }
2447 if (!WIFSTOPPED(status)) {
2448 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2449 droptcb(tcp);
2450 continue;
2451 }
2452 if (debug)
2453 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002454 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002455
Roland McGrath02203312007-06-11 22:06:31 +00002456 /*
2457 * Interestingly, the process may stop
2458 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002459 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002460 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002461 * A no-MMU vforked child won't send up a signal,
2462 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002463 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002464 if ((tcp->flags & TCB_STARTUP) &&
2465 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002466 /*
2467 * This flag is there to keep us in sync.
2468 * Next time this process stops it should
2469 * really be entering a system call.
2470 */
2471 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002473 /*
2474 * One example is a breakpoint inherited from
2475 * parent through fork ().
2476 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002477 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2478 droptcb(tcp);
2479 cleanup();
2480 return -1;
2481 }
2482 }
2483 goto tracing;
2484 }
2485
Roland McGratheb9e2e82009-06-02 16:49:22 -07002486 if (WSTOPSIG(status) != SIGTRAP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002487 if (WSTOPSIG(status) == SIGSTOP &&
2488 (tcp->flags & TCB_SIGTRAPPED)) {
2489 /*
2490 * Trapped attempt to block SIGTRAP
2491 * Hope we are back in control now.
2492 */
2493 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002494 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495 cleanup();
2496 return -1;
2497 }
2498 continue;
2499 }
2500 if (!cflag
2501 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002502 unsigned long addr = 0;
2503 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002504#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002505# define PSR_RI 41
2506 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002507 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002508
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002509 upeek(tcp, PT_CR_IPSR, &psr);
2510 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002511
2512 pc += (psr >> PSR_RI) & 0x3;
2513 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2514 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002515#elif defined PTRACE_GETSIGINFO
2516 if (WSTOPSIG(status) == SIGSEGV ||
2517 WSTOPSIG(status) == SIGBUS) {
2518 siginfo_t si;
2519 if (ptrace(PTRACE_GETSIGINFO, pid,
2520 0, &si) == 0)
2521 addr = (unsigned long)
2522 si.si_addr;
2523 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002524#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002525 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002526 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002527 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002528 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002529 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002530 }
Roland McGrath05690952004-10-20 01:00:27 +00002531 if (((tcp->flags & TCB_ATTACHED) ||
2532 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002533 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002534#ifdef TCB_GROUP_EXITING
2535 handle_group_exit(tcp, WSTOPSIG(status));
2536#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002538#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 continue;
2540 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002541 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002542 cleanup();
2543 return -1;
2544 }
2545 tcp->flags &= ~TCB_SUSPENDED;
2546 continue;
2547 }
Roland McGrath02203312007-06-11 22:06:31 +00002548 /* we handled the STATUS, we are permitted to interrupt now. */
2549 if (interrupted)
2550 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002551 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2552 /* ptrace() failed in trace_syscall() with ESRCH.
2553 * Likely a result of process disappearing mid-flight.
2554 * Observed case: exit_group() terminating
2555 * all processes in thread group. In this case, threads
2556 * "disappear" in an unpredictable moment without any
2557 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002558 */
2559 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002560 if (tcp_last) {
2561 /* Do we have dangling line "syscall(param, param"?
2562 * Finish the line then. We cannot
2563 */
2564 tcp_last->flags |= TCB_REPRINT;
2565 tprintf(" <unfinished ...>");
2566 printtrailer();
2567 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002568 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002569 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002570 ptrace(PTRACE_KILL,
2571 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572 droptcb(tcp);
2573 }
2574 continue;
2575 }
2576 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002577#ifdef TCB_GROUP_EXITING
2578 if (tcp->flags & TCB_GROUP_EXITING) {
2579 if (handle_group_exit(tcp, 0) < 0)
2580 return -1;
2581 continue;
2582 }
2583#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 if (tcp->flags & TCB_ATTACHED)
2585 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002586 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002587 cleanup();
2588 return -1;
2589 }
2590 continue;
2591 }
2592 if (tcp->flags & TCB_SUSPENDED) {
2593 if (!qflag)
2594 fprintf(stderr, "Process %u suspended\n", pid);
2595 continue;
2596 }
2597 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002598 /* Remember current print column before continuing. */
2599 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002600 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002601 cleanup();
2602 return -1;
2603 }
2604 }
2605 return 0;
2606}
2607
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002608#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002609
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002610#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002611
2612void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002614{
2615 va_list args;
2616
Andreas Schwabe5355de2009-10-27 16:56:43 +01002617 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002618 if (outf) {
2619 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002620 if (n < 0) {
2621 if (outf != stderr)
2622 perror(outfname == NULL
2623 ? "<writing to pipe>" : outfname);
2624 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002625 curcol += n;
2626 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002627 va_end(args);
2628 return;
2629}
2630
2631void
Roland McGratheb9e2e82009-06-02 16:49:22 -07002632printleader(tcp)
2633struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002634{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002635 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002636 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002637 if (tcp_last->flags & TCB_INSYSCALL) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002638 tprintf(" <unavailable>)");
2639 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002640 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002641 tprintf("= ? <unavailable>\n");
2642 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002643 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002644 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002645 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002646 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002647 }
2648 curcol = 0;
2649 if ((followfork == 1 || pflag_seen > 1) && outfname)
2650 tprintf("%-5d ", tcp->pid);
2651 else if (nprocs > 1 && !outfname)
2652 tprintf("[pid %5u] ", tcp->pid);
2653 if (tflag) {
2654 char str[sizeof("HH:MM:SS")];
2655 struct timeval tv, dtv;
2656 static struct timeval otv;
2657
2658 gettimeofday(&tv, NULL);
2659 if (rflag) {
2660 if (otv.tv_sec == 0)
2661 otv = tv;
2662 tv_sub(&dtv, &tv, &otv);
2663 tprintf("%6ld.%06ld ",
2664 (long) dtv.tv_sec, (long) dtv.tv_usec);
2665 otv = tv;
2666 }
2667 else if (tflag > 2) {
2668 tprintf("%ld.%06ld ",
2669 (long) tv.tv_sec, (long) tv.tv_usec);
2670 }
2671 else {
2672 time_t local = tv.tv_sec;
2673 strftime(str, sizeof(str), "%T", localtime(&local));
2674 if (tflag > 1)
2675 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2676 else
2677 tprintf("%s ", str);
2678 }
2679 }
2680 if (iflag)
2681 printcall(tcp);
2682}
2683
2684void
2685tabto(col)
2686int col;
2687{
2688 if (curcol < col)
2689 tprintf("%*s", col - curcol, "");
2690}
2691
2692void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002693printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694{
2695 tprintf("\n");
2696 tcp_last = NULL;
2697}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002698
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002699#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002700
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002701int
2702mp_ioctl(int fd, int cmd, void *arg, int size)
2703{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002704 struct iovec iov[2];
2705 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002706
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002707 iov[0].iov_base = &cmd;
2708 iov[0].iov_len = sizeof cmd;
2709 if (arg) {
2710 ++n;
2711 iov[1].iov_base = arg;
2712 iov[1].iov_len = size;
2713 }
Roland McGrath553a6092002-12-16 20:40:39 +00002714
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002715 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002716}
2717
2718#endif