blob: ba23b217f59e1e0f9f79dcf7bc9967a57a5917c8 [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;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000086/*
87 * daemonized_tracer supports -D option.
88 * With this option, strace forks twice.
89 * Unlike normal case, with -D *grandparent* process exec's,
90 * becoming a traced process. Child exits (this prevents traced process
91 * from having children it doesn't expect to have), and grandchild
92 * attaches to grandparent similarly to strace -p PID.
93 * This allows for more transparent interaction in cases
94 * when process and its parent are communicating via signals,
95 * wait() etc. Without -D, strace process gets lodged in between,
96 * disrupting parent<->child link.
97 */
98static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000100/* Sometimes we want to print only succeeding syscalls. */
101int not_failing_only = 0;
102
Dmitry V. Levina6809652008-11-10 17:14:58 +0000103static int exit_code = 0;
104static int strace_child = 0;
Denys Vlasenko96d5a762008-12-29 19:13:27 +0000105static int ptrace_stop_sig = SIGTRAP;
106static bool ptrace_opts_set;
Dmitry V. Levina6809652008-11-10 17:14:58 +0000107
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000108static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109uid_t run_uid;
110gid_t run_gid;
111
112int acolumn = DEFAULT_ACOLUMN;
113int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000114static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +0000116struct tcb **tcbtab;
117unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119
Roland McGrath0a463882007-07-05 18:43:16 +0000120static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121static int trace P((void));
122static void cleanup P((void));
123static void interrupt P((int sig));
124static sigset_t empty_set, blocked_set;
125
126#ifdef HAVE_SIG_ATOMIC_T
127static volatile sig_atomic_t interrupted;
128#else /* !HAVE_SIG_ATOMIC_T */
129#ifdef __STDC__
130static volatile int interrupted;
131#else /* !__STDC__ */
132static int interrupted;
133#endif /* !__STDC__ */
134#endif /* !HAVE_SIG_ATOMIC_T */
135
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000136#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137
138static struct tcb *pfd2tcb P((int pfd));
139static void reaper P((int sig));
140static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000141static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142
143#ifndef HAVE_POLLABLE_PROCFS
144
145static void proc_poll_open P((void));
146static void proc_poller P((int pfd));
147
148struct proc_pollfd {
149 int fd;
150 int revents;
151 int pid;
152};
153
154static int poller_pid;
155static int proc_poll_pipe[2] = { -1, -1 };
156
157#endif /* !HAVE_POLLABLE_PROCFS */
158
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000159#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000160#define POLLWANT POLLWRNORM
161#else
162#define POLLWANT POLLPRI
163#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000164#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000165
166static void
167usage(ofp, exitval)
168FILE *ofp;
169int exitval;
170{
171 fprintf(ofp, "\
172usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000173 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
174 [command [arg ...]]\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000175 or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000176 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000177-c -- count time, calls, and errors for each syscall and report summary\n\
178-f -- follow forks, -ff -- with output into separate files\n\
179-F -- attempt to follow vforks, -h -- print help message\n\
180-i -- print instruction pointer at time of syscall\n\
181-q -- suppress messages about attaching, detaching, etc.\n\
182-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
183-T -- print time spent in each syscall, -V -- print version\n\
184-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
185-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
186-a column -- alignment COLUMN for printing syscall results (default %d)\n\
187-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
188 options: trace, abbrev, verbose, raw, signal, read, or write\n\
189-o file -- send trace output to FILE instead of stderr\n\
190-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
191-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000192-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
194-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
195-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000196-E var=val -- put var=val in the environment for command\n\
197-E var -- remove var from the environment for command\n\
198" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000199-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000200 */
201, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202 exit(exitval);
203}
204
205#ifdef SVR4
206#ifdef MIPS
207void
208foobar()
209{
210}
211#endif /* MIPS */
212#endif /* SVR4 */
213
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000214static int
215set_cloexec_flag(int fd)
216{
217 int flags, newflags;
218
219 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
220 {
221 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
222 progname, strerror(errno));
223 return -1;
224 }
225
226 newflags = flags | FD_CLOEXEC;
227 if (flags == newflags)
228 return 0;
229
230 if (fcntl(fd, F_SETFD, newflags) < 0)
231 {
232 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
233 progname, strerror(errno));
234 return -1;
235 }
236
237 return 0;
238}
239
240/*
241 * When strace is setuid executable, we have to swap uids
242 * before and after filesystem and process management operations.
243 */
244static void
245swap_uid(void)
246{
247#ifndef SVR4
248 int euid = geteuid(), uid = getuid();
249
250 if (euid != uid && setreuid(euid, uid) < 0)
251 {
252 fprintf(stderr, "%s: setreuid: %s\n",
253 progname, strerror(errno));
254 exit(1);
255 }
256#endif
257}
258
Roland McGrath4bfa6262007-07-05 20:03:16 +0000259#if _LFS64_LARGEFILE
260# define fopen_for_output fopen64
261#else
262# define fopen_for_output fopen
263#endif
264
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000265static FILE *
266strace_fopen(const char *path, const char *mode)
267{
268 FILE *fp;
269
270 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000271 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000272 fprintf(stderr, "%s: can't fopen '%s': %s\n",
273 progname, path, strerror(errno));
274 swap_uid();
275 if (fp && set_cloexec_flag(fileno(fp)) < 0)
276 {
277 fclose(fp);
278 fp = NULL;
279 }
280 return fp;
281}
282
283static int popen_pid = -1;
284
285#ifndef _PATH_BSHELL
286# define _PATH_BSHELL "/bin/sh"
287#endif
288
289/*
290 * We cannot use standard popen(3) here because we have to distinguish
291 * popen child process from other processes we trace, and standard popen(3)
292 * does not export its child's pid.
293 */
294static FILE *
295strace_popen(const char *command)
296{
297 int fds[2];
298
299 swap_uid();
300 if (pipe(fds) < 0)
301 {
302 fprintf(stderr, "%s: pipe: %s\n",
303 progname, strerror(errno));
304 swap_uid();
305 return NULL;
306 }
307
308 if (set_cloexec_flag(fds[1]) < 0)
309 {
310 close(fds[0]);
311 close(fds[1]);
312 swap_uid();
313 return NULL;
314 }
315
316 if ((popen_pid = fork()) == -1)
317 {
318 fprintf(stderr, "%s: fork: %s\n",
319 progname, strerror(errno));
320 close(fds[0]);
321 close(fds[1]);
322 swap_uid();
323 return NULL;
324 }
325
326 if (popen_pid)
327 {
328 /* parent */
329 close(fds[0]);
330 swap_uid();
331 return fdopen(fds[1], "w");
332 } else
333 {
334 /* child */
335 close(fds[1]);
336 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
337 {
338 fprintf(stderr, "%s: dup2: %s\n",
339 progname, strerror(errno));
340 _exit(1);
341 }
342 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
343 fprintf(stderr, "%s: execl: %s: %s\n",
344 progname, _PATH_BSHELL, strerror(errno));
345 _exit(1);
346 }
347}
348
349static int
350newoutf(struct tcb *tcp)
351{
352 if (outfname && followfork > 1) {
353 char name[MAXPATHLEN];
354 FILE *fp;
355
356 sprintf(name, "%s.%u", outfname, tcp->pid);
357 if ((fp = strace_fopen(name, "w")) == NULL)
358 return -1;
359 tcp->outf = fp;
360 }
361 return 0;
362}
363
Roland McGrath02203312007-06-11 22:06:31 +0000364static void
365startup_attach(void)
366{
367 int tcbi;
368 struct tcb *tcp;
369
370 /*
371 * Block user interruptions as we would leave the traced
372 * process stopped (process state T) if we would terminate in
373 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
374 * We rely on cleanup () from this point on.
375 */
376 if (interactive)
377 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
378
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000379 if (daemonized_tracer) {
380 pid_t pid = fork();
381 if (pid < 0) {
382 _exit(1);
383 }
384 if (pid) { /* parent */
385 /*
386 * Wait for child to attach to straced process
387 * (our parent). Child SIGKILLs us after it attached.
388 * Parent's wait() is unblocked by our death,
389 * it proceeds to exec the straced program.
390 */
391 pause();
392 _exit(0); /* paranoia */
393 }
394 }
395
Roland McGrath02203312007-06-11 22:06:31 +0000396 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
397 tcp = tcbtab[tcbi];
398 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
399 continue;
400#ifdef LINUX
401 if (tcp->flags & TCB_CLONE_THREAD)
402 continue;
403#endif
404 /* Reinitialize the output since it may have changed. */
405 tcp->outf = outf;
406 if (newoutf(tcp) < 0)
407 exit(1);
408
409#ifdef USE_PROCFS
410 if (proc_open(tcp, 1) < 0) {
411 fprintf(stderr, "trouble opening proc file\n");
412 droptcb(tcp);
413 continue;
414 }
415#else /* !USE_PROCFS */
416# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000417 if (followfork && !daemonized_tracer) {
Roland McGrath02203312007-06-11 22:06:31 +0000418 char procdir[MAXPATHLEN];
419 DIR *dir;
420
421 sprintf(procdir, "/proc/%d/task", tcp->pid);
422 dir = opendir(procdir);
423 if (dir != NULL) {
424 unsigned int ntid = 0, nerr = 0;
425 struct dirent *de;
426 int tid;
427 while ((de = readdir(dir)) != NULL) {
428 if (de->d_fileno == 0 ||
429 de->d_name[0] == '.')
430 continue;
431 tid = atoi(de->d_name);
432 if (tid <= 0)
433 continue;
434 ++ntid;
435 if (ptrace(PTRACE_ATTACH, tid,
436 (char *) 1, 0) < 0)
437 ++nerr;
438 else if (tid != tcbtab[tcbi]->pid) {
439 if (nprocs == tcbtabsize &&
440 expand_tcbtab())
441 tcp = NULL;
442 else
443 tcp = alloctcb(tid);
444 if (tcp == NULL)
445 exit(1);
446 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
447 tcbtab[tcbi]->nchildren++;
448 tcbtab[tcbi]->nclone_threads++;
449 tcbtab[tcbi]->nclone_detached++;
450 tcp->parent = tcbtab[tcbi];
451 }
452 if (interactive) {
453 sigprocmask(SIG_SETMASK, &empty_set, NULL);
454 if (interrupted)
455 return;
456 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
457 }
458 }
459 closedir(dir);
460 if (nerr == ntid) {
461 perror("attach: ptrace(PTRACE_ATTACH, ...)");
462 droptcb(tcp);
463 continue;
464 }
465 if (!qflag) {
466 ntid -= nerr;
467 if (ntid > 1)
468 fprintf(stderr, "\
469Process %u attached with %u threads - interrupt to quit\n",
470 tcp->pid, ntid);
471 else
472 fprintf(stderr, "\
473Process %u attached - interrupt to quit\n",
474 tcp->pid);
475 }
476 continue;
477 }
478 }
479# endif
480 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
481 perror("attach: ptrace(PTRACE_ATTACH, ...)");
482 droptcb(tcp);
483 continue;
484 }
485 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000486
487 if (daemonized_tracer) {
488 /*
489 * It is our grandparent we trace, not a -p PID.
490 * Don't want to just detach on exit, so...
491 */
492 tcp->flags &= ~TCB_ATTACHED;
493 /*
494 * Make parent go away.
495 * Also makes grandparent's wait() unblock.
496 */
497 kill(getppid(), SIGKILL);
498 }
499
Roland McGrath02203312007-06-11 22:06:31 +0000500#endif /* !USE_PROCFS */
501 if (!qflag)
502 fprintf(stderr,
503 "Process %u attached - interrupt to quit\n",
504 tcp->pid);
505 }
506
507 if (interactive)
508 sigprocmask(SIG_SETMASK, &empty_set, NULL);
509}
510
511static void
512startup_child (char **argv)
513{
514 struct stat statbuf;
515 const char *filename;
516 char pathname[MAXPATHLEN];
517 int pid = 0;
518 struct tcb *tcp;
519
520 filename = argv[0];
521 if (strchr(filename, '/')) {
522 if (strlen(filename) > sizeof pathname - 1) {
523 errno = ENAMETOOLONG;
524 perror("strace: exec");
525 exit(1);
526 }
527 strcpy(pathname, filename);
528 }
529#ifdef USE_DEBUGGING_EXEC
530 /*
531 * Debuggers customarily check the current directory
532 * first regardless of the path but doing that gives
533 * security geeks a panic attack.
534 */
535 else if (stat(filename, &statbuf) == 0)
536 strcpy(pathname, filename);
537#endif /* USE_DEBUGGING_EXEC */
538 else {
539 char *path;
540 int m, n, len;
541
542 for (path = getenv("PATH"); path && *path; path += m) {
543 if (strchr(path, ':')) {
544 n = strchr(path, ':') - path;
545 m = n + 1;
546 }
547 else
548 m = n = strlen(path);
549 if (n == 0) {
550 if (!getcwd(pathname, MAXPATHLEN))
551 continue;
552 len = strlen(pathname);
553 }
554 else if (n > sizeof pathname - 1)
555 continue;
556 else {
557 strncpy(pathname, path, n);
558 len = n;
559 }
560 if (len && pathname[len - 1] != '/')
561 pathname[len++] = '/';
562 strcpy(pathname + len, filename);
563 if (stat(pathname, &statbuf) == 0 &&
564 /* Accept only regular files
565 with some execute bits set.
566 XXX not perfect, might still fail */
567 S_ISREG(statbuf.st_mode) &&
568 (statbuf.st_mode & 0111))
569 break;
570 }
571 }
572 if (stat(pathname, &statbuf) < 0) {
573 fprintf(stderr, "%s: %s: command not found\n",
574 progname, filename);
575 exit(1);
576 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000577 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000578 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000579 perror("strace: fork");
580 cleanup();
581 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000582 }
583 if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
584 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
585 ) {
586 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000587#ifdef USE_PROCFS
588 if (outf != stderr) close (fileno (outf));
589#ifdef MIPS
590 /* Kludge for SGI, see proc_open for details. */
591 sa.sa_handler = foobar;
592 sa.sa_flags = 0;
593 sigemptyset(&sa.sa_mask);
594 sigaction(SIGINT, &sa, NULL);
595#endif /* MIPS */
596#ifndef FREEBSD
597 pause();
598#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000599 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000600#endif /* FREEBSD */
601#else /* !USE_PROCFS */
602 if (outf!=stderr)
603 close(fileno (outf));
604
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000605 if (!daemonized_tracer) {
606 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
607 perror("strace: ptrace(PTRACE_TRACEME, ...)");
608 exit(1);
609 }
610 if (debug)
611 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000612 }
Roland McGrath02203312007-06-11 22:06:31 +0000613
614 if (username != NULL || geteuid() == 0) {
615 uid_t run_euid = run_uid;
616 gid_t run_egid = run_gid;
617
618 if (statbuf.st_mode & S_ISUID)
619 run_euid = statbuf.st_uid;
620 if (statbuf.st_mode & S_ISGID)
621 run_egid = statbuf.st_gid;
622
623 /*
624 * It is important to set groups before we
625 * lose privileges on setuid.
626 */
627 if (username != NULL) {
628 if (initgroups(username, run_gid) < 0) {
629 perror("initgroups");
630 exit(1);
631 }
632 if (setregid(run_gid, run_egid) < 0) {
633 perror("setregid");
634 exit(1);
635 }
636 if (setreuid(run_uid, run_euid) < 0) {
637 perror("setreuid");
638 exit(1);
639 }
640 }
641 }
642 else
643 setreuid(run_uid, run_uid);
644
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000645 if (!daemonized_tracer) {
646 /*
647 * Induce an immediate stop so that the parent
648 * will resume us with PTRACE_SYSCALL and display
649 * this execve call normally.
650 */
651 kill(getpid(), SIGSTOP);
652 } else {
653 struct sigaction sv_sigchld;
654 sigaction(SIGCHLD, NULL, &sv_sigchld);
655 /*
656 * Make sure it is not SIG_IGN, otherwise wait
657 * will not block.
658 */
659 signal(SIGCHLD, SIG_DFL);
660 /*
661 * Wait for grandchild to attach to us.
662 * It kills child after that, and wait() unblocks.
663 */
664 alarm(3);
665 wait(NULL);
666 alarm(0);
667 sigaction(SIGCHLD, &sv_sigchld, NULL);
668 }
Roland McGrath02203312007-06-11 22:06:31 +0000669#endif /* !USE_PROCFS */
670
671 execv(pathname, argv);
672 perror("strace: exec");
673 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000674 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000675
676 /* We are the tracer. */
677 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
678 if (tcp == NULL) {
679 cleanup();
680 exit(1);
681 }
682 if (daemonized_tracer) {
683 /* We want subsequent startup_attach() to attach to it. */
684 tcp->flags |= TCB_ATTACHED;
685 }
Roland McGrath02203312007-06-11 22:06:31 +0000686#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000687 if (proc_open(tcp, 0) < 0) {
688 fprintf(stderr, "trouble opening proc file\n");
689 cleanup();
690 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000691 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000692#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000693}
694
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000696main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697{
698 extern int optind;
699 extern char *optarg;
700 struct tcb *tcp;
701 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000702 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000703 struct sigaction sa;
704
705 static char buf[BUFSIZ];
706
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000707 progname = argv[0] ? argv[0] : "strace";
708
Roland McGrathee9d4352002-12-18 04:16:10 +0000709 /* Allocate the initial tcbtab. */
710 tcbtabsize = argc; /* Surely enough for all -p args. */
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000711 if ((tcbtab = calloc (tcbtabsize, sizeof tcbtab[0])) == NULL) {
712 fprintf(stderr, "%s: out of memory\n", progname);
713 exit(1);
714 }
715 if ((tcbtab[0] = calloc (tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
716 fprintf(stderr, "%s: out of memory\n", progname);
717 exit(1);
718 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000719 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
720 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
721
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 outf = stderr;
723 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000724 set_sortby(DEFAULT_SORTBY);
725 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000726 qualify("trace=all");
727 qualify("abbrev=all");
728 qualify("verbose=all");
729 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000730 while ((c = getopt(argc, argv,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000731 "+cdfFhiqrtTvVxz"
732#ifndef USE_PROCFS
733 "D"
734#endif
735 "a:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000736 switch (c) {
737 case 'c':
738 cflag++;
739 dtime++;
740 break;
741 case 'd':
742 debug++;
743 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000744#ifndef USE_PROCFS
745 /* Experimental, not documented in manpage yet. */
746 case 'D':
747 daemonized_tracer = 1;
748 break;
749#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000750 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000751 optF = 1;
752 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000753 case 'f':
754 followfork++;
755 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 case 'h':
757 usage(stdout, 0);
758 break;
759 case 'i':
760 iflag++;
761 break;
762 case 'q':
763 qflag++;
764 break;
765 case 'r':
766 rflag++;
767 tflag++;
768 break;
769 case 't':
770 tflag++;
771 break;
772 case 'T':
773 dtime++;
774 break;
775 case 'x':
776 xflag++;
777 break;
778 case 'v':
779 qualify("abbrev=none");
780 break;
781 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000782 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 exit(0);
784 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000785 case 'z':
786 not_failing_only = 1;
787 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000788 case 'a':
789 acolumn = atoi(optarg);
790 break;
791 case 'e':
792 qualify(optarg);
793 break;
794 case 'o':
795 outfname = strdup(optarg);
796 break;
797 case 'O':
798 set_overhead(atoi(optarg));
799 break;
800 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000801 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802 fprintf(stderr, "%s: Invalid process id: %s\n",
803 progname, optarg);
804 break;
805 }
806 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000807 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000808 break;
809 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000810 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000811 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 progname);
813 exit(1);
814 }
815 tcp->flags |= TCB_ATTACHED;
816 pflag_seen++;
817 break;
818 case 's':
819 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000820 if (max_strlen < 0) {
821 fprintf(stderr,
822 "%s: invalid -s argument: %s\n",
823 progname, optarg);
824 exit(1);
825 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 break;
827 case 'S':
828 set_sortby(optarg);
829 break;
830 case 'u':
831 username = strdup(optarg);
832 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000833 case 'E':
834 if (putenv(optarg) < 0) {
835 fprintf(stderr, "%s: out of memory\n",
836 progname);
837 exit(1);
838 }
839 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 default:
841 usage(stderr, 1);
842 break;
843 }
844 }
845
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000846 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000847 usage(stderr, 1);
848
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000849 if (!followfork)
850 followfork = optF;
851
Roland McGrathcb9def62006-04-25 07:48:03 +0000852 if (followfork > 1 && cflag) {
853 fprintf(stderr,
854 "%s: -c and -ff are mutually exclusive options\n",
855 progname);
856 exit(1);
857 }
858
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000859 /* See if they want to run as another user. */
860 if (username != NULL) {
861 struct passwd *pent;
862
863 if (getuid() != 0 || geteuid() != 0) {
864 fprintf(stderr,
865 "%s: you must be root to use the -u option\n",
866 progname);
867 exit(1);
868 }
869 if ((pent = getpwnam(username)) == NULL) {
870 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000871 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000872 exit(1);
873 }
874 run_uid = pent->pw_uid;
875 run_gid = pent->pw_gid;
876 }
877 else {
878 run_uid = getuid();
879 run_gid = getgid();
880 }
881
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 /* Check if they want to redirect the output. */
883 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000884 /* See if they want to pipe the output. */
885 if (outfname[0] == '|' || outfname[0] == '!') {
886 /*
887 * We can't do the <outfname>.PID funny business
888 * when using popen, so prohibit it.
889 */
890 if (followfork > 1) {
891 fprintf(stderr, "\
892%s: piping the output and -ff are mutually exclusive options\n",
893 progname);
894 exit(1);
895 }
896
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000897 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000898 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000899 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000900 else if (followfork <= 1 &&
901 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903 }
904
Roland McGrath37b9a662003-11-07 02:26:54 +0000905 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000907 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000908 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000910 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000911 /* Valid states here:
912 optind < argc pflag_seen outfname interactive
913 1 0 0 1
914 0 1 0 1
915 1 0 1 0
916 0 1 1 1
917 */
918
919 /* STARTUP_CHILD must be called before the signal handlers get
920 installed below as they are inherited into the spawned process.
921 Also we do not need to be protected by them as during interruption
922 in the STARTUP_CHILD mode we kill the spawned process anyway. */
923 if (!pflag_seen)
924 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926 sigemptyset(&empty_set);
927 sigemptyset(&blocked_set);
928 sa.sa_handler = SIG_IGN;
929 sigemptyset(&sa.sa_mask);
930 sa.sa_flags = 0;
931 sigaction(SIGTTOU, &sa, NULL);
932 sigaction(SIGTTIN, &sa, NULL);
933 if (interactive) {
934 sigaddset(&blocked_set, SIGHUP);
935 sigaddset(&blocked_set, SIGINT);
936 sigaddset(&blocked_set, SIGQUIT);
937 sigaddset(&blocked_set, SIGPIPE);
938 sigaddset(&blocked_set, SIGTERM);
939 sa.sa_handler = interrupt;
940#ifdef SUNOS4
941 /* POSIX signals on sunos4.1 are a little broken. */
942 sa.sa_flags = SA_INTERRUPT;
943#endif /* SUNOS4 */
944 }
945 sigaction(SIGHUP, &sa, NULL);
946 sigaction(SIGINT, &sa, NULL);
947 sigaction(SIGQUIT, &sa, NULL);
948 sigaction(SIGPIPE, &sa, NULL);
949 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000950#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 sa.sa_handler = reaper;
952 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000953#else
954 /* Make sure SIGCHLD has the default action so that waitpid
955 definitely works without losing track of children. The user
956 should not have given us a bogus state to inherit, but he might
957 have. Arguably we should detect SIG_IGN here and pass it on
958 to children, but probably noone really needs that. */
959 sa.sa_handler = SIG_DFL;
960 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000961#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000963 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +0000964 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000965
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 if (trace() < 0)
967 exit(1);
968 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000969 fflush(NULL);
970 if (exit_code > 0xff) {
971 /* Child was killed by a signal, mimic that. */
972 exit_code &= 0xff;
973 signal(exit_code, SIG_DFL);
974 raise(exit_code);
975 /* Paranoia - what if this signal is not fatal?
976 Exit with 128 + signo then. */
977 exit_code += 128;
978 }
979 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980}
981
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000982int
983expand_tcbtab()
984{
985 /* Allocate some more TCBs and expand the table.
986 We don't want to relocate the TCBs because our
987 callers have pointers and it would be a pain.
988 So tcbtab is a table of pointers. Since we never
989 free the TCBs, we allocate a single chunk of many. */
990 struct tcb **newtab = (struct tcb **)
991 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
992 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
993 sizeof *newtcbs);
994 int i;
995 if (newtab == NULL || newtcbs == NULL) {
996 if (newtab != NULL)
997 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000998 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
999 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001000 return 1;
1001 }
1002 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
1003 newtab[i] = &newtcbs[i - tcbtabsize];
1004 tcbtabsize *= 2;
1005 tcbtab = newtab;
1006
1007 return 0;
1008}
1009
1010
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001011struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001012alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013{
1014 int i;
1015 struct tcb *tcp;
1016
Roland McGrathee9d4352002-12-18 04:16:10 +00001017 for (i = 0; i < tcbtabsize; i++) {
1018 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 if ((tcp->flags & TCB_INUSE) == 0) {
1020 tcp->pid = pid;
1021 tcp->parent = NULL;
1022 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +00001023 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001024#ifdef TCB_CLONE_THREAD
1025 tcp->nclone_threads = tcp->nclone_detached = 0;
1026 tcp->nclone_waiting = 0;
1027#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 tcp->flags = TCB_INUSE | TCB_STARTUP;
1029 tcp->outf = outf; /* Initialise to current out file */
1030 tcp->stime.tv_sec = 0;
1031 tcp->stime.tv_usec = 0;
1032 tcp->pfd = -1;
1033 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001034 if (command_options_parsed)
1035 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036 return tcp;
1037 }
1038 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001039 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040 return NULL;
1041}
1042
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001043#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001044int
1045proc_open(tcp, attaching)
1046struct tcb *tcp;
1047int attaching;
1048{
1049 char proc[32];
1050 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001051#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001052 int i;
1053 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 sigset_t signals;
1055 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001056#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057#ifndef HAVE_POLLABLE_PROCFS
1058 static int last_pfd;
1059#endif
1060
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001061#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001062 /* Open the process pseudo-files in /proc. */
1063 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1064 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 perror("strace: open(\"/proc/...\", ...)");
1066 return -1;
1067 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001068 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 return -1;
1070 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001071 sprintf(proc, "/proc/%d/status", tcp->pid);
1072 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1073 perror("strace: open(\"/proc/...\", ...)");
1074 return -1;
1075 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001076 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001077 return -1;
1078 }
1079 sprintf(proc, "/proc/%d/as", tcp->pid);
1080 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1081 perror("strace: open(\"/proc/...\", ...)");
1082 return -1;
1083 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001084 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001085 return -1;
1086 }
1087#else
1088 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001089#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001090 sprintf(proc, "/proc/%d", tcp->pid);
1091 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001092#else /* FREEBSD */
1093 sprintf(proc, "/proc/%d/mem", tcp->pid);
1094 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1095#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001096 perror("strace: open(\"/proc/...\", ...)");
1097 return -1;
1098 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001099 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001100 return -1;
1101 }
1102#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001103#ifdef FREEBSD
1104 sprintf(proc, "/proc/%d/regs", tcp->pid);
1105 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1106 perror("strace: open(\"/proc/.../regs\", ...)");
1107 return -1;
1108 }
1109 if (cflag) {
1110 sprintf(proc, "/proc/%d/status", tcp->pid);
1111 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1112 perror("strace: open(\"/proc/.../status\", ...)");
1113 return -1;
1114 }
1115 } else
1116 tcp->pfd_status = -1;
1117#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001118 rebuild_pollv();
1119 if (!attaching) {
1120 /*
1121 * Wait for the child to pause. Because of a race
1122 * condition we have to poll for the event.
1123 */
1124 for (;;) {
1125 if (IOCTL_STATUS (tcp) < 0) {
1126 perror("strace: PIOCSTATUS");
1127 return -1;
1128 }
1129 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001130 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001131 }
1132 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001133#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001134 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001135 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001136 perror("strace: PIOCSTOP");
1137 return -1;
1138 }
Roland McGrath553a6092002-12-16 20:40:39 +00001139#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140#ifdef PIOCSET
1141 /* Set Run-on-Last-Close. */
1142 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001143 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 perror("PIOCSET PR_RLC");
1145 return -1;
1146 }
1147 /* Set or Reset Inherit-on-Fork. */
1148 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001149 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 perror("PIOC{SET,RESET} PR_FORK");
1151 return -1;
1152 }
1153#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001154#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1156 perror("PIOCSRLC");
1157 return -1;
1158 }
1159 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1160 perror("PIOC{S,R}FORK");
1161 return -1;
1162 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001163#else /* FREEBSD */
1164 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1165 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1166 perror("PIOCGFL");
1167 return -1;
1168 }
1169 arg &= ~PF_LINGER;
1170 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1171 perror("PIOCSFL");
1172 return -1;
1173 }
1174#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001176#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001177 /* Enable all syscall entries we care about. */
1178 premptyset(&syscalls);
1179 for (i = 1; i < MAX_QUALS; ++i) {
1180 if (i > (sizeof syscalls) * CHAR_BIT) break;
1181 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1182 }
1183 praddset (&syscalls, SYS_execve);
1184 if (followfork) {
1185 praddset (&syscalls, SYS_fork);
1186#ifdef SYS_forkall
1187 praddset (&syscalls, SYS_forkall);
1188#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001189#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001190 praddset (&syscalls, SYS_fork1);
1191#endif
1192#ifdef SYS_rfork1
1193 praddset (&syscalls, SYS_rfork1);
1194#endif
1195#ifdef SYS_rforkall
1196 praddset (&syscalls, SYS_rforkall);
1197#endif
1198 }
1199 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200 perror("PIOCSENTRY");
1201 return -1;
1202 }
John Hughes19e49982001-10-19 08:59:12 +00001203 /* Enable the syscall exits. */
1204 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 perror("PIOSEXIT");
1206 return -1;
1207 }
John Hughes19e49982001-10-19 08:59:12 +00001208 /* Enable signals we care about. */
1209 premptyset(&signals);
1210 for (i = 1; i < MAX_QUALS; ++i) {
1211 if (i > (sizeof signals) * CHAR_BIT) break;
1212 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1213 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001214 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 perror("PIOCSTRACE");
1216 return -1;
1217 }
John Hughes19e49982001-10-19 08:59:12 +00001218 /* Enable faults we care about */
1219 premptyset(&faults);
1220 for (i = 1; i < MAX_QUALS; ++i) {
1221 if (i > (sizeof faults) * CHAR_BIT) break;
1222 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1223 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001224 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225 perror("PIOCSFAULT");
1226 return -1;
1227 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001228#else /* FREEBSD */
1229 /* set events flags. */
1230 arg = S_SIG | S_SCE | S_SCX ;
1231 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1232 perror("PIOCBIS");
1233 return -1;
1234 }
1235#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 if (!attaching) {
1237#ifdef MIPS
1238 /*
1239 * The SGI PRSABORT doesn't work for pause() so
1240 * we send it a caught signal to wake it up.
1241 */
1242 kill(tcp->pid, SIGINT);
1243#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001244#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001246 arg = PRSABORT;
1247 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 perror("PIOCRUN");
1249 return -1;
1250 }
Roland McGrath553a6092002-12-16 20:40:39 +00001251#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001252#endif /* !MIPS*/
1253#ifdef FREEBSD
1254 /* wake up the child if it received the SIGSTOP */
1255 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001256#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257 for (;;) {
1258 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001259 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 perror("PIOCWSTOP");
1261 return -1;
1262 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001263 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001264 tcp->flags &= ~TCB_INSYSCALL;
1265 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001266 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267 break;
1268 }
1269 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001270#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001271 arg = 0;
1272 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001273#else /* FREEBSD */
1274 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001275#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 perror("PIOCRUN");
1277 return -1;
1278 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001279#ifdef FREEBSD
1280 /* handle the case where we "opened" the child before
1281 it did the kill -STOP */
1282 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1283 tcp->status.PR_WHAT == SIGSTOP)
1284 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001285#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001286 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001287#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001289#else /* FREEBSD */
1290 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001291 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001292 /* We are attaching to an already running process.
1293 * Try to figure out the state of the process in syscalls,
1294 * to handle the first event well.
1295 * This is done by having a look at the "wchan" property of the
1296 * process, which tells where it is stopped (if it is). */
1297 FILE * status;
1298 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001299
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001300 sprintf(proc, "/proc/%d/status", tcp->pid);
1301 status = fopen(proc, "r");
1302 if (status &&
1303 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1304 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1305 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1306 strcmp(wchan, "stopevent")) {
1307 /* The process is asleep in the middle of a syscall.
1308 Fake the syscall entry event */
1309 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1310 tcp->status.PR_WHY = PR_SYSENTRY;
1311 trace_syscall(tcp);
1312 }
1313 if (status)
1314 fclose(status);
1315 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001316 }
1317#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318#ifndef HAVE_POLLABLE_PROCFS
1319 if (proc_poll_pipe[0] != -1)
1320 proc_poller(tcp->pfd);
1321 else if (nprocs > 1) {
1322 proc_poll_open();
1323 proc_poller(last_pfd);
1324 proc_poller(tcp->pfd);
1325 }
1326 last_pfd = tcp->pfd;
1327#endif /* !HAVE_POLLABLE_PROCFS */
1328 return 0;
1329}
1330
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001331#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001333struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334pid2tcb(pid)
1335int pid;
1336{
1337 int i;
1338 struct tcb *tcp;
1339
Roland McGrathee9d4352002-12-18 04:16:10 +00001340 for (i = 0; i < tcbtabsize; i++) {
1341 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 if (pid && tcp->pid != pid)
1343 continue;
1344 if (tcp->flags & TCB_INUSE)
1345 return tcp;
1346 }
1347 return NULL;
1348}
1349
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001350#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001351
1352static struct tcb *
1353pfd2tcb(pfd)
1354int pfd;
1355{
1356 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001357
Roland McGrathca16be82003-01-10 19:55:28 +00001358 for (i = 0; i < tcbtabsize; i++) {
1359 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 if (tcp->pfd != pfd)
1361 continue;
1362 if (tcp->flags & TCB_INUSE)
1363 return tcp;
1364 }
1365 return NULL;
1366}
1367
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001368#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001369
1370void
1371droptcb(tcp)
1372struct tcb *tcp;
1373{
1374 if (tcp->pid == 0)
1375 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001376#ifdef TCB_CLONE_THREAD
1377 if (tcp->nclone_threads > 0) {
1378 /* There are other threads left in this process, but this
1379 is the one whose PID represents the whole process.
1380 We need to keep this record around as a zombie until
1381 all the threads die. */
1382 tcp->flags |= TCB_EXITING;
1383 return;
1384 }
1385#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386 nprocs--;
1387 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001388
Roland McGrathe29341c2003-01-10 20:14:20 +00001389 if (tcp->parent != NULL) {
1390 tcp->parent->nchildren--;
1391#ifdef TCB_CLONE_THREAD
1392 if (tcp->flags & TCB_CLONE_DETACHED)
1393 tcp->parent->nclone_detached--;
1394 if (tcp->flags & TCB_CLONE_THREAD)
1395 tcp->parent->nclone_threads--;
1396#endif
Roland McGrath09623452003-05-23 02:27:13 +00001397#ifdef TCB_CLONE_DETACHED
1398 if (!(tcp->flags & TCB_CLONE_DETACHED))
1399#endif
1400 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001401#ifdef LINUX
1402 /* Update `tcp->parent->parent->nchildren' and the other fields
1403 like NCLONE_DETACHED, only for zombie group leader that has
1404 already reported and been short-circuited at the top of this
1405 function. The same condition as at the top of DETACH. */
1406 if ((tcp->flags & TCB_CLONE_THREAD) &&
1407 tcp->parent->nclone_threads == 0 &&
1408 (tcp->parent->flags & TCB_EXITING))
1409 droptcb(tcp->parent);
1410#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001411 tcp->parent = NULL;
1412 }
1413
1414 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 if (tcp->pfd != -1) {
1416 close(tcp->pfd);
1417 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001418#ifdef FREEBSD
1419 if (tcp->pfd_reg != -1) {
1420 close(tcp->pfd_reg);
1421 tcp->pfd_reg = -1;
1422 }
1423 if (tcp->pfd_status != -1) {
1424 close(tcp->pfd_status);
1425 tcp->pfd_status = -1;
1426 }
Roland McGrath553a6092002-12-16 20:40:39 +00001427#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001428#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001429 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430#endif
1431 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001432
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001433 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001434 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001435
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 tcp->outf = 0;
1437}
1438
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001439#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001440
1441static int
1442resume(tcp)
1443struct tcb *tcp;
1444{
1445 if (tcp == NULL)
1446 return -1;
1447
1448 if (!(tcp->flags & TCB_SUSPENDED)) {
1449 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1450 return -1;
1451 }
1452 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001453#ifdef TCB_CLONE_THREAD
1454 if (tcp->flags & TCB_CLONE_THREAD)
1455 tcp->parent->nclone_waiting--;
1456#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001458 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460
1461 if (!qflag)
1462 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1463 return 0;
1464}
1465
Roland McGrath1bfd3102007-08-03 10:02:00 +00001466static int
1467resume_from_tcp (struct tcb *tcp)
1468{
1469 int error = 0;
1470 int resumed = 0;
1471
1472 /* XXX This won't always be quite right (but it never was).
1473 A waiter with argument 0 or < -1 is waiting for any pid in
1474 a particular pgrp, which this child might or might not be
1475 in. The waiter will only wake up if it's argument is -1
1476 or if it's waiting for tcp->pid's pgrp. It makes a
1477 difference to wake up a waiter when there might be more
1478 traced children, because it could get a false ECHILD
1479 error. OTOH, if this was the last child in the pgrp, then
1480 it ought to wake up and get ECHILD. We would have to
1481 search the system for all pid's in the pgrp to be sure.
1482
1483 && (t->waitpid == -1 ||
1484 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1485 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1486 */
1487
1488 if (tcp->parent &&
1489 (tcp->parent->flags & TCB_SUSPENDED) &&
1490 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1491 error = resume(tcp->parent);
1492 ++resumed;
1493 }
1494#ifdef TCB_CLONE_THREAD
1495 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1496 /* Some other threads of our parent are waiting too. */
1497 unsigned int i;
1498
1499 /* Resume all the threads that were waiting for this PID. */
1500 for (i = 0; i < tcbtabsize; i++) {
1501 struct tcb *t = tcbtab[i];
1502 if (t->parent == tcp->parent && t != tcp
1503 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1504 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1505 && t->waitpid == tcp->pid) {
1506 error |= resume (t);
1507 ++resumed;
1508 }
1509 }
1510 if (resumed == 0)
1511 /* Noone was waiting for this PID in particular,
1512 so now we might need to resume some wildcarders. */
1513 for (i = 0; i < tcbtabsize; i++) {
1514 struct tcb *t = tcbtab[i];
1515 if (t->parent == tcp->parent && t != tcp
1516 && ((t->flags
1517 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1518 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1519 && t->waitpid <= 0
1520 ) {
1521 error |= resume (t);
1522 break;
1523 }
1524 }
1525 }
1526
1527 return error;
1528}
1529#endif
1530
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001531#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532
Roland McGrath0a463882007-07-05 18:43:16 +00001533/* detach traced process; continue with sig
1534 Never call DETACH twice on the same process as both unattached and
1535 attached-unstopped processes give the same ESRCH. For unattached process we
1536 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537
1538static int
1539detach(tcp, sig)
1540struct tcb *tcp;
1541int sig;
1542{
1543 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001544#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001545 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001546 struct tcb *zombie = NULL;
1547
1548 /* If the group leader is lingering only because of this other
1549 thread now dying, then detach the leader as well. */
1550 if ((tcp->flags & TCB_CLONE_THREAD) &&
1551 tcp->parent->nclone_threads == 1 &&
1552 (tcp->parent->flags & TCB_EXITING))
1553 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001554#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555
1556 if (tcp->flags & TCB_BPTSET)
1557 sig = SIGKILL;
1558
1559#ifdef LINUX
1560 /*
1561 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001562 * before detaching. Arghh. We go through hoops
1563 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001565#if defined(SPARC)
1566#undef PTRACE_DETACH
1567#define PTRACE_DETACH PTRACE_SUNDETACH
1568#endif
Roland McGrath02203312007-06-11 22:06:31 +00001569 /*
1570 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1571 * expected SIGSTOP. We must catch exactly one as otherwise the
1572 * detached process would be left stopped (process state T).
1573 */
1574 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1576 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001577 }
1578 else if (errno != ESRCH) {
1579 /* Shouldn't happen. */
1580 perror("detach: ptrace(PTRACE_DETACH, ...)");
1581 }
Roland McGrath134813a2007-06-02 00:07:33 +00001582 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1583 : tcp->pid),
1584 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001585 if (errno != ESRCH)
1586 perror("detach: checking sanity");
1587 }
Roland McGrath02203312007-06-11 22:06:31 +00001588 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1589 ? tcp->parent->pid : tcp->pid),
1590 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001591 if (errno != ESRCH)
1592 perror("detach: stopping child");
1593 }
Roland McGrath02203312007-06-11 22:06:31 +00001594 else
1595 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001596 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001598#ifdef __WALL
1599 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1600 if (errno == ECHILD) /* Already gone. */
1601 break;
1602 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001603 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001604 break;
1605 }
1606#endif /* __WALL */
1607 /* No __WALL here. */
1608 if (waitpid(tcp->pid, &status, 0) < 0) {
1609 if (errno != ECHILD) {
1610 perror("detach: waiting");
1611 break;
1612 }
1613#ifdef __WCLONE
1614 /* If no processes, try clones. */
1615 if (wait4(tcp->pid, &status, __WCLONE,
1616 NULL) < 0) {
1617 if (errno != ECHILD)
1618 perror("detach: waiting");
1619 break;
1620 }
1621#endif /* __WCLONE */
1622 }
1623#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001624 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001625#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626 if (!WIFSTOPPED(status)) {
1627 /* Au revoir, mon ami. */
1628 break;
1629 }
1630 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001631 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632 break;
1633 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001634 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko96d5a762008-12-29 19:13:27 +00001635 WSTOPSIG(status) == ptrace_stop_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001636 : WSTOPSIG(status));
1637 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001640 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001641#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642
1643#if defined(SUNOS4)
1644 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1645 if (sig && kill(tcp->pid, sig) < 0)
1646 perror("detach: kill");
1647 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001648 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649#endif /* SUNOS4 */
1650
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001651#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001652 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001653#endif
1654
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655 if (!qflag)
1656 fprintf(stderr, "Process %u detached\n", tcp->pid);
1657
1658 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001659
1660#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001661 if (zombie != NULL) {
1662 /* TCP no longer exists therefore you must not detach () it. */
1663 droptcb(zombie);
1664 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001665#endif
1666
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667 return error;
1668}
1669
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001670#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671
1672static void
1673reaper(sig)
1674int sig;
1675{
1676 int pid;
1677 int status;
1678
1679 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1680#if 0
1681 struct tcb *tcp;
1682
1683 tcp = pid2tcb(pid);
1684 if (tcp)
1685 droptcb(tcp);
1686#endif
1687 }
1688}
1689
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001690#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691
1692static void
1693cleanup()
1694{
1695 int i;
1696 struct tcb *tcp;
1697
Roland McGrathee9d4352002-12-18 04:16:10 +00001698 for (i = 0; i < tcbtabsize; i++) {
1699 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700 if (!(tcp->flags & TCB_INUSE))
1701 continue;
1702 if (debug)
1703 fprintf(stderr,
1704 "cleanup: looking at pid %u\n", tcp->pid);
1705 if (tcp_last &&
1706 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001707 tprintf(" <unfinished ...>");
1708 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709 }
1710 if (tcp->flags & TCB_ATTACHED)
1711 detach(tcp, 0);
1712 else {
1713 kill(tcp->pid, SIGCONT);
1714 kill(tcp->pid, SIGTERM);
1715 }
1716 }
1717 if (cflag)
1718 call_summary(outf);
1719}
1720
1721static void
1722interrupt(sig)
1723int sig;
1724{
1725 interrupted = 1;
1726}
1727
1728#ifndef HAVE_STRERROR
1729
Roland McGrath6d2b3492002-12-30 00:51:30 +00001730#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731extern int sys_nerr;
1732extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001733#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734
1735const char *
1736strerror(errno)
1737int errno;
1738{
1739 static char buf[64];
1740
1741 if (errno < 1 || errno >= sys_nerr) {
1742 sprintf(buf, "Unknown error %d", errno);
1743 return buf;
1744 }
1745 return sys_errlist[errno];
1746}
1747
1748#endif /* HAVE_STERRROR */
1749
1750#ifndef HAVE_STRSIGNAL
1751
Roland McGrath8f474e02003-01-14 07:53:33 +00001752#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001753extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001755#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1756extern char *_sys_siglist[];
1757#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
1759const char *
1760strsignal(sig)
1761int sig;
1762{
1763 static char buf[64];
1764
1765 if (sig < 1 || sig >= NSIG) {
1766 sprintf(buf, "Unknown signal %d", sig);
1767 return buf;
1768 }
1769#ifdef HAVE__SYS_SIGLIST
1770 return _sys_siglist[sig];
1771#else
1772 return sys_siglist[sig];
1773#endif
1774}
1775
1776#endif /* HAVE_STRSIGNAL */
1777
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001778#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779
1780static void
1781rebuild_pollv()
1782{
1783 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784
Roland McGrathee9d4352002-12-18 04:16:10 +00001785 if (pollv != NULL)
1786 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001787 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001788 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001789 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001790 exit(1);
1791 }
1792
Roland McGrathca16be82003-01-10 19:55:28 +00001793 for (i = j = 0; i < tcbtabsize; i++) {
1794 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 if (!(tcp->flags & TCB_INUSE))
1796 continue;
1797 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001798 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799 j++;
1800 }
1801 if (j != nprocs) {
1802 fprintf(stderr, "strace: proc miscount\n");
1803 exit(1);
1804 }
1805}
1806
1807#ifndef HAVE_POLLABLE_PROCFS
1808
1809static void
1810proc_poll_open()
1811{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812 int i;
1813
1814 if (pipe(proc_poll_pipe) < 0) {
1815 perror("pipe");
1816 exit(1);
1817 }
1818 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001819 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820 exit(1);
1821 }
1822 }
1823}
1824
1825static int
1826proc_poll(pollv, nfds, timeout)
1827struct pollfd *pollv;
1828int nfds;
1829int timeout;
1830{
1831 int i;
1832 int n;
1833 struct proc_pollfd pollinfo;
1834
1835 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1836 return n;
1837 if (n != sizeof(struct proc_pollfd)) {
1838 fprintf(stderr, "panic: short read: %d\n", n);
1839 exit(1);
1840 }
1841 for (i = 0; i < nprocs; i++) {
1842 if (pollv[i].fd == pollinfo.fd)
1843 pollv[i].revents = pollinfo.revents;
1844 else
1845 pollv[i].revents = 0;
1846 }
1847 poller_pid = pollinfo.pid;
1848 return 1;
1849}
1850
1851static void
1852wakeup_handler(sig)
1853int sig;
1854{
1855}
1856
1857static void
1858proc_poller(pfd)
1859int pfd;
1860{
1861 struct proc_pollfd pollinfo;
1862 struct sigaction sa;
1863 sigset_t blocked_set, empty_set;
1864 int i;
1865 int n;
1866 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001867#ifdef FREEBSD
1868 struct procfs_status pfs;
1869#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870
1871 switch (fork()) {
1872 case -1:
1873 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001874 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875 case 0:
1876 break;
1877 default:
1878 return;
1879 }
1880
1881 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1882 sa.sa_flags = 0;
1883 sigemptyset(&sa.sa_mask);
1884 sigaction(SIGHUP, &sa, NULL);
1885 sigaction(SIGINT, &sa, NULL);
1886 sigaction(SIGQUIT, &sa, NULL);
1887 sigaction(SIGPIPE, &sa, NULL);
1888 sigaction(SIGTERM, &sa, NULL);
1889 sa.sa_handler = wakeup_handler;
1890 sigaction(SIGUSR1, &sa, NULL);
1891 sigemptyset(&blocked_set);
1892 sigaddset(&blocked_set, SIGUSR1);
1893 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1894 sigemptyset(&empty_set);
1895
1896 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1897 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001898 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 }
1900 n = rl.rlim_cur;
1901 for (i = 0; i < n; i++) {
1902 if (i != pfd && i != proc_poll_pipe[1])
1903 close(i);
1904 }
1905
1906 pollinfo.fd = pfd;
1907 pollinfo.pid = getpid();
1908 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001909#ifndef FREEBSD
1910 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1911#else /* FREEBSD */
1912 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1913#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001914 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001915 switch (errno) {
1916 case EINTR:
1917 continue;
1918 case EBADF:
1919 pollinfo.revents = POLLERR;
1920 break;
1921 case ENOENT:
1922 pollinfo.revents = POLLHUP;
1923 break;
1924 default:
1925 perror("proc_poller: PIOCWSTOP");
1926 }
1927 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1928 _exit(0);
1929 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001930 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1932 sigsuspend(&empty_set);
1933 }
1934}
1935
1936#endif /* !HAVE_POLLABLE_PROCFS */
1937
1938static int
1939choose_pfd()
1940{
1941 int i, j;
1942 struct tcb *tcp;
1943
1944 static int last;
1945
1946 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001947 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948 /*
1949 * The previous process is ready to run again. We'll
1950 * let it do so if it is currently in a syscall. This
1951 * heuristic improves the readability of the trace.
1952 */
1953 tcp = pfd2tcb(pollv[last].fd);
1954 if (tcp && (tcp->flags & TCB_INSYSCALL))
1955 return pollv[last].fd;
1956 }
1957
1958 for (i = 0; i < nprocs; i++) {
1959 /* Let competing children run round robin. */
1960 j = (i + last + 1) % nprocs;
1961 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1962 tcp = pfd2tcb(pollv[j].fd);
1963 if (!tcp) {
1964 fprintf(stderr, "strace: lost proc\n");
1965 exit(1);
1966 }
1967 droptcb(tcp);
1968 return -1;
1969 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001970 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971 last = j;
1972 return pollv[j].fd;
1973 }
1974 }
1975 fprintf(stderr, "strace: nothing ready\n");
1976 exit(1);
1977}
1978
1979static int
1980trace()
1981{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001982#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001983 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001984#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001985 struct tcb *tcp;
1986 int pfd;
1987 int what;
1988 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001989 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001990
1991 for (;;) {
1992 if (interactive)
1993 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1994
1995 if (nprocs == 0)
1996 break;
1997
1998 switch (nprocs) {
1999 case 1:
2000#ifndef HAVE_POLLABLE_PROCFS
2001 if (proc_poll_pipe[0] == -1) {
2002#endif
2003 tcp = pid2tcb(0);
2004 if (!tcp)
2005 continue;
2006 pfd = tcp->pfd;
2007 if (pfd == -1)
2008 continue;
2009 break;
2010#ifndef HAVE_POLLABLE_PROCFS
2011 }
2012 /* fall through ... */
2013#endif /* !HAVE_POLLABLE_PROCFS */
2014 default:
2015#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002016#ifdef POLL_HACK
2017 /* On some systems (e.g. UnixWare) we get too much ugly
2018 "unfinished..." stuff when multiple proceses are in
2019 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002020
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002021 if (in_syscall) {
2022 struct pollfd pv;
2023 tcp = in_syscall;
2024 in_syscall = NULL;
2025 pv.fd = tcp->pfd;
2026 pv.events = POLLWANT;
2027 if ((what = poll (&pv, 1, 1)) < 0) {
2028 if (interrupted)
2029 return 0;
2030 continue;
2031 }
2032 else if (what == 1 && pv.revents & POLLWANT) {
2033 goto FOUND;
2034 }
2035 }
2036#endif
2037
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038 if (poll(pollv, nprocs, INFTIM) < 0) {
2039 if (interrupted)
2040 return 0;
2041 continue;
2042 }
2043#else /* !HAVE_POLLABLE_PROCFS */
2044 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2045 if (interrupted)
2046 return 0;
2047 continue;
2048 }
2049#endif /* !HAVE_POLLABLE_PROCFS */
2050 pfd = choose_pfd();
2051 if (pfd == -1)
2052 continue;
2053 break;
2054 }
2055
2056 /* Look up `pfd' in our table. */
2057 if ((tcp = pfd2tcb(pfd)) == NULL) {
2058 fprintf(stderr, "unknown pfd: %u\n", pfd);
2059 exit(1);
2060 }
John Hughesb6643082002-05-23 11:02:22 +00002061#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002062 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002063#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002064 /* Get the status of the process. */
2065 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002066#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002067 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002068#else /* FREEBSD */
2069 /* Thanks to some scheduling mystery, the first poller
2070 sometimes waits for the already processed end of fork
2071 event. Doing a non blocking poll here solves the problem. */
2072 if (proc_poll_pipe[0] != -1)
2073 ioctl_result = IOCTL_STATUS (tcp);
2074 else
2075 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002076#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002077 ioctl_errno = errno;
2078#ifndef HAVE_POLLABLE_PROCFS
2079 if (proc_poll_pipe[0] != -1) {
2080 if (ioctl_result < 0)
2081 kill(poller_pid, SIGKILL);
2082 else
2083 kill(poller_pid, SIGUSR1);
2084 }
2085#endif /* !HAVE_POLLABLE_PROCFS */
2086 }
2087 if (interrupted)
2088 return 0;
2089
2090 if (interactive)
2091 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2092
2093 if (ioctl_result < 0) {
2094 /* Find out what happened if it failed. */
2095 switch (ioctl_errno) {
2096 case EINTR:
2097 case EBADF:
2098 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002099#ifdef FREEBSD
2100 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002101#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002102 case ENOENT:
2103 droptcb(tcp);
2104 continue;
2105 default:
2106 perror("PIOCWSTOP");
2107 exit(1);
2108 }
2109 }
2110
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002111#ifdef FREEBSD
2112 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2113 /* discard first event for a syscall we never entered */
2114 IOCTL (tcp->pfd, PIOCRUN, 0);
2115 continue;
2116 }
Roland McGrath553a6092002-12-16 20:40:39 +00002117#endif
2118
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002119 /* clear the just started flag */
2120 tcp->flags &= ~TCB_STARTUP;
2121
2122 /* set current output file */
2123 outf = tcp->outf;
2124
2125 if (cflag) {
2126 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002127#ifdef FREEBSD
2128 char buf[1024];
2129 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002131 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2132 buf[len] = '\0';
2133 sscanf(buf,
2134 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2135 &stime.tv_sec, &stime.tv_usec);
2136 } else
2137 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002138#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2140 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002141#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2143 tcp->stime = stime;
2144 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002145 what = tcp->status.PR_WHAT;
2146 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002147#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002149 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2150 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002151 if (trace_syscall(tcp) < 0) {
2152 fprintf(stderr, "syscall trouble\n");
2153 exit(1);
2154 }
2155 }
2156 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002157#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002158 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002159#ifdef POLL_HACK
2160 in_syscall = tcp;
2161#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002162 case PR_SYSEXIT:
2163 if (trace_syscall(tcp) < 0) {
2164 fprintf(stderr, "syscall trouble\n");
2165 exit(1);
2166 }
2167 break;
2168 case PR_SIGNALLED:
2169 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2170 printleader(tcp);
2171 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002172 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002173 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002174#ifdef PR_INFO
2175 if (tcp->status.PR_INFO.si_signo == what) {
2176 printleader(tcp);
2177 tprintf(" siginfo=");
2178 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002179 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002180 }
2181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182 }
2183 break;
2184 case PR_FAULTED:
2185 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2186 printleader(tcp);
2187 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002188 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 }
2190 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002191#ifdef FREEBSD
2192 case 0: /* handle case we polled for nothing */
2193 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002194#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002196 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 exit(1);
2198 break;
2199 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002200 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002201#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002202 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002203#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002204 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002205#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002206 perror("PIOCRUN");
2207 exit(1);
2208 }
2209 }
2210 return 0;
2211}
2212
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002213#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002214
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002215#ifdef TCB_GROUP_EXITING
2216/* Handle an exit detach or death signal that is taking all the
2217 related clone threads with it. This is called in three circumstances:
2218 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2219 SIG == 0 Continuing TCP will perform an exit_group syscall.
2220 SIG == other Continuing TCP with SIG will kill the process.
2221*/
2222static int
2223handle_group_exit(struct tcb *tcp, int sig)
2224{
2225 /* We need to locate our records of all the clone threads
2226 related to TCP, either its children or siblings. */
2227 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2228 ? tcp->parent
2229 : tcp->nclone_detached > 0
2230 ? tcp : NULL);
2231
2232 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002233 if (leader != NULL && leader != tcp &&
2234 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002235 fprintf(stderr,
2236 "PANIC: handle_group_exit: %d leader %d\n",
2237 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002238 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002239#ifndef USE_PROCFS
2240 resume_from_tcp (tcp);
2241#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002242 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002243 }
2244 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002245 /* Mark that we are taking the process down. */
2246 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002247 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002248 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002249 if (leader != NULL && leader != tcp)
2250 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002251 } else {
2252 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2253 cleanup();
2254 return -1;
2255 }
2256 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002257 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002258 if (leader != tcp)
2259 droptcb(tcp);
2260 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002261 /* The leader will report to us as parent now,
2262 and then we'll get to the SIG==-1 case. */
2263 return 0;
2264 }
2265 }
2266
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002267 return 0;
2268}
2269#endif
2270
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002271static int
2272trace()
2273{
2274 int pid;
2275 int wait_errno;
2276 int status;
2277 struct tcb *tcp;
2278#ifdef LINUX
2279 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002280#ifdef __WALL
2281 static int wait4_options = __WALL;
2282#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002283#endif /* LINUX */
2284
2285 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002286 if (interrupted)
2287 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288 if (interactive)
2289 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2290#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002291#ifdef __WALL
2292 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002293 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002294 /* this kernel does not support __WALL */
2295 wait4_options &= ~__WALL;
2296 errno = 0;
2297 pid = wait4(-1, &status, wait4_options,
2298 cflag ? &ru : NULL);
2299 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002300 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002301 /* most likely a "cloned" process */
2302 pid = wait4(-1, &status, __WCLONE,
2303 cflag ? &ru : NULL);
2304 if (pid == -1) {
2305 fprintf(stderr, "strace: clone wait4 "
2306 "failed: %s\n", strerror(errno));
2307 }
2308 }
2309#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002310 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002311#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312#endif /* LINUX */
2313#ifdef SUNOS4
2314 pid = wait(&status);
2315#endif /* SUNOS4 */
2316 wait_errno = errno;
2317 if (interactive)
2318 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2319
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002320 if (pid == -1) {
2321 switch (wait_errno) {
2322 case EINTR:
2323 continue;
2324 case ECHILD:
2325 /*
2326 * We would like to verify this case
2327 * but sometimes a race in Solbourne's
2328 * version of SunOS sometimes reports
2329 * ECHILD before sending us SIGCHILD.
2330 */
2331#if 0
2332 if (nprocs == 0)
2333 return 0;
2334 fprintf(stderr, "strace: proc miscount\n");
2335 exit(1);
2336#endif
2337 return 0;
2338 default:
2339 errno = wait_errno;
2340 perror("strace: wait");
2341 return -1;
2342 }
2343 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002344 if (pid == popen_pid) {
2345 if (WIFEXITED(status) || WIFSIGNALED(status))
2346 popen_pid = -1;
2347 continue;
2348 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002349 if (debug)
2350 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2351
2352 /* Look up `pid' in our table. */
2353 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002354#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002355 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002356 /* This is needed to go with the CLONE_PTRACE
2357 changes in process.c/util.c: we might see
2358 the child's initial trap before we see the
2359 parent return from the clone syscall.
2360 Leave the child suspended until the parent
2361 returns from its system call. Only then
2362 will we have the association of parent and
2363 child so that we know how to do clearbpt
2364 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002365 if (nprocs == tcbtabsize &&
2366 expand_tcbtab())
2367 tcp = NULL;
2368 else
2369 tcp = alloctcb(pid);
2370 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002371 kill(pid, SIGKILL); /* XXX */
2372 return 0;
2373 }
2374 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002375 if (!qflag)
2376 fprintf(stderr, "\
2377Process %d attached (waiting for parent)\n",
2378 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002379 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002380 else
2381 /* This can happen if a clone call used
2382 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002383#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002384 {
2385 fprintf(stderr, "unknown pid: %u\n", pid);
2386 if (WIFSTOPPED(status))
2387 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2388 exit(1);
2389 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002390 }
2391 /* set current output file */
2392 outf = tcp->outf;
2393 if (cflag) {
2394#ifdef LINUX
2395 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2396 tcp->stime = ru.ru_stime;
2397#endif /* !LINUX */
2398 }
2399
2400 if (tcp->flags & TCB_SUSPENDED) {
2401 /*
2402 * Apparently, doing any ptrace() call on a stopped
2403 * process, provokes the kernel to report the process
2404 * status again on a subsequent wait(), even if the
2405 * process has not been actually restarted.
2406 * Since we have inspected the arguments of suspended
2407 * processes we end up here testing for this case.
2408 */
2409 continue;
2410 }
2411 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002412 if (pid == strace_child)
2413 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002414 if (!cflag
2415 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2416 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002417 tprintf("+++ killed by %s %s+++",
2418 signame(WTERMSIG(status)),
2419#ifdef WCOREDUMP
2420 WCOREDUMP(status) ? "(core dumped) " :
2421#endif
2422 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002423 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002424 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002425#ifdef TCB_GROUP_EXITING
2426 handle_group_exit(tcp, -1);
2427#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002428 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002429#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002430 continue;
2431 }
2432 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002433 if (pid == strace_child)
2434 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002435 if (debug)
2436 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002437 if ((tcp->flags & TCB_ATTACHED)
2438#ifdef TCB_GROUP_EXITING
2439 && !(tcp->parent && (tcp->parent->flags &
2440 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002441 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002442#endif
2443 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444 fprintf(stderr,
2445 "PANIC: attached pid %u exited\n",
2446 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002447 if (tcp == tcp_last) {
2448 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2449 == TCB_INSYSCALL)
2450 tprintf(" <unfinished ... exit status %d>\n",
2451 WEXITSTATUS(status));
2452 tcp_last = NULL;
2453 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002454#ifdef TCB_GROUP_EXITING
2455 handle_group_exit(tcp, -1);
2456#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002457 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002458#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002459 continue;
2460 }
2461 if (!WIFSTOPPED(status)) {
2462 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2463 droptcb(tcp);
2464 continue;
2465 }
2466 if (debug)
2467 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002468 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002469
Roland McGrath02203312007-06-11 22:06:31 +00002470 /*
2471 * Interestingly, the process may stop
2472 * with STOPSIG equal to some other signal
2473 * than SIGSTOP if we happend to attach
2474 * just before the process takes a signal.
2475 */
2476 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002477 /*
2478 * This flag is there to keep us in sync.
2479 * Next time this process stops it should
2480 * really be entering a system call.
2481 */
2482 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002483 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002484 /*
2485 * One example is a breakpoint inherited from
2486 * parent through fork ().
2487 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2489 droptcb(tcp);
2490 cleanup();
2491 return -1;
2492 }
2493 }
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002494/* Add more OSes after you verified it works for them. */
Denys Vlasenko0861ecb2009-01-02 16:55:24 +00002495/* PTRACE_SETOPTIONS is not a #define. PT_SETOPTIONS is. */
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002496#if defined LINUX && defined PT_SETOPTIONS
Denys Vlasenko0861ecb2009-01-02 16:55:24 +00002497# ifndef PTRACE_O_TRACESYSGOOD
2498# define PTRACE_O_TRACESYSGOOD 0x00000001
2499# endif
2500# ifndef PTRACE_O_TRACEEXEC
2501# define PTRACE_O_TRACEEXEC 0x00000010
2502# endif
2503# ifndef PTRACE_EVENT_EXEC
2504# define PTRACE_EVENT_EXEC 4
2505# endif
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002506 /*
2507 * Ask kernel to set signo to SIGTRAP | 0x80
2508 * on ptrace-generated SIGTRAPs, and mark
2509 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
2510 */
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002511 if (!ptrace_opts_set) {
2512 ptrace_opts_set = 1;
2513 /*
2514 * NB: even if this "succeeds", we can
2515 * revert back to SIGTRAP if we later see
2516 * that it didnt really work.
2517 * Old kernels are known to lie here.
2518 */
2519 if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
2520 (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
2521 ptrace_stop_sig = SIGTRAP | 0x80;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002522 }
2523#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002524 goto tracing;
2525 }
2526
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002527#if defined LINUX && defined PT_SETOPTIONS
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002528 if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002529 /*
2530 * We told ptrace to report SIGTRAP | 0x80 on this process
2531 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
2532 * kill(pid, SIGTRAP), trap insn, etc;
2533 * but be paranoid about it.
2534 */
2535 if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
2536 /* It's post-exec ptrace stop. */
2537 /* Set WSTOPSIG(status) = (SIGTRAP | 0x80). */
2538 status |= 0x8000;
2539 } else {
2540 /* Take a better look... */
2541 siginfo_t si;
2542 ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
2543 /*
2544 * Check some fields to make sure we see
2545 * real SIGTRAP.
2546 * Otherwise interpret it as ptrace stop.
2547 * Real SIGTRAPs (int3 insn on x86, kill() etc)
2548 * have these values:
2549 * int3: kill -TRAP $pid:
2550 * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
2551 * si_errno:0 si_errno:(?)
2552 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
2553 * si_pid:0 si_pid:(>0?)
2554 * si_band:0 si_band:(?)
2555 * Ptrace stops have garbage there instead.
2556 */
2557 if (si.si_signo != SIGTRAP
2558 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
2559 ) {
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002560 fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
2561 ptrace_stop_sig = SIGTRAP;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002562 }
2563 }
2564 }
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002565#endif
2566
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002567 if (WSTOPSIG(status) != ptrace_stop_sig) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002568 /* This isn't a ptrace stop. */
2569
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002570 if (WSTOPSIG(status) == SIGSTOP &&
2571 (tcp->flags & TCB_SIGTRAPPED)) {
2572 /*
2573 * Trapped attempt to block SIGTRAP
2574 * Hope we are back in control now.
2575 */
2576 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002577 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002578 cleanup();
2579 return -1;
2580 }
2581 continue;
2582 }
2583 if (!cflag
2584 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002585 unsigned long addr = 0;
2586 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002587#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002588# define PSR_RI 41
2589 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002590 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002591
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002592 upeek(tcp, PT_CR_IPSR, &psr);
2593 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002594
2595 pc += (psr >> PSR_RI) & 0x3;
2596 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2597 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002598#elif defined PTRACE_GETSIGINFO
2599 if (WSTOPSIG(status) == SIGSEGV ||
2600 WSTOPSIG(status) == SIGBUS) {
2601 siginfo_t si;
2602 if (ptrace(PTRACE_GETSIGINFO, pid,
2603 0, &si) == 0)
2604 addr = (unsigned long)
2605 si.si_addr;
2606 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002607#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002608 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002609 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002610 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002611 strsignal(WSTOPSIG(status)), pc, addr);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002612 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613 }
Roland McGrath05690952004-10-20 01:00:27 +00002614 if (((tcp->flags & TCB_ATTACHED) ||
2615 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002616 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002617#ifdef TCB_GROUP_EXITING
2618 handle_group_exit(tcp, WSTOPSIG(status));
2619#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002620 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002621#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002622 continue;
2623 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002624 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002625 cleanup();
2626 return -1;
2627 }
2628 tcp->flags &= ~TCB_SUSPENDED;
2629 continue;
2630 }
Roland McGrath02203312007-06-11 22:06:31 +00002631 /* we handled the STATUS, we are permitted to interrupt now. */
2632 if (interrupted)
2633 return 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002634 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002635 /* ptrace() failed in trace_syscall() with ESRCH.
2636 * Likely a result of process disappearing mid-flight.
2637 * Observed case: exit_group() terminating
2638 * all processes in thread group. In this case, threads
2639 * "disappear" in an unpredictable moment without any
2640 * notification to strace via wait().
2641 */
2642 if (tcp->flags & TCB_ATTACHED) {
2643 if (tcp_last) {
2644 /* Do we have dangling line "syscall(param, param"?
2645 * Finish the line then. We cannot
2646 */
2647 tcp_last->flags |= TCB_REPRINT;
2648 tprintf(" <unfinished ...>");
2649 printtrailer();
2650 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002651 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002652 } else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002653 ptrace(PTRACE_KILL,
2654 tcp->pid, (char *) 1, SIGTERM);
2655 droptcb(tcp);
2656 }
2657 continue;
2658 }
2659 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002660#ifdef TCB_GROUP_EXITING
2661 if (tcp->flags & TCB_GROUP_EXITING) {
2662 if (handle_group_exit(tcp, 0) < 0)
2663 return -1;
2664 continue;
2665 }
2666#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002667 if (tcp->flags & TCB_ATTACHED)
2668 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002669 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002670 cleanup();
2671 return -1;
2672 }
2673 continue;
2674 }
2675 if (tcp->flags & TCB_SUSPENDED) {
2676 if (!qflag)
2677 fprintf(stderr, "Process %u suspended\n", pid);
2678 continue;
2679 }
2680 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002681 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002682 cleanup();
2683 return -1;
2684 }
2685 }
2686 return 0;
2687}
2688
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002689#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002690
2691static int curcol;
2692
2693#ifdef __STDC__
2694#include <stdarg.h>
2695#define VA_START(a, b) va_start(a, b)
2696#else
2697#include <varargs.h>
2698#define VA_START(a, b) va_start(a)
2699#endif
2700
2701void
2702#ifdef __STDC__
2703tprintf(const char *fmt, ...)
2704#else
2705tprintf(fmt, va_alist)
2706char *fmt;
2707va_dcl
2708#endif
2709{
2710 va_list args;
2711
2712 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002713 if (outf) {
2714 int n = vfprintf(outf, fmt, args);
2715 if (n < 0 && outf != stderr)
2716 perror(outfname == NULL
2717 ? "<writing to pipe>" : outfname);
2718 else
2719 curcol += n;
2720 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002721 va_end(args);
2722 return;
2723}
2724
2725void
2726printleader(tcp)
2727struct tcb *tcp;
2728{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002729 if (tcp_last) {
2730 if (tcp_last->ptrace_errno) {
2731 if (tcp_last->flags & TCB_INSYSCALL) {
2732 tprintf(" <unavailable>)");
2733 tabto(acolumn);
2734 }
2735 tprintf("= ? <unavailable>\n");
2736 tcp_last->ptrace_errno = 0;
2737 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
2738 tcp_last->flags |= TCB_REPRINT;
2739 tprintf(" <unfinished ...>\n");
2740 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002741 }
2742 curcol = 0;
2743 if ((followfork == 1 || pflag_seen > 1) && outfname)
2744 tprintf("%-5d ", tcp->pid);
2745 else if (nprocs > 1 && !outfname)
2746 tprintf("[pid %5u] ", tcp->pid);
2747 if (tflag) {
2748 char str[sizeof("HH:MM:SS")];
2749 struct timeval tv, dtv;
2750 static struct timeval otv;
2751
2752 gettimeofday(&tv, NULL);
2753 if (rflag) {
2754 if (otv.tv_sec == 0)
2755 otv = tv;
2756 tv_sub(&dtv, &tv, &otv);
2757 tprintf("%6ld.%06ld ",
2758 (long) dtv.tv_sec, (long) dtv.tv_usec);
2759 otv = tv;
2760 }
2761 else if (tflag > 2) {
2762 tprintf("%ld.%06ld ",
2763 (long) tv.tv_sec, (long) tv.tv_usec);
2764 }
2765 else {
2766 time_t local = tv.tv_sec;
2767 strftime(str, sizeof(str), "%T", localtime(&local));
2768 if (tflag > 1)
2769 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2770 else
2771 tprintf("%s ", str);
2772 }
2773 }
2774 if (iflag)
2775 printcall(tcp);
2776}
2777
2778void
2779tabto(col)
2780int col;
2781{
2782 if (curcol < col)
2783 tprintf("%*s", col - curcol, "");
2784}
2785
2786void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002787printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002788{
2789 tprintf("\n");
2790 tcp_last = NULL;
2791}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002792
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002793#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002794
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002795int
2796mp_ioctl(int fd, int cmd, void *arg, int size)
2797{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002798 struct iovec iov[2];
2799 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002800
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002801 iov[0].iov_base = &cmd;
2802 iov[0].iov_len = sizeof cmd;
2803 if (arg) {
2804 ++n;
2805 iov[1].iov_base = arg;
2806 iov[1].iov_len = size;
2807 }
Roland McGrath553a6092002-12-16 20:40:39 +00002808
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002809 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002810}
2811
2812#endif