blob: 1acfd0aad422dc85f263a23f6fd3c132150ede34 [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
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000081int debug = 0, followfork = 0, followvfork = 0;
82int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
83static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
Michal Ludvig17f8fb32002-11-06 13:17:21 +000085/* Sometimes we want to print only succeeding syscalls. */
86int not_failing_only = 0;
87
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000088static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089uid_t run_uid;
90gid_t run_gid;
91
92int acolumn = DEFAULT_ACOLUMN;
93int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000094static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +000096struct tcb **tcbtab;
97unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099extern char **environ;
100
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101static int trace P((void));
102static void cleanup P((void));
103static void interrupt P((int sig));
104static sigset_t empty_set, blocked_set;
105
106#ifdef HAVE_SIG_ATOMIC_T
107static volatile sig_atomic_t interrupted;
108#else /* !HAVE_SIG_ATOMIC_T */
109#ifdef __STDC__
110static volatile int interrupted;
111#else /* !__STDC__ */
112static int interrupted;
113#endif /* !__STDC__ */
114#endif /* !HAVE_SIG_ATOMIC_T */
115
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000116#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117
118static struct tcb *pfd2tcb P((int pfd));
119static void reaper P((int sig));
120static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000121static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122
123#ifndef HAVE_POLLABLE_PROCFS
124
125static void proc_poll_open P((void));
126static void proc_poller P((int pfd));
127
128struct proc_pollfd {
129 int fd;
130 int revents;
131 int pid;
132};
133
134static int poller_pid;
135static int proc_poll_pipe[2] = { -1, -1 };
136
137#endif /* !HAVE_POLLABLE_PROCFS */
138
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000139#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000140#define POLLWANT POLLWRNORM
141#else
142#define POLLWANT POLLPRI
143#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000144#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145
146static void
147usage(ofp, exitval)
148FILE *ofp;
149int exitval;
150{
151 fprintf(ofp, "\
152usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000153 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
154 [command [arg ...]]\n\
155 or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
156 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157-c -- count time, calls, and errors for each syscall and report summary\n\
158-f -- follow forks, -ff -- with output into separate files\n\
159-F -- attempt to follow vforks, -h -- print help message\n\
160-i -- print instruction pointer at time of syscall\n\
161-q -- suppress messages about attaching, detaching, etc.\n\
162-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
163-T -- print time spent in each syscall, -V -- print version\n\
164-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
165-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
166-a column -- alignment COLUMN for printing syscall results (default %d)\n\
167-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
168 options: trace, abbrev, verbose, raw, signal, read, or write\n\
169-o file -- send trace output to FILE instead of stderr\n\
170-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
171-p pid -- trace process with process id PID, may be repeated\n\
172-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
173-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
174-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000175-E var=val -- put var=val in the environment for command\n\
176-E var -- remove var from the environment for command\n\
177" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000178-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000179 */
180, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181 exit(exitval);
182}
183
184#ifdef SVR4
185#ifdef MIPS
186void
187foobar()
188{
189}
190#endif /* MIPS */
191#endif /* SVR4 */
192
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000193static int
194set_cloexec_flag(int fd)
195{
196 int flags, newflags;
197
198 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
199 {
200 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
201 progname, strerror(errno));
202 return -1;
203 }
204
205 newflags = flags | FD_CLOEXEC;
206 if (flags == newflags)
207 return 0;
208
209 if (fcntl(fd, F_SETFD, newflags) < 0)
210 {
211 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
212 progname, strerror(errno));
213 return -1;
214 }
215
216 return 0;
217}
218
219/*
220 * When strace is setuid executable, we have to swap uids
221 * before and after filesystem and process management operations.
222 */
223static void
224swap_uid(void)
225{
226#ifndef SVR4
227 int euid = geteuid(), uid = getuid();
228
229 if (euid != uid && setreuid(euid, uid) < 0)
230 {
231 fprintf(stderr, "%s: setreuid: %s\n",
232 progname, strerror(errno));
233 exit(1);
234 }
235#endif
236}
237
238static FILE *
239strace_fopen(const char *path, const char *mode)
240{
241 FILE *fp;
242
243 swap_uid();
244 if ((fp = fopen(path, mode)) == NULL)
245 fprintf(stderr, "%s: can't fopen '%s': %s\n",
246 progname, path, strerror(errno));
247 swap_uid();
248 if (fp && set_cloexec_flag(fileno(fp)) < 0)
249 {
250 fclose(fp);
251 fp = NULL;
252 }
253 return fp;
254}
255
256static int popen_pid = -1;
257
258#ifndef _PATH_BSHELL
259# define _PATH_BSHELL "/bin/sh"
260#endif
261
262/*
263 * We cannot use standard popen(3) here because we have to distinguish
264 * popen child process from other processes we trace, and standard popen(3)
265 * does not export its child's pid.
266 */
267static FILE *
268strace_popen(const char *command)
269{
270 int fds[2];
271
272 swap_uid();
273 if (pipe(fds) < 0)
274 {
275 fprintf(stderr, "%s: pipe: %s\n",
276 progname, strerror(errno));
277 swap_uid();
278 return NULL;
279 }
280
281 if (set_cloexec_flag(fds[1]) < 0)
282 {
283 close(fds[0]);
284 close(fds[1]);
285 swap_uid();
286 return NULL;
287 }
288
289 if ((popen_pid = fork()) == -1)
290 {
291 fprintf(stderr, "%s: fork: %s\n",
292 progname, strerror(errno));
293 close(fds[0]);
294 close(fds[1]);
295 swap_uid();
296 return NULL;
297 }
298
299 if (popen_pid)
300 {
301 /* parent */
302 close(fds[0]);
303 swap_uid();
304 return fdopen(fds[1], "w");
305 } else
306 {
307 /* child */
308 close(fds[1]);
309 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
310 {
311 fprintf(stderr, "%s: dup2: %s\n",
312 progname, strerror(errno));
313 _exit(1);
314 }
315 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
316 fprintf(stderr, "%s: execl: %s: %s\n",
317 progname, _PATH_BSHELL, strerror(errno));
318 _exit(1);
319 }
320}
321
322static int
323newoutf(struct tcb *tcp)
324{
325 if (outfname && followfork > 1) {
326 char name[MAXPATHLEN];
327 FILE *fp;
328
329 sprintf(name, "%s.%u", outfname, tcp->pid);
330 if ((fp = strace_fopen(name, "w")) == NULL)
331 return -1;
332 tcp->outf = fp;
333 }
334 return 0;
335}
336
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000337int
338main(argc, argv)
339int argc;
340char *argv[];
341{
342 extern int optind;
343 extern char *optarg;
344 struct tcb *tcp;
345 int c, pid = 0;
346 struct sigaction sa;
347
348 static char buf[BUFSIZ];
349
Roland McGrathee9d4352002-12-18 04:16:10 +0000350 /* Allocate the initial tcbtab. */
351 tcbtabsize = argc; /* Surely enough for all -p args. */
352 tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
353 tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
354 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
355 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
356
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000357 progname = argv[0];
358 outf = stderr;
359 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000360 set_sortby(DEFAULT_SORTBY);
361 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000362 qualify("trace=all");
363 qualify("abbrev=all");
364 qualify("verbose=all");
365 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000366 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000367 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000368 switch (c) {
369 case 'c':
370 cflag++;
371 dtime++;
372 break;
373 case 'd':
374 debug++;
375 break;
376 case 'f':
377 followfork++;
378 break;
379 case 'F':
380 followvfork++;
381 break;
382 case 'h':
383 usage(stdout, 0);
384 break;
385 case 'i':
386 iflag++;
387 break;
388 case 'q':
389 qflag++;
390 break;
391 case 'r':
392 rflag++;
393 tflag++;
394 break;
395 case 't':
396 tflag++;
397 break;
398 case 'T':
399 dtime++;
400 break;
401 case 'x':
402 xflag++;
403 break;
404 case 'v':
405 qualify("abbrev=none");
406 break;
407 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000408 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409 exit(0);
410 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000411 case 'z':
412 not_failing_only = 1;
413 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000414 case 'a':
415 acolumn = atoi(optarg);
416 break;
417 case 'e':
418 qualify(optarg);
419 break;
420 case 'o':
421 outfname = strdup(optarg);
422 break;
423 case 'O':
424 set_overhead(atoi(optarg));
425 break;
426 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000427 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000428 fprintf(stderr, "%s: Invalid process id: %s\n",
429 progname, optarg);
430 break;
431 }
432 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000433 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000434 break;
435 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000436 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000437 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438 progname);
439 exit(1);
440 }
441 tcp->flags |= TCB_ATTACHED;
442 pflag_seen++;
443 break;
444 case 's':
445 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000446 if (max_strlen < 0) {
447 fprintf(stderr,
448 "%s: invalid -s argument: %s\n",
449 progname, optarg);
450 exit(1);
451 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000452 break;
453 case 'S':
454 set_sortby(optarg);
455 break;
456 case 'u':
457 username = strdup(optarg);
458 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000459 case 'E':
460 if (putenv(optarg) < 0) {
461 fprintf(stderr, "%s: out of memory\n",
462 progname);
463 exit(1);
464 }
465 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 default:
467 usage(stderr, 1);
468 break;
469 }
470 }
471
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000472 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000473 usage(stderr, 1);
474
Roland McGrathcb9def62006-04-25 07:48:03 +0000475 if (followfork > 1 && cflag) {
476 fprintf(stderr,
477 "%s: -c and -ff are mutually exclusive options\n",
478 progname);
479 exit(1);
480 }
481
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000482 /* See if they want to run as another user. */
483 if (username != NULL) {
484 struct passwd *pent;
485
486 if (getuid() != 0 || geteuid() != 0) {
487 fprintf(stderr,
488 "%s: you must be root to use the -u option\n",
489 progname);
490 exit(1);
491 }
492 if ((pent = getpwnam(username)) == NULL) {
493 fprintf(stderr, "%s: cannot find user `%s'\n",
494 progname, optarg);
495 exit(1);
496 }
497 run_uid = pent->pw_uid;
498 run_gid = pent->pw_gid;
499 }
500 else {
501 run_uid = getuid();
502 run_gid = getgid();
503 }
504
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505 /* Check if they want to redirect the output. */
506 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000507 /* See if they want to pipe the output. */
508 if (outfname[0] == '|' || outfname[0] == '!') {
509 /*
510 * We can't do the <outfname>.PID funny business
511 * when using popen, so prohibit it.
512 */
513 if (followfork > 1) {
514 fprintf(stderr, "\
515%s: piping the output and -ff are mutually exclusive options\n",
516 progname);
517 exit(1);
518 }
519
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000520 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000521 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000522 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000523 else if (followfork <= 1 &&
524 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000525 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000526 }
527
Roland McGrath37b9a662003-11-07 02:26:54 +0000528 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000529 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000530 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000531 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000533 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534
Roland McGrathee9d4352002-12-18 04:16:10 +0000535 for (c = 0; c < tcbtabsize; c++) {
536 tcp = tcbtab[c];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
538 continue;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000539#ifdef LINUX
540 if (tcp->flags & TCB_CLONE_THREAD)
541 continue;
542#endif
543 /* Reinitialize the output since it may have changed. */
544 tcp->outf = outf;
545 if (newoutf(tcp) < 0)
546 exit(1);
547
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000548#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000549 if (proc_open(tcp, 1) < 0) {
550 fprintf(stderr, "trouble opening proc file\n");
551 droptcb(tcp);
552 continue;
553 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000554#else /* !USE_PROCFS */
Roland McGrath70b08532004-04-09 00:25:21 +0000555# ifdef LINUX
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000556 if (followfork) {
Roland McGrath70b08532004-04-09 00:25:21 +0000557 char procdir[MAXPATHLEN];
558 DIR *dir;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000559
Roland McGrath70b08532004-04-09 00:25:21 +0000560 sprintf(procdir, "/proc/%d/task", tcp->pid);
561 dir = opendir(procdir);
562 if (dir != NULL) {
563 unsigned int ntid = 0, nerr = 0;
564 struct dirent *de;
565 int tid;
566 while ((de = readdir(dir)) != NULL) {
567 if (de->d_fileno == 0 ||
568 de->d_name[0] == '.')
569 continue;
570 tid = atoi(de->d_name);
571 if (tid <= 0)
572 continue;
573 ++ntid;
574 if (ptrace(PTRACE_ATTACH, tid,
575 (char *) 1, 0) < 0)
576 ++nerr;
577 else if (tid != tcbtab[c]->pid) {
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000578 if (nprocs == tcbtabsize &&
579 expand_tcbtab())
580 tcp = NULL;
581 else
582 tcp = alloctcb(tid);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000583 if (tcp == NULL)
Roland McGrath70b08532004-04-09 00:25:21 +0000584 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000585 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath70b08532004-04-09 00:25:21 +0000586 tcbtab[c]->nchildren++;
587 tcbtab[c]->nclone_threads++;
588 tcbtab[c]->nclone_detached++;
589 tcp->parent = tcbtab[c];
590 }
591 }
592 closedir(dir);
593 if (nerr == ntid) {
594 perror("attach: ptrace(PTRACE_ATTACH, ...)");
595 droptcb(tcp);
596 continue;
597 }
598 if (!qflag) {
599 ntid -= nerr;
600 if (ntid > 1)
601 fprintf(stderr, "\
602Process %u attached with %u threads - interrupt to quit\n",
603 tcp->pid, ntid);
604 else
605 fprintf(stderr, "\
606Process %u attached - interrupt to quit\n",
607 tcp->pid);
608 }
609 continue;
610 }
611 }
612# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000613 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
614 perror("attach: ptrace(PTRACE_ATTACH, ...)");
615 droptcb(tcp);
616 continue;
617 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000618#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619 if (!qflag)
620 fprintf(stderr,
621 "Process %u attached - interrupt to quit\n",
Roland McGrathc3266d52004-02-20 02:23:52 +0000622 tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000623 }
624
Roland McGrathce0d1542003-11-11 21:24:23 +0000625 if (!pflag_seen) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000626 struct stat statbuf;
627 char *filename;
628 char pathname[MAXPATHLEN];
629
630 filename = argv[optind];
Roland McGrathbdb09df2004-03-02 06:50:04 +0000631 if (strchr(filename, '/')) {
632 if (strlen(filename) > sizeof pathname - 1) {
633 errno = ENAMETOOLONG;
634 perror("strace: exec");
635 exit(1);
636 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000637 strcpy(pathname, filename);
Roland McGrathbdb09df2004-03-02 06:50:04 +0000638 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000639#ifdef USE_DEBUGGING_EXEC
640 /*
641 * Debuggers customarily check the current directory
642 * first regardless of the path but doing that gives
643 * security geeks a panic attack.
644 */
645 else if (stat(filename, &statbuf) == 0)
646 strcpy(pathname, filename);
647#endif /* USE_DEBUGGING_EXEC */
648 else {
649 char *path;
650 int m, n, len;
651
652 for (path = getenv("PATH"); path && *path; path += m) {
653 if (strchr(path, ':')) {
654 n = strchr(path, ':') - path;
655 m = n + 1;
656 }
657 else
658 m = n = strlen(path);
659 if (n == 0) {
Dmitry V. Levincbd470f2006-10-14 14:23:57 +0000660 if (!getcwd(pathname, MAXPATHLEN))
661 continue;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000662 len = strlen(pathname);
663 }
Roland McGrathbdb09df2004-03-02 06:50:04 +0000664 else if (n > sizeof pathname - 1)
665 continue;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 else {
667 strncpy(pathname, path, n);
668 len = n;
669 }
670 if (len && pathname[len - 1] != '/')
671 pathname[len++] = '/';
672 strcpy(pathname + len, filename);
Roland McGrathed645162003-06-03 07:18:19 +0000673 if (stat(pathname, &statbuf) == 0 &&
674 /* Accept only regular files
675 with some execute bits set.
676 XXX not perfect, might still fail */
677 S_ISREG(statbuf.st_mode) &&
678 (statbuf.st_mode & 0111))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679 break;
680 }
681 }
682 if (stat(pathname, &statbuf) < 0) {
683 fprintf(stderr, "%s: %s: command not found\n",
684 progname, filename);
685 exit(1);
686 }
687 switch (pid = fork()) {
688 case -1:
689 perror("strace: fork");
690 cleanup();
691 exit(1);
692 break;
693 case 0: {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000694#ifdef USE_PROCFS
695 if (outf != stderr) close (fileno (outf));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000696#ifdef MIPS
697 /* Kludge for SGI, see proc_open for details. */
698 sa.sa_handler = foobar;
699 sa.sa_flags = 0;
700 sigemptyset(&sa.sa_mask);
701 sigaction(SIGINT, &sa, NULL);
702#endif /* MIPS */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000703#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000704 pause();
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000705#else /* FREEBSD */
706 kill(getpid(), SIGSTOP); /* stop HERE */
Roland McGrath553a6092002-12-16 20:40:39 +0000707#endif /* FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000708#else /* !USE_PROCFS */
Roland McGrath553a6092002-12-16 20:40:39 +0000709 if (outf!=stderr)
Wichert Akkerman7987cdf2000-07-05 16:05:39 +0000710 close(fileno (outf));
Wichert Akkermanbd4125c2000-06-27 17:28:06 +0000711
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
713 perror("strace: ptrace(PTRACE_TRACEME, ...)");
714 return -1;
715 }
716 if (debug)
717 kill(getpid(), SIGSTOP);
718
719 if (username != NULL || geteuid() == 0) {
720 uid_t run_euid = run_uid;
721 gid_t run_egid = run_gid;
722
723 if (statbuf.st_mode & S_ISUID)
724 run_euid = statbuf.st_uid;
725 if (statbuf.st_mode & S_ISGID)
726 run_egid = statbuf.st_gid;
727
728 /*
729 * It is important to set groups before we
730 * lose privileges on setuid.
731 */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +0000732 if (username != NULL) {
733 if (initgroups(username, run_gid) < 0) {
734 perror("initgroups");
735 exit(1);
736 }
737 if (setregid(run_gid, run_egid) < 0) {
738 perror("setregid");
739 exit(1);
740 }
741 if (setreuid(run_uid, run_euid) < 0) {
742 perror("setreuid");
743 exit(1);
744 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000745 }
746 }
747 else
748 setreuid(run_uid, run_uid);
Roland McGrath15dca8e2005-02-06 01:16:32 +0000749
750 /*
751 * Induce an immediate stop so that the parent
752 * will resume us with PTRACE_SYSCALL and display
753 * this execve call normally.
754 */
755 kill(getpid(), SIGSTOP);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000756#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757
758 execv(pathname, &argv[optind]);
759 perror("strace: exec");
760 _exit(1);
761 break;
762 }
763 default:
764 if ((tcp = alloctcb(pid)) == NULL) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000765 cleanup();
766 exit(1);
767 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000768#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000769 if (proc_open(tcp, 0) < 0) {
770 fprintf(stderr, "trouble opening proc file\n");
771 cleanup();
772 exit(1);
773 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000774#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000775 break;
776 }
777 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778
779 sigemptyset(&empty_set);
780 sigemptyset(&blocked_set);
781 sa.sa_handler = SIG_IGN;
782 sigemptyset(&sa.sa_mask);
783 sa.sa_flags = 0;
784 sigaction(SIGTTOU, &sa, NULL);
785 sigaction(SIGTTIN, &sa, NULL);
786 if (interactive) {
787 sigaddset(&blocked_set, SIGHUP);
788 sigaddset(&blocked_set, SIGINT);
789 sigaddset(&blocked_set, SIGQUIT);
790 sigaddset(&blocked_set, SIGPIPE);
791 sigaddset(&blocked_set, SIGTERM);
792 sa.sa_handler = interrupt;
793#ifdef SUNOS4
794 /* POSIX signals on sunos4.1 are a little broken. */
795 sa.sa_flags = SA_INTERRUPT;
796#endif /* SUNOS4 */
797 }
798 sigaction(SIGHUP, &sa, NULL);
799 sigaction(SIGINT, &sa, NULL);
800 sigaction(SIGQUIT, &sa, NULL);
801 sigaction(SIGPIPE, &sa, NULL);
802 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000803#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000804 sa.sa_handler = reaper;
805 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000806#else
807 /* Make sure SIGCHLD has the default action so that waitpid
808 definitely works without losing track of children. The user
809 should not have given us a bogus state to inherit, but he might
810 have. Arguably we should detect SIG_IGN here and pass it on
811 to children, but probably noone really needs that. */
812 sa.sa_handler = SIG_DFL;
813 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000814#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815
816 if (trace() < 0)
817 exit(1);
818 cleanup();
819 exit(0);
820}
821
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000822int
823expand_tcbtab()
824{
825 /* Allocate some more TCBs and expand the table.
826 We don't want to relocate the TCBs because our
827 callers have pointers and it would be a pain.
828 So tcbtab is a table of pointers. Since we never
829 free the TCBs, we allocate a single chunk of many. */
830 struct tcb **newtab = (struct tcb **)
831 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
832 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
833 sizeof *newtcbs);
834 int i;
835 if (newtab == NULL || newtcbs == NULL) {
836 if (newtab != NULL)
837 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000838 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
839 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000840 return 1;
841 }
842 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
843 newtab[i] = &newtcbs[i - tcbtabsize];
844 tcbtabsize *= 2;
845 tcbtab = newtab;
846
847 return 0;
848}
849
850
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000851struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000852alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000853{
854 int i;
855 struct tcb *tcp;
856
Roland McGrathee9d4352002-12-18 04:16:10 +0000857 for (i = 0; i < tcbtabsize; i++) {
858 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000859 if ((tcp->flags & TCB_INUSE) == 0) {
860 tcp->pid = pid;
861 tcp->parent = NULL;
862 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000863 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000864#ifdef TCB_CLONE_THREAD
865 tcp->nclone_threads = tcp->nclone_detached = 0;
866 tcp->nclone_waiting = 0;
867#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868 tcp->flags = TCB_INUSE | TCB_STARTUP;
869 tcp->outf = outf; /* Initialise to current out file */
870 tcp->stime.tv_sec = 0;
871 tcp->stime.tv_usec = 0;
872 tcp->pfd = -1;
873 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000874 if (command_options_parsed)
875 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000876 return tcp;
877 }
878 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000879 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000880 return NULL;
881}
882
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000883#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884int
885proc_open(tcp, attaching)
886struct tcb *tcp;
887int attaching;
888{
889 char proc[32];
890 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000891#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000892 int i;
893 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 sigset_t signals;
895 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000896#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897#ifndef HAVE_POLLABLE_PROCFS
898 static int last_pfd;
899#endif
900
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000901#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000902 /* Open the process pseudo-files in /proc. */
903 sprintf(proc, "/proc/%d/ctl", tcp->pid);
904 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905 perror("strace: open(\"/proc/...\", ...)");
906 return -1;
907 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000908 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 return -1;
910 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000911 sprintf(proc, "/proc/%d/status", tcp->pid);
912 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
913 perror("strace: open(\"/proc/...\", ...)");
914 return -1;
915 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000916 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000917 return -1;
918 }
919 sprintf(proc, "/proc/%d/as", tcp->pid);
920 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
921 perror("strace: open(\"/proc/...\", ...)");
922 return -1;
923 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000924 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000925 return -1;
926 }
927#else
928 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000929#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000930 sprintf(proc, "/proc/%d", tcp->pid);
931 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000932#else /* FREEBSD */
933 sprintf(proc, "/proc/%d/mem", tcp->pid);
934 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
935#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000936 perror("strace: open(\"/proc/...\", ...)");
937 return -1;
938 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000939 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000940 return -1;
941 }
942#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000943#ifdef FREEBSD
944 sprintf(proc, "/proc/%d/regs", tcp->pid);
945 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
946 perror("strace: open(\"/proc/.../regs\", ...)");
947 return -1;
948 }
949 if (cflag) {
950 sprintf(proc, "/proc/%d/status", tcp->pid);
951 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
952 perror("strace: open(\"/proc/.../status\", ...)");
953 return -1;
954 }
955 } else
956 tcp->pfd_status = -1;
957#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000958 rebuild_pollv();
959 if (!attaching) {
960 /*
961 * Wait for the child to pause. Because of a race
962 * condition we have to poll for the event.
963 */
964 for (;;) {
965 if (IOCTL_STATUS (tcp) < 0) {
966 perror("strace: PIOCSTATUS");
967 return -1;
968 }
969 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000970 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000971 }
972 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000973#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000974 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000975 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000976 perror("strace: PIOCSTOP");
977 return -1;
978 }
Roland McGrath553a6092002-12-16 20:40:39 +0000979#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980#ifdef PIOCSET
981 /* Set Run-on-Last-Close. */
982 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000983 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 perror("PIOCSET PR_RLC");
985 return -1;
986 }
987 /* Set or Reset Inherit-on-Fork. */
988 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000989 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990 perror("PIOC{SET,RESET} PR_FORK");
991 return -1;
992 }
993#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +0000994#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
996 perror("PIOCSRLC");
997 return -1;
998 }
999 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1000 perror("PIOC{S,R}FORK");
1001 return -1;
1002 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001003#else /* FREEBSD */
1004 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1005 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1006 perror("PIOCGFL");
1007 return -1;
1008 }
1009 arg &= ~PF_LINGER;
1010 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1011 perror("PIOCSFL");
1012 return -1;
1013 }
1014#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001016#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001017 /* Enable all syscall entries we care about. */
1018 premptyset(&syscalls);
1019 for (i = 1; i < MAX_QUALS; ++i) {
1020 if (i > (sizeof syscalls) * CHAR_BIT) break;
1021 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1022 }
1023 praddset (&syscalls, SYS_execve);
1024 if (followfork) {
1025 praddset (&syscalls, SYS_fork);
1026#ifdef SYS_forkall
1027 praddset (&syscalls, SYS_forkall);
1028#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001029#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001030 praddset (&syscalls, SYS_fork1);
1031#endif
1032#ifdef SYS_rfork1
1033 praddset (&syscalls, SYS_rfork1);
1034#endif
1035#ifdef SYS_rforkall
1036 praddset (&syscalls, SYS_rforkall);
1037#endif
1038 }
1039 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001040 perror("PIOCSENTRY");
1041 return -1;
1042 }
John Hughes19e49982001-10-19 08:59:12 +00001043 /* Enable the syscall exits. */
1044 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 perror("PIOSEXIT");
1046 return -1;
1047 }
John Hughes19e49982001-10-19 08:59:12 +00001048 /* Enable signals we care about. */
1049 premptyset(&signals);
1050 for (i = 1; i < MAX_QUALS; ++i) {
1051 if (i > (sizeof signals) * CHAR_BIT) break;
1052 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1053 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001054 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 perror("PIOCSTRACE");
1056 return -1;
1057 }
John Hughes19e49982001-10-19 08:59:12 +00001058 /* Enable faults we care about */
1059 premptyset(&faults);
1060 for (i = 1; i < MAX_QUALS; ++i) {
1061 if (i > (sizeof faults) * CHAR_BIT) break;
1062 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1063 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001064 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 perror("PIOCSFAULT");
1066 return -1;
1067 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001068#else /* FREEBSD */
1069 /* set events flags. */
1070 arg = S_SIG | S_SCE | S_SCX ;
1071 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1072 perror("PIOCBIS");
1073 return -1;
1074 }
1075#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 if (!attaching) {
1077#ifdef MIPS
1078 /*
1079 * The SGI PRSABORT doesn't work for pause() so
1080 * we send it a caught signal to wake it up.
1081 */
1082 kill(tcp->pid, SIGINT);
1083#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001084#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001086 arg = PRSABORT;
1087 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 perror("PIOCRUN");
1089 return -1;
1090 }
Roland McGrath553a6092002-12-16 20:40:39 +00001091#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001092#endif /* !MIPS*/
1093#ifdef FREEBSD
1094 /* wake up the child if it received the SIGSTOP */
1095 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001096#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097 for (;;) {
1098 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001099 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 perror("PIOCWSTOP");
1101 return -1;
1102 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001103 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001104 tcp->flags &= ~TCB_INSYSCALL;
1105 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001106 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 break;
1108 }
1109 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001110#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001111 arg = 0;
1112 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001113#else /* FREEBSD */
1114 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001115#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001116 perror("PIOCRUN");
1117 return -1;
1118 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001119#ifdef FREEBSD
1120 /* handle the case where we "opened" the child before
1121 it did the kill -STOP */
1122 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1123 tcp->status.PR_WHAT == SIGSTOP)
1124 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001125#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001126 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001127#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001129#else /* FREEBSD */
1130 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001131 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001132 /* We are attaching to an already running process.
1133 * Try to figure out the state of the process in syscalls,
1134 * to handle the first event well.
1135 * This is done by having a look at the "wchan" property of the
1136 * process, which tells where it is stopped (if it is). */
1137 FILE * status;
1138 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001139
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001140 sprintf(proc, "/proc/%d/status", tcp->pid);
1141 status = fopen(proc, "r");
1142 if (status &&
1143 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1144 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1145 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1146 strcmp(wchan, "stopevent")) {
1147 /* The process is asleep in the middle of a syscall.
1148 Fake the syscall entry event */
1149 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1150 tcp->status.PR_WHY = PR_SYSENTRY;
1151 trace_syscall(tcp);
1152 }
1153 if (status)
1154 fclose(status);
1155 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001156 }
1157#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158#ifndef HAVE_POLLABLE_PROCFS
1159 if (proc_poll_pipe[0] != -1)
1160 proc_poller(tcp->pfd);
1161 else if (nprocs > 1) {
1162 proc_poll_open();
1163 proc_poller(last_pfd);
1164 proc_poller(tcp->pfd);
1165 }
1166 last_pfd = tcp->pfd;
1167#endif /* !HAVE_POLLABLE_PROCFS */
1168 return 0;
1169}
1170
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001171#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001173struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174pid2tcb(pid)
1175int pid;
1176{
1177 int i;
1178 struct tcb *tcp;
1179
Roland McGrathee9d4352002-12-18 04:16:10 +00001180 for (i = 0; i < tcbtabsize; i++) {
1181 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 if (pid && tcp->pid != pid)
1183 continue;
1184 if (tcp->flags & TCB_INUSE)
1185 return tcp;
1186 }
1187 return NULL;
1188}
1189
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001190#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191
1192static struct tcb *
1193pfd2tcb(pfd)
1194int pfd;
1195{
1196 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001197
Roland McGrathca16be82003-01-10 19:55:28 +00001198 for (i = 0; i < tcbtabsize; i++) {
1199 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200 if (tcp->pfd != pfd)
1201 continue;
1202 if (tcp->flags & TCB_INUSE)
1203 return tcp;
1204 }
1205 return NULL;
1206}
1207
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001208#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209
1210void
1211droptcb(tcp)
1212struct tcb *tcp;
1213{
1214 if (tcp->pid == 0)
1215 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001216#ifdef TCB_CLONE_THREAD
1217 if (tcp->nclone_threads > 0) {
1218 /* There are other threads left in this process, but this
1219 is the one whose PID represents the whole process.
1220 We need to keep this record around as a zombie until
1221 all the threads die. */
1222 tcp->flags |= TCB_EXITING;
1223 return;
1224 }
1225#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226 nprocs--;
1227 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001228
Roland McGrathe29341c2003-01-10 20:14:20 +00001229 if (tcp->parent != NULL) {
1230 tcp->parent->nchildren--;
1231#ifdef TCB_CLONE_THREAD
1232 if (tcp->flags & TCB_CLONE_DETACHED)
1233 tcp->parent->nclone_detached--;
1234 if (tcp->flags & TCB_CLONE_THREAD)
1235 tcp->parent->nclone_threads--;
1236#endif
Roland McGrath09623452003-05-23 02:27:13 +00001237#ifdef TCB_CLONE_DETACHED
1238 if (!(tcp->flags & TCB_CLONE_DETACHED))
1239#endif
1240 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001241 tcp->parent = NULL;
1242 }
1243
1244 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 if (tcp->pfd != -1) {
1246 close(tcp->pfd);
1247 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001248#ifdef FREEBSD
1249 if (tcp->pfd_reg != -1) {
1250 close(tcp->pfd_reg);
1251 tcp->pfd_reg = -1;
1252 }
1253 if (tcp->pfd_status != -1) {
1254 close(tcp->pfd_status);
1255 tcp->pfd_status = -1;
1256 }
Roland McGrath553a6092002-12-16 20:40:39 +00001257#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001258#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001259 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260#endif
1261 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001262
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001263 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001265
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 tcp->outf = 0;
1267}
1268
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001269#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270
1271static int
1272resume(tcp)
1273struct tcb *tcp;
1274{
1275 if (tcp == NULL)
1276 return -1;
1277
1278 if (!(tcp->flags & TCB_SUSPENDED)) {
1279 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1280 return -1;
1281 }
1282 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001283#ifdef TCB_CLONE_THREAD
1284 if (tcp->flags & TCB_CLONE_THREAD)
1285 tcp->parent->nclone_waiting--;
1286#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287
1288 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1289 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1290 return -1;
1291 }
1292
1293 if (!qflag)
1294 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1295 return 0;
1296}
1297
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001298#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299
1300/* detach traced process; continue with sig */
1301
1302static int
1303detach(tcp, sig)
1304struct tcb *tcp;
1305int sig;
1306{
1307 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001308#ifdef LINUX
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001309 int status, resumed;
Roland McGratha08a97e2005-08-03 11:23:46 +00001310 struct tcb *zombie = NULL;
1311
1312 /* If the group leader is lingering only because of this other
1313 thread now dying, then detach the leader as well. */
1314 if ((tcp->flags & TCB_CLONE_THREAD) &&
1315 tcp->parent->nclone_threads == 1 &&
1316 (tcp->parent->flags & TCB_EXITING))
1317 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001318#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319
1320 if (tcp->flags & TCB_BPTSET)
1321 sig = SIGKILL;
1322
1323#ifdef LINUX
1324 /*
1325 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001326 * before detaching. Arghh. We go through hoops
1327 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001329#if defined(SPARC)
1330#undef PTRACE_DETACH
1331#define PTRACE_DETACH PTRACE_SUNDETACH
1332#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1334 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001335 }
1336 else if (errno != ESRCH) {
1337 /* Shouldn't happen. */
1338 perror("detach: ptrace(PTRACE_DETACH, ...)");
1339 }
Roland McGrath134813a2007-06-02 00:07:33 +00001340 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1341 : tcp->pid),
1342 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001343 if (errno != ESRCH)
1344 perror("detach: checking sanity");
1345 }
Roland McGrath134813a2007-06-02 00:07:33 +00001346 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1347 : tcp->pid),
1348 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001349 if (errno != ESRCH)
1350 perror("detach: stopping child");
1351 }
1352 else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001354#ifdef __WALL
1355 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1356 if (errno == ECHILD) /* Already gone. */
1357 break;
1358 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001359 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001360 break;
1361 }
1362#endif /* __WALL */
1363 /* No __WALL here. */
1364 if (waitpid(tcp->pid, &status, 0) < 0) {
1365 if (errno != ECHILD) {
1366 perror("detach: waiting");
1367 break;
1368 }
1369#ifdef __WCLONE
1370 /* If no processes, try clones. */
1371 if (wait4(tcp->pid, &status, __WCLONE,
1372 NULL) < 0) {
1373 if (errno != ECHILD)
1374 perror("detach: waiting");
1375 break;
1376 }
1377#endif /* __WCLONE */
1378 }
1379#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001380 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001381#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382 if (!WIFSTOPPED(status)) {
1383 /* Au revoir, mon ami. */
1384 break;
1385 }
1386 if (WSTOPSIG(status) == SIGSTOP) {
1387 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001388 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389 if (errno != ESRCH)
1390 perror("detach: ptrace(PTRACE_DETACH, ...)");
1391 /* I died trying. */
1392 }
1393 break;
1394 }
1395 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001396 WSTOPSIG(status) == SIGTRAP ?
1397 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398 if (errno != ESRCH)
1399 perror("detach: ptrace(PTRACE_CONT, ...)");
1400 break;
1401 }
1402 }
1403 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001404#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405
1406#if defined(SUNOS4)
1407 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1408 if (sig && kill(tcp->pid, sig) < 0)
1409 perror("detach: kill");
1410 sig = 0;
1411 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1412 perror("detach: ptrace(PTRACE_DETACH, ...)");
1413#endif /* SUNOS4 */
1414
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001415#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001416 resumed = 0;
1417
1418 /* XXX This won't always be quite right (but it never was).
1419 A waiter with argument 0 or < -1 is waiting for any pid in
1420 a particular pgrp, which this child might or might not be
1421 in. The waiter will only wake up if it's argument is -1
1422 or if it's waiting for tcp->pid's pgrp. It makes a
1423 difference to wake up a waiter when there might be more
1424 traced children, because it could get a false ECHILD
1425 error. OTOH, if this was the last child in the pgrp, then
1426 it ought to wake up and get ECHILD. We would have to
1427 search the system for all pid's in the pgrp to be sure.
1428
1429 && (t->waitpid == -1 ||
1430 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1431 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1432 */
1433
1434 if (tcp->parent &&
1435 (tcp->parent->flags & TCB_SUSPENDED) &&
1436 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1437 error = resume(tcp->parent);
1438 ++resumed;
1439 }
1440#ifdef TCB_CLONE_THREAD
1441 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1442 /* Some other threads of our parent are waiting too. */
1443 unsigned int i;
1444
1445 /* Resume all the threads that were waiting for this PID. */
1446 for (i = 0; i < tcbtabsize; i++) {
1447 struct tcb *t = tcbtab[i];
1448 if (t->parent == tcp->parent && t != tcp
1449 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1450 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1451 && t->waitpid == tcp->pid) {
1452 error |= resume (t);
1453 ++resumed;
1454 }
1455 }
1456 if (resumed == 0)
1457 /* Noone was waiting for this PID in particular,
1458 so now we might need to resume some wildcarders. */
1459 for (i = 0; i < tcbtabsize; i++) {
1460 struct tcb *t = tcbtab[i];
1461 if (t->parent == tcp->parent && t != tcp
1462 && ((t->flags
1463 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1464 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1465 && t->waitpid <= 0
1466 ) {
1467 error |= resume (t);
1468 break;
1469 }
1470 }
1471 }
1472#endif
1473
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001474#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475
1476 if (!qflag)
1477 fprintf(stderr, "Process %u detached\n", tcp->pid);
1478
1479 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001480
1481#ifdef LINUX
1482 if (zombie != NULL)
1483 error = detach(zombie) || error;
1484#endif
1485
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001486 return error;
1487}
1488
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001489#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490
1491static void
1492reaper(sig)
1493int sig;
1494{
1495 int pid;
1496 int status;
1497
1498 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1499#if 0
1500 struct tcb *tcp;
1501
1502 tcp = pid2tcb(pid);
1503 if (tcp)
1504 droptcb(tcp);
1505#endif
1506 }
1507}
1508
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001509#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510
1511static void
1512cleanup()
1513{
1514 int i;
1515 struct tcb *tcp;
1516
Roland McGrathee9d4352002-12-18 04:16:10 +00001517 for (i = 0; i < tcbtabsize; i++) {
1518 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 if (!(tcp->flags & TCB_INUSE))
1520 continue;
1521 if (debug)
1522 fprintf(stderr,
1523 "cleanup: looking at pid %u\n", tcp->pid);
1524 if (tcp_last &&
1525 (!outfname || followfork < 2 || tcp_last == tcp)) {
1526 tprintf(" <unfinished ...>\n");
1527 tcp_last = NULL;
1528 }
1529 if (tcp->flags & TCB_ATTACHED)
1530 detach(tcp, 0);
1531 else {
1532 kill(tcp->pid, SIGCONT);
1533 kill(tcp->pid, SIGTERM);
1534 }
1535 }
1536 if (cflag)
1537 call_summary(outf);
1538}
1539
1540static void
1541interrupt(sig)
1542int sig;
1543{
1544 interrupted = 1;
1545}
1546
1547#ifndef HAVE_STRERROR
1548
Roland McGrath6d2b3492002-12-30 00:51:30 +00001549#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550extern int sys_nerr;
1551extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001552#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553
1554const char *
1555strerror(errno)
1556int errno;
1557{
1558 static char buf[64];
1559
1560 if (errno < 1 || errno >= sys_nerr) {
1561 sprintf(buf, "Unknown error %d", errno);
1562 return buf;
1563 }
1564 return sys_errlist[errno];
1565}
1566
1567#endif /* HAVE_STERRROR */
1568
1569#ifndef HAVE_STRSIGNAL
1570
Roland McGrath8f474e02003-01-14 07:53:33 +00001571#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001572extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001574#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1575extern char *_sys_siglist[];
1576#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577
1578const char *
1579strsignal(sig)
1580int sig;
1581{
1582 static char buf[64];
1583
1584 if (sig < 1 || sig >= NSIG) {
1585 sprintf(buf, "Unknown signal %d", sig);
1586 return buf;
1587 }
1588#ifdef HAVE__SYS_SIGLIST
1589 return _sys_siglist[sig];
1590#else
1591 return sys_siglist[sig];
1592#endif
1593}
1594
1595#endif /* HAVE_STRSIGNAL */
1596
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001597#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598
1599static void
1600rebuild_pollv()
1601{
1602 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603
Roland McGrathee9d4352002-12-18 04:16:10 +00001604 if (pollv != NULL)
1605 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001606 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001607 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001608 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001609 exit(1);
1610 }
1611
Roland McGrathca16be82003-01-10 19:55:28 +00001612 for (i = j = 0; i < tcbtabsize; i++) {
1613 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 if (!(tcp->flags & TCB_INUSE))
1615 continue;
1616 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001617 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618 j++;
1619 }
1620 if (j != nprocs) {
1621 fprintf(stderr, "strace: proc miscount\n");
1622 exit(1);
1623 }
1624}
1625
1626#ifndef HAVE_POLLABLE_PROCFS
1627
1628static void
1629proc_poll_open()
1630{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 int i;
1632
1633 if (pipe(proc_poll_pipe) < 0) {
1634 perror("pipe");
1635 exit(1);
1636 }
1637 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001638 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 exit(1);
1640 }
1641 }
1642}
1643
1644static int
1645proc_poll(pollv, nfds, timeout)
1646struct pollfd *pollv;
1647int nfds;
1648int timeout;
1649{
1650 int i;
1651 int n;
1652 struct proc_pollfd pollinfo;
1653
1654 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1655 return n;
1656 if (n != sizeof(struct proc_pollfd)) {
1657 fprintf(stderr, "panic: short read: %d\n", n);
1658 exit(1);
1659 }
1660 for (i = 0; i < nprocs; i++) {
1661 if (pollv[i].fd == pollinfo.fd)
1662 pollv[i].revents = pollinfo.revents;
1663 else
1664 pollv[i].revents = 0;
1665 }
1666 poller_pid = pollinfo.pid;
1667 return 1;
1668}
1669
1670static void
1671wakeup_handler(sig)
1672int sig;
1673{
1674}
1675
1676static void
1677proc_poller(pfd)
1678int pfd;
1679{
1680 struct proc_pollfd pollinfo;
1681 struct sigaction sa;
1682 sigset_t blocked_set, empty_set;
1683 int i;
1684 int n;
1685 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001686#ifdef FREEBSD
1687 struct procfs_status pfs;
1688#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689
1690 switch (fork()) {
1691 case -1:
1692 perror("fork");
1693 _exit(0);
1694 case 0:
1695 break;
1696 default:
1697 return;
1698 }
1699
1700 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1701 sa.sa_flags = 0;
1702 sigemptyset(&sa.sa_mask);
1703 sigaction(SIGHUP, &sa, NULL);
1704 sigaction(SIGINT, &sa, NULL);
1705 sigaction(SIGQUIT, &sa, NULL);
1706 sigaction(SIGPIPE, &sa, NULL);
1707 sigaction(SIGTERM, &sa, NULL);
1708 sa.sa_handler = wakeup_handler;
1709 sigaction(SIGUSR1, &sa, NULL);
1710 sigemptyset(&blocked_set);
1711 sigaddset(&blocked_set, SIGUSR1);
1712 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1713 sigemptyset(&empty_set);
1714
1715 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1716 perror("getrlimit(RLIMIT_NOFILE, ...)");
1717 _exit(0);
1718 }
1719 n = rl.rlim_cur;
1720 for (i = 0; i < n; i++) {
1721 if (i != pfd && i != proc_poll_pipe[1])
1722 close(i);
1723 }
1724
1725 pollinfo.fd = pfd;
1726 pollinfo.pid = getpid();
1727 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001728#ifndef FREEBSD
1729 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1730#else /* FREEBSD */
1731 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1732#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001733 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 switch (errno) {
1735 case EINTR:
1736 continue;
1737 case EBADF:
1738 pollinfo.revents = POLLERR;
1739 break;
1740 case ENOENT:
1741 pollinfo.revents = POLLHUP;
1742 break;
1743 default:
1744 perror("proc_poller: PIOCWSTOP");
1745 }
1746 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1747 _exit(0);
1748 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001749 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1751 sigsuspend(&empty_set);
1752 }
1753}
1754
1755#endif /* !HAVE_POLLABLE_PROCFS */
1756
1757static int
1758choose_pfd()
1759{
1760 int i, j;
1761 struct tcb *tcp;
1762
1763 static int last;
1764
1765 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001766 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 /*
1768 * The previous process is ready to run again. We'll
1769 * let it do so if it is currently in a syscall. This
1770 * heuristic improves the readability of the trace.
1771 */
1772 tcp = pfd2tcb(pollv[last].fd);
1773 if (tcp && (tcp->flags & TCB_INSYSCALL))
1774 return pollv[last].fd;
1775 }
1776
1777 for (i = 0; i < nprocs; i++) {
1778 /* Let competing children run round robin. */
1779 j = (i + last + 1) % nprocs;
1780 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1781 tcp = pfd2tcb(pollv[j].fd);
1782 if (!tcp) {
1783 fprintf(stderr, "strace: lost proc\n");
1784 exit(1);
1785 }
1786 droptcb(tcp);
1787 return -1;
1788 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001789 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 last = j;
1791 return pollv[j].fd;
1792 }
1793 }
1794 fprintf(stderr, "strace: nothing ready\n");
1795 exit(1);
1796}
1797
1798static int
1799trace()
1800{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001801#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001802 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001803#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 struct tcb *tcp;
1805 int pfd;
1806 int what;
1807 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001808 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809
1810 for (;;) {
1811 if (interactive)
1812 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1813
1814 if (nprocs == 0)
1815 break;
1816
1817 switch (nprocs) {
1818 case 1:
1819#ifndef HAVE_POLLABLE_PROCFS
1820 if (proc_poll_pipe[0] == -1) {
1821#endif
1822 tcp = pid2tcb(0);
1823 if (!tcp)
1824 continue;
1825 pfd = tcp->pfd;
1826 if (pfd == -1)
1827 continue;
1828 break;
1829#ifndef HAVE_POLLABLE_PROCFS
1830 }
1831 /* fall through ... */
1832#endif /* !HAVE_POLLABLE_PROCFS */
1833 default:
1834#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001835#ifdef POLL_HACK
1836 /* On some systems (e.g. UnixWare) we get too much ugly
1837 "unfinished..." stuff when multiple proceses are in
1838 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001839
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001840 if (in_syscall) {
1841 struct pollfd pv;
1842 tcp = in_syscall;
1843 in_syscall = NULL;
1844 pv.fd = tcp->pfd;
1845 pv.events = POLLWANT;
1846 if ((what = poll (&pv, 1, 1)) < 0) {
1847 if (interrupted)
1848 return 0;
1849 continue;
1850 }
1851 else if (what == 1 && pv.revents & POLLWANT) {
1852 goto FOUND;
1853 }
1854 }
1855#endif
1856
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 if (poll(pollv, nprocs, INFTIM) < 0) {
1858 if (interrupted)
1859 return 0;
1860 continue;
1861 }
1862#else /* !HAVE_POLLABLE_PROCFS */
1863 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1864 if (interrupted)
1865 return 0;
1866 continue;
1867 }
1868#endif /* !HAVE_POLLABLE_PROCFS */
1869 pfd = choose_pfd();
1870 if (pfd == -1)
1871 continue;
1872 break;
1873 }
1874
1875 /* Look up `pfd' in our table. */
1876 if ((tcp = pfd2tcb(pfd)) == NULL) {
1877 fprintf(stderr, "unknown pfd: %u\n", pfd);
1878 exit(1);
1879 }
John Hughesb6643082002-05-23 11:02:22 +00001880#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001881 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001882#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001883 /* Get the status of the process. */
1884 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001885#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001886 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001887#else /* FREEBSD */
1888 /* Thanks to some scheduling mystery, the first poller
1889 sometimes waits for the already processed end of fork
1890 event. Doing a non blocking poll here solves the problem. */
1891 if (proc_poll_pipe[0] != -1)
1892 ioctl_result = IOCTL_STATUS (tcp);
1893 else
1894 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001895#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 ioctl_errno = errno;
1897#ifndef HAVE_POLLABLE_PROCFS
1898 if (proc_poll_pipe[0] != -1) {
1899 if (ioctl_result < 0)
1900 kill(poller_pid, SIGKILL);
1901 else
1902 kill(poller_pid, SIGUSR1);
1903 }
1904#endif /* !HAVE_POLLABLE_PROCFS */
1905 }
1906 if (interrupted)
1907 return 0;
1908
1909 if (interactive)
1910 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1911
1912 if (ioctl_result < 0) {
1913 /* Find out what happened if it failed. */
1914 switch (ioctl_errno) {
1915 case EINTR:
1916 case EBADF:
1917 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001918#ifdef FREEBSD
1919 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001920#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921 case ENOENT:
1922 droptcb(tcp);
1923 continue;
1924 default:
1925 perror("PIOCWSTOP");
1926 exit(1);
1927 }
1928 }
1929
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001930#ifdef FREEBSD
1931 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1932 /* discard first event for a syscall we never entered */
1933 IOCTL (tcp->pfd, PIOCRUN, 0);
1934 continue;
1935 }
Roland McGrath553a6092002-12-16 20:40:39 +00001936#endif
1937
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 /* clear the just started flag */
1939 tcp->flags &= ~TCB_STARTUP;
1940
1941 /* set current output file */
1942 outf = tcp->outf;
1943
1944 if (cflag) {
1945 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001946#ifdef FREEBSD
1947 char buf[1024];
1948 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001950 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1951 buf[len] = '\0';
1952 sscanf(buf,
1953 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1954 &stime.tv_sec, &stime.tv_usec);
1955 } else
1956 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001957#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001958 stime.tv_sec = tcp->status.pr_stime.tv_sec;
1959 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001960#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 tv_sub(&tcp->dtime, &stime, &tcp->stime);
1962 tcp->stime = stime;
1963 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001964 what = tcp->status.PR_WHAT;
1965 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001966#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001967 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001968 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
1969 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001970 if (trace_syscall(tcp) < 0) {
1971 fprintf(stderr, "syscall trouble\n");
1972 exit(1);
1973 }
1974 }
1975 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001976#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001977 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001978#ifdef POLL_HACK
1979 in_syscall = tcp;
1980#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981 case PR_SYSEXIT:
1982 if (trace_syscall(tcp) < 0) {
1983 fprintf(stderr, "syscall trouble\n");
1984 exit(1);
1985 }
1986 break;
1987 case PR_SIGNALLED:
1988 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
1989 printleader(tcp);
1990 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00001991 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001992 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00001993#ifdef PR_INFO
1994 if (tcp->status.PR_INFO.si_signo == what) {
1995 printleader(tcp);
1996 tprintf(" siginfo=");
1997 printsiginfo(&tcp->status.PR_INFO, 1);
1998 printtrailer(tcp);
1999 }
2000#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 }
2002 break;
2003 case PR_FAULTED:
2004 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2005 printleader(tcp);
2006 tprintf("=== FAULT %d ===", what);
2007 printtrailer(tcp);
2008 }
2009 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002010#ifdef FREEBSD
2011 case 0: /* handle case we polled for nothing */
2012 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002013#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002014 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002015 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002016 exit(1);
2017 break;
2018 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002019 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002020#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002021 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002022#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002023 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002024#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 perror("PIOCRUN");
2026 exit(1);
2027 }
2028 }
2029 return 0;
2030}
2031
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002032#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002033
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002034#ifdef TCB_GROUP_EXITING
2035/* Handle an exit detach or death signal that is taking all the
2036 related clone threads with it. This is called in three circumstances:
2037 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2038 SIG == 0 Continuing TCP will perform an exit_group syscall.
2039 SIG == other Continuing TCP with SIG will kill the process.
2040*/
2041static int
2042handle_group_exit(struct tcb *tcp, int sig)
2043{
2044 /* We need to locate our records of all the clone threads
2045 related to TCP, either its children or siblings. */
2046 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2047 ? tcp->parent
2048 : tcp->nclone_detached > 0
2049 ? tcp : NULL);
2050
2051 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002052 if (leader != NULL && leader != tcp &&
2053 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002054 fprintf(stderr,
2055 "PANIC: handle_group_exit: %d leader %d\n",
2056 tcp->pid, leader ? leader->pid : -1);
Roland McGratha08a97e2005-08-03 11:23:46 +00002057 detach(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002058 }
2059 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002060 /* Mark that we are taking the process down. */
2061 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002062 if (tcp->flags & TCB_ATTACHED) {
Roland McGrath00dc13f2004-10-20 02:04:15 +00002063 if (leader != NULL && leader != tcp) {
2064 if (leader->flags & TCB_ATTACHED) {
2065 /* We need to detach the leader so
2066 that the process death will be
2067 reported to its real parent.
2068 But we kill it first to prevent
2069 it doing anything before we kill
2070 the whole process in a moment.
2071 We can use PTRACE_KILL on a
2072 thread that's not already
2073 stopped. Then the value we pass
2074 in PTRACE_DETACH just sets the
2075 death signal reported to the
2076 real parent. */
2077 ptrace(PTRACE_KILL, leader->pid, 0, 0);
2078 if (debug)
2079 fprintf(stderr,
2080 " [%d exit %d kills %d]\n",
2081 tcp->pid, sig, leader->pid);
2082 detach(leader, sig);
2083 }
2084 else
2085 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002086 }
2087 detach(tcp, sig);
2088 }
2089 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2090 perror("strace: ptrace(PTRACE_CONT, ...)");
2091 cleanup();
2092 return -1;
2093 }
2094 else {
Roland McGrath05690952004-10-20 01:00:27 +00002095 if (leader != NULL)
2096 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002097 if (leader != NULL && leader != tcp)
2098 droptcb(tcp);
2099 /* The leader will report to us as parent now,
2100 and then we'll get to the SIG==-1 case. */
2101 return 0;
2102 }
2103 }
2104
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002105 return 0;
2106}
2107#endif
2108
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002109static int
2110trace()
2111{
2112 int pid;
2113 int wait_errno;
2114 int status;
2115 struct tcb *tcp;
2116#ifdef LINUX
2117 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002118#ifdef __WALL
2119 static int wait4_options = __WALL;
2120#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121#endif /* LINUX */
2122
2123 while (nprocs != 0) {
2124 if (interactive)
2125 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2126#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002127#ifdef __WALL
2128 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002129 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002130 /* this kernel does not support __WALL */
2131 wait4_options &= ~__WALL;
2132 errno = 0;
2133 pid = wait4(-1, &status, wait4_options,
2134 cflag ? &ru : NULL);
2135 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002136 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002137 /* most likely a "cloned" process */
2138 pid = wait4(-1, &status, __WCLONE,
2139 cflag ? &ru : NULL);
2140 if (pid == -1) {
2141 fprintf(stderr, "strace: clone wait4 "
2142 "failed: %s\n", strerror(errno));
2143 }
2144 }
2145#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002147#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148#endif /* LINUX */
2149#ifdef SUNOS4
2150 pid = wait(&status);
2151#endif /* SUNOS4 */
2152 wait_errno = errno;
2153 if (interactive)
2154 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2155
2156 if (interrupted)
2157 return 0;
2158
2159 if (pid == -1) {
2160 switch (wait_errno) {
2161 case EINTR:
2162 continue;
2163 case ECHILD:
2164 /*
2165 * We would like to verify this case
2166 * but sometimes a race in Solbourne's
2167 * version of SunOS sometimes reports
2168 * ECHILD before sending us SIGCHILD.
2169 */
2170#if 0
2171 if (nprocs == 0)
2172 return 0;
2173 fprintf(stderr, "strace: proc miscount\n");
2174 exit(1);
2175#endif
2176 return 0;
2177 default:
2178 errno = wait_errno;
2179 perror("strace: wait");
2180 return -1;
2181 }
2182 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002183 if (pid == popen_pid) {
2184 if (WIFEXITED(status) || WIFSIGNALED(status))
2185 popen_pid = -1;
2186 continue;
2187 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188 if (debug)
2189 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2190
2191 /* Look up `pid' in our table. */
2192 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002193#ifdef LINUX
2194 if (followfork || followvfork) {
2195 /* This is needed to go with the CLONE_PTRACE
2196 changes in process.c/util.c: we might see
2197 the child's initial trap before we see the
2198 parent return from the clone syscall.
2199 Leave the child suspended until the parent
2200 returns from its system call. Only then
2201 will we have the association of parent and
2202 child so that we know how to do clearbpt
2203 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002204 if (nprocs == tcbtabsize &&
2205 expand_tcbtab())
2206 tcp = NULL;
2207 else
2208 tcp = alloctcb(pid);
2209 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002210 kill(pid, SIGKILL); /* XXX */
2211 return 0;
2212 }
2213 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002214 if (!qflag)
2215 fprintf(stderr, "\
2216Process %d attached (waiting for parent)\n",
2217 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002218 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002219 else
2220 /* This can happen if a clone call used
2221 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002222#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002223 {
2224 fprintf(stderr, "unknown pid: %u\n", pid);
2225 if (WIFSTOPPED(status))
2226 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2227 exit(1);
2228 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229 }
2230 /* set current output file */
2231 outf = tcp->outf;
2232 if (cflag) {
2233#ifdef LINUX
2234 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2235 tcp->stime = ru.ru_stime;
2236#endif /* !LINUX */
2237 }
2238
2239 if (tcp->flags & TCB_SUSPENDED) {
2240 /*
2241 * Apparently, doing any ptrace() call on a stopped
2242 * process, provokes the kernel to report the process
2243 * status again on a subsequent wait(), even if the
2244 * process has not been actually restarted.
2245 * Since we have inspected the arguments of suspended
2246 * processes we end up here testing for this case.
2247 */
2248 continue;
2249 }
2250 if (WIFSIGNALED(status)) {
2251 if (!cflag
2252 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2253 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002254 tprintf("+++ killed by %s %s+++",
2255 signame(WTERMSIG(status)),
2256#ifdef WCOREDUMP
2257 WCOREDUMP(status) ? "(core dumped) " :
2258#endif
2259 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002260 printtrailer(tcp);
2261 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002262#ifdef TCB_GROUP_EXITING
2263 handle_group_exit(tcp, -1);
2264#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002266#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002267 continue;
2268 }
2269 if (WIFEXITED(status)) {
2270 if (debug)
2271 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002272 if ((tcp->flags & TCB_ATTACHED)
2273#ifdef TCB_GROUP_EXITING
2274 && !(tcp->parent && (tcp->parent->flags &
2275 TCB_GROUP_EXITING))
2276#endif
2277 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002278 fprintf(stderr,
2279 "PANIC: attached pid %u exited\n",
2280 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002281 if (tcp == tcp_last) {
2282 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2283 == TCB_INSYSCALL)
2284 tprintf(" <unfinished ... exit status %d>\n",
2285 WEXITSTATUS(status));
2286 tcp_last = NULL;
2287 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002288#ifdef TCB_GROUP_EXITING
2289 handle_group_exit(tcp, -1);
2290#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002291 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002292#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002293 continue;
2294 }
2295 if (!WIFSTOPPED(status)) {
2296 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2297 droptcb(tcp);
2298 continue;
2299 }
2300 if (debug)
2301 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002302 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002303
2304 if (tcp->flags & TCB_STARTUP) {
2305 /*
2306 * This flag is there to keep us in sync.
2307 * Next time this process stops it should
2308 * really be entering a system call.
2309 */
2310 tcp->flags &= ~TCB_STARTUP;
2311 if (tcp->flags & TCB_ATTACHED) {
2312 /*
2313 * Interestingly, the process may stop
2314 * with STOPSIG equal to some other signal
2315 * than SIGSTOP if we happend to attach
2316 * just before the process takes a signal.
2317 */
2318 if (!WIFSTOPPED(status)) {
2319 fprintf(stderr,
2320 "pid %u not stopped\n", pid);
2321 detach(tcp, WSTOPSIG(status));
2322 continue;
2323 }
2324 }
2325 else {
2326#ifdef SUNOS4
2327 /* A child of us stopped at exec */
2328 if (WSTOPSIG(status) == SIGTRAP && followvfork)
2329 fixvfork(tcp);
2330#endif /* SUNOS4 */
2331 }
2332 if (tcp->flags & TCB_BPTSET) {
2333 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2334 droptcb(tcp);
2335 cleanup();
2336 return -1;
2337 }
2338 }
2339 goto tracing;
2340 }
2341
2342 if (WSTOPSIG(status) != SIGTRAP) {
2343 if (WSTOPSIG(status) == SIGSTOP &&
2344 (tcp->flags & TCB_SIGTRAPPED)) {
2345 /*
2346 * Trapped attempt to block SIGTRAP
2347 * Hope we are back in control now.
2348 */
2349 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2350 if (ptrace(PTRACE_SYSCALL,
2351 pid, (char *) 1, 0) < 0) {
2352 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2353 cleanup();
2354 return -1;
2355 }
2356 continue;
2357 }
2358 if (!cflag
2359 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002360 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002361#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002362# define PSR_RI 41
2363 struct siginfo si;
2364 unsigned long psr;
2365
2366 upeek(pid, PT_CR_IPSR, &psr);
2367 upeek(pid, PT_CR_IIP, &pc);
2368
2369 pc += (psr >> PSR_RI) & 0x3;
2370 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2371 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002372#elif defined PTRACE_GETSIGINFO
2373 if (WSTOPSIG(status) == SIGSEGV ||
2374 WSTOPSIG(status) == SIGBUS) {
2375 siginfo_t si;
2376 if (ptrace(PTRACE_GETSIGINFO, pid,
2377 0, &si) == 0)
2378 addr = (unsigned long)
2379 si.si_addr;
2380 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002381#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002382 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002383 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002384 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002385 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386 printtrailer(tcp);
2387 }
Roland McGrath05690952004-10-20 01:00:27 +00002388 if (((tcp->flags & TCB_ATTACHED) ||
2389 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002390 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002391#ifdef TCB_GROUP_EXITING
2392 handle_group_exit(tcp, WSTOPSIG(status));
2393#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002395#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 continue;
2397 }
2398 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2399 WSTOPSIG(status)) < 0) {
2400 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2401 cleanup();
2402 return -1;
2403 }
2404 tcp->flags &= ~TCB_SUSPENDED;
2405 continue;
2406 }
2407 if (trace_syscall(tcp) < 0) {
2408 if (tcp->flags & TCB_ATTACHED)
2409 detach(tcp, 0);
2410 else {
2411 ptrace(PTRACE_KILL,
2412 tcp->pid, (char *) 1, SIGTERM);
2413 droptcb(tcp);
2414 }
2415 continue;
2416 }
2417 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002418#ifdef TCB_GROUP_EXITING
2419 if (tcp->flags & TCB_GROUP_EXITING) {
2420 if (handle_group_exit(tcp, 0) < 0)
2421 return -1;
2422 continue;
2423 }
2424#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002425 if (tcp->flags & TCB_ATTACHED)
2426 detach(tcp, 0);
2427 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2428 perror("strace: ptrace(PTRACE_CONT, ...)");
2429 cleanup();
2430 return -1;
2431 }
2432 continue;
2433 }
2434 if (tcp->flags & TCB_SUSPENDED) {
2435 if (!qflag)
2436 fprintf(stderr, "Process %u suspended\n", pid);
2437 continue;
2438 }
2439 tracing:
2440 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2441 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2442 cleanup();
2443 return -1;
2444 }
2445 }
2446 return 0;
2447}
2448
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002449#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002450
2451static int curcol;
2452
2453#ifdef __STDC__
2454#include <stdarg.h>
2455#define VA_START(a, b) va_start(a, b)
2456#else
2457#include <varargs.h>
2458#define VA_START(a, b) va_start(a)
2459#endif
2460
2461void
2462#ifdef __STDC__
2463tprintf(const char *fmt, ...)
2464#else
2465tprintf(fmt, va_alist)
2466char *fmt;
2467va_dcl
2468#endif
2469{
2470 va_list args;
2471
2472 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002473 if (outf) {
2474 int n = vfprintf(outf, fmt, args);
2475 if (n < 0 && outf != stderr)
2476 perror(outfname == NULL
2477 ? "<writing to pipe>" : outfname);
2478 else
2479 curcol += n;
2480 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002481 va_end(args);
2482 return;
2483}
2484
2485void
2486printleader(tcp)
2487struct tcb *tcp;
2488{
2489 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2490 tcp_last->flags |= TCB_REPRINT;
2491 tprintf(" <unfinished ...>\n");
2492 }
2493 curcol = 0;
2494 if ((followfork == 1 || pflag_seen > 1) && outfname)
2495 tprintf("%-5d ", tcp->pid);
2496 else if (nprocs > 1 && !outfname)
2497 tprintf("[pid %5u] ", tcp->pid);
2498 if (tflag) {
2499 char str[sizeof("HH:MM:SS")];
2500 struct timeval tv, dtv;
2501 static struct timeval otv;
2502
2503 gettimeofday(&tv, NULL);
2504 if (rflag) {
2505 if (otv.tv_sec == 0)
2506 otv = tv;
2507 tv_sub(&dtv, &tv, &otv);
2508 tprintf("%6ld.%06ld ",
2509 (long) dtv.tv_sec, (long) dtv.tv_usec);
2510 otv = tv;
2511 }
2512 else if (tflag > 2) {
2513 tprintf("%ld.%06ld ",
2514 (long) tv.tv_sec, (long) tv.tv_usec);
2515 }
2516 else {
2517 time_t local = tv.tv_sec;
2518 strftime(str, sizeof(str), "%T", localtime(&local));
2519 if (tflag > 1)
2520 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2521 else
2522 tprintf("%s ", str);
2523 }
2524 }
2525 if (iflag)
2526 printcall(tcp);
2527}
2528
2529void
2530tabto(col)
2531int col;
2532{
2533 if (curcol < col)
2534 tprintf("%*s", col - curcol, "");
2535}
2536
2537void
2538printtrailer(tcp)
2539struct tcb *tcp;
2540{
2541 tprintf("\n");
2542 tcp_last = NULL;
2543}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002544
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002545#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002546
2547int mp_ioctl (int fd, int cmd, void *arg, int size) {
2548
2549 struct iovec iov[2];
2550 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002551
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002552 iov[0].iov_base = &cmd;
2553 iov[0].iov_len = sizeof cmd;
2554 if (arg) {
2555 ++n;
2556 iov[1].iov_base = arg;
2557 iov[1].iov_len = size;
2558 }
Roland McGrath553a6092002-12-16 20:40:39 +00002559
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002560 return writev (fd, iov, n);
2561}
2562
2563#endif