blob: 5c483fe6076ccd334a8225923c7b4ac15371a214 [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;
1596 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 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001640#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001641
1642#if defined(SUNOS4)
1643 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1644 if (sig && kill(tcp->pid, sig) < 0)
1645 perror("detach: kill");
1646 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001647 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648#endif /* SUNOS4 */
1649
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001650#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001651 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001652#endif
1653
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 if (!qflag)
1655 fprintf(stderr, "Process %u detached\n", tcp->pid);
1656
1657 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001658
1659#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001660 if (zombie != NULL) {
1661 /* TCP no longer exists therefore you must not detach () it. */
1662 droptcb(zombie);
1663 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001664#endif
1665
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666 return error;
1667}
1668
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001669#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670
1671static void
1672reaper(sig)
1673int sig;
1674{
1675 int pid;
1676 int status;
1677
1678 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1679#if 0
1680 struct tcb *tcp;
1681
1682 tcp = pid2tcb(pid);
1683 if (tcp)
1684 droptcb(tcp);
1685#endif
1686 }
1687}
1688
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001689#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690
1691static void
1692cleanup()
1693{
1694 int i;
1695 struct tcb *tcp;
1696
Roland McGrathee9d4352002-12-18 04:16:10 +00001697 for (i = 0; i < tcbtabsize; i++) {
1698 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699 if (!(tcp->flags & TCB_INUSE))
1700 continue;
1701 if (debug)
1702 fprintf(stderr,
1703 "cleanup: looking at pid %u\n", tcp->pid);
1704 if (tcp_last &&
1705 (!outfname || followfork < 2 || tcp_last == tcp)) {
1706 tprintf(" <unfinished ...>\n");
1707 tcp_last = NULL;
1708 }
1709 if (tcp->flags & TCB_ATTACHED)
1710 detach(tcp, 0);
1711 else {
1712 kill(tcp->pid, SIGCONT);
1713 kill(tcp->pid, SIGTERM);
1714 }
1715 }
1716 if (cflag)
1717 call_summary(outf);
1718}
1719
1720static void
1721interrupt(sig)
1722int sig;
1723{
1724 interrupted = 1;
1725}
1726
1727#ifndef HAVE_STRERROR
1728
Roland McGrath6d2b3492002-12-30 00:51:30 +00001729#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730extern int sys_nerr;
1731extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001732#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001733
1734const char *
1735strerror(errno)
1736int errno;
1737{
1738 static char buf[64];
1739
1740 if (errno < 1 || errno >= sys_nerr) {
1741 sprintf(buf, "Unknown error %d", errno);
1742 return buf;
1743 }
1744 return sys_errlist[errno];
1745}
1746
1747#endif /* HAVE_STERRROR */
1748
1749#ifndef HAVE_STRSIGNAL
1750
Roland McGrath8f474e02003-01-14 07:53:33 +00001751#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001752extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001754#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1755extern char *_sys_siglist[];
1756#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757
1758const char *
1759strsignal(sig)
1760int sig;
1761{
1762 static char buf[64];
1763
1764 if (sig < 1 || sig >= NSIG) {
1765 sprintf(buf, "Unknown signal %d", sig);
1766 return buf;
1767 }
1768#ifdef HAVE__SYS_SIGLIST
1769 return _sys_siglist[sig];
1770#else
1771 return sys_siglist[sig];
1772#endif
1773}
1774
1775#endif /* HAVE_STRSIGNAL */
1776
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001777#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778
1779static void
1780rebuild_pollv()
1781{
1782 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783
Roland McGrathee9d4352002-12-18 04:16:10 +00001784 if (pollv != NULL)
1785 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001786 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001787 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001788 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001789 exit(1);
1790 }
1791
Roland McGrathca16be82003-01-10 19:55:28 +00001792 for (i = j = 0; i < tcbtabsize; i++) {
1793 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 if (!(tcp->flags & TCB_INUSE))
1795 continue;
1796 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001797 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798 j++;
1799 }
1800 if (j != nprocs) {
1801 fprintf(stderr, "strace: proc miscount\n");
1802 exit(1);
1803 }
1804}
1805
1806#ifndef HAVE_POLLABLE_PROCFS
1807
1808static void
1809proc_poll_open()
1810{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001811 int i;
1812
1813 if (pipe(proc_poll_pipe) < 0) {
1814 perror("pipe");
1815 exit(1);
1816 }
1817 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001818 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819 exit(1);
1820 }
1821 }
1822}
1823
1824static int
1825proc_poll(pollv, nfds, timeout)
1826struct pollfd *pollv;
1827int nfds;
1828int timeout;
1829{
1830 int i;
1831 int n;
1832 struct proc_pollfd pollinfo;
1833
1834 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1835 return n;
1836 if (n != sizeof(struct proc_pollfd)) {
1837 fprintf(stderr, "panic: short read: %d\n", n);
1838 exit(1);
1839 }
1840 for (i = 0; i < nprocs; i++) {
1841 if (pollv[i].fd == pollinfo.fd)
1842 pollv[i].revents = pollinfo.revents;
1843 else
1844 pollv[i].revents = 0;
1845 }
1846 poller_pid = pollinfo.pid;
1847 return 1;
1848}
1849
1850static void
1851wakeup_handler(sig)
1852int sig;
1853{
1854}
1855
1856static void
1857proc_poller(pfd)
1858int pfd;
1859{
1860 struct proc_pollfd pollinfo;
1861 struct sigaction sa;
1862 sigset_t blocked_set, empty_set;
1863 int i;
1864 int n;
1865 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001866#ifdef FREEBSD
1867 struct procfs_status pfs;
1868#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869
1870 switch (fork()) {
1871 case -1:
1872 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001873 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874 case 0:
1875 break;
1876 default:
1877 return;
1878 }
1879
1880 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1881 sa.sa_flags = 0;
1882 sigemptyset(&sa.sa_mask);
1883 sigaction(SIGHUP, &sa, NULL);
1884 sigaction(SIGINT, &sa, NULL);
1885 sigaction(SIGQUIT, &sa, NULL);
1886 sigaction(SIGPIPE, &sa, NULL);
1887 sigaction(SIGTERM, &sa, NULL);
1888 sa.sa_handler = wakeup_handler;
1889 sigaction(SIGUSR1, &sa, NULL);
1890 sigemptyset(&blocked_set);
1891 sigaddset(&blocked_set, SIGUSR1);
1892 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1893 sigemptyset(&empty_set);
1894
1895 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1896 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001897 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898 }
1899 n = rl.rlim_cur;
1900 for (i = 0; i < n; i++) {
1901 if (i != pfd && i != proc_poll_pipe[1])
1902 close(i);
1903 }
1904
1905 pollinfo.fd = pfd;
1906 pollinfo.pid = getpid();
1907 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001908#ifndef FREEBSD
1909 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1910#else /* FREEBSD */
1911 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1912#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001913 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914 switch (errno) {
1915 case EINTR:
1916 continue;
1917 case EBADF:
1918 pollinfo.revents = POLLERR;
1919 break;
1920 case ENOENT:
1921 pollinfo.revents = POLLHUP;
1922 break;
1923 default:
1924 perror("proc_poller: PIOCWSTOP");
1925 }
1926 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1927 _exit(0);
1928 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001929 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001930 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1931 sigsuspend(&empty_set);
1932 }
1933}
1934
1935#endif /* !HAVE_POLLABLE_PROCFS */
1936
1937static int
1938choose_pfd()
1939{
1940 int i, j;
1941 struct tcb *tcp;
1942
1943 static int last;
1944
1945 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001946 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001947 /*
1948 * The previous process is ready to run again. We'll
1949 * let it do so if it is currently in a syscall. This
1950 * heuristic improves the readability of the trace.
1951 */
1952 tcp = pfd2tcb(pollv[last].fd);
1953 if (tcp && (tcp->flags & TCB_INSYSCALL))
1954 return pollv[last].fd;
1955 }
1956
1957 for (i = 0; i < nprocs; i++) {
1958 /* Let competing children run round robin. */
1959 j = (i + last + 1) % nprocs;
1960 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1961 tcp = pfd2tcb(pollv[j].fd);
1962 if (!tcp) {
1963 fprintf(stderr, "strace: lost proc\n");
1964 exit(1);
1965 }
1966 droptcb(tcp);
1967 return -1;
1968 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001969 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001970 last = j;
1971 return pollv[j].fd;
1972 }
1973 }
1974 fprintf(stderr, "strace: nothing ready\n");
1975 exit(1);
1976}
1977
1978static int
1979trace()
1980{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001981#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001982 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001983#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984 struct tcb *tcp;
1985 int pfd;
1986 int what;
1987 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001988 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989
1990 for (;;) {
1991 if (interactive)
1992 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1993
1994 if (nprocs == 0)
1995 break;
1996
1997 switch (nprocs) {
1998 case 1:
1999#ifndef HAVE_POLLABLE_PROCFS
2000 if (proc_poll_pipe[0] == -1) {
2001#endif
2002 tcp = pid2tcb(0);
2003 if (!tcp)
2004 continue;
2005 pfd = tcp->pfd;
2006 if (pfd == -1)
2007 continue;
2008 break;
2009#ifndef HAVE_POLLABLE_PROCFS
2010 }
2011 /* fall through ... */
2012#endif /* !HAVE_POLLABLE_PROCFS */
2013 default:
2014#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002015#ifdef POLL_HACK
2016 /* On some systems (e.g. UnixWare) we get too much ugly
2017 "unfinished..." stuff when multiple proceses are in
2018 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002019
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002020 if (in_syscall) {
2021 struct pollfd pv;
2022 tcp = in_syscall;
2023 in_syscall = NULL;
2024 pv.fd = tcp->pfd;
2025 pv.events = POLLWANT;
2026 if ((what = poll (&pv, 1, 1)) < 0) {
2027 if (interrupted)
2028 return 0;
2029 continue;
2030 }
2031 else if (what == 1 && pv.revents & POLLWANT) {
2032 goto FOUND;
2033 }
2034 }
2035#endif
2036
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002037 if (poll(pollv, nprocs, INFTIM) < 0) {
2038 if (interrupted)
2039 return 0;
2040 continue;
2041 }
2042#else /* !HAVE_POLLABLE_PROCFS */
2043 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2044 if (interrupted)
2045 return 0;
2046 continue;
2047 }
2048#endif /* !HAVE_POLLABLE_PROCFS */
2049 pfd = choose_pfd();
2050 if (pfd == -1)
2051 continue;
2052 break;
2053 }
2054
2055 /* Look up `pfd' in our table. */
2056 if ((tcp = pfd2tcb(pfd)) == NULL) {
2057 fprintf(stderr, "unknown pfd: %u\n", pfd);
2058 exit(1);
2059 }
John Hughesb6643082002-05-23 11:02:22 +00002060#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002061 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002062#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002063 /* Get the status of the process. */
2064 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002065#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002066 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002067#else /* FREEBSD */
2068 /* Thanks to some scheduling mystery, the first poller
2069 sometimes waits for the already processed end of fork
2070 event. Doing a non blocking poll here solves the problem. */
2071 if (proc_poll_pipe[0] != -1)
2072 ioctl_result = IOCTL_STATUS (tcp);
2073 else
2074 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002075#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002076 ioctl_errno = errno;
2077#ifndef HAVE_POLLABLE_PROCFS
2078 if (proc_poll_pipe[0] != -1) {
2079 if (ioctl_result < 0)
2080 kill(poller_pid, SIGKILL);
2081 else
2082 kill(poller_pid, SIGUSR1);
2083 }
2084#endif /* !HAVE_POLLABLE_PROCFS */
2085 }
2086 if (interrupted)
2087 return 0;
2088
2089 if (interactive)
2090 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2091
2092 if (ioctl_result < 0) {
2093 /* Find out what happened if it failed. */
2094 switch (ioctl_errno) {
2095 case EINTR:
2096 case EBADF:
2097 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002098#ifdef FREEBSD
2099 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002100#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 case ENOENT:
2102 droptcb(tcp);
2103 continue;
2104 default:
2105 perror("PIOCWSTOP");
2106 exit(1);
2107 }
2108 }
2109
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002110#ifdef FREEBSD
2111 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2112 /* discard first event for a syscall we never entered */
2113 IOCTL (tcp->pfd, PIOCRUN, 0);
2114 continue;
2115 }
Roland McGrath553a6092002-12-16 20:40:39 +00002116#endif
2117
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002118 /* clear the just started flag */
2119 tcp->flags &= ~TCB_STARTUP;
2120
2121 /* set current output file */
2122 outf = tcp->outf;
2123
2124 if (cflag) {
2125 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002126#ifdef FREEBSD
2127 char buf[1024];
2128 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002130 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2131 buf[len] = '\0';
2132 sscanf(buf,
2133 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2134 &stime.tv_sec, &stime.tv_usec);
2135 } else
2136 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002137#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2139 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002140#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2142 tcp->stime = stime;
2143 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002144 what = tcp->status.PR_WHAT;
2145 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002146#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002147 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002148 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2149 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002150 if (trace_syscall(tcp) < 0) {
2151 fprintf(stderr, "syscall trouble\n");
2152 exit(1);
2153 }
2154 }
2155 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002156#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002157 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002158#ifdef POLL_HACK
2159 in_syscall = tcp;
2160#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002161 case PR_SYSEXIT:
2162 if (trace_syscall(tcp) < 0) {
2163 fprintf(stderr, "syscall trouble\n");
2164 exit(1);
2165 }
2166 break;
2167 case PR_SIGNALLED:
2168 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2169 printleader(tcp);
2170 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002171 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002172 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002173#ifdef PR_INFO
2174 if (tcp->status.PR_INFO.si_signo == what) {
2175 printleader(tcp);
2176 tprintf(" siginfo=");
2177 printsiginfo(&tcp->status.PR_INFO, 1);
2178 printtrailer(tcp);
2179 }
2180#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002181 }
2182 break;
2183 case PR_FAULTED:
2184 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2185 printleader(tcp);
2186 tprintf("=== FAULT %d ===", what);
2187 printtrailer(tcp);
2188 }
2189 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002190#ifdef FREEBSD
2191 case 0: /* handle case we polled for nothing */
2192 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002193#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002194 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002195 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 exit(1);
2197 break;
2198 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002199 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002200#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002201 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002202#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002203 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002204#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002205 perror("PIOCRUN");
2206 exit(1);
2207 }
2208 }
2209 return 0;
2210}
2211
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002212#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002213
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002214#ifdef TCB_GROUP_EXITING
2215/* Handle an exit detach or death signal that is taking all the
2216 related clone threads with it. This is called in three circumstances:
2217 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2218 SIG == 0 Continuing TCP will perform an exit_group syscall.
2219 SIG == other Continuing TCP with SIG will kill the process.
2220*/
2221static int
2222handle_group_exit(struct tcb *tcp, int sig)
2223{
2224 /* We need to locate our records of all the clone threads
2225 related to TCP, either its children or siblings. */
2226 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2227 ? tcp->parent
2228 : tcp->nclone_detached > 0
2229 ? tcp : NULL);
2230
2231 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002232 if (leader != NULL && leader != tcp &&
2233 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002234 fprintf(stderr,
2235 "PANIC: handle_group_exit: %d leader %d\n",
2236 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002237 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002238#ifndef USE_PROCFS
2239 resume_from_tcp (tcp);
2240#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002241 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002242 }
2243 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002244 /* Mark that we are taking the process down. */
2245 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002246 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002247 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002248 if (leader != NULL && leader != tcp)
2249 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002250 } else {
2251 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2252 cleanup();
2253 return -1;
2254 }
2255 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002256 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002257 if (leader != tcp)
2258 droptcb(tcp);
2259 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002260 /* The leader will report to us as parent now,
2261 and then we'll get to the SIG==-1 case. */
2262 return 0;
2263 }
2264 }
2265
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002266 return 0;
2267}
2268#endif
2269
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002270static int
2271trace()
2272{
2273 int pid;
2274 int wait_errno;
2275 int status;
2276 struct tcb *tcp;
2277#ifdef LINUX
2278 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002279#ifdef __WALL
2280 static int wait4_options = __WALL;
2281#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002282#endif /* LINUX */
2283
2284 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002285 if (interrupted)
2286 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287 if (interactive)
2288 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2289#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002290#ifdef __WALL
2291 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002292 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002293 /* this kernel does not support __WALL */
2294 wait4_options &= ~__WALL;
2295 errno = 0;
2296 pid = wait4(-1, &status, wait4_options,
2297 cflag ? &ru : NULL);
2298 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002299 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002300 /* most likely a "cloned" process */
2301 pid = wait4(-1, &status, __WCLONE,
2302 cflag ? &ru : NULL);
2303 if (pid == -1) {
2304 fprintf(stderr, "strace: clone wait4 "
2305 "failed: %s\n", strerror(errno));
2306 }
2307 }
2308#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002309 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002310#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002311#endif /* LINUX */
2312#ifdef SUNOS4
2313 pid = wait(&status);
2314#endif /* SUNOS4 */
2315 wait_errno = errno;
2316 if (interactive)
2317 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2318
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002319 if (pid == -1) {
2320 switch (wait_errno) {
2321 case EINTR:
2322 continue;
2323 case ECHILD:
2324 /*
2325 * We would like to verify this case
2326 * but sometimes a race in Solbourne's
2327 * version of SunOS sometimes reports
2328 * ECHILD before sending us SIGCHILD.
2329 */
2330#if 0
2331 if (nprocs == 0)
2332 return 0;
2333 fprintf(stderr, "strace: proc miscount\n");
2334 exit(1);
2335#endif
2336 return 0;
2337 default:
2338 errno = wait_errno;
2339 perror("strace: wait");
2340 return -1;
2341 }
2342 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002343 if (pid == popen_pid) {
2344 if (WIFEXITED(status) || WIFSIGNALED(status))
2345 popen_pid = -1;
2346 continue;
2347 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348 if (debug)
2349 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2350
2351 /* Look up `pid' in our table. */
2352 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002353#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002354 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002355 /* This is needed to go with the CLONE_PTRACE
2356 changes in process.c/util.c: we might see
2357 the child's initial trap before we see the
2358 parent return from the clone syscall.
2359 Leave the child suspended until the parent
2360 returns from its system call. Only then
2361 will we have the association of parent and
2362 child so that we know how to do clearbpt
2363 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002364 if (nprocs == tcbtabsize &&
2365 expand_tcbtab())
2366 tcp = NULL;
2367 else
2368 tcp = alloctcb(pid);
2369 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002370 kill(pid, SIGKILL); /* XXX */
2371 return 0;
2372 }
2373 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002374 if (!qflag)
2375 fprintf(stderr, "\
2376Process %d attached (waiting for parent)\n",
2377 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002378 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002379 else
2380 /* This can happen if a clone call used
2381 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002382#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002383 {
2384 fprintf(stderr, "unknown pid: %u\n", pid);
2385 if (WIFSTOPPED(status))
2386 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2387 exit(1);
2388 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002389 }
2390 /* set current output file */
2391 outf = tcp->outf;
2392 if (cflag) {
2393#ifdef LINUX
2394 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2395 tcp->stime = ru.ru_stime;
2396#endif /* !LINUX */
2397 }
2398
2399 if (tcp->flags & TCB_SUSPENDED) {
2400 /*
2401 * Apparently, doing any ptrace() call on a stopped
2402 * process, provokes the kernel to report the process
2403 * status again on a subsequent wait(), even if the
2404 * process has not been actually restarted.
2405 * Since we have inspected the arguments of suspended
2406 * processes we end up here testing for this case.
2407 */
2408 continue;
2409 }
2410 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002411 if (pid == strace_child)
2412 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002413 if (!cflag
2414 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2415 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002416 tprintf("+++ killed by %s %s+++",
2417 signame(WTERMSIG(status)),
2418#ifdef WCOREDUMP
2419 WCOREDUMP(status) ? "(core dumped) " :
2420#endif
2421 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002422 printtrailer(tcp);
2423 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002424#ifdef TCB_GROUP_EXITING
2425 handle_group_exit(tcp, -1);
2426#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002427 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002428#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002429 continue;
2430 }
2431 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002432 if (pid == strace_child)
2433 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 if (debug)
2435 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002436 if ((tcp->flags & TCB_ATTACHED)
2437#ifdef TCB_GROUP_EXITING
2438 && !(tcp->parent && (tcp->parent->flags &
2439 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002440 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002441#endif
2442 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 fprintf(stderr,
2444 "PANIC: attached pid %u exited\n",
2445 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002446 if (tcp == tcp_last) {
2447 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2448 == TCB_INSYSCALL)
2449 tprintf(" <unfinished ... exit status %d>\n",
2450 WEXITSTATUS(status));
2451 tcp_last = NULL;
2452 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002453#ifdef TCB_GROUP_EXITING
2454 handle_group_exit(tcp, -1);
2455#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002457#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002458 continue;
2459 }
2460 if (!WIFSTOPPED(status)) {
2461 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2462 droptcb(tcp);
2463 continue;
2464 }
2465 if (debug)
2466 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002467 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002468
Roland McGrath02203312007-06-11 22:06:31 +00002469 /*
2470 * Interestingly, the process may stop
2471 * with STOPSIG equal to some other signal
2472 * than SIGSTOP if we happend to attach
2473 * just before the process takes a signal.
2474 */
2475 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002476 /*
2477 * This flag is there to keep us in sync.
2478 * Next time this process stops it should
2479 * really be entering a system call.
2480 */
2481 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002482 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002483 /*
2484 * One example is a breakpoint inherited from
2485 * parent through fork ().
2486 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002487 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2488 droptcb(tcp);
2489 cleanup();
2490 return -1;
2491 }
2492 }
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002493/* Add more OSes after you verified it works for them. */
Denys Vlasenko0861ecb2009-01-02 16:55:24 +00002494/* PTRACE_SETOPTIONS is not a #define. PT_SETOPTIONS is. */
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002495#if defined LINUX && defined PT_SETOPTIONS
Denys Vlasenko0861ecb2009-01-02 16:55:24 +00002496# ifndef PTRACE_O_TRACESYSGOOD
2497# define PTRACE_O_TRACESYSGOOD 0x00000001
2498# endif
2499# ifndef PTRACE_O_TRACEEXEC
2500# define PTRACE_O_TRACEEXEC 0x00000010
2501# endif
2502# ifndef PTRACE_EVENT_EXEC
2503# define PTRACE_EVENT_EXEC 4
2504# endif
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002505 /*
2506 * Ask kernel to set signo to SIGTRAP | 0x80
2507 * on ptrace-generated SIGTRAPs, and mark
2508 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
2509 */
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002510 if (!ptrace_opts_set) {
2511 ptrace_opts_set = 1;
2512 /*
2513 * NB: even if this "succeeds", we can
2514 * revert back to SIGTRAP if we later see
2515 * that it didnt really work.
2516 * Old kernels are known to lie here.
2517 */
2518 if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
2519 (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
2520 ptrace_stop_sig = SIGTRAP | 0x80;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002521 }
2522#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002523 goto tracing;
2524 }
2525
Denys Vlasenkob1efe532008-12-23 16:14:42 +00002526#if defined LINUX && defined PT_SETOPTIONS
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002527 if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002528 /*
2529 * We told ptrace to report SIGTRAP | 0x80 on this process
2530 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
2531 * kill(pid, SIGTRAP), trap insn, etc;
2532 * but be paranoid about it.
2533 */
2534 if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
2535 /* It's post-exec ptrace stop. */
2536 /* Set WSTOPSIG(status) = (SIGTRAP | 0x80). */
2537 status |= 0x8000;
2538 } else {
2539 /* Take a better look... */
2540 siginfo_t si;
2541 ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
2542 /*
2543 * Check some fields to make sure we see
2544 * real SIGTRAP.
2545 * Otherwise interpret it as ptrace stop.
2546 * Real SIGTRAPs (int3 insn on x86, kill() etc)
2547 * have these values:
2548 * int3: kill -TRAP $pid:
2549 * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
2550 * si_errno:0 si_errno:(?)
2551 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
2552 * si_pid:0 si_pid:(>0?)
2553 * si_band:0 si_band:(?)
2554 * Ptrace stops have garbage there instead.
2555 */
2556 if (si.si_signo != SIGTRAP
2557 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
2558 ) {
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002559 fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
2560 ptrace_stop_sig = SIGTRAP;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002561 }
2562 }
2563 }
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002564#endif
2565
Denys Vlasenko96d5a762008-12-29 19:13:27 +00002566 if (WSTOPSIG(status) != ptrace_stop_sig) {
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002567 /* This isn't a ptrace stop. */
2568
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002569 if (WSTOPSIG(status) == SIGSTOP &&
2570 (tcp->flags & TCB_SIGTRAPPED)) {
2571 /*
2572 * Trapped attempt to block SIGTRAP
2573 * Hope we are back in control now.
2574 */
2575 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002576 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577 cleanup();
2578 return -1;
2579 }
2580 continue;
2581 }
2582 if (!cflag
2583 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002584 unsigned long addr = 0;
2585 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002586#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002587# define PSR_RI 41
2588 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002589 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002590
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002591 upeek(tcp, PT_CR_IPSR, &psr);
2592 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002593
2594 pc += (psr >> PSR_RI) & 0x3;
2595 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2596 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002597#elif defined PTRACE_GETSIGINFO
2598 if (WSTOPSIG(status) == SIGSEGV ||
2599 WSTOPSIG(status) == SIGBUS) {
2600 siginfo_t si;
2601 if (ptrace(PTRACE_GETSIGINFO, pid,
2602 0, &si) == 0)
2603 addr = (unsigned long)
2604 si.si_addr;
2605 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002606#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002607 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002608 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002609 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002610 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002611 printtrailer(tcp);
2612 }
Roland McGrath05690952004-10-20 01:00:27 +00002613 if (((tcp->flags & TCB_ATTACHED) ||
2614 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002615 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002616#ifdef TCB_GROUP_EXITING
2617 handle_group_exit(tcp, WSTOPSIG(status));
2618#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002619 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002620#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002621 continue;
2622 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002623 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002624 cleanup();
2625 return -1;
2626 }
2627 tcp->flags &= ~TCB_SUSPENDED;
2628 continue;
2629 }
Roland McGrath02203312007-06-11 22:06:31 +00002630 /* we handled the STATUS, we are permitted to interrupt now. */
2631 if (interrupted)
2632 return 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002633 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002634 if (tcp->flags & TCB_ATTACHED)
2635 detach(tcp, 0);
2636 else {
2637 ptrace(PTRACE_KILL,
2638 tcp->pid, (char *) 1, SIGTERM);
2639 droptcb(tcp);
2640 }
2641 continue;
2642 }
2643 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002644#ifdef TCB_GROUP_EXITING
2645 if (tcp->flags & TCB_GROUP_EXITING) {
2646 if (handle_group_exit(tcp, 0) < 0)
2647 return -1;
2648 continue;
2649 }
2650#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002651 if (tcp->flags & TCB_ATTACHED)
2652 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002653 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002654 cleanup();
2655 return -1;
2656 }
2657 continue;
2658 }
2659 if (tcp->flags & TCB_SUSPENDED) {
2660 if (!qflag)
2661 fprintf(stderr, "Process %u suspended\n", pid);
2662 continue;
2663 }
2664 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002665 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002666 cleanup();
2667 return -1;
2668 }
2669 }
2670 return 0;
2671}
2672
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002673#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002674
2675static int curcol;
2676
2677#ifdef __STDC__
2678#include <stdarg.h>
2679#define VA_START(a, b) va_start(a, b)
2680#else
2681#include <varargs.h>
2682#define VA_START(a, b) va_start(a)
2683#endif
2684
2685void
2686#ifdef __STDC__
2687tprintf(const char *fmt, ...)
2688#else
2689tprintf(fmt, va_alist)
2690char *fmt;
2691va_dcl
2692#endif
2693{
2694 va_list args;
2695
2696 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002697 if (outf) {
2698 int n = vfprintf(outf, fmt, args);
2699 if (n < 0 && outf != stderr)
2700 perror(outfname == NULL
2701 ? "<writing to pipe>" : outfname);
2702 else
2703 curcol += n;
2704 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002705 va_end(args);
2706 return;
2707}
2708
2709void
2710printleader(tcp)
2711struct tcb *tcp;
2712{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002713 if (tcp_last) {
2714 if (tcp_last->ptrace_errno) {
2715 if (tcp_last->flags & TCB_INSYSCALL) {
2716 tprintf(" <unavailable>)");
2717 tabto(acolumn);
2718 }
2719 tprintf("= ? <unavailable>\n");
2720 tcp_last->ptrace_errno = 0;
2721 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
2722 tcp_last->flags |= TCB_REPRINT;
2723 tprintf(" <unfinished ...>\n");
2724 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002725 }
2726 curcol = 0;
2727 if ((followfork == 1 || pflag_seen > 1) && outfname)
2728 tprintf("%-5d ", tcp->pid);
2729 else if (nprocs > 1 && !outfname)
2730 tprintf("[pid %5u] ", tcp->pid);
2731 if (tflag) {
2732 char str[sizeof("HH:MM:SS")];
2733 struct timeval tv, dtv;
2734 static struct timeval otv;
2735
2736 gettimeofday(&tv, NULL);
2737 if (rflag) {
2738 if (otv.tv_sec == 0)
2739 otv = tv;
2740 tv_sub(&dtv, &tv, &otv);
2741 tprintf("%6ld.%06ld ",
2742 (long) dtv.tv_sec, (long) dtv.tv_usec);
2743 otv = tv;
2744 }
2745 else if (tflag > 2) {
2746 tprintf("%ld.%06ld ",
2747 (long) tv.tv_sec, (long) tv.tv_usec);
2748 }
2749 else {
2750 time_t local = tv.tv_sec;
2751 strftime(str, sizeof(str), "%T", localtime(&local));
2752 if (tflag > 1)
2753 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2754 else
2755 tprintf("%s ", str);
2756 }
2757 }
2758 if (iflag)
2759 printcall(tcp);
2760}
2761
2762void
2763tabto(col)
2764int col;
2765{
2766 if (curcol < col)
2767 tprintf("%*s", col - curcol, "");
2768}
2769
2770void
2771printtrailer(tcp)
2772struct tcb *tcp;
2773{
2774 tprintf("\n");
2775 tcp_last = NULL;
2776}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002777
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002778#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002779
2780int mp_ioctl (int fd, int cmd, void *arg, int size) {
2781
2782 struct iovec iov[2];
2783 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002784
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002785 iov[0].iov_base = &cmd;
2786 iov[0].iov_len = sizeof cmd;
2787 if (arg) {
2788 ++n;
2789 iov[1].iov_base = arg;
2790 iov[1].iov_len = size;
2791 }
Roland McGrath553a6092002-12-16 20:40:39 +00002792
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002793 return writev (fd, iov, n);
2794}
2795
2796#endif