blob: 9bda5537c7a1c46955136d752d1fa601dcac2194 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <signal.h>
37#include <errno.h>
38#include <sys/param.h>
39#include <fcntl.h>
40#include <sys/resource.h>
41#include <sys/wait.h>
42#include <sys/stat.h>
43#include <pwd.h>
44#include <grp.h>
45#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000046#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# include <asm/unistd.h>
51# if defined __NR_tgkill
52# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53# elif defined __NR_tkill
54# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55# else
56 /* kill() may choose arbitrarily the target task of the process group
57 while we later wait on a that specific TID. PID process waits become
58 TID task specific waits for a process under ptrace(2). */
59# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60# define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61# endif
62#endif
63
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000064#if defined(IA64) && defined(LINUX)
65# include <asm/ptrace_offsets.h>
66#endif
67
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000068#ifdef USE_PROCFS
69#include <poll.h>
70#endif
71
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000072#ifdef SVR4
73#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000074#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000075#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000076#include <sys/uio.h>
77#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000079#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000080extern char **environ;
81
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082
Roland McGrath41c48222008-07-18 00:25:10 +000083int debug = 0, followfork = 0;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000084int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
85static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086
Michal Ludvig17f8fb32002-11-06 13:17:21 +000087/* Sometimes we want to print only succeeding syscalls. */
88int not_failing_only = 0;
89
Dmitry V. Levina6809652008-11-10 17:14:58 +000090static int exit_code = 0;
91static int strace_child = 0;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000092static int ptrace_stop_sig = SIGTRAP;
93static bool ptrace_opts_set;
Dmitry V. Levina6809652008-11-10 17:14:58 +000094
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000095static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096uid_t run_uid;
97gid_t run_gid;
98
99int acolumn = DEFAULT_ACOLUMN;
100int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000101static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +0000103struct tcb **tcbtab;
104unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
Roland McGrath0a463882007-07-05 18:43:16 +0000107static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108static int trace P((void));
109static void cleanup P((void));
110static void interrupt P((int sig));
111static sigset_t empty_set, blocked_set;
112
113#ifdef HAVE_SIG_ATOMIC_T
114static volatile sig_atomic_t interrupted;
115#else /* !HAVE_SIG_ATOMIC_T */
116#ifdef __STDC__
117static volatile int interrupted;
118#else /* !__STDC__ */
119static int interrupted;
120#endif /* !__STDC__ */
121#endif /* !HAVE_SIG_ATOMIC_T */
122
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000123#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124
125static struct tcb *pfd2tcb P((int pfd));
126static void reaper P((int sig));
127static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000128static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129
130#ifndef HAVE_POLLABLE_PROCFS
131
132static void proc_poll_open P((void));
133static void proc_poller P((int pfd));
134
135struct proc_pollfd {
136 int fd;
137 int revents;
138 int pid;
139};
140
141static int poller_pid;
142static int proc_poll_pipe[2] = { -1, -1 };
143
144#endif /* !HAVE_POLLABLE_PROCFS */
145
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000146#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000147#define POLLWANT POLLWRNORM
148#else
149#define POLLWANT POLLPRI
150#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000151#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152
153static void
154usage(ofp, exitval)
155FILE *ofp;
156int exitval;
157{
158 fprintf(ofp, "\
159usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000160 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
161 [command [arg ...]]\n\
162 or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
163 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164-c -- count time, calls, and errors for each syscall and report summary\n\
165-f -- follow forks, -ff -- with output into separate files\n\
166-F -- attempt to follow vforks, -h -- print help message\n\
167-i -- print instruction pointer at time of syscall\n\
168-q -- suppress messages about attaching, detaching, etc.\n\
169-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
170-T -- print time spent in each syscall, -V -- print version\n\
171-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
172-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
173-a column -- alignment COLUMN for printing syscall results (default %d)\n\
174-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
175 options: trace, abbrev, verbose, raw, signal, read, or write\n\
176-o file -- send trace output to FILE instead of stderr\n\
177-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
178-p pid -- trace process with process id PID, may be repeated\n\
179-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
180-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
181-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000182-E var=val -- put var=val in the environment for command\n\
183-E var -- remove var from the environment for command\n\
184" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000185-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000186 */
187, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188 exit(exitval);
189}
190
191#ifdef SVR4
192#ifdef MIPS
193void
194foobar()
195{
196}
197#endif /* MIPS */
198#endif /* SVR4 */
199
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000200static int
201set_cloexec_flag(int fd)
202{
203 int flags, newflags;
204
205 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
206 {
207 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
208 progname, strerror(errno));
209 return -1;
210 }
211
212 newflags = flags | FD_CLOEXEC;
213 if (flags == newflags)
214 return 0;
215
216 if (fcntl(fd, F_SETFD, newflags) < 0)
217 {
218 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
219 progname, strerror(errno));
220 return -1;
221 }
222
223 return 0;
224}
225
226/*
227 * When strace is setuid executable, we have to swap uids
228 * before and after filesystem and process management operations.
229 */
230static void
231swap_uid(void)
232{
233#ifndef SVR4
234 int euid = geteuid(), uid = getuid();
235
236 if (euid != uid && setreuid(euid, uid) < 0)
237 {
238 fprintf(stderr, "%s: setreuid: %s\n",
239 progname, strerror(errno));
240 exit(1);
241 }
242#endif
243}
244
Roland McGrath4bfa6262007-07-05 20:03:16 +0000245#if _LFS64_LARGEFILE
246# define fopen_for_output fopen64
247#else
248# define fopen_for_output fopen
249#endif
250
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000251static FILE *
252strace_fopen(const char *path, const char *mode)
253{
254 FILE *fp;
255
256 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000257 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000258 fprintf(stderr, "%s: can't fopen '%s': %s\n",
259 progname, path, strerror(errno));
260 swap_uid();
261 if (fp && set_cloexec_flag(fileno(fp)) < 0)
262 {
263 fclose(fp);
264 fp = NULL;
265 }
266 return fp;
267}
268
269static int popen_pid = -1;
270
271#ifndef _PATH_BSHELL
272# define _PATH_BSHELL "/bin/sh"
273#endif
274
275/*
276 * We cannot use standard popen(3) here because we have to distinguish
277 * popen child process from other processes we trace, and standard popen(3)
278 * does not export its child's pid.
279 */
280static FILE *
281strace_popen(const char *command)
282{
283 int fds[2];
284
285 swap_uid();
286 if (pipe(fds) < 0)
287 {
288 fprintf(stderr, "%s: pipe: %s\n",
289 progname, strerror(errno));
290 swap_uid();
291 return NULL;
292 }
293
294 if (set_cloexec_flag(fds[1]) < 0)
295 {
296 close(fds[0]);
297 close(fds[1]);
298 swap_uid();
299 return NULL;
300 }
301
302 if ((popen_pid = fork()) == -1)
303 {
304 fprintf(stderr, "%s: fork: %s\n",
305 progname, strerror(errno));
306 close(fds[0]);
307 close(fds[1]);
308 swap_uid();
309 return NULL;
310 }
311
312 if (popen_pid)
313 {
314 /* parent */
315 close(fds[0]);
316 swap_uid();
317 return fdopen(fds[1], "w");
318 } else
319 {
320 /* child */
321 close(fds[1]);
322 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
323 {
324 fprintf(stderr, "%s: dup2: %s\n",
325 progname, strerror(errno));
326 _exit(1);
327 }
328 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
329 fprintf(stderr, "%s: execl: %s: %s\n",
330 progname, _PATH_BSHELL, strerror(errno));
331 _exit(1);
332 }
333}
334
335static int
336newoutf(struct tcb *tcp)
337{
338 if (outfname && followfork > 1) {
339 char name[MAXPATHLEN];
340 FILE *fp;
341
342 sprintf(name, "%s.%u", outfname, tcp->pid);
343 if ((fp = strace_fopen(name, "w")) == NULL)
344 return -1;
345 tcp->outf = fp;
346 }
347 return 0;
348}
349
Roland McGrath02203312007-06-11 22:06:31 +0000350static void
351startup_attach(void)
352{
353 int tcbi;
354 struct tcb *tcp;
355
356 /*
357 * Block user interruptions as we would leave the traced
358 * process stopped (process state T) if we would terminate in
359 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
360 * We rely on cleanup () from this point on.
361 */
362 if (interactive)
363 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
364
365 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
366 tcp = tcbtab[tcbi];
367 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
368 continue;
369#ifdef LINUX
370 if (tcp->flags & TCB_CLONE_THREAD)
371 continue;
372#endif
373 /* Reinitialize the output since it may have changed. */
374 tcp->outf = outf;
375 if (newoutf(tcp) < 0)
376 exit(1);
377
378#ifdef USE_PROCFS
379 if (proc_open(tcp, 1) < 0) {
380 fprintf(stderr, "trouble opening proc file\n");
381 droptcb(tcp);
382 continue;
383 }
384#else /* !USE_PROCFS */
385# ifdef LINUX
386 if (followfork) {
387 char procdir[MAXPATHLEN];
388 DIR *dir;
389
390 sprintf(procdir, "/proc/%d/task", tcp->pid);
391 dir = opendir(procdir);
392 if (dir != NULL) {
393 unsigned int ntid = 0, nerr = 0;
394 struct dirent *de;
395 int tid;
396 while ((de = readdir(dir)) != NULL) {
397 if (de->d_fileno == 0 ||
398 de->d_name[0] == '.')
399 continue;
400 tid = atoi(de->d_name);
401 if (tid <= 0)
402 continue;
403 ++ntid;
404 if (ptrace(PTRACE_ATTACH, tid,
405 (char *) 1, 0) < 0)
406 ++nerr;
407 else if (tid != tcbtab[tcbi]->pid) {
408 if (nprocs == tcbtabsize &&
409 expand_tcbtab())
410 tcp = NULL;
411 else
412 tcp = alloctcb(tid);
413 if (tcp == NULL)
414 exit(1);
415 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
416 tcbtab[tcbi]->nchildren++;
417 tcbtab[tcbi]->nclone_threads++;
418 tcbtab[tcbi]->nclone_detached++;
419 tcp->parent = tcbtab[tcbi];
420 }
421 if (interactive) {
422 sigprocmask(SIG_SETMASK, &empty_set, NULL);
423 if (interrupted)
424 return;
425 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
426 }
427 }
428 closedir(dir);
429 if (nerr == ntid) {
430 perror("attach: ptrace(PTRACE_ATTACH, ...)");
431 droptcb(tcp);
432 continue;
433 }
434 if (!qflag) {
435 ntid -= nerr;
436 if (ntid > 1)
437 fprintf(stderr, "\
438Process %u attached with %u threads - interrupt to quit\n",
439 tcp->pid, ntid);
440 else
441 fprintf(stderr, "\
442Process %u attached - interrupt to quit\n",
443 tcp->pid);
444 }
445 continue;
446 }
447 }
448# endif
449 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
450 perror("attach: ptrace(PTRACE_ATTACH, ...)");
451 droptcb(tcp);
452 continue;
453 }
454 /* INTERRUPTED is going to be checked at the top of TRACE. */
455#endif /* !USE_PROCFS */
456 if (!qflag)
457 fprintf(stderr,
458 "Process %u attached - interrupt to quit\n",
459 tcp->pid);
460 }
461
462 if (interactive)
463 sigprocmask(SIG_SETMASK, &empty_set, NULL);
464}
465
466static void
467startup_child (char **argv)
468{
469 struct stat statbuf;
470 const char *filename;
471 char pathname[MAXPATHLEN];
472 int pid = 0;
473 struct tcb *tcp;
474
475 filename = argv[0];
476 if (strchr(filename, '/')) {
477 if (strlen(filename) > sizeof pathname - 1) {
478 errno = ENAMETOOLONG;
479 perror("strace: exec");
480 exit(1);
481 }
482 strcpy(pathname, filename);
483 }
484#ifdef USE_DEBUGGING_EXEC
485 /*
486 * Debuggers customarily check the current directory
487 * first regardless of the path but doing that gives
488 * security geeks a panic attack.
489 */
490 else if (stat(filename, &statbuf) == 0)
491 strcpy(pathname, filename);
492#endif /* USE_DEBUGGING_EXEC */
493 else {
494 char *path;
495 int m, n, len;
496
497 for (path = getenv("PATH"); path && *path; path += m) {
498 if (strchr(path, ':')) {
499 n = strchr(path, ':') - path;
500 m = n + 1;
501 }
502 else
503 m = n = strlen(path);
504 if (n == 0) {
505 if (!getcwd(pathname, MAXPATHLEN))
506 continue;
507 len = strlen(pathname);
508 }
509 else if (n > sizeof pathname - 1)
510 continue;
511 else {
512 strncpy(pathname, path, n);
513 len = n;
514 }
515 if (len && pathname[len - 1] != '/')
516 pathname[len++] = '/';
517 strcpy(pathname + len, filename);
518 if (stat(pathname, &statbuf) == 0 &&
519 /* Accept only regular files
520 with some execute bits set.
521 XXX not perfect, might still fail */
522 S_ISREG(statbuf.st_mode) &&
523 (statbuf.st_mode & 0111))
524 break;
525 }
526 }
527 if (stat(pathname, &statbuf) < 0) {
528 fprintf(stderr, "%s: %s: command not found\n",
529 progname, filename);
530 exit(1);
531 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000532 strace_child = pid = fork();
533 switch (pid) {
Roland McGrath02203312007-06-11 22:06:31 +0000534 case -1:
535 perror("strace: fork");
536 cleanup();
537 exit(1);
538 break;
539 case 0: {
540#ifdef USE_PROCFS
541 if (outf != stderr) close (fileno (outf));
542#ifdef MIPS
543 /* Kludge for SGI, see proc_open for details. */
544 sa.sa_handler = foobar;
545 sa.sa_flags = 0;
546 sigemptyset(&sa.sa_mask);
547 sigaction(SIGINT, &sa, NULL);
548#endif /* MIPS */
549#ifndef FREEBSD
550 pause();
551#else /* FREEBSD */
552 kill(getpid(), SIGSTOP); /* stop HERE */
553#endif /* FREEBSD */
554#else /* !USE_PROCFS */
555 if (outf!=stderr)
556 close(fileno (outf));
557
558 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
559 perror("strace: ptrace(PTRACE_TRACEME, ...)");
560 exit(1);
561 }
562 if (debug)
563 kill(getpid(), SIGSTOP);
564
565 if (username != NULL || geteuid() == 0) {
566 uid_t run_euid = run_uid;
567 gid_t run_egid = run_gid;
568
569 if (statbuf.st_mode & S_ISUID)
570 run_euid = statbuf.st_uid;
571 if (statbuf.st_mode & S_ISGID)
572 run_egid = statbuf.st_gid;
573
574 /*
575 * It is important to set groups before we
576 * lose privileges on setuid.
577 */
578 if (username != NULL) {
579 if (initgroups(username, run_gid) < 0) {
580 perror("initgroups");
581 exit(1);
582 }
583 if (setregid(run_gid, run_egid) < 0) {
584 perror("setregid");
585 exit(1);
586 }
587 if (setreuid(run_uid, run_euid) < 0) {
588 perror("setreuid");
589 exit(1);
590 }
591 }
592 }
593 else
594 setreuid(run_uid, run_uid);
595
596 /*
597 * Induce an immediate stop so that the parent
598 * will resume us with PTRACE_SYSCALL and display
599 * this execve call normally.
600 */
601 kill(getpid(), SIGSTOP);
602#endif /* !USE_PROCFS */
603
604 execv(pathname, argv);
605 perror("strace: exec");
606 _exit(1);
607 break;
608 }
609 default:
610 if ((tcp = alloctcb(pid)) == NULL) {
611 cleanup();
612 exit(1);
613 }
614#ifdef USE_PROCFS
615 if (proc_open(tcp, 0) < 0) {
616 fprintf(stderr, "trouble opening proc file\n");
617 cleanup();
618 exit(1);
619 }
620#endif /* USE_PROCFS */
621 break;
622 }
623}
624
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000625int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000626main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627{
628 extern int optind;
629 extern char *optarg;
630 struct tcb *tcp;
631 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000632 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000633 struct sigaction sa;
634
635 static char buf[BUFSIZ];
636
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000637 progname = argv[0] ? argv[0] : "strace";
638
Roland McGrathee9d4352002-12-18 04:16:10 +0000639 /* Allocate the initial tcbtab. */
640 tcbtabsize = argc; /* Surely enough for all -p args. */
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000641 if ((tcbtab = calloc (tcbtabsize, sizeof tcbtab[0])) == NULL) {
642 fprintf(stderr, "%s: out of memory\n", progname);
643 exit(1);
644 }
645 if ((tcbtab[0] = calloc (tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
646 fprintf(stderr, "%s: out of memory\n", progname);
647 exit(1);
648 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000649 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
650 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
651
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652 outf = stderr;
653 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000654 set_sortby(DEFAULT_SORTBY);
655 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000656 qualify("trace=all");
657 qualify("abbrev=all");
658 qualify("verbose=all");
659 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000660 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000661 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000662 switch (c) {
663 case 'c':
664 cflag++;
665 dtime++;
666 break;
667 case 'd':
668 debug++;
669 break;
Roland McGrath41c48222008-07-18 00:25:10 +0000670 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000671 optF = 1;
672 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000673 case 'f':
674 followfork++;
675 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676 case 'h':
677 usage(stdout, 0);
678 break;
679 case 'i':
680 iflag++;
681 break;
682 case 'q':
683 qflag++;
684 break;
685 case 'r':
686 rflag++;
687 tflag++;
688 break;
689 case 't':
690 tflag++;
691 break;
692 case 'T':
693 dtime++;
694 break;
695 case 'x':
696 xflag++;
697 break;
698 case 'v':
699 qualify("abbrev=none");
700 break;
701 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000702 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000703 exit(0);
704 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000705 case 'z':
706 not_failing_only = 1;
707 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000708 case 'a':
709 acolumn = atoi(optarg);
710 break;
711 case 'e':
712 qualify(optarg);
713 break;
714 case 'o':
715 outfname = strdup(optarg);
716 break;
717 case 'O':
718 set_overhead(atoi(optarg));
719 break;
720 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000721 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 fprintf(stderr, "%s: Invalid process id: %s\n",
723 progname, optarg);
724 break;
725 }
726 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000727 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000728 break;
729 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000730 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000731 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732 progname);
733 exit(1);
734 }
735 tcp->flags |= TCB_ATTACHED;
736 pflag_seen++;
737 break;
738 case 's':
739 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000740 if (max_strlen < 0) {
741 fprintf(stderr,
742 "%s: invalid -s argument: %s\n",
743 progname, optarg);
744 exit(1);
745 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000746 break;
747 case 'S':
748 set_sortby(optarg);
749 break;
750 case 'u':
751 username = strdup(optarg);
752 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000753 case 'E':
754 if (putenv(optarg) < 0) {
755 fprintf(stderr, "%s: out of memory\n",
756 progname);
757 exit(1);
758 }
759 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 default:
761 usage(stderr, 1);
762 break;
763 }
764 }
765
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000766 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000767 usage(stderr, 1);
768
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000769 if (!followfork)
770 followfork = optF;
771
Roland McGrathcb9def62006-04-25 07:48:03 +0000772 if (followfork > 1 && cflag) {
773 fprintf(stderr,
774 "%s: -c and -ff are mutually exclusive options\n",
775 progname);
776 exit(1);
777 }
778
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779 /* See if they want to run as another user. */
780 if (username != NULL) {
781 struct passwd *pent;
782
783 if (getuid() != 0 || geteuid() != 0) {
784 fprintf(stderr,
785 "%s: you must be root to use the -u option\n",
786 progname);
787 exit(1);
788 }
789 if ((pent = getpwnam(username)) == NULL) {
790 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000791 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 exit(1);
793 }
794 run_uid = pent->pw_uid;
795 run_gid = pent->pw_gid;
796 }
797 else {
798 run_uid = getuid();
799 run_gid = getgid();
800 }
801
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802 /* Check if they want to redirect the output. */
803 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000804 /* See if they want to pipe the output. */
805 if (outfname[0] == '|' || outfname[0] == '!') {
806 /*
807 * We can't do the <outfname>.PID funny business
808 * when using popen, so prohibit it.
809 */
810 if (followfork > 1) {
811 fprintf(stderr, "\
812%s: piping the output and -ff are mutually exclusive options\n",
813 progname);
814 exit(1);
815 }
816
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000817 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000818 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000819 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000820 else if (followfork <= 1 &&
821 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000822 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000823 }
824
Roland McGrath37b9a662003-11-07 02:26:54 +0000825 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000827 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000828 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000829 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000830 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000831 /* Valid states here:
832 optind < argc pflag_seen outfname interactive
833 1 0 0 1
834 0 1 0 1
835 1 0 1 0
836 0 1 1 1
837 */
838
839 /* STARTUP_CHILD must be called before the signal handlers get
840 installed below as they are inherited into the spawned process.
841 Also we do not need to be protected by them as during interruption
842 in the STARTUP_CHILD mode we kill the spawned process anyway. */
843 if (!pflag_seen)
844 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000846 sigemptyset(&empty_set);
847 sigemptyset(&blocked_set);
848 sa.sa_handler = SIG_IGN;
849 sigemptyset(&sa.sa_mask);
850 sa.sa_flags = 0;
851 sigaction(SIGTTOU, &sa, NULL);
852 sigaction(SIGTTIN, &sa, NULL);
853 if (interactive) {
854 sigaddset(&blocked_set, SIGHUP);
855 sigaddset(&blocked_set, SIGINT);
856 sigaddset(&blocked_set, SIGQUIT);
857 sigaddset(&blocked_set, SIGPIPE);
858 sigaddset(&blocked_set, SIGTERM);
859 sa.sa_handler = interrupt;
860#ifdef SUNOS4
861 /* POSIX signals on sunos4.1 are a little broken. */
862 sa.sa_flags = SA_INTERRUPT;
863#endif /* SUNOS4 */
864 }
865 sigaction(SIGHUP, &sa, NULL);
866 sigaction(SIGINT, &sa, NULL);
867 sigaction(SIGQUIT, &sa, NULL);
868 sigaction(SIGPIPE, &sa, NULL);
869 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000870#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871 sa.sa_handler = reaper;
872 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000873#else
874 /* Make sure SIGCHLD has the default action so that waitpid
875 definitely works without losing track of children. The user
876 should not have given us a bogus state to inherit, but he might
877 have. Arguably we should detect SIG_IGN here and pass it on
878 to children, but probably noone really needs that. */
879 sa.sa_handler = SIG_DFL;
880 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000881#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882
Roland McGrath02203312007-06-11 22:06:31 +0000883 if (pflag_seen)
884 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000885
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886 if (trace() < 0)
887 exit(1);
888 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000889 fflush(NULL);
890 if (exit_code > 0xff) {
891 /* Child was killed by a signal, mimic that. */
892 exit_code &= 0xff;
893 signal(exit_code, SIG_DFL);
894 raise(exit_code);
895 /* Paranoia - what if this signal is not fatal?
896 Exit with 128 + signo then. */
897 exit_code += 128;
898 }
899 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900}
901
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000902int
903expand_tcbtab()
904{
905 /* Allocate some more TCBs and expand the table.
906 We don't want to relocate the TCBs because our
907 callers have pointers and it would be a pain.
908 So tcbtab is a table of pointers. Since we never
909 free the TCBs, we allocate a single chunk of many. */
910 struct tcb **newtab = (struct tcb **)
911 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
912 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
913 sizeof *newtcbs);
914 int i;
915 if (newtab == NULL || newtcbs == NULL) {
916 if (newtab != NULL)
917 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000918 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
919 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000920 return 1;
921 }
922 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
923 newtab[i] = &newtcbs[i - tcbtabsize];
924 tcbtabsize *= 2;
925 tcbtab = newtab;
926
927 return 0;
928}
929
930
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000932alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933{
934 int i;
935 struct tcb *tcp;
936
Roland McGrathee9d4352002-12-18 04:16:10 +0000937 for (i = 0; i < tcbtabsize; i++) {
938 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939 if ((tcp->flags & TCB_INUSE) == 0) {
940 tcp->pid = pid;
941 tcp->parent = NULL;
942 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000943 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000944#ifdef TCB_CLONE_THREAD
945 tcp->nclone_threads = tcp->nclone_detached = 0;
946 tcp->nclone_waiting = 0;
947#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 tcp->flags = TCB_INUSE | TCB_STARTUP;
949 tcp->outf = outf; /* Initialise to current out file */
950 tcp->stime.tv_sec = 0;
951 tcp->stime.tv_usec = 0;
952 tcp->pfd = -1;
953 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000954 if (command_options_parsed)
955 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956 return tcp;
957 }
958 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000959 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000960 return NULL;
961}
962
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000963#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000964int
965proc_open(tcp, attaching)
966struct tcb *tcp;
967int attaching;
968{
969 char proc[32];
970 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000971#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000972 int i;
973 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974 sigset_t signals;
975 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000976#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977#ifndef HAVE_POLLABLE_PROCFS
978 static int last_pfd;
979#endif
980
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000981#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000982 /* Open the process pseudo-files in /proc. */
983 sprintf(proc, "/proc/%d/ctl", tcp->pid);
984 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985 perror("strace: open(\"/proc/...\", ...)");
986 return -1;
987 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000988 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989 return -1;
990 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000991 sprintf(proc, "/proc/%d/status", tcp->pid);
992 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
993 perror("strace: open(\"/proc/...\", ...)");
994 return -1;
995 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000996 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000997 return -1;
998 }
999 sprintf(proc, "/proc/%d/as", tcp->pid);
1000 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1001 perror("strace: open(\"/proc/...\", ...)");
1002 return -1;
1003 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001004 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001005 return -1;
1006 }
1007#else
1008 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001009#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001010 sprintf(proc, "/proc/%d", tcp->pid);
1011 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001012#else /* FREEBSD */
1013 sprintf(proc, "/proc/%d/mem", tcp->pid);
1014 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1015#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001016 perror("strace: open(\"/proc/...\", ...)");
1017 return -1;
1018 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001019 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001020 return -1;
1021 }
1022#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001023#ifdef FREEBSD
1024 sprintf(proc, "/proc/%d/regs", tcp->pid);
1025 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1026 perror("strace: open(\"/proc/.../regs\", ...)");
1027 return -1;
1028 }
1029 if (cflag) {
1030 sprintf(proc, "/proc/%d/status", tcp->pid);
1031 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1032 perror("strace: open(\"/proc/.../status\", ...)");
1033 return -1;
1034 }
1035 } else
1036 tcp->pfd_status = -1;
1037#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001038 rebuild_pollv();
1039 if (!attaching) {
1040 /*
1041 * Wait for the child to pause. Because of a race
1042 * condition we have to poll for the event.
1043 */
1044 for (;;) {
1045 if (IOCTL_STATUS (tcp) < 0) {
1046 perror("strace: PIOCSTATUS");
1047 return -1;
1048 }
1049 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001050 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001051 }
1052 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001053#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001054 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001055 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001056 perror("strace: PIOCSTOP");
1057 return -1;
1058 }
Roland McGrath553a6092002-12-16 20:40:39 +00001059#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060#ifdef PIOCSET
1061 /* Set Run-on-Last-Close. */
1062 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001063 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 perror("PIOCSET PR_RLC");
1065 return -1;
1066 }
1067 /* Set or Reset Inherit-on-Fork. */
1068 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001069 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 perror("PIOC{SET,RESET} PR_FORK");
1071 return -1;
1072 }
1073#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001074#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1076 perror("PIOCSRLC");
1077 return -1;
1078 }
1079 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1080 perror("PIOC{S,R}FORK");
1081 return -1;
1082 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001083#else /* FREEBSD */
1084 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1085 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1086 perror("PIOCGFL");
1087 return -1;
1088 }
1089 arg &= ~PF_LINGER;
1090 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1091 perror("PIOCSFL");
1092 return -1;
1093 }
1094#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001095#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001096#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001097 /* Enable all syscall entries we care about. */
1098 premptyset(&syscalls);
1099 for (i = 1; i < MAX_QUALS; ++i) {
1100 if (i > (sizeof syscalls) * CHAR_BIT) break;
1101 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1102 }
1103 praddset (&syscalls, SYS_execve);
1104 if (followfork) {
1105 praddset (&syscalls, SYS_fork);
1106#ifdef SYS_forkall
1107 praddset (&syscalls, SYS_forkall);
1108#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001109#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001110 praddset (&syscalls, SYS_fork1);
1111#endif
1112#ifdef SYS_rfork1
1113 praddset (&syscalls, SYS_rfork1);
1114#endif
1115#ifdef SYS_rforkall
1116 praddset (&syscalls, SYS_rforkall);
1117#endif
1118 }
1119 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 perror("PIOCSENTRY");
1121 return -1;
1122 }
John Hughes19e49982001-10-19 08:59:12 +00001123 /* Enable the syscall exits. */
1124 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125 perror("PIOSEXIT");
1126 return -1;
1127 }
John Hughes19e49982001-10-19 08:59:12 +00001128 /* Enable signals we care about. */
1129 premptyset(&signals);
1130 for (i = 1; i < MAX_QUALS; ++i) {
1131 if (i > (sizeof signals) * CHAR_BIT) break;
1132 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1133 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001134 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 perror("PIOCSTRACE");
1136 return -1;
1137 }
John Hughes19e49982001-10-19 08:59:12 +00001138 /* Enable faults we care about */
1139 premptyset(&faults);
1140 for (i = 1; i < MAX_QUALS; ++i) {
1141 if (i > (sizeof faults) * CHAR_BIT) break;
1142 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1143 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001144 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145 perror("PIOCSFAULT");
1146 return -1;
1147 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001148#else /* FREEBSD */
1149 /* set events flags. */
1150 arg = S_SIG | S_SCE | S_SCX ;
1151 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1152 perror("PIOCBIS");
1153 return -1;
1154 }
1155#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 if (!attaching) {
1157#ifdef MIPS
1158 /*
1159 * The SGI PRSABORT doesn't work for pause() so
1160 * we send it a caught signal to wake it up.
1161 */
1162 kill(tcp->pid, SIGINT);
1163#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001164#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001166 arg = PRSABORT;
1167 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 perror("PIOCRUN");
1169 return -1;
1170 }
Roland McGrath553a6092002-12-16 20:40:39 +00001171#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001172#endif /* !MIPS*/
1173#ifdef FREEBSD
1174 /* wake up the child if it received the SIGSTOP */
1175 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001176#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 for (;;) {
1178 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001179 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180 perror("PIOCWSTOP");
1181 return -1;
1182 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001183 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001184 tcp->flags &= ~TCB_INSYSCALL;
1185 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001186 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 break;
1188 }
1189 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001190#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001191 arg = 0;
1192 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001193#else /* FREEBSD */
1194 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001195#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001196 perror("PIOCRUN");
1197 return -1;
1198 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001199#ifdef FREEBSD
1200 /* handle the case where we "opened" the child before
1201 it did the kill -STOP */
1202 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1203 tcp->status.PR_WHAT == SIGSTOP)
1204 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001205#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001207#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001209#else /* FREEBSD */
1210 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001211 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001212 /* We are attaching to an already running process.
1213 * Try to figure out the state of the process in syscalls,
1214 * to handle the first event well.
1215 * This is done by having a look at the "wchan" property of the
1216 * process, which tells where it is stopped (if it is). */
1217 FILE * status;
1218 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001219
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001220 sprintf(proc, "/proc/%d/status", tcp->pid);
1221 status = fopen(proc, "r");
1222 if (status &&
1223 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1224 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1225 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1226 strcmp(wchan, "stopevent")) {
1227 /* The process is asleep in the middle of a syscall.
1228 Fake the syscall entry event */
1229 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1230 tcp->status.PR_WHY = PR_SYSENTRY;
1231 trace_syscall(tcp);
1232 }
1233 if (status)
1234 fclose(status);
1235 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001236 }
1237#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238#ifndef HAVE_POLLABLE_PROCFS
1239 if (proc_poll_pipe[0] != -1)
1240 proc_poller(tcp->pfd);
1241 else if (nprocs > 1) {
1242 proc_poll_open();
1243 proc_poller(last_pfd);
1244 proc_poller(tcp->pfd);
1245 }
1246 last_pfd = tcp->pfd;
1247#endif /* !HAVE_POLLABLE_PROCFS */
1248 return 0;
1249}
1250
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001251#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001253struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254pid2tcb(pid)
1255int pid;
1256{
1257 int i;
1258 struct tcb *tcp;
1259
Roland McGrathee9d4352002-12-18 04:16:10 +00001260 for (i = 0; i < tcbtabsize; i++) {
1261 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 if (pid && tcp->pid != pid)
1263 continue;
1264 if (tcp->flags & TCB_INUSE)
1265 return tcp;
1266 }
1267 return NULL;
1268}
1269
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001270#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271
1272static struct tcb *
1273pfd2tcb(pfd)
1274int pfd;
1275{
1276 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001277
Roland McGrathca16be82003-01-10 19:55:28 +00001278 for (i = 0; i < tcbtabsize; i++) {
1279 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280 if (tcp->pfd != pfd)
1281 continue;
1282 if (tcp->flags & TCB_INUSE)
1283 return tcp;
1284 }
1285 return NULL;
1286}
1287
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001288#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289
1290void
1291droptcb(tcp)
1292struct tcb *tcp;
1293{
1294 if (tcp->pid == 0)
1295 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001296#ifdef TCB_CLONE_THREAD
1297 if (tcp->nclone_threads > 0) {
1298 /* There are other threads left in this process, but this
1299 is the one whose PID represents the whole process.
1300 We need to keep this record around as a zombie until
1301 all the threads die. */
1302 tcp->flags |= TCB_EXITING;
1303 return;
1304 }
1305#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306 nprocs--;
1307 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001308
Roland McGrathe29341c2003-01-10 20:14:20 +00001309 if (tcp->parent != NULL) {
1310 tcp->parent->nchildren--;
1311#ifdef TCB_CLONE_THREAD
1312 if (tcp->flags & TCB_CLONE_DETACHED)
1313 tcp->parent->nclone_detached--;
1314 if (tcp->flags & TCB_CLONE_THREAD)
1315 tcp->parent->nclone_threads--;
1316#endif
Roland McGrath09623452003-05-23 02:27:13 +00001317#ifdef TCB_CLONE_DETACHED
1318 if (!(tcp->flags & TCB_CLONE_DETACHED))
1319#endif
1320 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001321#ifdef LINUX
1322 /* Update `tcp->parent->parent->nchildren' and the other fields
1323 like NCLONE_DETACHED, only for zombie group leader that has
1324 already reported and been short-circuited at the top of this
1325 function. The same condition as at the top of DETACH. */
1326 if ((tcp->flags & TCB_CLONE_THREAD) &&
1327 tcp->parent->nclone_threads == 0 &&
1328 (tcp->parent->flags & TCB_EXITING))
1329 droptcb(tcp->parent);
1330#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001331 tcp->parent = NULL;
1332 }
1333
1334 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335 if (tcp->pfd != -1) {
1336 close(tcp->pfd);
1337 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338#ifdef FREEBSD
1339 if (tcp->pfd_reg != -1) {
1340 close(tcp->pfd_reg);
1341 tcp->pfd_reg = -1;
1342 }
1343 if (tcp->pfd_status != -1) {
1344 close(tcp->pfd_status);
1345 tcp->pfd_status = -1;
1346 }
Roland McGrath553a6092002-12-16 20:40:39 +00001347#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001348#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001349 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350#endif
1351 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001352
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001353 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001355
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356 tcp->outf = 0;
1357}
1358
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001359#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360
1361static int
1362resume(tcp)
1363struct tcb *tcp;
1364{
1365 if (tcp == NULL)
1366 return -1;
1367
1368 if (!(tcp->flags & TCB_SUSPENDED)) {
1369 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1370 return -1;
1371 }
1372 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001373#ifdef TCB_CLONE_THREAD
1374 if (tcp->flags & TCB_CLONE_THREAD)
1375 tcp->parent->nclone_waiting--;
1376#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001378 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001379 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380
1381 if (!qflag)
1382 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1383 return 0;
1384}
1385
Roland McGrath1bfd3102007-08-03 10:02:00 +00001386static int
1387resume_from_tcp (struct tcb *tcp)
1388{
1389 int error = 0;
1390 int resumed = 0;
1391
1392 /* XXX This won't always be quite right (but it never was).
1393 A waiter with argument 0 or < -1 is waiting for any pid in
1394 a particular pgrp, which this child might or might not be
1395 in. The waiter will only wake up if it's argument is -1
1396 or if it's waiting for tcp->pid's pgrp. It makes a
1397 difference to wake up a waiter when there might be more
1398 traced children, because it could get a false ECHILD
1399 error. OTOH, if this was the last child in the pgrp, then
1400 it ought to wake up and get ECHILD. We would have to
1401 search the system for all pid's in the pgrp to be sure.
1402
1403 && (t->waitpid == -1 ||
1404 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1405 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1406 */
1407
1408 if (tcp->parent &&
1409 (tcp->parent->flags & TCB_SUSPENDED) &&
1410 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1411 error = resume(tcp->parent);
1412 ++resumed;
1413 }
1414#ifdef TCB_CLONE_THREAD
1415 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1416 /* Some other threads of our parent are waiting too. */
1417 unsigned int i;
1418
1419 /* Resume all the threads that were waiting for this PID. */
1420 for (i = 0; i < tcbtabsize; i++) {
1421 struct tcb *t = tcbtab[i];
1422 if (t->parent == tcp->parent && t != tcp
1423 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1424 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1425 && t->waitpid == tcp->pid) {
1426 error |= resume (t);
1427 ++resumed;
1428 }
1429 }
1430 if (resumed == 0)
1431 /* Noone was waiting for this PID in particular,
1432 so now we might need to resume some wildcarders. */
1433 for (i = 0; i < tcbtabsize; i++) {
1434 struct tcb *t = tcbtab[i];
1435 if (t->parent == tcp->parent && t != tcp
1436 && ((t->flags
1437 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1438 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1439 && t->waitpid <= 0
1440 ) {
1441 error |= resume (t);
1442 break;
1443 }
1444 }
1445 }
1446
1447 return error;
1448}
1449#endif
1450
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001451#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001452
Roland McGrath0a463882007-07-05 18:43:16 +00001453/* detach traced process; continue with sig
1454 Never call DETACH twice on the same process as both unattached and
1455 attached-unstopped processes give the same ESRCH. For unattached process we
1456 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457
1458static int
1459detach(tcp, sig)
1460struct tcb *tcp;
1461int sig;
1462{
1463 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001464#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001465 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001466 struct tcb *zombie = NULL;
1467
1468 /* If the group leader is lingering only because of this other
1469 thread now dying, then detach the leader as well. */
1470 if ((tcp->flags & TCB_CLONE_THREAD) &&
1471 tcp->parent->nclone_threads == 1 &&
1472 (tcp->parent->flags & TCB_EXITING))
1473 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001474#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475
1476 if (tcp->flags & TCB_BPTSET)
1477 sig = SIGKILL;
1478
1479#ifdef LINUX
1480 /*
1481 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001482 * before detaching. Arghh. We go through hoops
1483 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001484 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001485#if defined(SPARC)
1486#undef PTRACE_DETACH
1487#define PTRACE_DETACH PTRACE_SUNDETACH
1488#endif
Roland McGrath02203312007-06-11 22:06:31 +00001489 /*
1490 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1491 * expected SIGSTOP. We must catch exactly one as otherwise the
1492 * detached process would be left stopped (process state T).
1493 */
1494 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1496 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001497 }
1498 else if (errno != ESRCH) {
1499 /* Shouldn't happen. */
1500 perror("detach: ptrace(PTRACE_DETACH, ...)");
1501 }
Roland McGrath134813a2007-06-02 00:07:33 +00001502 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1503 : tcp->pid),
1504 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001505 if (errno != ESRCH)
1506 perror("detach: checking sanity");
1507 }
Roland McGrath02203312007-06-11 22:06:31 +00001508 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1509 ? tcp->parent->pid : tcp->pid),
1510 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001511 if (errno != ESRCH)
1512 perror("detach: stopping child");
1513 }
Roland McGrath02203312007-06-11 22:06:31 +00001514 else
1515 catch_sigstop = 1;
1516 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001518#ifdef __WALL
1519 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1520 if (errno == ECHILD) /* Already gone. */
1521 break;
1522 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001523 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001524 break;
1525 }
1526#endif /* __WALL */
1527 /* No __WALL here. */
1528 if (waitpid(tcp->pid, &status, 0) < 0) {
1529 if (errno != ECHILD) {
1530 perror("detach: waiting");
1531 break;
1532 }
1533#ifdef __WCLONE
1534 /* If no processes, try clones. */
1535 if (wait4(tcp->pid, &status, __WCLONE,
1536 NULL) < 0) {
1537 if (errno != ECHILD)
1538 perror("detach: waiting");
1539 break;
1540 }
1541#endif /* __WCLONE */
1542 }
1543#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001544 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001545#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546 if (!WIFSTOPPED(status)) {
1547 /* Au revoir, mon ami. */
1548 break;
1549 }
1550 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001551 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552 break;
1553 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001554 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko96d5a762008-12-29 19:13:27 +00001555 WSTOPSIG(status) == ptrace_stop_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001556 : WSTOPSIG(status));
1557 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001558 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001560#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561
1562#if defined(SUNOS4)
1563 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1564 if (sig && kill(tcp->pid, sig) < 0)
1565 perror("detach: kill");
1566 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001567 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568#endif /* SUNOS4 */
1569
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001570#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001571 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001572#endif
1573
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 if (!qflag)
1575 fprintf(stderr, "Process %u detached\n", tcp->pid);
1576
1577 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001578
1579#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001580 if (zombie != NULL) {
1581 /* TCP no longer exists therefore you must not detach () it. */
1582 droptcb(zombie);
1583 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001584#endif
1585
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586 return error;
1587}
1588
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001589#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590
1591static void
1592reaper(sig)
1593int sig;
1594{
1595 int pid;
1596 int status;
1597
1598 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1599#if 0
1600 struct tcb *tcp;
1601
1602 tcp = pid2tcb(pid);
1603 if (tcp)
1604 droptcb(tcp);
1605#endif
1606 }
1607}
1608
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001609#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610
1611static void
1612cleanup()
1613{
1614 int i;
1615 struct tcb *tcp;
1616
Roland McGrathee9d4352002-12-18 04:16:10 +00001617 for (i = 0; i < tcbtabsize; i++) {
1618 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619 if (!(tcp->flags & TCB_INUSE))
1620 continue;
1621 if (debug)
1622 fprintf(stderr,
1623 "cleanup: looking at pid %u\n", tcp->pid);
1624 if (tcp_last &&
1625 (!outfname || followfork < 2 || tcp_last == tcp)) {
1626 tprintf(" <unfinished ...>\n");
1627 tcp_last = NULL;
1628 }
1629 if (tcp->flags & TCB_ATTACHED)
1630 detach(tcp, 0);
1631 else {
1632 kill(tcp->pid, SIGCONT);
1633 kill(tcp->pid, SIGTERM);
1634 }
1635 }
1636 if (cflag)
1637 call_summary(outf);
1638}
1639
1640static void
1641interrupt(sig)
1642int sig;
1643{
1644 interrupted = 1;
1645}
1646
1647#ifndef HAVE_STRERROR
1648
Roland McGrath6d2b3492002-12-30 00:51:30 +00001649#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650extern int sys_nerr;
1651extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001652#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653
1654const char *
1655strerror(errno)
1656int errno;
1657{
1658 static char buf[64];
1659
1660 if (errno < 1 || errno >= sys_nerr) {
1661 sprintf(buf, "Unknown error %d", errno);
1662 return buf;
1663 }
1664 return sys_errlist[errno];
1665}
1666
1667#endif /* HAVE_STERRROR */
1668
1669#ifndef HAVE_STRSIGNAL
1670
Roland McGrath8f474e02003-01-14 07:53:33 +00001671#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001672extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001674#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1675extern char *_sys_siglist[];
1676#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677
1678const char *
1679strsignal(sig)
1680int sig;
1681{
1682 static char buf[64];
1683
1684 if (sig < 1 || sig >= NSIG) {
1685 sprintf(buf, "Unknown signal %d", sig);
1686 return buf;
1687 }
1688#ifdef HAVE__SYS_SIGLIST
1689 return _sys_siglist[sig];
1690#else
1691 return sys_siglist[sig];
1692#endif
1693}
1694
1695#endif /* HAVE_STRSIGNAL */
1696
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001697#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698
1699static void
1700rebuild_pollv()
1701{
1702 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703
Roland McGrathee9d4352002-12-18 04:16:10 +00001704 if (pollv != NULL)
1705 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001706 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001707 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001708 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001709 exit(1);
1710 }
1711
Roland McGrathca16be82003-01-10 19:55:28 +00001712 for (i = j = 0; i < tcbtabsize; i++) {
1713 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 if (!(tcp->flags & TCB_INUSE))
1715 continue;
1716 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001717 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 j++;
1719 }
1720 if (j != nprocs) {
1721 fprintf(stderr, "strace: proc miscount\n");
1722 exit(1);
1723 }
1724}
1725
1726#ifndef HAVE_POLLABLE_PROCFS
1727
1728static void
1729proc_poll_open()
1730{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731 int i;
1732
1733 if (pipe(proc_poll_pipe) < 0) {
1734 perror("pipe");
1735 exit(1);
1736 }
1737 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001738 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 exit(1);
1740 }
1741 }
1742}
1743
1744static int
1745proc_poll(pollv, nfds, timeout)
1746struct pollfd *pollv;
1747int nfds;
1748int timeout;
1749{
1750 int i;
1751 int n;
1752 struct proc_pollfd pollinfo;
1753
1754 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1755 return n;
1756 if (n != sizeof(struct proc_pollfd)) {
1757 fprintf(stderr, "panic: short read: %d\n", n);
1758 exit(1);
1759 }
1760 for (i = 0; i < nprocs; i++) {
1761 if (pollv[i].fd == pollinfo.fd)
1762 pollv[i].revents = pollinfo.revents;
1763 else
1764 pollv[i].revents = 0;
1765 }
1766 poller_pid = pollinfo.pid;
1767 return 1;
1768}
1769
1770static void
1771wakeup_handler(sig)
1772int sig;
1773{
1774}
1775
1776static void
1777proc_poller(pfd)
1778int pfd;
1779{
1780 struct proc_pollfd pollinfo;
1781 struct sigaction sa;
1782 sigset_t blocked_set, empty_set;
1783 int i;
1784 int n;
1785 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001786#ifdef FREEBSD
1787 struct procfs_status pfs;
1788#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789
1790 switch (fork()) {
1791 case -1:
1792 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001793 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 case 0:
1795 break;
1796 default:
1797 return;
1798 }
1799
1800 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1801 sa.sa_flags = 0;
1802 sigemptyset(&sa.sa_mask);
1803 sigaction(SIGHUP, &sa, NULL);
1804 sigaction(SIGINT, &sa, NULL);
1805 sigaction(SIGQUIT, &sa, NULL);
1806 sigaction(SIGPIPE, &sa, NULL);
1807 sigaction(SIGTERM, &sa, NULL);
1808 sa.sa_handler = wakeup_handler;
1809 sigaction(SIGUSR1, &sa, NULL);
1810 sigemptyset(&blocked_set);
1811 sigaddset(&blocked_set, SIGUSR1);
1812 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1813 sigemptyset(&empty_set);
1814
1815 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1816 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001817 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818 }
1819 n = rl.rlim_cur;
1820 for (i = 0; i < n; i++) {
1821 if (i != pfd && i != proc_poll_pipe[1])
1822 close(i);
1823 }
1824
1825 pollinfo.fd = pfd;
1826 pollinfo.pid = getpid();
1827 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001828#ifndef FREEBSD
1829 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1830#else /* FREEBSD */
1831 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1832#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001833 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834 switch (errno) {
1835 case EINTR:
1836 continue;
1837 case EBADF:
1838 pollinfo.revents = POLLERR;
1839 break;
1840 case ENOENT:
1841 pollinfo.revents = POLLHUP;
1842 break;
1843 default:
1844 perror("proc_poller: PIOCWSTOP");
1845 }
1846 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1847 _exit(0);
1848 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001849 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001850 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1851 sigsuspend(&empty_set);
1852 }
1853}
1854
1855#endif /* !HAVE_POLLABLE_PROCFS */
1856
1857static int
1858choose_pfd()
1859{
1860 int i, j;
1861 struct tcb *tcp;
1862
1863 static int last;
1864
1865 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001866 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001867 /*
1868 * The previous process is ready to run again. We'll
1869 * let it do so if it is currently in a syscall. This
1870 * heuristic improves the readability of the trace.
1871 */
1872 tcp = pfd2tcb(pollv[last].fd);
1873 if (tcp && (tcp->flags & TCB_INSYSCALL))
1874 return pollv[last].fd;
1875 }
1876
1877 for (i = 0; i < nprocs; i++) {
1878 /* Let competing children run round robin. */
1879 j = (i + last + 1) % nprocs;
1880 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1881 tcp = pfd2tcb(pollv[j].fd);
1882 if (!tcp) {
1883 fprintf(stderr, "strace: lost proc\n");
1884 exit(1);
1885 }
1886 droptcb(tcp);
1887 return -1;
1888 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001889 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890 last = j;
1891 return pollv[j].fd;
1892 }
1893 }
1894 fprintf(stderr, "strace: nothing ready\n");
1895 exit(1);
1896}
1897
1898static int
1899trace()
1900{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001901#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001902 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001903#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904 struct tcb *tcp;
1905 int pfd;
1906 int what;
1907 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001908 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909
1910 for (;;) {
1911 if (interactive)
1912 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1913
1914 if (nprocs == 0)
1915 break;
1916
1917 switch (nprocs) {
1918 case 1:
1919#ifndef HAVE_POLLABLE_PROCFS
1920 if (proc_poll_pipe[0] == -1) {
1921#endif
1922 tcp = pid2tcb(0);
1923 if (!tcp)
1924 continue;
1925 pfd = tcp->pfd;
1926 if (pfd == -1)
1927 continue;
1928 break;
1929#ifndef HAVE_POLLABLE_PROCFS
1930 }
1931 /* fall through ... */
1932#endif /* !HAVE_POLLABLE_PROCFS */
1933 default:
1934#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001935#ifdef POLL_HACK
1936 /* On some systems (e.g. UnixWare) we get too much ugly
1937 "unfinished..." stuff when multiple proceses are in
1938 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001939
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001940 if (in_syscall) {
1941 struct pollfd pv;
1942 tcp = in_syscall;
1943 in_syscall = NULL;
1944 pv.fd = tcp->pfd;
1945 pv.events = POLLWANT;
1946 if ((what = poll (&pv, 1, 1)) < 0) {
1947 if (interrupted)
1948 return 0;
1949 continue;
1950 }
1951 else if (what == 1 && pv.revents & POLLWANT) {
1952 goto FOUND;
1953 }
1954 }
1955#endif
1956
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 if (poll(pollv, nprocs, INFTIM) < 0) {
1958 if (interrupted)
1959 return 0;
1960 continue;
1961 }
1962#else /* !HAVE_POLLABLE_PROCFS */
1963 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1964 if (interrupted)
1965 return 0;
1966 continue;
1967 }
1968#endif /* !HAVE_POLLABLE_PROCFS */
1969 pfd = choose_pfd();
1970 if (pfd == -1)
1971 continue;
1972 break;
1973 }
1974
1975 /* Look up `pfd' in our table. */
1976 if ((tcp = pfd2tcb(pfd)) == NULL) {
1977 fprintf(stderr, "unknown pfd: %u\n", pfd);
1978 exit(1);
1979 }
John Hughesb6643082002-05-23 11:02:22 +00001980#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001981 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001982#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001983 /* Get the status of the process. */
1984 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001985#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001986 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001987#else /* FREEBSD */
1988 /* Thanks to some scheduling mystery, the first poller
1989 sometimes waits for the already processed end of fork
1990 event. Doing a non blocking poll here solves the problem. */
1991 if (proc_poll_pipe[0] != -1)
1992 ioctl_result = IOCTL_STATUS (tcp);
1993 else
1994 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001995#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001996 ioctl_errno = errno;
1997#ifndef HAVE_POLLABLE_PROCFS
1998 if (proc_poll_pipe[0] != -1) {
1999 if (ioctl_result < 0)
2000 kill(poller_pid, SIGKILL);
2001 else
2002 kill(poller_pid, SIGUSR1);
2003 }
2004#endif /* !HAVE_POLLABLE_PROCFS */
2005 }
2006 if (interrupted)
2007 return 0;
2008
2009 if (interactive)
2010 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2011
2012 if (ioctl_result < 0) {
2013 /* Find out what happened if it failed. */
2014 switch (ioctl_errno) {
2015 case EINTR:
2016 case EBADF:
2017 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002018#ifdef FREEBSD
2019 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002020#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 case ENOENT:
2022 droptcb(tcp);
2023 continue;
2024 default:
2025 perror("PIOCWSTOP");
2026 exit(1);
2027 }
2028 }
2029
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002030#ifdef FREEBSD
2031 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2032 /* discard first event for a syscall we never entered */
2033 IOCTL (tcp->pfd, PIOCRUN, 0);
2034 continue;
2035 }
Roland McGrath553a6092002-12-16 20:40:39 +00002036#endif
2037
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038 /* clear the just started flag */
2039 tcp->flags &= ~TCB_STARTUP;
2040
2041 /* set current output file */
2042 outf = tcp->outf;
2043
2044 if (cflag) {
2045 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002046#ifdef FREEBSD
2047 char buf[1024];
2048 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002050 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2051 buf[len] = '\0';
2052 sscanf(buf,
2053 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2054 &stime.tv_sec, &stime.tv_usec);
2055 } else
2056 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002057#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2059 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002060#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002061 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2062 tcp->stime = stime;
2063 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002064 what = tcp->status.PR_WHAT;
2065 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002066#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002068 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2069 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 if (trace_syscall(tcp) < 0) {
2071 fprintf(stderr, "syscall trouble\n");
2072 exit(1);
2073 }
2074 }
2075 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002076#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002077 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002078#ifdef POLL_HACK
2079 in_syscall = tcp;
2080#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002081 case PR_SYSEXIT:
2082 if (trace_syscall(tcp) < 0) {
2083 fprintf(stderr, "syscall trouble\n");
2084 exit(1);
2085 }
2086 break;
2087 case PR_SIGNALLED:
2088 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2089 printleader(tcp);
2090 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002091 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002093#ifdef PR_INFO
2094 if (tcp->status.PR_INFO.si_signo == what) {
2095 printleader(tcp);
2096 tprintf(" siginfo=");
2097 printsiginfo(&tcp->status.PR_INFO, 1);
2098 printtrailer(tcp);
2099 }
2100#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 }
2102 break;
2103 case PR_FAULTED:
2104 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2105 printleader(tcp);
2106 tprintf("=== FAULT %d ===", what);
2107 printtrailer(tcp);
2108 }
2109 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002110#ifdef FREEBSD
2111 case 0: /* handle case we polled for nothing */
2112 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002113#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002115 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 exit(1);
2117 break;
2118 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002119 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002120#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002121 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002122#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002123 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002124#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002125 perror("PIOCRUN");
2126 exit(1);
2127 }
2128 }
2129 return 0;
2130}
2131
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002132#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002133
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002134#ifdef TCB_GROUP_EXITING
2135/* Handle an exit detach or death signal that is taking all the
2136 related clone threads with it. This is called in three circumstances:
2137 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2138 SIG == 0 Continuing TCP will perform an exit_group syscall.
2139 SIG == other Continuing TCP with SIG will kill the process.
2140*/
2141static int
2142handle_group_exit(struct tcb *tcp, int sig)
2143{
2144 /* We need to locate our records of all the clone threads
2145 related to TCP, either its children or siblings. */
2146 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2147 ? tcp->parent
2148 : tcp->nclone_detached > 0
2149 ? tcp : NULL);
2150
2151 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002152 if (leader != NULL && leader != tcp &&
2153 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002154 fprintf(stderr,
2155 "PANIC: handle_group_exit: %d leader %d\n",
2156 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002157 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002158#ifndef USE_PROCFS
2159 resume_from_tcp (tcp);
2160#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002161 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002162 }
2163 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002164 /* Mark that we are taking the process down. */
2165 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002166 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002167 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002168 if (leader != NULL && leader != tcp)
2169 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002170 } else {
2171 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2172 cleanup();
2173 return -1;
2174 }
2175 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002176 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002177 if (leader != tcp)
2178 droptcb(tcp);
2179 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002180 /* The leader will report to us as parent now,
2181 and then we'll get to the SIG==-1 case. */
2182 return 0;
2183 }
2184 }
2185
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002186 return 0;
2187}
2188#endif
2189
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190static int
2191trace()
2192{
2193 int pid;
2194 int wait_errno;
2195 int status;
2196 struct tcb *tcp;
2197#ifdef LINUX
2198 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002199#ifdef __WALL
2200 static int wait4_options = __WALL;
2201#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002202#endif /* LINUX */
2203
2204 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002205 if (interrupted)
2206 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207 if (interactive)
2208 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2209#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002210#ifdef __WALL
2211 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002212 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002213 /* this kernel does not support __WALL */
2214 wait4_options &= ~__WALL;
2215 errno = 0;
2216 pid = wait4(-1, &status, wait4_options,
2217 cflag ? &ru : NULL);
2218 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002219 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002220 /* most likely a "cloned" process */
2221 pid = wait4(-1, &status, __WCLONE,
2222 cflag ? &ru : NULL);
2223 if (pid == -1) {
2224 fprintf(stderr, "strace: clone wait4 "
2225 "failed: %s\n", strerror(errno));
2226 }
2227 }
2228#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002230#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231#endif /* LINUX */
2232#ifdef SUNOS4
2233 pid = wait(&status);
2234#endif /* SUNOS4 */
2235 wait_errno = errno;
2236 if (interactive)
2237 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2238
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002239 if (pid == -1) {
2240 switch (wait_errno) {
2241 case EINTR:
2242 continue;
2243 case ECHILD:
2244 /*
2245 * We would like to verify this case
2246 * but sometimes a race in Solbourne's
2247 * version of SunOS sometimes reports
2248 * ECHILD before sending us SIGCHILD.
2249 */
2250#if 0
2251 if (nprocs == 0)
2252 return 0;
2253 fprintf(stderr, "strace: proc miscount\n");
2254 exit(1);
2255#endif
2256 return 0;
2257 default:
2258 errno = wait_errno;
2259 perror("strace: wait");
2260 return -1;
2261 }
2262 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002263 if (pid == popen_pid) {
2264 if (WIFEXITED(status) || WIFSIGNALED(status))
2265 popen_pid = -1;
2266 continue;
2267 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002268 if (debug)
2269 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2270
2271 /* Look up `pid' in our table. */
2272 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002273#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002274 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002275 /* This is needed to go with the CLONE_PTRACE
2276 changes in process.c/util.c: we might see
2277 the child's initial trap before we see the
2278 parent return from the clone syscall.
2279 Leave the child suspended until the parent
2280 returns from its system call. Only then
2281 will we have the association of parent and
2282 child so that we know how to do clearbpt
2283 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002284 if (nprocs == tcbtabsize &&
2285 expand_tcbtab())
2286 tcp = NULL;
2287 else
2288 tcp = alloctcb(pid);
2289 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002290 kill(pid, SIGKILL); /* XXX */
2291 return 0;
2292 }
2293 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002294 if (!qflag)
2295 fprintf(stderr, "\
2296Process %d attached (waiting for parent)\n",
2297 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002298 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002299 else
2300 /* This can happen if a clone call used
2301 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002302#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002303 {
2304 fprintf(stderr, "unknown pid: %u\n", pid);
2305 if (WIFSTOPPED(status))
2306 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2307 exit(1);
2308 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002309 }
2310 /* set current output file */
2311 outf = tcp->outf;
2312 if (cflag) {
2313#ifdef LINUX
2314 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2315 tcp->stime = ru.ru_stime;
2316#endif /* !LINUX */
2317 }
2318
2319 if (tcp->flags & TCB_SUSPENDED) {
2320 /*
2321 * Apparently, doing any ptrace() call on a stopped
2322 * process, provokes the kernel to report the process
2323 * status again on a subsequent wait(), even if the
2324 * process has not been actually restarted.
2325 * Since we have inspected the arguments of suspended
2326 * processes we end up here testing for this case.
2327 */
2328 continue;
2329 }
2330 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002331 if (pid == strace_child)
2332 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002333 if (!cflag
2334 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2335 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002336 tprintf("+++ killed by %s %s+++",
2337 signame(WTERMSIG(status)),
2338#ifdef WCOREDUMP
2339 WCOREDUMP(status) ? "(core dumped) " :
2340#endif
2341 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002342 printtrailer(tcp);
2343 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002344#ifdef TCB_GROUP_EXITING
2345 handle_group_exit(tcp, -1);
2346#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002348#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002349 continue;
2350 }
2351 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002352 if (pid == strace_child)
2353 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002354 if (debug)
2355 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002356 if ((tcp->flags & TCB_ATTACHED)
2357#ifdef TCB_GROUP_EXITING
2358 && !(tcp->parent && (tcp->parent->flags &
2359 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002360 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002361#endif
2362 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363 fprintf(stderr,
2364 "PANIC: attached pid %u exited\n",
2365 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002366 if (tcp == tcp_last) {
2367 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2368 == TCB_INSYSCALL)
2369 tprintf(" <unfinished ... exit status %d>\n",
2370 WEXITSTATUS(status));
2371 tcp_last = NULL;
2372 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002373#ifdef TCB_GROUP_EXITING
2374 handle_group_exit(tcp, -1);
2375#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002376 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002377#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002378 continue;
2379 }
2380 if (!WIFSTOPPED(status)) {
2381 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2382 droptcb(tcp);
2383 continue;
2384 }
2385 if (debug)
2386 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002387 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388
Roland McGrath02203312007-06-11 22:06:31 +00002389 /*
2390 * Interestingly, the process may stop
2391 * with STOPSIG equal to some other signal
2392 * than SIGSTOP if we happend to attach
2393 * just before the process takes a signal.
2394 */
2395 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 /*
2397 * This flag is there to keep us in sync.
2398 * Next time this process stops it should
2399 * really be entering a system call.
2400 */
2401 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002402 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002403 /*
2404 * One example is a breakpoint inherited from
2405 * parent through fork ().
2406 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002407 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2408 droptcb(tcp);
2409 cleanup();
2410 return -1;
2411 }
2412 }
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002413/* PTRACE_SETOPTIONS is not a #define. PT_SETOPTIONS is. */
2414/* Add more OSes after you verified it works for them. */
2415#if defined LINUX && defined PT_SETOPTIONS
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002416 /*
2417 * Ask kernel to set signo to SIGTRAP | 0x80
2418 * on ptrace-generated SIGTRAPs, and mark
2419 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
2420 */
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002421 if (!ptrace_opts_set) {
2422 ptrace_opts_set = 1;
2423 /*
2424 * NB: even if this "succeeds", we can
2425 * revert back to SIGTRAP if we later see
2426 * that it didnt really work.
2427 * Old kernels are known to lie here.
2428 */
2429 if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
2430 (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
2431 ptrace_stop_sig = SIGTRAP | 0x80;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002432 }
2433#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 goto tracing;
2435 }
2436
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002437#if defined LINUX && defined PT_SETOPTIONS
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002438 if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002439 /*
2440 * We told ptrace to report SIGTRAP | 0x80 on this process
2441 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
2442 * kill(pid, SIGTRAP), trap insn, etc;
2443 * but be paranoid about it.
2444 */
2445 if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
2446 /* It's post-exec ptrace stop. */
2447 /* Set WSTOPSIG(status) = (SIGTRAP | 0x80). */
2448 status |= 0x8000;
2449 } else {
2450 /* Take a better look... */
2451 siginfo_t si;
2452 ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
2453 /*
2454 * Check some fields to make sure we see
2455 * real SIGTRAP.
2456 * Otherwise interpret it as ptrace stop.
2457 * Real SIGTRAPs (int3 insn on x86, kill() etc)
2458 * have these values:
2459 * int3: kill -TRAP $pid:
2460 * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
2461 * si_errno:0 si_errno:(?)
2462 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
2463 * si_pid:0 si_pid:(>0?)
2464 * si_band:0 si_band:(?)
2465 * Ptrace stops have garbage there instead.
2466 */
2467 if (si.si_signo != SIGTRAP
2468 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
2469 ) {
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002470 fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
2471 ptrace_stop_sig = SIGTRAP;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002472 }
2473 }
2474 }
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002475#endif
2476
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002477 if (WSTOPSIG(status) != ptrace_stop_sig) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002478 /* This isn't a ptrace stop. */
2479
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002480 if (WSTOPSIG(status) == SIGSTOP &&
2481 (tcp->flags & TCB_SIGTRAPPED)) {
2482 /*
2483 * Trapped attempt to block SIGTRAP
2484 * Hope we are back in control now.
2485 */
2486 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002487 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488 cleanup();
2489 return -1;
2490 }
2491 continue;
2492 }
2493 if (!cflag
2494 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002495 unsigned long addr = 0;
2496 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002497#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002498# define PSR_RI 41
2499 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002500 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002501
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002502 upeek(tcp, PT_CR_IPSR, &psr);
2503 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002504
2505 pc += (psr >> PSR_RI) & 0x3;
2506 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2507 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002508#elif defined PTRACE_GETSIGINFO
2509 if (WSTOPSIG(status) == SIGSEGV ||
2510 WSTOPSIG(status) == SIGBUS) {
2511 siginfo_t si;
2512 if (ptrace(PTRACE_GETSIGINFO, pid,
2513 0, &si) == 0)
2514 addr = (unsigned long)
2515 si.si_addr;
2516 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002517#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002518 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002519 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002520 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002521 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002522 printtrailer(tcp);
2523 }
Roland McGrath05690952004-10-20 01:00:27 +00002524 if (((tcp->flags & TCB_ATTACHED) ||
2525 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002526 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002527#ifdef TCB_GROUP_EXITING
2528 handle_group_exit(tcp, WSTOPSIG(status));
2529#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002530 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002531#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002532 continue;
2533 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002534 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002535 cleanup();
2536 return -1;
2537 }
2538 tcp->flags &= ~TCB_SUSPENDED;
2539 continue;
2540 }
Roland McGrath02203312007-06-11 22:06:31 +00002541 /* we handled the STATUS, we are permitted to interrupt now. */
2542 if (interrupted)
2543 return 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002544 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002545 if (tcp->flags & TCB_ATTACHED)
2546 detach(tcp, 0);
2547 else {
2548 ptrace(PTRACE_KILL,
2549 tcp->pid, (char *) 1, SIGTERM);
2550 droptcb(tcp);
2551 }
2552 continue;
2553 }
2554 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002555#ifdef TCB_GROUP_EXITING
2556 if (tcp->flags & TCB_GROUP_EXITING) {
2557 if (handle_group_exit(tcp, 0) < 0)
2558 return -1;
2559 continue;
2560 }
2561#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002562 if (tcp->flags & TCB_ATTACHED)
2563 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002564 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002565 cleanup();
2566 return -1;
2567 }
2568 continue;
2569 }
2570 if (tcp->flags & TCB_SUSPENDED) {
2571 if (!qflag)
2572 fprintf(stderr, "Process %u suspended\n", pid);
2573 continue;
2574 }
2575 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002576 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577 cleanup();
2578 return -1;
2579 }
2580 }
2581 return 0;
2582}
2583
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002584#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002585
2586static int curcol;
2587
2588#ifdef __STDC__
2589#include <stdarg.h>
2590#define VA_START(a, b) va_start(a, b)
2591#else
2592#include <varargs.h>
2593#define VA_START(a, b) va_start(a)
2594#endif
2595
2596void
2597#ifdef __STDC__
2598tprintf(const char *fmt, ...)
2599#else
2600tprintf(fmt, va_alist)
2601char *fmt;
2602va_dcl
2603#endif
2604{
2605 va_list args;
2606
2607 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002608 if (outf) {
2609 int n = vfprintf(outf, fmt, args);
2610 if (n < 0 && outf != stderr)
2611 perror(outfname == NULL
2612 ? "<writing to pipe>" : outfname);
2613 else
2614 curcol += n;
2615 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002616 va_end(args);
2617 return;
2618}
2619
2620void
2621printleader(tcp)
2622struct tcb *tcp;
2623{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002624 if (tcp_last) {
2625 if (tcp_last->ptrace_errno) {
2626 if (tcp_last->flags & TCB_INSYSCALL) {
2627 tprintf(" <unavailable>)");
2628 tabto(acolumn);
2629 }
2630 tprintf("= ? <unavailable>\n");
2631 tcp_last->ptrace_errno = 0;
2632 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
2633 tcp_last->flags |= TCB_REPRINT;
2634 tprintf(" <unfinished ...>\n");
2635 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636 }
2637 curcol = 0;
2638 if ((followfork == 1 || pflag_seen > 1) && outfname)
2639 tprintf("%-5d ", tcp->pid);
2640 else if (nprocs > 1 && !outfname)
2641 tprintf("[pid %5u] ", tcp->pid);
2642 if (tflag) {
2643 char str[sizeof("HH:MM:SS")];
2644 struct timeval tv, dtv;
2645 static struct timeval otv;
2646
2647 gettimeofday(&tv, NULL);
2648 if (rflag) {
2649 if (otv.tv_sec == 0)
2650 otv = tv;
2651 tv_sub(&dtv, &tv, &otv);
2652 tprintf("%6ld.%06ld ",
2653 (long) dtv.tv_sec, (long) dtv.tv_usec);
2654 otv = tv;
2655 }
2656 else if (tflag > 2) {
2657 tprintf("%ld.%06ld ",
2658 (long) tv.tv_sec, (long) tv.tv_usec);
2659 }
2660 else {
2661 time_t local = tv.tv_sec;
2662 strftime(str, sizeof(str), "%T", localtime(&local));
2663 if (tflag > 1)
2664 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2665 else
2666 tprintf("%s ", str);
2667 }
2668 }
2669 if (iflag)
2670 printcall(tcp);
2671}
2672
2673void
2674tabto(col)
2675int col;
2676{
2677 if (curcol < col)
2678 tprintf("%*s", col - curcol, "");
2679}
2680
2681void
2682printtrailer(tcp)
2683struct tcb *tcp;
2684{
2685 tprintf("\n");
2686 tcp_last = NULL;
2687}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002688
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002689#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002690
2691int mp_ioctl (int fd, int cmd, void *arg, int size) {
2692
2693 struct iovec iov[2];
2694 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002695
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002696 iov[0].iov_base = &cmd;
2697 iov[0].iov_len = sizeof cmd;
2698 if (arg) {
2699 ++n;
2700 iov[1].iov_base = arg;
2701 iov[1].iov_len = size;
2702 }
Roland McGrath553a6092002-12-16 20:40:39 +00002703
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002704 return writev (fd, iov, n);
2705}
2706
2707#endif