blob: e275bfd12acb7fa90bd04d395762b4f5a9e59d81 [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>
Denys Vlasenko7e0615f2009-01-28 19:00:54 +000043#include <sys/utsname.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000044#include <pwd.h>
45#include <grp.h>
46#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000047#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000048#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
52# if defined __NR_tgkill
53# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
54# elif defined __NR_tkill
55# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
56# else
57 /* kill() may choose arbitrarily the target task of the process group
58 while we later wait on a that specific TID. PID process waits become
59 TID task specific waits for a process under ptrace(2). */
60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
62# endif
63#endif
64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000065#if defined(IA64) && defined(LINUX)
66# include <asm/ptrace_offsets.h>
67#endif
68
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000069#ifdef USE_PROCFS
70#include <poll.h>
71#endif
72
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#ifdef SVR4
74#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000075#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000076#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000077#include <sys/uio.h>
78#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000080#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000082extern int optind;
83extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000084
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085
Roland McGrath41c48222008-07-18 00:25:10 +000086int debug = 0, followfork = 0;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000087int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
88static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000089/*
90 * daemonized_tracer supports -D option.
91 * With this option, strace forks twice.
92 * Unlike normal case, with -D *grandparent* process exec's,
93 * becoming a traced process. Child exits (this prevents traced process
94 * from having children it doesn't expect to have), and grandchild
95 * attaches to grandparent similarly to strace -p PID.
96 * This allows for more transparent interaction in cases
97 * when process and its parent are communicating via signals,
98 * wait() etc. Without -D, strace process gets lodged in between,
99 * disrupting parent<->child link.
100 */
101static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
Denys Vlasenko7e0615f2009-01-28 19:00:54 +0000103static struct utsname utsname_buf;
104
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000105/* Sometimes we want to print only succeeding syscalls. */
106int not_failing_only = 0;
107
Dmitry V. Levina6809652008-11-10 17:14:58 +0000108static int exit_code = 0;
109static int strace_child = 0;
Denys Vlasenko96d5a762008-12-29 19:13:27 +0000110static int ptrace_stop_sig = SIGTRAP;
Denys Vlasenko8ed57272009-02-25 14:24:02 +0000111#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
Denys Vlasenko96d5a762008-12-29 19:13:27 +0000112static bool ptrace_opts_set;
Denys Vlasenko8ed57272009-02-25 14:24:02 +0000113#endif
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000114static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115uid_t run_uid;
116gid_t run_gid;
117
118int acolumn = DEFAULT_ACOLUMN;
119int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000120static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +0000122struct tcb **tcbtab;
123unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125
Roland McGrath0a463882007-07-05 18:43:16 +0000126static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127static int trace P((void));
128static void cleanup P((void));
129static void interrupt P((int sig));
130static sigset_t empty_set, blocked_set;
131
132#ifdef HAVE_SIG_ATOMIC_T
133static volatile sig_atomic_t interrupted;
134#else /* !HAVE_SIG_ATOMIC_T */
135#ifdef __STDC__
136static volatile int interrupted;
137#else /* !__STDC__ */
138static int interrupted;
139#endif /* !__STDC__ */
140#endif /* !HAVE_SIG_ATOMIC_T */
141
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000142#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
144static struct tcb *pfd2tcb P((int pfd));
145static void reaper P((int sig));
146static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000147static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148
149#ifndef HAVE_POLLABLE_PROCFS
150
151static void proc_poll_open P((void));
152static void proc_poller P((int pfd));
153
154struct proc_pollfd {
155 int fd;
156 int revents;
157 int pid;
158};
159
160static int poller_pid;
161static int proc_poll_pipe[2] = { -1, -1 };
162
163#endif /* !HAVE_POLLABLE_PROCFS */
164
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000165#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000166#define POLLWANT POLLWRNORM
167#else
168#define POLLWANT POLLPRI
169#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000170#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000171
172static void
173usage(ofp, exitval)
174FILE *ofp;
175int exitval;
176{
177 fprintf(ofp, "\
178usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000179 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
180 [command [arg ...]]\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000181 or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000182 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183-c -- count time, calls, and errors for each syscall and report summary\n\
184-f -- follow forks, -ff -- with output into separate files\n\
185-F -- attempt to follow vforks, -h -- print help message\n\
186-i -- print instruction pointer at time of syscall\n\
187-q -- suppress messages about attaching, detaching, etc.\n\
188-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
189-T -- print time spent in each syscall, -V -- print version\n\
190-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
191-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
192-a column -- alignment COLUMN for printing syscall results (default %d)\n\
193-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
194 options: trace, abbrev, verbose, raw, signal, read, or write\n\
195-o file -- send trace output to FILE instead of stderr\n\
196-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
197-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000198-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
200-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
201-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000202-E var=val -- put var=val in the environment for command\n\
203-E var -- remove var from the environment for command\n\
204" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000205-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000206 */
207, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000208 exit(exitval);
209}
210
211#ifdef SVR4
212#ifdef MIPS
213void
214foobar()
215{
216}
217#endif /* MIPS */
218#endif /* SVR4 */
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);
Denys Vlasenko84e20af2009-02-10 16:03:20 +0000444 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED;
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.
644 */
645 kill(getpid(), SIGSTOP);
646 } else {
647 struct sigaction sv_sigchld;
648 sigaction(SIGCHLD, NULL, &sv_sigchld);
649 /*
650 * Make sure it is not SIG_IGN, otherwise wait
651 * will not block.
652 */
653 signal(SIGCHLD, SIG_DFL);
654 /*
655 * Wait for grandchild to attach to us.
656 * It kills child after that, and wait() unblocks.
657 */
658 alarm(3);
659 wait(NULL);
660 alarm(0);
661 sigaction(SIGCHLD, &sv_sigchld, NULL);
662 }
Roland McGrath02203312007-06-11 22:06:31 +0000663#endif /* !USE_PROCFS */
664
665 execv(pathname, argv);
666 perror("strace: exec");
667 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000668 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000669
670 /* We are the tracer. */
671 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000672 if (daemonized_tracer) {
673 /* We want subsequent startup_attach() to attach to it. */
674 tcp->flags |= TCB_ATTACHED;
675 }
Roland McGrath02203312007-06-11 22:06:31 +0000676#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677 if (proc_open(tcp, 0) < 0) {
678 fprintf(stderr, "trouble opening proc file\n");
679 cleanup();
680 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000681 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000682#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000683}
684
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000686main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000687{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688 struct tcb *tcp;
689 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000690 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000691 struct sigaction sa;
692
693 static char buf[BUFSIZ];
694
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000695 progname = argv[0] ? argv[0] : "strace";
696
Denys Vlasenko7e0615f2009-01-28 19:00:54 +0000697 uname(&utsname_buf);
698
Roland McGrathee9d4352002-12-18 04:16:10 +0000699 /* Allocate the initial tcbtab. */
700 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000701 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000702 fprintf(stderr, "%s: out of memory\n", progname);
703 exit(1);
704 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000705 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000706 fprintf(stderr, "%s: out of memory\n", progname);
707 exit(1);
708 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000709 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
710 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
711
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712 outf = stderr;
713 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000714 set_sortby(DEFAULT_SORTBY);
715 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000716 qualify("trace=all");
717 qualify("abbrev=all");
718 qualify("verbose=all");
719 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000721 "+cdfFhiqrtTvVxz"
722#ifndef USE_PROCFS
723 "D"
724#endif
725 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000726 switch (c) {
727 case 'c':
728 cflag++;
729 dtime++;
730 break;
731 case 'd':
732 debug++;
733 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000734#ifndef USE_PROCFS
735 /* Experimental, not documented in manpage yet. */
736 case 'D':
737 daemonized_tracer = 1;
738 break;
739#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000740 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000741 optF = 1;
742 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000743 case 'f':
744 followfork++;
745 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000746 case 'h':
747 usage(stdout, 0);
748 break;
749 case 'i':
750 iflag++;
751 break;
752 case 'q':
753 qflag++;
754 break;
755 case 'r':
756 rflag++;
757 tflag++;
758 break;
759 case 't':
760 tflag++;
761 break;
762 case 'T':
763 dtime++;
764 break;
765 case 'x':
766 xflag++;
767 break;
768 case 'v':
769 qualify("abbrev=none");
770 break;
771 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000772 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000773 exit(0);
774 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000775 case 'z':
776 not_failing_only = 1;
777 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 case 'a':
779 acolumn = atoi(optarg);
780 break;
781 case 'e':
782 qualify(optarg);
783 break;
784 case 'o':
785 outfname = strdup(optarg);
786 break;
787 case 'O':
788 set_overhead(atoi(optarg));
789 break;
790 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000791 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 fprintf(stderr, "%s: Invalid process id: %s\n",
793 progname, optarg);
794 break;
795 }
796 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000797 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000798 break;
799 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000800 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000801 tcp->flags |= TCB_ATTACHED;
802 pflag_seen++;
803 break;
804 case 's':
805 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000806 if (max_strlen < 0) {
807 fprintf(stderr,
808 "%s: invalid -s argument: %s\n",
809 progname, optarg);
810 exit(1);
811 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 break;
813 case 'S':
814 set_sortby(optarg);
815 break;
816 case 'u':
817 username = strdup(optarg);
818 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000819 case 'E':
820 if (putenv(optarg) < 0) {
821 fprintf(stderr, "%s: out of memory\n",
822 progname);
823 exit(1);
824 }
825 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 default:
827 usage(stderr, 1);
828 break;
829 }
830 }
831
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000832 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000833 usage(stderr, 1);
834
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000835 if (!followfork)
836 followfork = optF;
837
Roland McGrathcb9def62006-04-25 07:48:03 +0000838 if (followfork > 1 && cflag) {
839 fprintf(stderr,
840 "%s: -c and -ff are mutually exclusive options\n",
841 progname);
842 exit(1);
843 }
844
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845 /* See if they want to run as another user. */
846 if (username != NULL) {
847 struct passwd *pent;
848
849 if (getuid() != 0 || geteuid() != 0) {
850 fprintf(stderr,
851 "%s: you must be root to use the -u option\n",
852 progname);
853 exit(1);
854 }
855 if ((pent = getpwnam(username)) == NULL) {
856 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000857 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 exit(1);
859 }
860 run_uid = pent->pw_uid;
861 run_gid = pent->pw_gid;
862 }
863 else {
864 run_uid = getuid();
865 run_gid = getgid();
866 }
867
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868 /* Check if they want to redirect the output. */
869 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000870 /* See if they want to pipe the output. */
871 if (outfname[0] == '|' || outfname[0] == '!') {
872 /*
873 * We can't do the <outfname>.PID funny business
874 * when using popen, so prohibit it.
875 */
876 if (followfork > 1) {
877 fprintf(stderr, "\
878%s: piping the output and -ff are mutually exclusive options\n",
879 progname);
880 exit(1);
881 }
882
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000883 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000884 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000885 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000886 else if (followfork <= 1 &&
887 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889 }
890
Roland McGrath37b9a662003-11-07 02:26:54 +0000891 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000892 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000893 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000896 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000897 /* Valid states here:
898 optind < argc pflag_seen outfname interactive
899 1 0 0 1
900 0 1 0 1
901 1 0 1 0
902 0 1 1 1
903 */
904
905 /* STARTUP_CHILD must be called before the signal handlers get
906 installed below as they are inherited into the spawned process.
907 Also we do not need to be protected by them as during interruption
908 in the STARTUP_CHILD mode we kill the spawned process anyway. */
909 if (!pflag_seen)
910 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000911
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 sigemptyset(&empty_set);
913 sigemptyset(&blocked_set);
914 sa.sa_handler = SIG_IGN;
915 sigemptyset(&sa.sa_mask);
916 sa.sa_flags = 0;
917 sigaction(SIGTTOU, &sa, NULL);
918 sigaction(SIGTTIN, &sa, NULL);
919 if (interactive) {
920 sigaddset(&blocked_set, SIGHUP);
921 sigaddset(&blocked_set, SIGINT);
922 sigaddset(&blocked_set, SIGQUIT);
923 sigaddset(&blocked_set, SIGPIPE);
924 sigaddset(&blocked_set, SIGTERM);
925 sa.sa_handler = interrupt;
926#ifdef SUNOS4
927 /* POSIX signals on sunos4.1 are a little broken. */
928 sa.sa_flags = SA_INTERRUPT;
929#endif /* SUNOS4 */
930 }
931 sigaction(SIGHUP, &sa, NULL);
932 sigaction(SIGINT, &sa, NULL);
933 sigaction(SIGQUIT, &sa, NULL);
934 sigaction(SIGPIPE, &sa, NULL);
935 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000936#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000937 sa.sa_handler = reaper;
938 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000939#else
940 /* Make sure SIGCHLD has the default action so that waitpid
941 definitely works without losing track of children. The user
942 should not have given us a bogus state to inherit, but he might
943 have. Arguably we should detect SIG_IGN here and pass it on
944 to children, but probably noone really needs that. */
945 sa.sa_handler = SIG_DFL;
946 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000947#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000949 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000950 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000951
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952 if (trace() < 0)
953 exit(1);
954 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000955 fflush(NULL);
956 if (exit_code > 0xff) {
957 /* Child was killed by a signal, mimic that. */
958 exit_code &= 0xff;
959 signal(exit_code, SIG_DFL);
960 raise(exit_code);
961 /* Paranoia - what if this signal is not fatal?
962 Exit with 128 + signo then. */
963 exit_code += 128;
964 }
965 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966}
967
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000968void
969expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000970{
971 /* Allocate some more TCBs and expand the table.
972 We don't want to relocate the TCBs because our
973 callers have pointers and it would be a pain.
974 So tcbtab is a table of pointers. Since we never
975 free the TCBs, we allocate a single chunk of many. */
976 struct tcb **newtab = (struct tcb **)
977 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
978 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
979 sizeof *newtcbs);
980 int i;
981 if (newtab == NULL || newtcbs == NULL) {
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000982 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
983 progname);
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000984 cleanup();
985 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000986 }
987 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
988 newtab[i] = &newtcbs[i - tcbtabsize];
989 tcbtabsize *= 2;
990 tcbtab = newtab;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000991}
992
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000994alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995{
996 int i;
997 struct tcb *tcp;
998
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000999 if (nprocs == tcbtabsize)
1000 expand_tcbtab();
1001
Roland McGrathee9d4352002-12-18 04:16:10 +00001002 for (i = 0; i < tcbtabsize; i++) {
1003 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00001005 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 tcp->flags = TCB_INUSE | TCB_STARTUP;
1008 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 tcp->pfd = -1;
1010 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001011 if (command_options_parsed)
1012 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013 return tcp;
1014 }
1015 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001016 fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1017 cleanup();
1018 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019}
1020
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001021#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001023proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024{
1025 char proc[32];
1026 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001027#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001028 int i;
1029 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001030 sigset_t signals;
1031 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001032#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033#ifndef HAVE_POLLABLE_PROCFS
1034 static int last_pfd;
1035#endif
1036
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001037#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001038 /* Open the process pseudo-files in /proc. */
1039 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1040 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 perror("strace: open(\"/proc/...\", ...)");
1042 return -1;
1043 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001044 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 return -1;
1046 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001047 sprintf(proc, "/proc/%d/status", tcp->pid);
1048 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1049 perror("strace: open(\"/proc/...\", ...)");
1050 return -1;
1051 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001052 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001053 return -1;
1054 }
1055 sprintf(proc, "/proc/%d/as", tcp->pid);
1056 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1057 perror("strace: open(\"/proc/...\", ...)");
1058 return -1;
1059 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001060 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001061 return -1;
1062 }
1063#else
1064 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001065#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001066 sprintf(proc, "/proc/%d", tcp->pid);
1067 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001068#else /* FREEBSD */
1069 sprintf(proc, "/proc/%d/mem", tcp->pid);
1070 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1071#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001072 perror("strace: open(\"/proc/...\", ...)");
1073 return -1;
1074 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001075 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001076 return -1;
1077 }
1078#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001079#ifdef FREEBSD
1080 sprintf(proc, "/proc/%d/regs", tcp->pid);
1081 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1082 perror("strace: open(\"/proc/.../regs\", ...)");
1083 return -1;
1084 }
1085 if (cflag) {
1086 sprintf(proc, "/proc/%d/status", tcp->pid);
1087 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1088 perror("strace: open(\"/proc/.../status\", ...)");
1089 return -1;
1090 }
1091 } else
1092 tcp->pfd_status = -1;
1093#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001094 rebuild_pollv();
1095 if (!attaching) {
1096 /*
1097 * Wait for the child to pause. Because of a race
1098 * condition we have to poll for the event.
1099 */
1100 for (;;) {
1101 if (IOCTL_STATUS (tcp) < 0) {
1102 perror("strace: PIOCSTATUS");
1103 return -1;
1104 }
1105 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001106 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001107 }
1108 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001109#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001110 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001111 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001112 perror("strace: PIOCSTOP");
1113 return -1;
1114 }
Roland McGrath553a6092002-12-16 20:40:39 +00001115#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001116#ifdef PIOCSET
1117 /* Set Run-on-Last-Close. */
1118 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001119 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 perror("PIOCSET PR_RLC");
1121 return -1;
1122 }
1123 /* Set or Reset Inherit-on-Fork. */
1124 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001125 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001126 perror("PIOC{SET,RESET} PR_FORK");
1127 return -1;
1128 }
1129#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001130#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1132 perror("PIOCSRLC");
1133 return -1;
1134 }
1135 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1136 perror("PIOC{S,R}FORK");
1137 return -1;
1138 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001139#else /* FREEBSD */
1140 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1141 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1142 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001143 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001144 }
1145 arg &= ~PF_LINGER;
1146 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001147 perror("PIOCSFL");
1148 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001149 }
1150#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001152#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001153 /* Enable all syscall entries we care about. */
1154 premptyset(&syscalls);
1155 for (i = 1; i < MAX_QUALS; ++i) {
1156 if (i > (sizeof syscalls) * CHAR_BIT) break;
1157 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1158 }
1159 praddset (&syscalls, SYS_execve);
1160 if (followfork) {
1161 praddset (&syscalls, SYS_fork);
1162#ifdef SYS_forkall
1163 praddset (&syscalls, SYS_forkall);
1164#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001165#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001166 praddset (&syscalls, SYS_fork1);
1167#endif
1168#ifdef SYS_rfork1
1169 praddset (&syscalls, SYS_rfork1);
1170#endif
1171#ifdef SYS_rforkall
1172 praddset (&syscalls, SYS_rforkall);
1173#endif
1174 }
1175 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176 perror("PIOCSENTRY");
1177 return -1;
1178 }
John Hughes19e49982001-10-19 08:59:12 +00001179 /* Enable the syscall exits. */
1180 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181 perror("PIOSEXIT");
1182 return -1;
1183 }
John Hughes19e49982001-10-19 08:59:12 +00001184 /* Enable signals we care about. */
1185 premptyset(&signals);
1186 for (i = 1; i < MAX_QUALS; ++i) {
1187 if (i > (sizeof signals) * CHAR_BIT) break;
1188 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1189 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001190 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 perror("PIOCSTRACE");
1192 return -1;
1193 }
John Hughes19e49982001-10-19 08:59:12 +00001194 /* Enable faults we care about */
1195 premptyset(&faults);
1196 for (i = 1; i < MAX_QUALS; ++i) {
1197 if (i > (sizeof faults) * CHAR_BIT) break;
1198 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1199 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001200 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 perror("PIOCSFAULT");
1202 return -1;
1203 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001204#else /* FREEBSD */
1205 /* set events flags. */
1206 arg = S_SIG | S_SCE | S_SCX ;
1207 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1208 perror("PIOCBIS");
1209 return -1;
1210 }
1211#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 if (!attaching) {
1213#ifdef MIPS
1214 /*
1215 * The SGI PRSABORT doesn't work for pause() so
1216 * we send it a caught signal to wake it up.
1217 */
1218 kill(tcp->pid, SIGINT);
1219#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001220#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001222 arg = PRSABORT;
1223 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 perror("PIOCRUN");
1225 return -1;
1226 }
Roland McGrath553a6092002-12-16 20:40:39 +00001227#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001228#endif /* !MIPS*/
1229#ifdef FREEBSD
1230 /* wake up the child if it received the SIGSTOP */
1231 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001232#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 for (;;) {
1234 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001235 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 perror("PIOCWSTOP");
1237 return -1;
1238 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001239 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001240 tcp->flags &= ~TCB_INSYSCALL;
1241 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001242 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001243 break;
1244 }
1245 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001246#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001247 arg = 0;
1248 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001249#else /* FREEBSD */
1250 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001251#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252 perror("PIOCRUN");
1253 return -1;
1254 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001255#ifdef FREEBSD
1256 /* handle the case where we "opened" the child before
1257 it did the kill -STOP */
1258 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1259 tcp->status.PR_WHAT == SIGSTOP)
1260 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001261#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001263#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001265#else /* FREEBSD */
1266 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001267 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001268 /* We are attaching to an already running process.
1269 * Try to figure out the state of the process in syscalls,
1270 * to handle the first event well.
1271 * This is done by having a look at the "wchan" property of the
1272 * process, which tells where it is stopped (if it is). */
1273 FILE * status;
1274 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001275
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001276 sprintf(proc, "/proc/%d/status", tcp->pid);
1277 status = fopen(proc, "r");
1278 if (status &&
1279 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1280 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1281 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1282 strcmp(wchan, "stopevent")) {
1283 /* The process is asleep in the middle of a syscall.
1284 Fake the syscall entry event */
1285 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1286 tcp->status.PR_WHY = PR_SYSENTRY;
1287 trace_syscall(tcp);
1288 }
1289 if (status)
1290 fclose(status);
1291 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001292 }
1293#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294#ifndef HAVE_POLLABLE_PROCFS
1295 if (proc_poll_pipe[0] != -1)
1296 proc_poller(tcp->pfd);
1297 else if (nprocs > 1) {
1298 proc_poll_open();
1299 proc_poller(last_pfd);
1300 proc_poller(tcp->pfd);
1301 }
1302 last_pfd = tcp->pfd;
1303#endif /* !HAVE_POLLABLE_PROCFS */
1304 return 0;
1305}
1306
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001307#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001308
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001309struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001310pid2tcb(pid)
1311int pid;
1312{
1313 int i;
1314 struct tcb *tcp;
1315
Roland McGrathee9d4352002-12-18 04:16:10 +00001316 for (i = 0; i < tcbtabsize; i++) {
1317 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318 if (pid && tcp->pid != pid)
1319 continue;
1320 if (tcp->flags & TCB_INUSE)
1321 return tcp;
1322 }
1323 return NULL;
1324}
1325
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001326#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001327
1328static struct tcb *
1329pfd2tcb(pfd)
1330int pfd;
1331{
1332 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333
Roland McGrathca16be82003-01-10 19:55:28 +00001334 for (i = 0; i < tcbtabsize; i++) {
1335 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336 if (tcp->pfd != pfd)
1337 continue;
1338 if (tcp->flags & TCB_INUSE)
1339 return tcp;
1340 }
1341 return NULL;
1342}
1343
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001344#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345
1346void
1347droptcb(tcp)
1348struct tcb *tcp;
1349{
1350 if (tcp->pid == 0)
1351 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001352#ifdef TCB_CLONE_THREAD
1353 if (tcp->nclone_threads > 0) {
1354 /* There are other threads left in this process, but this
1355 is the one whose PID represents the whole process.
1356 We need to keep this record around as a zombie until
1357 all the threads die. */
1358 tcp->flags |= TCB_EXITING;
1359 return;
1360 }
1361#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001362 nprocs--;
1363 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001364
Roland McGrathe29341c2003-01-10 20:14:20 +00001365 if (tcp->parent != NULL) {
1366 tcp->parent->nchildren--;
1367#ifdef TCB_CLONE_THREAD
1368 if (tcp->flags & TCB_CLONE_DETACHED)
1369 tcp->parent->nclone_detached--;
1370 if (tcp->flags & TCB_CLONE_THREAD)
1371 tcp->parent->nclone_threads--;
1372#endif
Roland McGrath09623452003-05-23 02:27:13 +00001373#ifdef TCB_CLONE_DETACHED
1374 if (!(tcp->flags & TCB_CLONE_DETACHED))
1375#endif
1376 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001377#ifdef LINUX
1378 /* Update `tcp->parent->parent->nchildren' and the other fields
1379 like NCLONE_DETACHED, only for zombie group leader that has
1380 already reported and been short-circuited at the top of this
1381 function. The same condition as at the top of DETACH. */
1382 if ((tcp->flags & TCB_CLONE_THREAD) &&
1383 tcp->parent->nclone_threads == 0 &&
1384 (tcp->parent->flags & TCB_EXITING))
1385 droptcb(tcp->parent);
1386#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001387 tcp->parent = NULL;
1388 }
1389
1390 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391 if (tcp->pfd != -1) {
1392 close(tcp->pfd);
1393 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001394#ifdef FREEBSD
1395 if (tcp->pfd_reg != -1) {
1396 close(tcp->pfd_reg);
1397 tcp->pfd_reg = -1;
1398 }
1399 if (tcp->pfd_status != -1) {
1400 close(tcp->pfd_status);
1401 tcp->pfd_status = -1;
1402 }
Roland McGrath553a6092002-12-16 20:40:39 +00001403#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001404#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001405 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406#endif
1407 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001408
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001409 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001411
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001412 tcp->outf = 0;
1413}
1414
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001415#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416
1417static int
1418resume(tcp)
1419struct tcb *tcp;
1420{
1421 if (tcp == NULL)
1422 return -1;
1423
1424 if (!(tcp->flags & TCB_SUSPENDED)) {
1425 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1426 return -1;
1427 }
1428 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001429#ifdef TCB_CLONE_THREAD
1430 if (tcp->flags & TCB_CLONE_THREAD)
1431 tcp->parent->nclone_waiting--;
1432#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001434 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436
1437 if (!qflag)
1438 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1439 return 0;
1440}
1441
Roland McGrath1bfd3102007-08-03 10:02:00 +00001442static int
1443resume_from_tcp (struct tcb *tcp)
1444{
1445 int error = 0;
1446 int resumed = 0;
1447
1448 /* XXX This won't always be quite right (but it never was).
1449 A waiter with argument 0 or < -1 is waiting for any pid in
1450 a particular pgrp, which this child might or might not be
1451 in. The waiter will only wake up if it's argument is -1
1452 or if it's waiting for tcp->pid's pgrp. It makes a
1453 difference to wake up a waiter when there might be more
1454 traced children, because it could get a false ECHILD
1455 error. OTOH, if this was the last child in the pgrp, then
1456 it ought to wake up and get ECHILD. We would have to
1457 search the system for all pid's in the pgrp to be sure.
1458
1459 && (t->waitpid == -1 ||
1460 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1461 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1462 */
1463
1464 if (tcp->parent &&
1465 (tcp->parent->flags & TCB_SUSPENDED) &&
1466 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001467 error = resume(tcp->parent);
Roland McGrath1bfd3102007-08-03 10:02:00 +00001468 ++resumed;
1469 }
1470#ifdef TCB_CLONE_THREAD
1471 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1472 /* Some other threads of our parent are waiting too. */
1473 unsigned int i;
1474
1475 /* Resume all the threads that were waiting for this PID. */
1476 for (i = 0; i < tcbtabsize; i++) {
1477 struct tcb *t = tcbtab[i];
1478 if (t->parent == tcp->parent && t != tcp
1479 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1480 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1481 && t->waitpid == tcp->pid) {
1482 error |= resume (t);
1483 ++resumed;
1484 }
1485 }
1486 if (resumed == 0)
1487 /* Noone was waiting for this PID in particular,
1488 so now we might need to resume some wildcarders. */
1489 for (i = 0; i < tcbtabsize; i++) {
1490 struct tcb *t = tcbtab[i];
1491 if (t->parent == tcp->parent && t != tcp
1492 && ((t->flags
1493 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1494 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1495 && t->waitpid <= 0
1496 ) {
1497 error |= resume (t);
1498 break;
1499 }
1500 }
1501 }
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001502#endif
Roland McGrath1bfd3102007-08-03 10:02:00 +00001503
1504 return error;
1505}
Roland McGrath1bfd3102007-08-03 10:02:00 +00001506
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001507#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001508
Roland McGrath0a463882007-07-05 18:43:16 +00001509/* detach traced process; continue with sig
1510 Never call DETACH twice on the same process as both unattached and
1511 attached-unstopped processes give the same ESRCH. For unattached process we
1512 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513
1514static int
1515detach(tcp, sig)
1516struct tcb *tcp;
1517int sig;
1518{
1519 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001520#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001521 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001522 struct tcb *zombie = NULL;
1523
1524 /* If the group leader is lingering only because of this other
1525 thread now dying, then detach the leader as well. */
1526 if ((tcp->flags & TCB_CLONE_THREAD) &&
1527 tcp->parent->nclone_threads == 1 &&
1528 (tcp->parent->flags & TCB_EXITING))
1529 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001530#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531
1532 if (tcp->flags & TCB_BPTSET)
1533 sig = SIGKILL;
1534
1535#ifdef LINUX
1536 /*
1537 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001538 * before detaching. Arghh. We go through hoops
1539 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001541#if defined(SPARC)
1542#undef PTRACE_DETACH
1543#define PTRACE_DETACH PTRACE_SUNDETACH
1544#endif
Roland McGrath02203312007-06-11 22:06:31 +00001545 /*
1546 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1547 * expected SIGSTOP. We must catch exactly one as otherwise the
1548 * detached process would be left stopped (process state T).
1549 */
1550 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1552 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001553 }
1554 else if (errno != ESRCH) {
1555 /* Shouldn't happen. */
1556 perror("detach: ptrace(PTRACE_DETACH, ...)");
1557 }
Roland McGrath134813a2007-06-02 00:07:33 +00001558 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1559 : tcp->pid),
1560 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001561 if (errno != ESRCH)
1562 perror("detach: checking sanity");
1563 }
Roland McGrath02203312007-06-11 22:06:31 +00001564 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1565 ? tcp->parent->pid : tcp->pid),
1566 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001567 if (errno != ESRCH)
1568 perror("detach: stopping child");
1569 }
Roland McGrath02203312007-06-11 22:06:31 +00001570 else
1571 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001572 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001574#ifdef __WALL
1575 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1576 if (errno == ECHILD) /* Already gone. */
1577 break;
1578 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001579 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001580 break;
1581 }
1582#endif /* __WALL */
1583 /* No __WALL here. */
1584 if (waitpid(tcp->pid, &status, 0) < 0) {
1585 if (errno != ECHILD) {
1586 perror("detach: waiting");
1587 break;
1588 }
1589#ifdef __WCLONE
1590 /* If no processes, try clones. */
1591 if (wait4(tcp->pid, &status, __WCLONE,
1592 NULL) < 0) {
1593 if (errno != ECHILD)
1594 perror("detach: waiting");
1595 break;
1596 }
1597#endif /* __WCLONE */
1598 }
1599#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001600 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001601#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001602 if (!WIFSTOPPED(status)) {
1603 /* Au revoir, mon ami. */
1604 break;
1605 }
1606 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001607 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608 break;
1609 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001610 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko96d5a762008-12-29 19:13:27 +00001611 WSTOPSIG(status) == ptrace_stop_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001612 : WSTOPSIG(status));
1613 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001616 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001617#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618
1619#if defined(SUNOS4)
1620 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1621 if (sig && kill(tcp->pid, sig) < 0)
1622 perror("detach: kill");
1623 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001624 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625#endif /* SUNOS4 */
1626
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001627#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001628 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001629#endif
1630
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 if (!qflag)
1632 fprintf(stderr, "Process %u detached\n", tcp->pid);
1633
1634 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001635
1636#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001637 if (zombie != NULL) {
1638 /* TCP no longer exists therefore you must not detach () it. */
1639 droptcb(zombie);
1640 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001641#endif
1642
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643 return error;
1644}
1645
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001646#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647
1648static void
1649reaper(sig)
1650int sig;
1651{
1652 int pid;
1653 int status;
1654
1655 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1656#if 0
1657 struct tcb *tcp;
1658
1659 tcp = pid2tcb(pid);
1660 if (tcp)
1661 droptcb(tcp);
1662#endif
1663 }
1664}
1665
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001666#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667
1668static void
1669cleanup()
1670{
1671 int i;
1672 struct tcb *tcp;
1673
Roland McGrathee9d4352002-12-18 04:16:10 +00001674 for (i = 0; i < tcbtabsize; i++) {
1675 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001676 if (!(tcp->flags & TCB_INUSE))
1677 continue;
1678 if (debug)
1679 fprintf(stderr,
1680 "cleanup: looking at pid %u\n", tcp->pid);
1681 if (tcp_last &&
1682 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001683 tprintf(" <unfinished ...>");
1684 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 }
1686 if (tcp->flags & TCB_ATTACHED)
1687 detach(tcp, 0);
1688 else {
1689 kill(tcp->pid, SIGCONT);
1690 kill(tcp->pid, SIGTERM);
1691 }
1692 }
1693 if (cflag)
1694 call_summary(outf);
1695}
1696
1697static void
1698interrupt(sig)
1699int sig;
1700{
1701 interrupted = 1;
1702}
1703
1704#ifndef HAVE_STRERROR
1705
Roland McGrath6d2b3492002-12-30 00:51:30 +00001706#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707extern int sys_nerr;
1708extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001709#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710
1711const char *
1712strerror(errno)
1713int errno;
1714{
1715 static char buf[64];
1716
1717 if (errno < 1 || errno >= sys_nerr) {
1718 sprintf(buf, "Unknown error %d", errno);
1719 return buf;
1720 }
1721 return sys_errlist[errno];
1722}
1723
1724#endif /* HAVE_STERRROR */
1725
1726#ifndef HAVE_STRSIGNAL
1727
Roland McGrath8f474e02003-01-14 07:53:33 +00001728#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001729extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001731#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1732extern char *_sys_siglist[];
1733#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734
1735const char *
1736strsignal(sig)
1737int sig;
1738{
1739 static char buf[64];
1740
1741 if (sig < 1 || sig >= NSIG) {
1742 sprintf(buf, "Unknown signal %d", sig);
1743 return buf;
1744 }
1745#ifdef HAVE__SYS_SIGLIST
1746 return _sys_siglist[sig];
1747#else
1748 return sys_siglist[sig];
1749#endif
1750}
1751
1752#endif /* HAVE_STRSIGNAL */
1753
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001754#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755
1756static void
1757rebuild_pollv()
1758{
1759 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760
Roland McGrathee9d4352002-12-18 04:16:10 +00001761 if (pollv != NULL)
1762 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001763 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001764 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001765 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001766 exit(1);
1767 }
1768
Roland McGrathca16be82003-01-10 19:55:28 +00001769 for (i = j = 0; i < tcbtabsize; i++) {
1770 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001771 if (!(tcp->flags & TCB_INUSE))
1772 continue;
1773 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001774 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775 j++;
1776 }
1777 if (j != nprocs) {
1778 fprintf(stderr, "strace: proc miscount\n");
1779 exit(1);
1780 }
1781}
1782
1783#ifndef HAVE_POLLABLE_PROCFS
1784
1785static void
1786proc_poll_open()
1787{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 int i;
1789
1790 if (pipe(proc_poll_pipe) < 0) {
1791 perror("pipe");
1792 exit(1);
1793 }
1794 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001795 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 exit(1);
1797 }
1798 }
1799}
1800
1801static int
1802proc_poll(pollv, nfds, timeout)
1803struct pollfd *pollv;
1804int nfds;
1805int timeout;
1806{
1807 int i;
1808 int n;
1809 struct proc_pollfd pollinfo;
1810
1811 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1812 return n;
1813 if (n != sizeof(struct proc_pollfd)) {
1814 fprintf(stderr, "panic: short read: %d\n", n);
1815 exit(1);
1816 }
1817 for (i = 0; i < nprocs; i++) {
1818 if (pollv[i].fd == pollinfo.fd)
1819 pollv[i].revents = pollinfo.revents;
1820 else
1821 pollv[i].revents = 0;
1822 }
1823 poller_pid = pollinfo.pid;
1824 return 1;
1825}
1826
1827static void
1828wakeup_handler(sig)
1829int sig;
1830{
1831}
1832
1833static void
1834proc_poller(pfd)
1835int pfd;
1836{
1837 struct proc_pollfd pollinfo;
1838 struct sigaction sa;
1839 sigset_t blocked_set, empty_set;
1840 int i;
1841 int n;
1842 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001843#ifdef FREEBSD
1844 struct procfs_status pfs;
1845#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846
1847 switch (fork()) {
1848 case -1:
1849 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001850 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851 case 0:
1852 break;
1853 default:
1854 return;
1855 }
1856
1857 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1858 sa.sa_flags = 0;
1859 sigemptyset(&sa.sa_mask);
1860 sigaction(SIGHUP, &sa, NULL);
1861 sigaction(SIGINT, &sa, NULL);
1862 sigaction(SIGQUIT, &sa, NULL);
1863 sigaction(SIGPIPE, &sa, NULL);
1864 sigaction(SIGTERM, &sa, NULL);
1865 sa.sa_handler = wakeup_handler;
1866 sigaction(SIGUSR1, &sa, NULL);
1867 sigemptyset(&blocked_set);
1868 sigaddset(&blocked_set, SIGUSR1);
1869 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1870 sigemptyset(&empty_set);
1871
1872 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1873 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001874 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875 }
1876 n = rl.rlim_cur;
1877 for (i = 0; i < n; i++) {
1878 if (i != pfd && i != proc_poll_pipe[1])
1879 close(i);
1880 }
1881
1882 pollinfo.fd = pfd;
1883 pollinfo.pid = getpid();
1884 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001885#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001886 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1887#else
1888 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1889#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001890 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001891 switch (errno) {
1892 case EINTR:
1893 continue;
1894 case EBADF:
1895 pollinfo.revents = POLLERR;
1896 break;
1897 case ENOENT:
1898 pollinfo.revents = POLLHUP;
1899 break;
1900 default:
1901 perror("proc_poller: PIOCWSTOP");
1902 }
1903 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1904 _exit(0);
1905 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001906 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1908 sigsuspend(&empty_set);
1909 }
1910}
1911
1912#endif /* !HAVE_POLLABLE_PROCFS */
1913
1914static int
1915choose_pfd()
1916{
1917 int i, j;
1918 struct tcb *tcp;
1919
1920 static int last;
1921
1922 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001923 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924 /*
1925 * The previous process is ready to run again. We'll
1926 * let it do so if it is currently in a syscall. This
1927 * heuristic improves the readability of the trace.
1928 */
1929 tcp = pfd2tcb(pollv[last].fd);
1930 if (tcp && (tcp->flags & TCB_INSYSCALL))
1931 return pollv[last].fd;
1932 }
1933
1934 for (i = 0; i < nprocs; i++) {
1935 /* Let competing children run round robin. */
1936 j = (i + last + 1) % nprocs;
1937 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1938 tcp = pfd2tcb(pollv[j].fd);
1939 if (!tcp) {
1940 fprintf(stderr, "strace: lost proc\n");
1941 exit(1);
1942 }
1943 droptcb(tcp);
1944 return -1;
1945 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001946 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001947 last = j;
1948 return pollv[j].fd;
1949 }
1950 }
1951 fprintf(stderr, "strace: nothing ready\n");
1952 exit(1);
1953}
1954
1955static int
1956trace()
1957{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001958#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001959 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001960#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 struct tcb *tcp;
1962 int pfd;
1963 int what;
1964 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001965 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966
1967 for (;;) {
1968 if (interactive)
1969 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1970
1971 if (nprocs == 0)
1972 break;
1973
1974 switch (nprocs) {
1975 case 1:
1976#ifndef HAVE_POLLABLE_PROCFS
1977 if (proc_poll_pipe[0] == -1) {
1978#endif
1979 tcp = pid2tcb(0);
1980 if (!tcp)
1981 continue;
1982 pfd = tcp->pfd;
1983 if (pfd == -1)
1984 continue;
1985 break;
1986#ifndef HAVE_POLLABLE_PROCFS
1987 }
1988 /* fall through ... */
1989#endif /* !HAVE_POLLABLE_PROCFS */
1990 default:
1991#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001992#ifdef POLL_HACK
1993 /* On some systems (e.g. UnixWare) we get too much ugly
1994 "unfinished..." stuff when multiple proceses are in
1995 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001996
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001997 if (in_syscall) {
1998 struct pollfd pv;
1999 tcp = in_syscall;
2000 in_syscall = NULL;
2001 pv.fd = tcp->pfd;
2002 pv.events = POLLWANT;
2003 if ((what = poll (&pv, 1, 1)) < 0) {
2004 if (interrupted)
2005 return 0;
2006 continue;
2007 }
2008 else if (what == 1 && pv.revents & POLLWANT) {
2009 goto FOUND;
2010 }
2011 }
2012#endif
2013
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002014 if (poll(pollv, nprocs, INFTIM) < 0) {
2015 if (interrupted)
2016 return 0;
2017 continue;
2018 }
2019#else /* !HAVE_POLLABLE_PROCFS */
2020 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2021 if (interrupted)
2022 return 0;
2023 continue;
2024 }
2025#endif /* !HAVE_POLLABLE_PROCFS */
2026 pfd = choose_pfd();
2027 if (pfd == -1)
2028 continue;
2029 break;
2030 }
2031
2032 /* Look up `pfd' in our table. */
2033 if ((tcp = pfd2tcb(pfd)) == NULL) {
2034 fprintf(stderr, "unknown pfd: %u\n", pfd);
2035 exit(1);
2036 }
John Hughesb6643082002-05-23 11:02:22 +00002037#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002038 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002039#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 /* Get the status of the process. */
2041 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002042#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002043 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002044#else /* FREEBSD */
2045 /* Thanks to some scheduling mystery, the first poller
2046 sometimes waits for the already processed end of fork
2047 event. Doing a non blocking poll here solves the problem. */
2048 if (proc_poll_pipe[0] != -1)
2049 ioctl_result = IOCTL_STATUS (tcp);
2050 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002051 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002052#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 ioctl_errno = errno;
2054#ifndef HAVE_POLLABLE_PROCFS
2055 if (proc_poll_pipe[0] != -1) {
2056 if (ioctl_result < 0)
2057 kill(poller_pid, SIGKILL);
2058 else
2059 kill(poller_pid, SIGUSR1);
2060 }
2061#endif /* !HAVE_POLLABLE_PROCFS */
2062 }
2063 if (interrupted)
2064 return 0;
2065
2066 if (interactive)
2067 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2068
2069 if (ioctl_result < 0) {
2070 /* Find out what happened if it failed. */
2071 switch (ioctl_errno) {
2072 case EINTR:
2073 case EBADF:
2074 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002075#ifdef FREEBSD
2076 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002077#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 case ENOENT:
2079 droptcb(tcp);
2080 continue;
2081 default:
2082 perror("PIOCWSTOP");
2083 exit(1);
2084 }
2085 }
2086
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002087#ifdef FREEBSD
2088 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2089 /* discard first event for a syscall we never entered */
2090 IOCTL (tcp->pfd, PIOCRUN, 0);
2091 continue;
2092 }
Roland McGrath553a6092002-12-16 20:40:39 +00002093#endif
2094
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 /* clear the just started flag */
2096 tcp->flags &= ~TCB_STARTUP;
2097
2098 /* set current output file */
2099 outf = tcp->outf;
2100
2101 if (cflag) {
2102 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002103#ifdef FREEBSD
2104 char buf[1024];
2105 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002107 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2108 buf[len] = '\0';
2109 sscanf(buf,
2110 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2111 &stime.tv_sec, &stime.tv_usec);
2112 } else
2113 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002114#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002115 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2116 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002117#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002118 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2119 tcp->stime = stime;
2120 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002121 what = tcp->status.PR_WHAT;
2122 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002123#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002124 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002125 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2126 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127 if (trace_syscall(tcp) < 0) {
2128 fprintf(stderr, "syscall trouble\n");
2129 exit(1);
2130 }
2131 }
2132 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002133#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002135#ifdef POLL_HACK
2136 in_syscall = tcp;
2137#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 case PR_SYSEXIT:
2139 if (trace_syscall(tcp) < 0) {
2140 fprintf(stderr, "syscall trouble\n");
2141 exit(1);
2142 }
2143 break;
2144 case PR_SIGNALLED:
2145 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2146 printleader(tcp);
2147 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002148 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002149 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002150#ifdef PR_INFO
2151 if (tcp->status.PR_INFO.si_signo == what) {
2152 printleader(tcp);
2153 tprintf(" siginfo=");
2154 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002155 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002156 }
2157#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002158 }
2159 break;
2160 case PR_FAULTED:
2161 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2162 printleader(tcp);
2163 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002164 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002165 }
2166 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002167#ifdef FREEBSD
2168 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002169 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002170#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002172 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002173 exit(1);
2174 break;
2175 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002176 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002177#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002178 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002179#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002180 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182 perror("PIOCRUN");
2183 exit(1);
2184 }
2185 }
2186 return 0;
2187}
2188
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002189#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002191#ifdef TCB_GROUP_EXITING
2192/* Handle an exit detach or death signal that is taking all the
2193 related clone threads with it. This is called in three circumstances:
2194 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2195 SIG == 0 Continuing TCP will perform an exit_group syscall.
2196 SIG == other Continuing TCP with SIG will kill the process.
2197*/
2198static int
2199handle_group_exit(struct tcb *tcp, int sig)
2200{
2201 /* We need to locate our records of all the clone threads
2202 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002203 struct tcb *leader = NULL;
2204
2205 if (tcp->flags & TCB_CLONE_THREAD)
2206 leader = tcp->parent;
2207 else if (tcp->nclone_detached > 0)
2208 leader = tcp;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002209
2210 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002211 if (leader != NULL && leader != tcp
2212 && !(leader->flags & TCB_GROUP_EXITING)
2213 && !(tcp->flags & TCB_STARTUP)
2214 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002215 fprintf(stderr,
2216 "PANIC: handle_group_exit: %d leader %d\n",
2217 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002218 }
2219 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002220#ifndef USE_PROCFS
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002221 resume_from_tcp(tcp);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002222#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002223 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002224 }
2225 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002226 /* Mark that we are taking the process down. */
2227 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002228 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002229 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002230 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002231 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002232 } else {
2233 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2234 cleanup();
2235 return -1;
2236 }
2237 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002238 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002239 if (leader != tcp)
2240 droptcb(tcp);
2241 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002242 /* The leader will report to us as parent now,
2243 and then we'll get to the SIG==-1 case. */
2244 return 0;
2245 }
2246 }
2247
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002248 return 0;
2249}
2250#endif
2251
Denys Vlasenko215cc272009-01-09 17:22:56 +00002252static struct tcb *
2253collect_stopped_tcbs(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002254{
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002255#ifdef LINUX
2256 static int remembered_pid;
2257 static int remembered_status;
2258#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002259 int pid;
2260 int wait_errno;
2261 int status;
2262 struct tcb *tcp;
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002263 struct tcb *found_tcps;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002264#ifdef LINUX
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002265 struct tcb **nextp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266 struct rusage ru;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002267 struct rusage* ru_ptr = cflag ? &ru : NULL;
2268 int wnohang = 0;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002269#ifdef __WALL
Denys Vlasenko215cc272009-01-09 17:22:56 +00002270 int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002271#endif
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002272
2273 if (remembered_pid > 0) {
2274 pid = remembered_pid;
2275 remembered_pid = 0;
2276 if (debug)
2277 fprintf(stderr, " [remembered wait(%#x) = %u]\n",
2278 remembered_status, pid);
2279 tcp = pid2tcb(pid); /* can't be NULL */
2280 tcp->wait_status = remembered_status;
2281 tcp->next_need_service = NULL;
2282 return tcp;
2283 }
2284 nextp = &found_tcps;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285#endif /* LINUX */
2286
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002287 found_tcps = NULL;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002288 while (1) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002289 if (interrupted)
2290 break;
2291 if (interactive)
2292 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002293#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002294#ifdef __WALL
Denys Vlasenko215cc272009-01-09 17:22:56 +00002295 pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
Roland McGrath5bc05552002-12-17 04:50:47 +00002296 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002297 /* this kernel does not support __WALL */
2298 wait4_options &= ~__WALL;
2299 errno = 0;
Denys Vlasenko215cc272009-01-09 17:22:56 +00002300 pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002301 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002302 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002303 /* most likely a "cloned" process */
Denys Vlasenko215cc272009-01-09 17:22:56 +00002304 pid = wait4(-1, &status, __WCLONE | wnohang, ru_ptr);
2305 if (pid < 0 && errno != ECHILD) {
2306 fprintf(stderr, "strace: wait4(WCLONE) "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002307 "failed: %s\n", strerror(errno));
2308 }
2309 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002310#else /* !__WALL */
2311 pid = wait4(-1, &status, wnohang, ru_ptr);
2312#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002313#endif /* LINUX */
2314#ifdef SUNOS4
2315 pid = wait(&status);
2316#endif /* SUNOS4 */
2317 wait_errno = errno;
2318 if (interactive)
2319 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2320
Denys Vlasenko215cc272009-01-09 17:22:56 +00002321 if (pid == 0 && wnohang) {
2322 /* We had at least one successful
2323 * wait() before. We waited
2324 * with WNOHANG second time.
2325 * Stop collecting more tracees,
2326 * process what we already have.
2327 */
2328 break;
2329 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330 if (pid == -1) {
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002331 if (wait_errno == EINTR)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002332 continue;
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002333 if (wait_errno == ECHILD) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 /*
2335 * We would like to verify this case
2336 * but sometimes a race in Solbourne's
2337 * version of SunOS sometimes reports
2338 * ECHILD before sending us SIGCHILD.
2339 */
2340#if 0
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002341 if (nprocs != 0) {
2342 fprintf(stderr, "strace: proc miscount\n");
2343 exit(1);
2344 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345#endif
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002346 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 }
Denys Vlasenko2c8a2582009-01-21 19:05:43 +00002348 errno = wait_errno;
2349 perror("strace: wait");
2350 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002351 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002352 if (pid == popen_pid) {
2353 if (WIFEXITED(status) || WIFSIGNALED(status))
2354 popen_pid = -1;
2355 continue;
2356 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002357 if (debug)
2358 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2359
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002360 /* RHEL5 bug workaround.
2361 * It can re-report stopped tasks. Happens on SIGSTOPs here.
2362 * Second (bogus) report has signal# set to 0.
2363 * Stop collecting and process what we have.
2364 */
2365 if (WIFSTOPPED(status) && WSTOPSIG(status) == 0)
2366 break;
2367
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002368 /* Look up `pid' in our table. */
2369 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002370#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002371 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002372 /* This is needed to go with the CLONE_PTRACE
2373 changes in process.c/util.c: we might see
2374 the child's initial trap before we see the
2375 parent return from the clone syscall.
2376 Leave the child suspended until the parent
2377 returns from its system call. Only then
2378 will we have the association of parent and
2379 child so that we know how to do clearbpt
2380 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002381 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002382 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002383 if (!qflag)
2384 fprintf(stderr, "\
2385Process %d attached (waiting for parent)\n",
2386 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002387 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002388 else
2389 /* This can happen if a clone call used
2390 CLONE_PTRACE itself. */
Denys Vlasenko215cc272009-01-09 17:22:56 +00002391#endif /* LINUX */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002392 {
2393 fprintf(stderr, "unknown pid: %u\n", pid);
2394 if (WIFSTOPPED(status))
2395 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2396 exit(1);
2397 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002399
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002400#ifdef LINUX
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002401 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002402 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2403 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002404 }
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002405#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002406 if (tcp->flags & TCB_SUSPENDED) {
2407 /*
2408 * Apparently, doing any ptrace() call on a stopped
2409 * process, provokes the kernel to report the process
2410 * status again on a subsequent wait(), even if the
2411 * process has not been actually restarted.
2412 * Since we have inspected the arguments of suspended
2413 * processes we end up here testing for this case.
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002414 *
2415 * We also end up here when we catch new pid of
2416 * CLONE_PTRACEd process. Do not process/restart it
2417 * until we see corresponding clone() syscall exit
2418 * in its parent.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002419 */
2420 continue;
2421 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002422
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002423#ifdef LINUX
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002424 /* So far observed only on RHEL5 ia64, but I imagine this
2425 * can legitimately happen elsewhere.
2426 * If we waited and got a stopped task notification,
2427 * subsequent wait may return the same pid again, for example,
2428 * with SIGKILL notification. SIGKILL kills even stopped tasks.
2429 * We must not add it to the list
2430 * (one task can't be inserted twice in the list).
2431 */
2432 {
2433 struct tcb *f = found_tcps;
2434 while (f) {
2435 if (f == tcp) {
2436 remembered_pid = pid;
2437 remembered_status = status;
2438 return found_tcps;
2439 }
2440 f = f->next_need_service;
2441 }
2442 }
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002443 /* It is important to not invert the order of tasks
2444 * to process. For one, alloc_tcb() above picks newly forked
2445 * threads in some order, processing of them and their parent
2446 * should be in the same order, otherwise bad things happen
2447 * (misinterpreted SIGSTOPs and such).
2448 */
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002449 tcp->wait_status = status;
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002450 *nextp = tcp;
2451 nextp = &tcp->next_need_service;
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002452 *nextp = NULL;
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002453 wnohang = WNOHANG;
2454#endif
2455#ifdef SUNOS4
2456 /* Probably need to replace wait with waitpid
2457 * and loop on Sun too, but I can't test it. Volunteers?
2458 */
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002459 tcp->wait_status = status;
2460 tcp->next_need_service = NULL;
2461 found_tcps = tcp;
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002462 break;
2463#endif
Denys Vlasenko47ce6df2009-01-27 19:38:44 +00002464 } /* while (1) - collecting all stopped/exited tracees */
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002465
Denys Vlasenkof9a7e632009-01-17 00:21:31 +00002466 return found_tcps;
2467}
2468
2469static int
2470handle_stopped_tcbs(struct tcb *tcp)
2471{
2472 for (; tcp; tcp = tcp->next_need_service) {
2473 int pid;
2474 int status;
2475
Denys Vlasenko215cc272009-01-09 17:22:56 +00002476 outf = tcp->outf;
2477 status = tcp->wait_status;
2478 pid = tcp->pid;
2479
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002480 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002481 if (pid == strace_child)
2482 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002483 if (!cflag
2484 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2485 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002486 tprintf("+++ killed by %s %s+++",
2487 signame(WTERMSIG(status)),
2488#ifdef WCOREDUMP
2489 WCOREDUMP(status) ? "(core dumped) " :
2490#endif
2491 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002492 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002493 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002494#ifdef TCB_GROUP_EXITING
2495 handle_group_exit(tcp, -1);
2496#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002497 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002498#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002499 continue;
2500 }
2501 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002502 if (pid == strace_child)
2503 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002504 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002505 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2506 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002507#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002508 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002509 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002510#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002511 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002512 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002513 "PANIC: attached pid %u exited with %d\n",
2514 pid, WEXITSTATUS(status));
2515 }
Roland McGrath0a396902003-06-10 03:05:53 +00002516 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002517 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002518 tprintf(" <unfinished ... exit status %d>\n",
2519 WEXITSTATUS(status));
2520 tcp_last = NULL;
2521 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002522#ifdef TCB_GROUP_EXITING
2523 handle_group_exit(tcp, -1);
2524#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002525 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002526#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002527 continue;
2528 }
2529 if (!WIFSTOPPED(status)) {
2530 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2531 droptcb(tcp);
2532 continue;
2533 }
2534 if (debug)
2535 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002536 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537
Roland McGrath02203312007-06-11 22:06:31 +00002538 /*
2539 * Interestingly, the process may stop
2540 * with STOPSIG equal to some other signal
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002541 * than SIGSTOP if we happen to attach
Roland McGrath02203312007-06-11 22:06:31 +00002542 * just before the process takes a signal.
2543 */
2544 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002545 /*
2546 * This flag is there to keep us in sync.
2547 * Next time this process stops it should
2548 * really be entering a system call.
2549 */
2550 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002552 /*
2553 * One example is a breakpoint inherited from
2554 * parent through fork ().
2555 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002556 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2557 droptcb(tcp);
2558 cleanup();
2559 return -1;
2560 }
2561 }
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002562/* Add more OSes after you verified it works for them. */
Denys Vlasenkof535b542009-01-13 18:30:55 +00002563/* PTRACE_SETOPTIONS may be an enum, not a #define.
2564 * But sometimes we can test for it by checking PT_SETOPTIONS.
2565 */
2566#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
Denys Vlasenko0861ecb2009-01-02 16:55:24 +00002567# ifndef PTRACE_O_TRACESYSGOOD
2568# define PTRACE_O_TRACESYSGOOD 0x00000001
2569# endif
2570# ifndef PTRACE_O_TRACEEXEC
2571# define PTRACE_O_TRACEEXEC 0x00000010
2572# endif
2573# ifndef PTRACE_EVENT_EXEC
2574# define PTRACE_EVENT_EXEC 4
2575# endif
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002576 /*
2577 * Ask kernel to set signo to SIGTRAP | 0x80
2578 * on ptrace-generated SIGTRAPs, and mark
2579 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
2580 */
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002581 if (!ptrace_opts_set) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002582 char *p;
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002583 ptrace_opts_set = 1;
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002584
2585 /* RHEL 2.6.18 definitely has crippling bugs */
2586 /* Vanilla and Fedora 2.6.29 seems to work */
2587 p = utsname_buf.release;
2588 if (strtoul(p, &p, 10) < 2 || *p != '.')
2589 goto tracing;
2590 if (strtoul(++p, &p, 10) < 6 || *p != '.')
2591 goto tracing;
2592 if (strtoul(++p, &p, 10) < 29)
2593 goto tracing;
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002594 /*
2595 * NB: even if this "succeeds", we can
2596 * revert back to SIGTRAP if we later see
2597 * that it didnt really work.
2598 * Old kernels are known to lie here.
2599 */
2600 if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
2601 (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
2602 ptrace_stop_sig = SIGTRAP | 0x80;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002603 }
2604#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605 goto tracing;
2606 }
2607
Denys Vlasenkof535b542009-01-13 18:30:55 +00002608#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002609 if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002610 /*
2611 * We told ptrace to report SIGTRAP | 0x80 on this process
2612 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
2613 * kill(pid, SIGTRAP), trap insn, etc;
2614 * but be paranoid about it.
2615 */
2616 if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
Denys Vlasenko1d5b1132009-01-17 01:06:18 +00002617 /* It's post-exec ptrace stop. Ignore it,
2618 * we will get syscall exit ptrace stop later.
2619 */
2620#ifdef TCB_WAITEXECVE
2621 tcp->flags &= ~TCB_WAITEXECVE;
2622#endif
2623 goto tracing;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002624 } else {
2625 /* Take a better look... */
2626 siginfo_t si;
Denys Vlasenko1d5b1132009-01-17 01:06:18 +00002627 si.si_signo = 0;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002628 ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
2629 /*
2630 * Check some fields to make sure we see
2631 * real SIGTRAP.
2632 * Otherwise interpret it as ptrace stop.
2633 * Real SIGTRAPs (int3 insn on x86, kill() etc)
2634 * have these values:
2635 * int3: kill -TRAP $pid:
2636 * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
2637 * si_errno:0 si_errno:(?)
2638 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
2639 * si_pid:0 si_pid:(>0?)
2640 * si_band:0 si_band:(?)
2641 * Ptrace stops have garbage there instead.
2642 */
2643 if (si.si_signo != SIGTRAP
2644 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
2645 ) {
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002646 fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
2647 ptrace_stop_sig = SIGTRAP;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002648 }
2649 }
2650 }
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002651#endif
2652
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002653 if (WSTOPSIG(status) != ptrace_stop_sig) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002654 /* This isn't a ptrace stop. */
2655
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002656 if (WSTOPSIG(status) == SIGSTOP &&
2657 (tcp->flags & TCB_SIGTRAPPED)) {
2658 /*
2659 * Trapped attempt to block SIGTRAP
2660 * Hope we are back in control now.
2661 */
2662 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002663 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002664 cleanup();
2665 return -1;
2666 }
2667 continue;
2668 }
2669 if (!cflag
2670 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002671 unsigned long addr = 0;
2672 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002673#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002674# define PSR_RI 41
2675 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002676 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002677
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002678 upeek(tcp, PT_CR_IPSR, &psr);
2679 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002680
2681 pc += (psr >> PSR_RI) & 0x3;
2682 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2683 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002684#elif defined PTRACE_GETSIGINFO
2685 if (WSTOPSIG(status) == SIGSEGV ||
2686 WSTOPSIG(status) == SIGBUS) {
2687 siginfo_t si;
2688 if (ptrace(PTRACE_GETSIGINFO, pid,
2689 0, &si) == 0)
2690 addr = (unsigned long)
2691 si.si_addr;
2692 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002693#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002695 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002696 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002697 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002698 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002699 }
Roland McGrath05690952004-10-20 01:00:27 +00002700 if (((tcp->flags & TCB_ATTACHED) ||
2701 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002702 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002703#ifdef TCB_GROUP_EXITING
2704 handle_group_exit(tcp, WSTOPSIG(status));
2705#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002706 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002707#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002708 continue;
2709 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002710 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002711 cleanup();
2712 return -1;
2713 }
2714 tcp->flags &= ~TCB_SUSPENDED;
2715 continue;
2716 }
Roland McGrath02203312007-06-11 22:06:31 +00002717 /* we handled the STATUS, we are permitted to interrupt now. */
2718 if (interrupted)
2719 return 0;
Denys Vlasenko4dedd562009-02-24 15:17:53 +00002720 if (trace_syscall(tcp) < 0) {
2721 /* trace_syscall printed incompletely decoded syscall,
2722 * add error indicator.
2723 * NB: modulo bugs, errno must be nonzero, do not add
2724 * "if (err != 0)", this will hide bugs.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002725 */
Denys Vlasenko4dedd562009-02-24 15:17:53 +00002726 int err = tcp->ptrace_errno;
2727 tcp->ptrace_errno = 0;
2728 if (err == ESRCH)
2729 tprintf(" <unavailable>");
2730 else
2731 tprintf(" <ptrace error %d (%s)>", err, strerror(err));
2732 printtrailer();
2733 if (err == ESRCH)
2734 /* Want to get death report anyway. */
2735 goto tracing;
2736 /* Strange error, we dare not continue. */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002737 if (tcp->flags & TCB_ATTACHED) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002738 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002739 } else {
Denys Vlasenko4dedd562009-02-24 15:17:53 +00002740 ptrace(PTRACE_KILL, tcp->pid, (char *) 1, SIGTERM);
2741 /* [why SIGTERM? why not also kill(SIGKILL)?] */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002742 droptcb(tcp);
2743 }
2744 continue;
2745 }
2746 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002747#ifdef TCB_GROUP_EXITING
2748 if (tcp->flags & TCB_GROUP_EXITING) {
2749 if (handle_group_exit(tcp, 0) < 0)
2750 return -1;
2751 continue;
2752 }
2753#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002754 if (tcp->flags & TCB_ATTACHED)
2755 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002756 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002757 cleanup();
2758 return -1;
2759 }
2760 continue;
2761 }
2762 if (tcp->flags & TCB_SUSPENDED) {
2763 if (!qflag)
2764 fprintf(stderr, "Process %u suspended\n", pid);
2765 continue;
2766 }
2767 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002768 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002769 cleanup();
2770 return -1;
2771 }
Denys Vlasenko215cc272009-01-09 17:22:56 +00002772 } /* for each tcp */
2773
2774 return 0;
2775}
2776
2777static int
2778trace()
2779{
2780 int rc;
2781 struct tcb *tcbs;
2782
2783 while (nprocs != 0) {
Denys Vlasenko215cc272009-01-09 17:22:56 +00002784 /* The loop of "wait for one tracee, serve it, repeat"
2785 * may leave some tracees never served.
2786 * Kernel provides no guarantees of fairness when you have
2787 * many waitable tasks.
2788 * Try strace -f with test/many_looping_threads.c example.
2789 * To fix it, we collect *all* waitable tasks, then handle
2790 * them all, then repeat.
2791 */
2792 tcbs = collect_stopped_tcbs();
2793 if (!tcbs)
2794 break;
2795 rc = handle_stopped_tcbs(tcbs);
2796 if (rc)
2797 return rc;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002798 }
2799 return 0;
2800}
2801
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002802#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002803
2804static int curcol;
2805
2806#ifdef __STDC__
2807#include <stdarg.h>
2808#define VA_START(a, b) va_start(a, b)
2809#else
2810#include <varargs.h>
2811#define VA_START(a, b) va_start(a)
2812#endif
2813
2814void
2815#ifdef __STDC__
2816tprintf(const char *fmt, ...)
2817#else
2818tprintf(fmt, va_alist)
2819char *fmt;
2820va_dcl
2821#endif
2822{
2823 va_list args;
2824
2825 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002826 if (outf) {
2827 int n = vfprintf(outf, fmt, args);
2828 if (n < 0 && outf != stderr)
2829 perror(outfname == NULL
2830 ? "<writing to pipe>" : outfname);
2831 else
2832 curcol += n;
2833 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002834 va_end(args);
2835 return;
2836}
2837
2838void
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002839printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002840{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002841 if (tcp_last) {
Denys Vlasenko4dedd562009-02-24 15:17:53 +00002842 int err = tcp_last->ptrace_errno;
2843 if (err) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002844 tcp_last->ptrace_errno = 0;
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002845 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko4dedd562009-02-24 15:17:53 +00002846 if (err == ESRCH)
2847 tprintf(" <unavailable ...>\n");
2848 else
2849 tprintf(" <ptrace error %d (%s) ...>\n", err, strerror(err));
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002850 tcp_last->flags |= TCB_REPRINT;
2851 } else {
Denys Vlasenko4dedd562009-02-24 15:17:53 +00002852 /* Not sure this branch can ever be reached.
2853 * Oh well. Using subtly different format
2854 * (without "?" after "=") to make it
2855 * noticeable (grep for '= <' in straces).
2856 */
2857 if (err == ESRCH)
2858 tprintf("= <unavailable>\n");
2859 else
2860 tprintf("= <ptrace error %d (%s)>\n", err, strerror(err));
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002861 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002862 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002863 tprintf(" <unfinished ...>\n");
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002864 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002865 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002866 }
2867 curcol = 0;
2868 if ((followfork == 1 || pflag_seen > 1) && outfname)
2869 tprintf("%-5d ", tcp->pid);
2870 else if (nprocs > 1 && !outfname)
2871 tprintf("[pid %5u] ", tcp->pid);
2872 if (tflag) {
2873 char str[sizeof("HH:MM:SS")];
2874 struct timeval tv, dtv;
2875 static struct timeval otv;
2876
2877 gettimeofday(&tv, NULL);
2878 if (rflag) {
2879 if (otv.tv_sec == 0)
2880 otv = tv;
2881 tv_sub(&dtv, &tv, &otv);
2882 tprintf("%6ld.%06ld ",
2883 (long) dtv.tv_sec, (long) dtv.tv_usec);
2884 otv = tv;
2885 }
2886 else if (tflag > 2) {
2887 tprintf("%ld.%06ld ",
2888 (long) tv.tv_sec, (long) tv.tv_usec);
2889 }
2890 else {
2891 time_t local = tv.tv_sec;
2892 strftime(str, sizeof(str), "%T", localtime(&local));
2893 if (tflag > 1)
2894 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2895 else
2896 tprintf("%s ", str);
2897 }
2898 }
2899 if (iflag)
2900 printcall(tcp);
2901}
2902
2903void
2904tabto(col)
2905int col;
2906{
2907 if (curcol < col)
2908 tprintf("%*s", col - curcol, "");
2909}
2910
2911void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002912printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002913{
2914 tprintf("\n");
2915 tcp_last = NULL;
2916}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002917
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002918#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002919
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002920int
2921mp_ioctl(int fd, int cmd, void *arg, int size)
2922{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002923 struct iovec iov[2];
2924 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002925
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002926 iov[0].iov_base = &cmd;
2927 iov[0].iov_len = sizeof cmd;
2928 if (arg) {
2929 ++n;
2930 iov[1].iov_base = arg;
2931 iov[1].iov_len = size;
2932 }
Roland McGrath553a6092002-12-16 20:40:39 +00002933
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002934 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002935}
2936
2937#endif