blob: ce7701e306ac227ca5491f29464bf95dd5170404 [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
Wichert Akkerman2ee6e452000-02-18 15:36:12 +000033#include <sys/types.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000034#include "defs.h"
35
36#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
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000049#if defined(IA64) && defined(LINUX)
50# include <asm/ptrace_offsets.h>
51#endif
52
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000053#ifdef USE_PROCFS
54#include <poll.h>
55#endif
56
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000057#ifdef SVR4
58#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000059#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000060#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000061#include <sys/uio.h>
62#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000064#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000065
66int debug = 0, followfork = 0, followvfork = 0, interactive = 0;
67int rflag = 0, tflag = 0, dtime = 0, cflag = 0;
68int iflag = 0, xflag = 0, qflag = 0;
69int pflag_seen = 0;
70
Michal Ludvig17f8fb32002-11-06 13:17:21 +000071/* Sometimes we want to print only succeeding syscalls. */
72int not_failing_only = 0;
73
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000074char *username = NULL;
75uid_t run_uid;
76gid_t run_gid;
77
78int acolumn = DEFAULT_ACOLUMN;
79int max_strlen = DEFAULT_STRLEN;
80char *outfname = NULL;
81FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +000082struct tcb **tcbtab;
83unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085extern char **environ;
86
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087static int trace P((void));
88static void cleanup P((void));
89static void interrupt P((int sig));
90static sigset_t empty_set, blocked_set;
91
92#ifdef HAVE_SIG_ATOMIC_T
93static volatile sig_atomic_t interrupted;
94#else /* !HAVE_SIG_ATOMIC_T */
95#ifdef __STDC__
96static volatile int interrupted;
97#else /* !__STDC__ */
98static int interrupted;
99#endif /* !__STDC__ */
100#endif /* !HAVE_SIG_ATOMIC_T */
101
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000102#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103
104static struct tcb *pfd2tcb P((int pfd));
105static void reaper P((int sig));
106static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000107static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108
109#ifndef HAVE_POLLABLE_PROCFS
110
111static void proc_poll_open P((void));
112static void proc_poller P((int pfd));
113
114struct proc_pollfd {
115 int fd;
116 int revents;
117 int pid;
118};
119
120static int poller_pid;
121static int proc_poll_pipe[2] = { -1, -1 };
122
123#endif /* !HAVE_POLLABLE_PROCFS */
124
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000125#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000126#define POLLWANT POLLWRNORM
127#else
128#define POLLWANT POLLPRI
129#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000130#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131
132static void
133usage(ofp, exitval)
134FILE *ofp;
135int exitval;
136{
137 fprintf(ofp, "\
138usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000139 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
140 [command [arg ...]]\n\
141 or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
142 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143-c -- count time, calls, and errors for each syscall and report summary\n\
144-f -- follow forks, -ff -- with output into separate files\n\
145-F -- attempt to follow vforks, -h -- print help message\n\
146-i -- print instruction pointer at time of syscall\n\
147-q -- suppress messages about attaching, detaching, etc.\n\
148-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
149-T -- print time spent in each syscall, -V -- print version\n\
150-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
151-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
152-a column -- alignment COLUMN for printing syscall results (default %d)\n\
153-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
154 options: trace, abbrev, verbose, raw, signal, read, or write\n\
155-o file -- send trace output to FILE instead of stderr\n\
156-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
157-p pid -- trace process with process id PID, may be repeated\n\
158-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
159-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
160-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000161-E var=val -- put var=val in the environment for command\n\
162-E var -- remove var from the environment for command\n\
163" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000164-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000165 */
166, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167 exit(exitval);
168}
169
170#ifdef SVR4
171#ifdef MIPS
172void
173foobar()
174{
175}
176#endif /* MIPS */
177#endif /* SVR4 */
178
179int
180main(argc, argv)
181int argc;
182char *argv[];
183{
184 extern int optind;
185 extern char *optarg;
186 struct tcb *tcp;
187 int c, pid = 0;
188 struct sigaction sa;
189
190 static char buf[BUFSIZ];
191
Roland McGrathee9d4352002-12-18 04:16:10 +0000192 /* Allocate the initial tcbtab. */
193 tcbtabsize = argc; /* Surely enough for all -p args. */
194 tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
195 tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
196 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
197 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
198
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199 progname = argv[0];
200 outf = stderr;
201 interactive = 1;
202 qualify("trace=all");
203 qualify("abbrev=all");
204 qualify("verbose=all");
205 qualify("signal=all");
206 set_sortby(DEFAULT_SORTBY);
207 set_personality(DEFAULT_PERSONALITY);
208 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000209 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000210 switch (c) {
211 case 'c':
212 cflag++;
213 dtime++;
214 break;
215 case 'd':
216 debug++;
217 break;
218 case 'f':
219 followfork++;
220 break;
221 case 'F':
222 followvfork++;
223 break;
224 case 'h':
225 usage(stdout, 0);
226 break;
227 case 'i':
228 iflag++;
229 break;
230 case 'q':
231 qflag++;
232 break;
233 case 'r':
234 rflag++;
235 tflag++;
236 break;
237 case 't':
238 tflag++;
239 break;
240 case 'T':
241 dtime++;
242 break;
243 case 'x':
244 xflag++;
245 break;
246 case 'v':
247 qualify("abbrev=none");
248 break;
249 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000250 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251 exit(0);
252 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000253 case 'z':
254 not_failing_only = 1;
255 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256 case 'a':
257 acolumn = atoi(optarg);
258 break;
259 case 'e':
260 qualify(optarg);
261 break;
262 case 'o':
263 outfname = strdup(optarg);
264 break;
265 case 'O':
266 set_overhead(atoi(optarg));
267 break;
268 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000269 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000270 fprintf(stderr, "%s: Invalid process id: %s\n",
271 progname, optarg);
272 break;
273 }
274 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000275 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000276 break;
277 }
278 if ((tcp = alloctcb(pid)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000279 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000280 progname);
281 exit(1);
282 }
283 tcp->flags |= TCB_ATTACHED;
284 pflag_seen++;
285 break;
286 case 's':
287 max_strlen = atoi(optarg);
288 break;
289 case 'S':
290 set_sortby(optarg);
291 break;
292 case 'u':
293 username = strdup(optarg);
294 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000295 case 'E':
296 if (putenv(optarg) < 0) {
297 fprintf(stderr, "%s: out of memory\n",
298 progname);
299 exit(1);
300 }
301 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302 default:
303 usage(stderr, 1);
304 break;
305 }
306 }
307
Roland McGrathce0d1542003-11-11 21:24:23 +0000308 if (optind == argc && !pflag_seen)
309 usage(stderr, 1);
310
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311 /* See if they want to run as another user. */
312 if (username != NULL) {
313 struct passwd *pent;
314
315 if (getuid() != 0 || geteuid() != 0) {
316 fprintf(stderr,
317 "%s: you must be root to use the -u option\n",
318 progname);
319 exit(1);
320 }
321 if ((pent = getpwnam(username)) == NULL) {
322 fprintf(stderr, "%s: cannot find user `%s'\n",
323 progname, optarg);
324 exit(1);
325 }
326 run_uid = pent->pw_uid;
327 run_gid = pent->pw_gid;
328 }
329 else {
330 run_uid = getuid();
331 run_gid = getgid();
332 }
333
334#ifndef SVR4
335 setreuid(geteuid(), getuid());
336#endif
337
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000338 /* Check if they want to redirect the output. */
339 if (outfname) {
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000340 long f;
341
Roland McGrath37b9a662003-11-07 02:26:54 +0000342 /* See if they want to pipe the output. */
343 if (outfname[0] == '|' || outfname[0] == '!') {
344 /*
345 * We can't do the <outfname>.PID funny business
346 * when using popen, so prohibit it.
347 */
348 if (followfork > 1) {
349 fprintf(stderr, "\
350%s: piping the output and -ff are mutually exclusive options\n",
351 progname);
352 exit(1);
353 }
354
355 if ((outf = popen(outfname + 1, "w")) == NULL) {
356 fprintf(stderr, "%s: can't popen '%s': %s\n",
357 progname, outfname + 1,
358 strerror(errno));
359 exit(1);
360 }
361 }
362 else if ((outf = fopen(outfname, "w")) == NULL) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000363 fprintf(stderr, "%s: can't fopen '%s': %s\n",
364 progname, outfname, strerror(errno));
365 exit(1);
366 }
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000367
368 if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
369 perror("failed to get flags for outputfile");
370 exit(1);
371 }
372
373 if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
374 perror("failed to set flags for outputfile");
375 exit(1);
376 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000377 }
378
379#ifndef SVR4
380 setreuid(geteuid(), getuid());
381#endif
382
Roland McGrath37b9a662003-11-07 02:26:54 +0000383 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000384 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000385 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000386 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000388 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000389
Roland McGrathee9d4352002-12-18 04:16:10 +0000390 for (c = 0; c < tcbtabsize; c++) {
391 tcp = tcbtab[c];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392 /* Reinitialize the output since it may have changed. */
393 tcp->outf = outf;
394 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
395 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000396#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397 if (proc_open(tcp, 1) < 0) {
398 fprintf(stderr, "trouble opening proc file\n");
399 droptcb(tcp);
400 continue;
401 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000402#else /* !USE_PROCFS */
Roland McGrath70b08532004-04-09 00:25:21 +0000403# ifdef LINUX
404 if (tcp->flags & TCB_CLONE_THREAD)
405 continue;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000406 if (followfork) {
Roland McGrath70b08532004-04-09 00:25:21 +0000407 char procdir[MAXPATHLEN];
408 DIR *dir;
409 sprintf(procdir, "/proc/%d/task", tcp->pid);
410 dir = opendir(procdir);
411 if (dir != NULL) {
412 unsigned int ntid = 0, nerr = 0;
413 struct dirent *de;
414 int tid;
415 while ((de = readdir(dir)) != NULL) {
416 if (de->d_fileno == 0 ||
417 de->d_name[0] == '.')
418 continue;
419 tid = atoi(de->d_name);
420 if (tid <= 0)
421 continue;
422 ++ntid;
423 if (ptrace(PTRACE_ATTACH, tid,
424 (char *) 1, 0) < 0)
425 ++nerr;
426 else if (tid != tcbtab[c]->pid) {
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000427 if (nprocs == tcbtabsize &&
428 expand_tcbtab())
429 tcp = NULL;
430 else
431 tcp = alloctcb(tid);
Roland McGrath70b08532004-04-09 00:25:21 +0000432 if (tcp == NULL) {
433 fprintf(stderr, "%s: out of memory\n",
434 progname);
435 exit(1);
436 }
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000437 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath70b08532004-04-09 00:25:21 +0000438 tcbtab[c]->nchildren++;
439 tcbtab[c]->nclone_threads++;
440 tcbtab[c]->nclone_detached++;
441 tcp->parent = tcbtab[c];
442 }
443 }
444 closedir(dir);
445 if (nerr == ntid) {
446 perror("attach: ptrace(PTRACE_ATTACH, ...)");
447 droptcb(tcp);
448 continue;
449 }
450 if (!qflag) {
451 ntid -= nerr;
452 if (ntid > 1)
453 fprintf(stderr, "\
454Process %u attached with %u threads - interrupt to quit\n",
455 tcp->pid, ntid);
456 else
457 fprintf(stderr, "\
458Process %u attached - interrupt to quit\n",
459 tcp->pid);
460 }
461 continue;
462 }
463 }
464# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000465 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
466 perror("attach: ptrace(PTRACE_ATTACH, ...)");
467 droptcb(tcp);
468 continue;
469 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000470#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000471 if (!qflag)
472 fprintf(stderr,
473 "Process %u attached - interrupt to quit\n",
Roland McGrathc3266d52004-02-20 02:23:52 +0000474 tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000475 }
476
Roland McGrathce0d1542003-11-11 21:24:23 +0000477 if (!pflag_seen) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478 struct stat statbuf;
479 char *filename;
480 char pathname[MAXPATHLEN];
481
482 filename = argv[optind];
Roland McGrathbdb09df2004-03-02 06:50:04 +0000483 if (strchr(filename, '/')) {
484 if (strlen(filename) > sizeof pathname - 1) {
485 errno = ENAMETOOLONG;
486 perror("strace: exec");
487 exit(1);
488 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000489 strcpy(pathname, filename);
Roland McGrathbdb09df2004-03-02 06:50:04 +0000490 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000491#ifdef USE_DEBUGGING_EXEC
492 /*
493 * Debuggers customarily check the current directory
494 * first regardless of the path but doing that gives
495 * security geeks a panic attack.
496 */
497 else if (stat(filename, &statbuf) == 0)
498 strcpy(pathname, filename);
499#endif /* USE_DEBUGGING_EXEC */
500 else {
501 char *path;
502 int m, n, len;
503
504 for (path = getenv("PATH"); path && *path; path += m) {
505 if (strchr(path, ':')) {
506 n = strchr(path, ':') - path;
507 m = n + 1;
508 }
509 else
510 m = n = strlen(path);
511 if (n == 0) {
512 getcwd(pathname, MAXPATHLEN);
513 len = strlen(pathname);
514 }
Roland McGrathbdb09df2004-03-02 06:50:04 +0000515 else if (n > sizeof pathname - 1)
516 continue;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000517 else {
518 strncpy(pathname, path, n);
519 len = n;
520 }
521 if (len && pathname[len - 1] != '/')
522 pathname[len++] = '/';
523 strcpy(pathname + len, filename);
Roland McGrathed645162003-06-03 07:18:19 +0000524 if (stat(pathname, &statbuf) == 0 &&
525 /* Accept only regular files
526 with some execute bits set.
527 XXX not perfect, might still fail */
528 S_ISREG(statbuf.st_mode) &&
529 (statbuf.st_mode & 0111))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000530 break;
531 }
532 }
533 if (stat(pathname, &statbuf) < 0) {
534 fprintf(stderr, "%s: %s: command not found\n",
535 progname, filename);
536 exit(1);
537 }
538 switch (pid = fork()) {
539 case -1:
540 perror("strace: fork");
541 cleanup();
542 exit(1);
543 break;
544 case 0: {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000545#ifdef USE_PROCFS
546 if (outf != stderr) close (fileno (outf));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547#ifdef MIPS
548 /* Kludge for SGI, see proc_open for details. */
549 sa.sa_handler = foobar;
550 sa.sa_flags = 0;
551 sigemptyset(&sa.sa_mask);
552 sigaction(SIGINT, &sa, NULL);
553#endif /* MIPS */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000554#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000555 pause();
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000556#else /* FREEBSD */
557 kill(getpid(), SIGSTOP); /* stop HERE */
Roland McGrath553a6092002-12-16 20:40:39 +0000558#endif /* FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000559#else /* !USE_PROCFS */
Roland McGrath553a6092002-12-16 20:40:39 +0000560 if (outf!=stderr)
Wichert Akkerman7987cdf2000-07-05 16:05:39 +0000561 close(fileno (outf));
Wichert Akkermanbd4125c2000-06-27 17:28:06 +0000562
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
564 perror("strace: ptrace(PTRACE_TRACEME, ...)");
565 return -1;
566 }
567 if (debug)
568 kill(getpid(), SIGSTOP);
569
570 if (username != NULL || geteuid() == 0) {
571 uid_t run_euid = run_uid;
572 gid_t run_egid = run_gid;
573
574 if (statbuf.st_mode & S_ISUID)
575 run_euid = statbuf.st_uid;
576 if (statbuf.st_mode & S_ISGID)
577 run_egid = statbuf.st_gid;
578
579 /*
580 * It is important to set groups before we
581 * lose privileges on setuid.
582 */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +0000583 if (username != NULL) {
584 if (initgroups(username, run_gid) < 0) {
585 perror("initgroups");
586 exit(1);
587 }
588 if (setregid(run_gid, run_egid) < 0) {
589 perror("setregid");
590 exit(1);
591 }
592 if (setreuid(run_uid, run_euid) < 0) {
593 perror("setreuid");
594 exit(1);
595 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 }
597 }
598 else
599 setreuid(run_uid, run_uid);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000600#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601
602 execv(pathname, &argv[optind]);
603 perror("strace: exec");
604 _exit(1);
605 break;
606 }
607 default:
608 if ((tcp = alloctcb(pid)) == NULL) {
609 fprintf(stderr, "tcb table full\n");
610 cleanup();
611 exit(1);
612 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000613#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614 if (proc_open(tcp, 0) < 0) {
615 fprintf(stderr, "trouble opening proc file\n");
616 cleanup();
617 exit(1);
618 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000619#endif /* USE_PROCFS */
620#ifndef USE_PROCFS
Roland McGrath08f0ae32004-08-31 07:01:56 +0000621 if (!cflag)
622 fake_execve(tcp, pathname,
623 &argv[optind], environ);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000624#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000625 break;
626 }
627 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000628
629 sigemptyset(&empty_set);
630 sigemptyset(&blocked_set);
631 sa.sa_handler = SIG_IGN;
632 sigemptyset(&sa.sa_mask);
633 sa.sa_flags = 0;
634 sigaction(SIGTTOU, &sa, NULL);
635 sigaction(SIGTTIN, &sa, NULL);
636 if (interactive) {
637 sigaddset(&blocked_set, SIGHUP);
638 sigaddset(&blocked_set, SIGINT);
639 sigaddset(&blocked_set, SIGQUIT);
640 sigaddset(&blocked_set, SIGPIPE);
641 sigaddset(&blocked_set, SIGTERM);
642 sa.sa_handler = interrupt;
643#ifdef SUNOS4
644 /* POSIX signals on sunos4.1 are a little broken. */
645 sa.sa_flags = SA_INTERRUPT;
646#endif /* SUNOS4 */
647 }
648 sigaction(SIGHUP, &sa, NULL);
649 sigaction(SIGINT, &sa, NULL);
650 sigaction(SIGQUIT, &sa, NULL);
651 sigaction(SIGPIPE, &sa, NULL);
652 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000653#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000654 sa.sa_handler = reaper;
655 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000656#else
657 /* Make sure SIGCHLD has the default action so that waitpid
658 definitely works without losing track of children. The user
659 should not have given us a bogus state to inherit, but he might
660 have. Arguably we should detect SIG_IGN here and pass it on
661 to children, but probably noone really needs that. */
662 sa.sa_handler = SIG_DFL;
663 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000664#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000665
666 if (trace() < 0)
667 exit(1);
668 cleanup();
669 exit(0);
670}
671
672void
673newoutf(tcp)
674struct tcb *tcp;
675{
676 char name[MAXPATHLEN];
677 FILE *fp;
678
679 if (outfname && followfork > 1) {
680 sprintf(name, "%s.%u", outfname, tcp->pid);
681#ifndef SVR4
682 setreuid(geteuid(), getuid());
683#endif
684 fp = fopen(name, "w");
685#ifndef SVR4
686 setreuid(geteuid(), getuid());
687#endif
688 if (fp == NULL) {
689 perror("fopen");
690 return;
691 }
692 tcp->outf = fp;
693 }
694 return;
695}
696
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000697int
698expand_tcbtab()
699{
700 /* Allocate some more TCBs and expand the table.
701 We don't want to relocate the TCBs because our
702 callers have pointers and it would be a pain.
703 So tcbtab is a table of pointers. Since we never
704 free the TCBs, we allocate a single chunk of many. */
705 struct tcb **newtab = (struct tcb **)
706 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
707 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
708 sizeof *newtcbs);
709 int i;
710 if (newtab == NULL || newtcbs == NULL) {
711 if (newtab != NULL)
712 free(newtab);
713 return 1;
714 }
715 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
716 newtab[i] = &newtcbs[i - tcbtabsize];
717 tcbtabsize *= 2;
718 tcbtab = newtab;
719
720 return 0;
721}
722
723
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000724struct tcb *
725alloctcb(pid)
726int pid;
727{
728 int i;
729 struct tcb *tcp;
730
Roland McGrathee9d4352002-12-18 04:16:10 +0000731 for (i = 0; i < tcbtabsize; i++) {
732 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000733 if ((tcp->flags & TCB_INUSE) == 0) {
734 tcp->pid = pid;
735 tcp->parent = NULL;
736 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000737 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000738#ifdef TCB_CLONE_THREAD
739 tcp->nclone_threads = tcp->nclone_detached = 0;
740 tcp->nclone_waiting = 0;
741#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000742 tcp->flags = TCB_INUSE | TCB_STARTUP;
743 tcp->outf = outf; /* Initialise to current out file */
744 tcp->stime.tv_sec = 0;
745 tcp->stime.tv_usec = 0;
746 tcp->pfd = -1;
747 nprocs++;
748 return tcp;
749 }
750 }
751 return NULL;
752}
753
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000754#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000755int
756proc_open(tcp, attaching)
757struct tcb *tcp;
758int attaching;
759{
760 char proc[32];
761 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000762#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000763 int i;
764 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000765 sigset_t signals;
766 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000767#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000768#ifndef HAVE_POLLABLE_PROCFS
769 static int last_pfd;
770#endif
771
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000772#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000773 /* Open the process pseudo-files in /proc. */
774 sprintf(proc, "/proc/%d/ctl", tcp->pid);
775 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776 perror("strace: open(\"/proc/...\", ...)");
777 return -1;
778 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
780 perror("F_GETFD");
781 return -1;
782 }
783 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
784 perror("F_SETFD");
785 return -1;
786 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000787 sprintf(proc, "/proc/%d/status", tcp->pid);
788 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
789 perror("strace: open(\"/proc/...\", ...)");
790 return -1;
791 }
792 if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
793 perror("F_GETFD");
794 return -1;
795 }
796 if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
797 perror("F_SETFD");
798 return -1;
799 }
800 sprintf(proc, "/proc/%d/as", tcp->pid);
801 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
802 perror("strace: open(\"/proc/...\", ...)");
803 return -1;
804 }
805 if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
806 perror("F_GETFD");
807 return -1;
808 }
809 if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
810 perror("F_SETFD");
811 return -1;
812 }
813#else
814 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000815#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000816 sprintf(proc, "/proc/%d", tcp->pid);
817 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000818#else /* FREEBSD */
819 sprintf(proc, "/proc/%d/mem", tcp->pid);
820 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
821#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000822 perror("strace: open(\"/proc/...\", ...)");
823 return -1;
824 }
825 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
826 perror("F_GETFD");
827 return -1;
828 }
829 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
830 perror("F_SETFD");
831 return -1;
832 }
833#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000834#ifdef FREEBSD
835 sprintf(proc, "/proc/%d/regs", tcp->pid);
836 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
837 perror("strace: open(\"/proc/.../regs\", ...)");
838 return -1;
839 }
840 if (cflag) {
841 sprintf(proc, "/proc/%d/status", tcp->pid);
842 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
843 perror("strace: open(\"/proc/.../status\", ...)");
844 return -1;
845 }
846 } else
847 tcp->pfd_status = -1;
848#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000849 rebuild_pollv();
850 if (!attaching) {
851 /*
852 * Wait for the child to pause. Because of a race
853 * condition we have to poll for the event.
854 */
855 for (;;) {
856 if (IOCTL_STATUS (tcp) < 0) {
857 perror("strace: PIOCSTATUS");
858 return -1;
859 }
860 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000861 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000862 }
863 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000864#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000865 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000866 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000867 perror("strace: PIOCSTOP");
868 return -1;
869 }
Roland McGrath553a6092002-12-16 20:40:39 +0000870#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871#ifdef PIOCSET
872 /* Set Run-on-Last-Close. */
873 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000874 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000875 perror("PIOCSET PR_RLC");
876 return -1;
877 }
878 /* Set or Reset Inherit-on-Fork. */
879 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000880 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881 perror("PIOC{SET,RESET} PR_FORK");
882 return -1;
883 }
884#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +0000885#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
887 perror("PIOCSRLC");
888 return -1;
889 }
890 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
891 perror("PIOC{S,R}FORK");
892 return -1;
893 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000894#else /* FREEBSD */
895 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
896 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
897 perror("PIOCGFL");
898 return -1;
899 }
900 arg &= ~PF_LINGER;
901 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
902 perror("PIOCSFL");
903 return -1;
904 }
905#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000907#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +0000908 /* Enable all syscall entries we care about. */
909 premptyset(&syscalls);
910 for (i = 1; i < MAX_QUALS; ++i) {
911 if (i > (sizeof syscalls) * CHAR_BIT) break;
912 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
913 }
914 praddset (&syscalls, SYS_execve);
915 if (followfork) {
916 praddset (&syscalls, SYS_fork);
917#ifdef SYS_forkall
918 praddset (&syscalls, SYS_forkall);
919#endif
Roland McGrath553a6092002-12-16 20:40:39 +0000920#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +0000921 praddset (&syscalls, SYS_fork1);
922#endif
923#ifdef SYS_rfork1
924 praddset (&syscalls, SYS_rfork1);
925#endif
926#ifdef SYS_rforkall
927 praddset (&syscalls, SYS_rforkall);
928#endif
929 }
930 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931 perror("PIOCSENTRY");
932 return -1;
933 }
John Hughes19e49982001-10-19 08:59:12 +0000934 /* Enable the syscall exits. */
935 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000936 perror("PIOSEXIT");
937 return -1;
938 }
John Hughes19e49982001-10-19 08:59:12 +0000939 /* Enable signals we care about. */
940 premptyset(&signals);
941 for (i = 1; i < MAX_QUALS; ++i) {
942 if (i > (sizeof signals) * CHAR_BIT) break;
943 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
944 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000945 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000946 perror("PIOCSTRACE");
947 return -1;
948 }
John Hughes19e49982001-10-19 08:59:12 +0000949 /* Enable faults we care about */
950 premptyset(&faults);
951 for (i = 1; i < MAX_QUALS; ++i) {
952 if (i > (sizeof faults) * CHAR_BIT) break;
953 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
954 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000955 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956 perror("PIOCSFAULT");
957 return -1;
958 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000959#else /* FREEBSD */
960 /* set events flags. */
961 arg = S_SIG | S_SCE | S_SCX ;
962 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
963 perror("PIOCBIS");
964 return -1;
965 }
966#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 if (!attaching) {
968#ifdef MIPS
969 /*
970 * The SGI PRSABORT doesn't work for pause() so
971 * we send it a caught signal to wake it up.
972 */
973 kill(tcp->pid, SIGINT);
974#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +0000975#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000976 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000977 arg = PRSABORT;
978 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979 perror("PIOCRUN");
980 return -1;
981 }
Roland McGrath553a6092002-12-16 20:40:39 +0000982#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000983#endif /* !MIPS*/
984#ifdef FREEBSD
985 /* wake up the child if it received the SIGSTOP */
986 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +0000987#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 for (;;) {
989 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000990 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 perror("PIOCWSTOP");
992 return -1;
993 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000994 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000995 tcp->flags &= ~TCB_INSYSCALL;
996 get_scno(tcp);
997 if (tcp->scno == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 break;
999 }
1000 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001001#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001002 arg = 0;
1003 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001004#else /* FREEBSD */
1005 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001006#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 perror("PIOCRUN");
1008 return -1;
1009 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001010#ifdef FREEBSD
1011 /* handle the case where we "opened" the child before
1012 it did the kill -STOP */
1013 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1014 tcp->status.PR_WHAT == SIGSTOP)
1015 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001016#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001018#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001020#else /* FREEBSD */
1021 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001022 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001023 /* We are attaching to an already running process.
1024 * Try to figure out the state of the process in syscalls,
1025 * to handle the first event well.
1026 * This is done by having a look at the "wchan" property of the
1027 * process, which tells where it is stopped (if it is). */
1028 FILE * status;
1029 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001030
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001031 sprintf(proc, "/proc/%d/status", tcp->pid);
1032 status = fopen(proc, "r");
1033 if (status &&
1034 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1035 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1036 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1037 strcmp(wchan, "stopevent")) {
1038 /* The process is asleep in the middle of a syscall.
1039 Fake the syscall entry event */
1040 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1041 tcp->status.PR_WHY = PR_SYSENTRY;
1042 trace_syscall(tcp);
1043 }
1044 if (status)
1045 fclose(status);
1046 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001047 }
1048#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049#ifndef HAVE_POLLABLE_PROCFS
1050 if (proc_poll_pipe[0] != -1)
1051 proc_poller(tcp->pfd);
1052 else if (nprocs > 1) {
1053 proc_poll_open();
1054 proc_poller(last_pfd);
1055 proc_poller(tcp->pfd);
1056 }
1057 last_pfd = tcp->pfd;
1058#endif /* !HAVE_POLLABLE_PROCFS */
1059 return 0;
1060}
1061
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001062#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001063
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001064struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065pid2tcb(pid)
1066int pid;
1067{
1068 int i;
1069 struct tcb *tcp;
1070
Roland McGrathee9d4352002-12-18 04:16:10 +00001071 for (i = 0; i < tcbtabsize; i++) {
1072 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 if (pid && tcp->pid != pid)
1074 continue;
1075 if (tcp->flags & TCB_INUSE)
1076 return tcp;
1077 }
1078 return NULL;
1079}
1080
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001081#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082
1083static struct tcb *
1084pfd2tcb(pfd)
1085int pfd;
1086{
1087 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088
Roland McGrathca16be82003-01-10 19:55:28 +00001089 for (i = 0; i < tcbtabsize; i++) {
1090 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 if (tcp->pfd != pfd)
1092 continue;
1093 if (tcp->flags & TCB_INUSE)
1094 return tcp;
1095 }
1096 return NULL;
1097}
1098
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001099#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100
1101void
1102droptcb(tcp)
1103struct tcb *tcp;
1104{
1105 if (tcp->pid == 0)
1106 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001107#ifdef TCB_CLONE_THREAD
1108 if (tcp->nclone_threads > 0) {
1109 /* There are other threads left in this process, but this
1110 is the one whose PID represents the whole process.
1111 We need to keep this record around as a zombie until
1112 all the threads die. */
1113 tcp->flags |= TCB_EXITING;
1114 return;
1115 }
1116#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 nprocs--;
1118 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001119
Roland McGrathe29341c2003-01-10 20:14:20 +00001120 if (tcp->parent != NULL) {
1121 tcp->parent->nchildren--;
1122#ifdef TCB_CLONE_THREAD
1123 if (tcp->flags & TCB_CLONE_DETACHED)
1124 tcp->parent->nclone_detached--;
1125 if (tcp->flags & TCB_CLONE_THREAD)
1126 tcp->parent->nclone_threads--;
1127#endif
Roland McGrath09623452003-05-23 02:27:13 +00001128#ifdef TCB_CLONE_DETACHED
1129 if (!(tcp->flags & TCB_CLONE_DETACHED))
1130#endif
1131 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001132 tcp->parent = NULL;
1133 }
1134
1135 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 if (tcp->pfd != -1) {
1137 close(tcp->pfd);
1138 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001139#ifdef FREEBSD
1140 if (tcp->pfd_reg != -1) {
1141 close(tcp->pfd_reg);
1142 tcp->pfd_reg = -1;
1143 }
1144 if (tcp->pfd_status != -1) {
1145 close(tcp->pfd_status);
1146 tcp->pfd_status = -1;
1147 }
Roland McGrath553a6092002-12-16 20:40:39 +00001148#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001149#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001150 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151#endif
1152 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001153
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001154 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001156
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 tcp->outf = 0;
1158}
1159
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001160#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161
1162static int
1163resume(tcp)
1164struct tcb *tcp;
1165{
1166 if (tcp == NULL)
1167 return -1;
1168
1169 if (!(tcp->flags & TCB_SUSPENDED)) {
1170 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1171 return -1;
1172 }
1173 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001174#ifdef TCB_CLONE_THREAD
1175 if (tcp->flags & TCB_CLONE_THREAD)
1176 tcp->parent->nclone_waiting--;
1177#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178
1179 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1180 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1181 return -1;
1182 }
1183
1184 if (!qflag)
1185 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1186 return 0;
1187}
1188
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001189#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190
1191/* detach traced process; continue with sig */
1192
1193static int
1194detach(tcp, sig)
1195struct tcb *tcp;
1196int sig;
1197{
1198 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001199#ifdef LINUX
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001200 int status, resumed;
Roland McGrathca16be82003-01-10 19:55:28 +00001201#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202
1203 if (tcp->flags & TCB_BPTSET)
1204 sig = SIGKILL;
1205
1206#ifdef LINUX
1207 /*
1208 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001209 * before detaching. Arghh. We go through hoops
1210 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001212#if defined(SPARC)
1213#undef PTRACE_DETACH
1214#define PTRACE_DETACH PTRACE_SUNDETACH
1215#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1217 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001218 }
1219 else if (errno != ESRCH) {
1220 /* Shouldn't happen. */
1221 perror("detach: ptrace(PTRACE_DETACH, ...)");
1222 }
1223 else if (kill(tcp->pid, 0) < 0) {
1224 if (errno != ESRCH)
1225 perror("detach: checking sanity");
1226 }
1227 else if (kill(tcp->pid, SIGSTOP) < 0) {
1228 if (errno != ESRCH)
1229 perror("detach: stopping child");
1230 }
1231 else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001233#ifdef __WALL
1234 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1235 if (errno == ECHILD) /* Already gone. */
1236 break;
1237 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001238 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001239 break;
1240 }
1241#endif /* __WALL */
1242 /* No __WALL here. */
1243 if (waitpid(tcp->pid, &status, 0) < 0) {
1244 if (errno != ECHILD) {
1245 perror("detach: waiting");
1246 break;
1247 }
1248#ifdef __WCLONE
1249 /* If no processes, try clones. */
1250 if (wait4(tcp->pid, &status, __WCLONE,
1251 NULL) < 0) {
1252 if (errno != ECHILD)
1253 perror("detach: waiting");
1254 break;
1255 }
1256#endif /* __WCLONE */
1257 }
1258#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001259 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001260#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 if (!WIFSTOPPED(status)) {
1262 /* Au revoir, mon ami. */
1263 break;
1264 }
1265 if (WSTOPSIG(status) == SIGSTOP) {
1266 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001267 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268 if (errno != ESRCH)
1269 perror("detach: ptrace(PTRACE_DETACH, ...)");
1270 /* I died trying. */
1271 }
1272 break;
1273 }
1274 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001275 WSTOPSIG(status) == SIGTRAP ?
1276 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001277 if (errno != ESRCH)
1278 perror("detach: ptrace(PTRACE_CONT, ...)");
1279 break;
1280 }
1281 }
1282 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001283#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284
1285#if defined(SUNOS4)
1286 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1287 if (sig && kill(tcp->pid, sig) < 0)
1288 perror("detach: kill");
1289 sig = 0;
1290 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1291 perror("detach: ptrace(PTRACE_DETACH, ...)");
1292#endif /* SUNOS4 */
1293
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001294#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001295 resumed = 0;
1296
1297 /* XXX This won't always be quite right (but it never was).
1298 A waiter with argument 0 or < -1 is waiting for any pid in
1299 a particular pgrp, which this child might or might not be
1300 in. The waiter will only wake up if it's argument is -1
1301 or if it's waiting for tcp->pid's pgrp. It makes a
1302 difference to wake up a waiter when there might be more
1303 traced children, because it could get a false ECHILD
1304 error. OTOH, if this was the last child in the pgrp, then
1305 it ought to wake up and get ECHILD. We would have to
1306 search the system for all pid's in the pgrp to be sure.
1307
1308 && (t->waitpid == -1 ||
1309 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1310 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1311 */
1312
1313 if (tcp->parent &&
1314 (tcp->parent->flags & TCB_SUSPENDED) &&
1315 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1316 error = resume(tcp->parent);
1317 ++resumed;
1318 }
1319#ifdef TCB_CLONE_THREAD
1320 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1321 /* Some other threads of our parent are waiting too. */
1322 unsigned int i;
1323
1324 /* Resume all the threads that were waiting for this PID. */
1325 for (i = 0; i < tcbtabsize; i++) {
1326 struct tcb *t = tcbtab[i];
1327 if (t->parent == tcp->parent && t != tcp
1328 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1329 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1330 && t->waitpid == tcp->pid) {
1331 error |= resume (t);
1332 ++resumed;
1333 }
1334 }
1335 if (resumed == 0)
1336 /* Noone was waiting for this PID in particular,
1337 so now we might need to resume some wildcarders. */
1338 for (i = 0; i < tcbtabsize; i++) {
1339 struct tcb *t = tcbtab[i];
1340 if (t->parent == tcp->parent && t != tcp
1341 && ((t->flags
1342 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1343 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1344 && t->waitpid <= 0
1345 ) {
1346 error |= resume (t);
1347 break;
1348 }
1349 }
1350 }
1351#endif
1352
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001353#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354
1355 if (!qflag)
1356 fprintf(stderr, "Process %u detached\n", tcp->pid);
1357
1358 droptcb(tcp);
1359 return error;
1360}
1361
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001362#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363
1364static void
1365reaper(sig)
1366int sig;
1367{
1368 int pid;
1369 int status;
1370
1371 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1372#if 0
1373 struct tcb *tcp;
1374
1375 tcp = pid2tcb(pid);
1376 if (tcp)
1377 droptcb(tcp);
1378#endif
1379 }
1380}
1381
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001382#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001383
1384static void
1385cleanup()
1386{
1387 int i;
1388 struct tcb *tcp;
1389
Roland McGrathee9d4352002-12-18 04:16:10 +00001390 for (i = 0; i < tcbtabsize; i++) {
1391 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392 if (!(tcp->flags & TCB_INUSE))
1393 continue;
1394 if (debug)
1395 fprintf(stderr,
1396 "cleanup: looking at pid %u\n", tcp->pid);
1397 if (tcp_last &&
1398 (!outfname || followfork < 2 || tcp_last == tcp)) {
1399 tprintf(" <unfinished ...>\n");
1400 tcp_last = NULL;
1401 }
1402 if (tcp->flags & TCB_ATTACHED)
1403 detach(tcp, 0);
1404 else {
1405 kill(tcp->pid, SIGCONT);
1406 kill(tcp->pid, SIGTERM);
1407 }
1408 }
1409 if (cflag)
1410 call_summary(outf);
1411}
1412
1413static void
1414interrupt(sig)
1415int sig;
1416{
1417 interrupted = 1;
1418}
1419
1420#ifndef HAVE_STRERROR
1421
Roland McGrath6d2b3492002-12-30 00:51:30 +00001422#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423extern int sys_nerr;
1424extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001425#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426
1427const char *
1428strerror(errno)
1429int errno;
1430{
1431 static char buf[64];
1432
1433 if (errno < 1 || errno >= sys_nerr) {
1434 sprintf(buf, "Unknown error %d", errno);
1435 return buf;
1436 }
1437 return sys_errlist[errno];
1438}
1439
1440#endif /* HAVE_STERRROR */
1441
1442#ifndef HAVE_STRSIGNAL
1443
Roland McGrath8f474e02003-01-14 07:53:33 +00001444#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001445extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001447#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1448extern char *_sys_siglist[];
1449#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450
1451const char *
1452strsignal(sig)
1453int sig;
1454{
1455 static char buf[64];
1456
1457 if (sig < 1 || sig >= NSIG) {
1458 sprintf(buf, "Unknown signal %d", sig);
1459 return buf;
1460 }
1461#ifdef HAVE__SYS_SIGLIST
1462 return _sys_siglist[sig];
1463#else
1464 return sys_siglist[sig];
1465#endif
1466}
1467
1468#endif /* HAVE_STRSIGNAL */
1469
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001470#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471
1472static void
1473rebuild_pollv()
1474{
1475 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476
Roland McGrathee9d4352002-12-18 04:16:10 +00001477 if (pollv != NULL)
1478 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001479 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001480 if (pollv == NULL) {
1481 fprintf(stderr, "strace: out of memory for poll vector\n");
1482 exit(1);
1483 }
1484
Roland McGrathca16be82003-01-10 19:55:28 +00001485 for (i = j = 0; i < tcbtabsize; i++) {
1486 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 if (!(tcp->flags & TCB_INUSE))
1488 continue;
1489 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001490 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 j++;
1492 }
1493 if (j != nprocs) {
1494 fprintf(stderr, "strace: proc miscount\n");
1495 exit(1);
1496 }
1497}
1498
1499#ifndef HAVE_POLLABLE_PROCFS
1500
1501static void
1502proc_poll_open()
1503{
1504 int arg;
1505 int i;
1506
1507 if (pipe(proc_poll_pipe) < 0) {
1508 perror("pipe");
1509 exit(1);
1510 }
1511 for (i = 0; i < 2; i++) {
1512 if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
1513 perror("F_GETFD");
1514 exit(1);
1515 }
1516 if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
1517 perror("F_SETFD");
1518 exit(1);
1519 }
1520 }
1521}
1522
1523static int
1524proc_poll(pollv, nfds, timeout)
1525struct pollfd *pollv;
1526int nfds;
1527int timeout;
1528{
1529 int i;
1530 int n;
1531 struct proc_pollfd pollinfo;
1532
1533 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1534 return n;
1535 if (n != sizeof(struct proc_pollfd)) {
1536 fprintf(stderr, "panic: short read: %d\n", n);
1537 exit(1);
1538 }
1539 for (i = 0; i < nprocs; i++) {
1540 if (pollv[i].fd == pollinfo.fd)
1541 pollv[i].revents = pollinfo.revents;
1542 else
1543 pollv[i].revents = 0;
1544 }
1545 poller_pid = pollinfo.pid;
1546 return 1;
1547}
1548
1549static void
1550wakeup_handler(sig)
1551int sig;
1552{
1553}
1554
1555static void
1556proc_poller(pfd)
1557int pfd;
1558{
1559 struct proc_pollfd pollinfo;
1560 struct sigaction sa;
1561 sigset_t blocked_set, empty_set;
1562 int i;
1563 int n;
1564 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001565#ifdef FREEBSD
1566 struct procfs_status pfs;
1567#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568
1569 switch (fork()) {
1570 case -1:
1571 perror("fork");
1572 _exit(0);
1573 case 0:
1574 break;
1575 default:
1576 return;
1577 }
1578
1579 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1580 sa.sa_flags = 0;
1581 sigemptyset(&sa.sa_mask);
1582 sigaction(SIGHUP, &sa, NULL);
1583 sigaction(SIGINT, &sa, NULL);
1584 sigaction(SIGQUIT, &sa, NULL);
1585 sigaction(SIGPIPE, &sa, NULL);
1586 sigaction(SIGTERM, &sa, NULL);
1587 sa.sa_handler = wakeup_handler;
1588 sigaction(SIGUSR1, &sa, NULL);
1589 sigemptyset(&blocked_set);
1590 sigaddset(&blocked_set, SIGUSR1);
1591 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1592 sigemptyset(&empty_set);
1593
1594 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1595 perror("getrlimit(RLIMIT_NOFILE, ...)");
1596 _exit(0);
1597 }
1598 n = rl.rlim_cur;
1599 for (i = 0; i < n; i++) {
1600 if (i != pfd && i != proc_poll_pipe[1])
1601 close(i);
1602 }
1603
1604 pollinfo.fd = pfd;
1605 pollinfo.pid = getpid();
1606 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001607#ifndef FREEBSD
1608 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1609#else /* FREEBSD */
1610 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1611#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001612 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613 switch (errno) {
1614 case EINTR:
1615 continue;
1616 case EBADF:
1617 pollinfo.revents = POLLERR;
1618 break;
1619 case ENOENT:
1620 pollinfo.revents = POLLHUP;
1621 break;
1622 default:
1623 perror("proc_poller: PIOCWSTOP");
1624 }
1625 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1626 _exit(0);
1627 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001628 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1630 sigsuspend(&empty_set);
1631 }
1632}
1633
1634#endif /* !HAVE_POLLABLE_PROCFS */
1635
1636static int
1637choose_pfd()
1638{
1639 int i, j;
1640 struct tcb *tcp;
1641
1642 static int last;
1643
1644 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001645 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646 /*
1647 * The previous process is ready to run again. We'll
1648 * let it do so if it is currently in a syscall. This
1649 * heuristic improves the readability of the trace.
1650 */
1651 tcp = pfd2tcb(pollv[last].fd);
1652 if (tcp && (tcp->flags & TCB_INSYSCALL))
1653 return pollv[last].fd;
1654 }
1655
1656 for (i = 0; i < nprocs; i++) {
1657 /* Let competing children run round robin. */
1658 j = (i + last + 1) % nprocs;
1659 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1660 tcp = pfd2tcb(pollv[j].fd);
1661 if (!tcp) {
1662 fprintf(stderr, "strace: lost proc\n");
1663 exit(1);
1664 }
1665 droptcb(tcp);
1666 return -1;
1667 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001668 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669 last = j;
1670 return pollv[j].fd;
1671 }
1672 }
1673 fprintf(stderr, "strace: nothing ready\n");
1674 exit(1);
1675}
1676
1677static int
1678trace()
1679{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001680#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001681 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001682#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 struct tcb *tcp;
1684 int pfd;
1685 int what;
1686 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001687 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688
1689 for (;;) {
1690 if (interactive)
1691 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1692
1693 if (nprocs == 0)
1694 break;
1695
1696 switch (nprocs) {
1697 case 1:
1698#ifndef HAVE_POLLABLE_PROCFS
1699 if (proc_poll_pipe[0] == -1) {
1700#endif
1701 tcp = pid2tcb(0);
1702 if (!tcp)
1703 continue;
1704 pfd = tcp->pfd;
1705 if (pfd == -1)
1706 continue;
1707 break;
1708#ifndef HAVE_POLLABLE_PROCFS
1709 }
1710 /* fall through ... */
1711#endif /* !HAVE_POLLABLE_PROCFS */
1712 default:
1713#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001714#ifdef POLL_HACK
1715 /* On some systems (e.g. UnixWare) we get too much ugly
1716 "unfinished..." stuff when multiple proceses are in
1717 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001718
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001719 if (in_syscall) {
1720 struct pollfd pv;
1721 tcp = in_syscall;
1722 in_syscall = NULL;
1723 pv.fd = tcp->pfd;
1724 pv.events = POLLWANT;
1725 if ((what = poll (&pv, 1, 1)) < 0) {
1726 if (interrupted)
1727 return 0;
1728 continue;
1729 }
1730 else if (what == 1 && pv.revents & POLLWANT) {
1731 goto FOUND;
1732 }
1733 }
1734#endif
1735
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736 if (poll(pollv, nprocs, INFTIM) < 0) {
1737 if (interrupted)
1738 return 0;
1739 continue;
1740 }
1741#else /* !HAVE_POLLABLE_PROCFS */
1742 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1743 if (interrupted)
1744 return 0;
1745 continue;
1746 }
1747#endif /* !HAVE_POLLABLE_PROCFS */
1748 pfd = choose_pfd();
1749 if (pfd == -1)
1750 continue;
1751 break;
1752 }
1753
1754 /* Look up `pfd' in our table. */
1755 if ((tcp = pfd2tcb(pfd)) == NULL) {
1756 fprintf(stderr, "unknown pfd: %u\n", pfd);
1757 exit(1);
1758 }
John Hughesb6643082002-05-23 11:02:22 +00001759#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001760 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001761#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762 /* Get the status of the process. */
1763 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001764#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001765 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001766#else /* FREEBSD */
1767 /* Thanks to some scheduling mystery, the first poller
1768 sometimes waits for the already processed end of fork
1769 event. Doing a non blocking poll here solves the problem. */
1770 if (proc_poll_pipe[0] != -1)
1771 ioctl_result = IOCTL_STATUS (tcp);
1772 else
1773 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001774#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775 ioctl_errno = errno;
1776#ifndef HAVE_POLLABLE_PROCFS
1777 if (proc_poll_pipe[0] != -1) {
1778 if (ioctl_result < 0)
1779 kill(poller_pid, SIGKILL);
1780 else
1781 kill(poller_pid, SIGUSR1);
1782 }
1783#endif /* !HAVE_POLLABLE_PROCFS */
1784 }
1785 if (interrupted)
1786 return 0;
1787
1788 if (interactive)
1789 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1790
1791 if (ioctl_result < 0) {
1792 /* Find out what happened if it failed. */
1793 switch (ioctl_errno) {
1794 case EINTR:
1795 case EBADF:
1796 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001797#ifdef FREEBSD
1798 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001799#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800 case ENOENT:
1801 droptcb(tcp);
1802 continue;
1803 default:
1804 perror("PIOCWSTOP");
1805 exit(1);
1806 }
1807 }
1808
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001809#ifdef FREEBSD
1810 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1811 /* discard first event for a syscall we never entered */
1812 IOCTL (tcp->pfd, PIOCRUN, 0);
1813 continue;
1814 }
Roland McGrath553a6092002-12-16 20:40:39 +00001815#endif
1816
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817 /* clear the just started flag */
1818 tcp->flags &= ~TCB_STARTUP;
1819
1820 /* set current output file */
1821 outf = tcp->outf;
1822
1823 if (cflag) {
1824 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001825#ifdef FREEBSD
1826 char buf[1024];
1827 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001829 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1830 buf[len] = '\0';
1831 sscanf(buf,
1832 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1833 &stime.tv_sec, &stime.tv_usec);
1834 } else
1835 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001836#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837 stime.tv_sec = tcp->status.pr_stime.tv_sec;
1838 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001839#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001840 tv_sub(&tcp->dtime, &stime, &tcp->stime);
1841 tcp->stime = stime;
1842 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001843 what = tcp->status.PR_WHAT;
1844 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001845#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001847 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
1848 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849 if (trace_syscall(tcp) < 0) {
1850 fprintf(stderr, "syscall trouble\n");
1851 exit(1);
1852 }
1853 }
1854 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001855#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001857#ifdef POLL_HACK
1858 in_syscall = tcp;
1859#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001860 case PR_SYSEXIT:
1861 if (trace_syscall(tcp) < 0) {
1862 fprintf(stderr, "syscall trouble\n");
1863 exit(1);
1864 }
1865 break;
1866 case PR_SIGNALLED:
1867 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
1868 printleader(tcp);
1869 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00001870 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00001872#ifdef PR_INFO
1873 if (tcp->status.PR_INFO.si_signo == what) {
1874 printleader(tcp);
1875 tprintf(" siginfo=");
1876 printsiginfo(&tcp->status.PR_INFO, 1);
1877 printtrailer(tcp);
1878 }
1879#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 }
1881 break;
1882 case PR_FAULTED:
1883 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
1884 printleader(tcp);
1885 tprintf("=== FAULT %d ===", what);
1886 printtrailer(tcp);
1887 }
1888 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001889#ifdef FREEBSD
1890 case 0: /* handle case we polled for nothing */
1891 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00001892#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001893 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001894 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001895 exit(1);
1896 break;
1897 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001898 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001899#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001900 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001901#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001902 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001903#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904 perror("PIOCRUN");
1905 exit(1);
1906 }
1907 }
1908 return 0;
1909}
1910
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001911#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001913#ifdef TCB_GROUP_EXITING
1914/* Handle an exit detach or death signal that is taking all the
1915 related clone threads with it. This is called in three circumstances:
1916 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
1917 SIG == 0 Continuing TCP will perform an exit_group syscall.
1918 SIG == other Continuing TCP with SIG will kill the process.
1919*/
1920static int
1921handle_group_exit(struct tcb *tcp, int sig)
1922{
1923 /* We need to locate our records of all the clone threads
1924 related to TCP, either its children or siblings. */
1925 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1926 ? tcp->parent
1927 : tcp->nclone_detached > 0
1928 ? tcp : NULL);
Roland McGrath05690952004-10-20 01:00:27 +00001929 fprintf(stderr,"handle_group_exit (%d [%d], %d)\n", tcp->pid,
1930 leader? leader->pid:-1, sig);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001931
1932 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00001933 if (leader != NULL && leader != tcp &&
1934 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001935 fprintf(stderr,
1936 "PANIC: handle_group_exit: %d leader %d\n",
1937 tcp->pid, leader ? leader->pid : -1);
1938 droptcb(tcp); /* Already died. */
1939 }
1940 else {
1941 if (tcp->flags & TCB_ATTACHED) {
Roland McGrath05690952004-10-20 01:00:27 +00001942 if (leader != NULL && leader != tcp &&
1943 (leader->flags & TCB_ATTACHED)) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001944 /* We need to detach the leader so that the
1945 process death will be reported to its real
1946 parent. But we kill it first to prevent
1947 it doing anything before we kill the whole
1948 process in a moment. We can use
1949 PTRACE_KILL on a thread that's not already
1950 stopped. Then the value we pass in
1951 PTRACE_DETACH just sets the death
1952 signal reported to the real parent. */
1953 ptrace(PTRACE_KILL, leader->pid, 0, 0);
1954 if (debug)
1955 fprintf(stderr,
1956 " [%d exit %d kills %d]\n",
1957 tcp->pid, sig, leader->pid);
1958 detach(leader, sig);
1959 }
1960 detach(tcp, sig);
1961 }
1962 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1963 perror("strace: ptrace(PTRACE_CONT, ...)");
1964 cleanup();
1965 return -1;
1966 }
1967 else {
Roland McGrath05690952004-10-20 01:00:27 +00001968 if (leader != NULL)
1969 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001970 if (leader != NULL && leader != tcp)
1971 droptcb(tcp);
1972 /* The leader will report to us as parent now,
1973 and then we'll get to the SIG==-1 case. */
1974 return 0;
1975 }
1976 }
1977
1978 /* Note that TCP and LEADER are no longer valid,
1979 but we can still compare against them. */
1980 if (leader != NULL) {
1981 unsigned int i;
1982 for (i = 0; i < tcbtabsize; i++) {
1983 struct tcb *t = tcbtab[i];
1984 if (t != tcp && (t->flags & TCB_CLONE_DETACHED)
1985 && t->parent == leader)
1986 droptcb(t);
1987 }
1988 }
1989
1990 return 0;
1991}
1992#endif
1993
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001994static int
1995trace()
1996{
1997 int pid;
1998 int wait_errno;
1999 int status;
2000 struct tcb *tcp;
2001#ifdef LINUX
2002 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002003#ifdef __WALL
2004 static int wait4_options = __WALL;
2005#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002006#endif /* LINUX */
2007
2008 while (nprocs != 0) {
2009 if (interactive)
2010 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2011#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002012#ifdef __WALL
2013 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002014 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002015 /* this kernel does not support __WALL */
2016 wait4_options &= ~__WALL;
2017 errno = 0;
2018 pid = wait4(-1, &status, wait4_options,
2019 cflag ? &ru : NULL);
2020 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002021 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002022 /* most likely a "cloned" process */
2023 pid = wait4(-1, &status, __WCLONE,
2024 cflag ? &ru : NULL);
2025 if (pid == -1) {
2026 fprintf(stderr, "strace: clone wait4 "
2027 "failed: %s\n", strerror(errno));
2028 }
2029 }
2030#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002032#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002033#endif /* LINUX */
2034#ifdef SUNOS4
2035 pid = wait(&status);
2036#endif /* SUNOS4 */
2037 wait_errno = errno;
2038 if (interactive)
2039 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2040
2041 if (interrupted)
2042 return 0;
2043
2044 if (pid == -1) {
2045 switch (wait_errno) {
2046 case EINTR:
2047 continue;
2048 case ECHILD:
2049 /*
2050 * We would like to verify this case
2051 * but sometimes a race in Solbourne's
2052 * version of SunOS sometimes reports
2053 * ECHILD before sending us SIGCHILD.
2054 */
2055#if 0
2056 if (nprocs == 0)
2057 return 0;
2058 fprintf(stderr, "strace: proc miscount\n");
2059 exit(1);
2060#endif
2061 return 0;
2062 default:
2063 errno = wait_errno;
2064 perror("strace: wait");
2065 return -1;
2066 }
2067 }
2068 if (debug)
2069 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2070
2071 /* Look up `pid' in our table. */
2072 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002073#ifdef LINUX
2074 if (followfork || followvfork) {
2075 /* This is needed to go with the CLONE_PTRACE
2076 changes in process.c/util.c: we might see
2077 the child's initial trap before we see the
2078 parent return from the clone syscall.
2079 Leave the child suspended until the parent
2080 returns from its system call. Only then
2081 will we have the association of parent and
2082 child so that we know how to do clearbpt
2083 in the child. */
2084 if ((tcp = alloctcb(pid)) == NULL) {
2085 fprintf(stderr, " [tcb table full]\n");
2086 kill(pid, SIGKILL); /* XXX */
2087 return 0;
2088 }
2089 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2090 newoutf(tcp);
2091 if (!qflag)
2092 fprintf(stderr, "\
2093Process %d attached (waiting for parent)\n",
2094 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002095 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002096 else
2097 /* This can happen if a clone call used
2098 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002099#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002100 {
2101 fprintf(stderr, "unknown pid: %u\n", pid);
2102 if (WIFSTOPPED(status))
2103 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2104 exit(1);
2105 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106 }
2107 /* set current output file */
2108 outf = tcp->outf;
2109 if (cflag) {
2110#ifdef LINUX
2111 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2112 tcp->stime = ru.ru_stime;
2113#endif /* !LINUX */
2114 }
2115
2116 if (tcp->flags & TCB_SUSPENDED) {
2117 /*
2118 * Apparently, doing any ptrace() call on a stopped
2119 * process, provokes the kernel to report the process
2120 * status again on a subsequent wait(), even if the
2121 * process has not been actually restarted.
2122 * Since we have inspected the arguments of suspended
2123 * processes we end up here testing for this case.
2124 */
2125 continue;
2126 }
2127 if (WIFSIGNALED(status)) {
2128 if (!cflag
2129 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2130 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002131 tprintf("+++ killed by %s %s+++",
2132 signame(WTERMSIG(status)),
2133#ifdef WCOREDUMP
2134 WCOREDUMP(status) ? "(core dumped) " :
2135#endif
2136 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002137 printtrailer(tcp);
2138 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002139#ifdef TCB_GROUP_EXITING
2140 handle_group_exit(tcp, -1);
2141#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002143#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002144 continue;
2145 }
2146 if (WIFEXITED(status)) {
2147 if (debug)
2148 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002149 if ((tcp->flags & TCB_ATTACHED)
2150#ifdef TCB_GROUP_EXITING
2151 && !(tcp->parent && (tcp->parent->flags &
2152 TCB_GROUP_EXITING))
2153#endif
2154 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002155 fprintf(stderr,
2156 "PANIC: attached pid %u exited\n",
2157 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002158 if (tcp == tcp_last) {
2159 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2160 == TCB_INSYSCALL)
2161 tprintf(" <unfinished ... exit status %d>\n",
2162 WEXITSTATUS(status));
2163 tcp_last = NULL;
2164 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002165#ifdef TCB_GROUP_EXITING
2166 handle_group_exit(tcp, -1);
2167#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002168 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002169#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 continue;
2171 }
2172 if (!WIFSTOPPED(status)) {
2173 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2174 droptcb(tcp);
2175 continue;
2176 }
2177 if (debug)
2178 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002179 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002180
2181 if (tcp->flags & TCB_STARTUP) {
2182 /*
2183 * This flag is there to keep us in sync.
2184 * Next time this process stops it should
2185 * really be entering a system call.
2186 */
2187 tcp->flags &= ~TCB_STARTUP;
2188 if (tcp->flags & TCB_ATTACHED) {
2189 /*
2190 * Interestingly, the process may stop
2191 * with STOPSIG equal to some other signal
2192 * than SIGSTOP if we happend to attach
2193 * just before the process takes a signal.
2194 */
2195 if (!WIFSTOPPED(status)) {
2196 fprintf(stderr,
2197 "pid %u not stopped\n", pid);
2198 detach(tcp, WSTOPSIG(status));
2199 continue;
2200 }
2201 }
2202 else {
2203#ifdef SUNOS4
2204 /* A child of us stopped at exec */
2205 if (WSTOPSIG(status) == SIGTRAP && followvfork)
2206 fixvfork(tcp);
2207#endif /* SUNOS4 */
2208 }
2209 if (tcp->flags & TCB_BPTSET) {
2210 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2211 droptcb(tcp);
2212 cleanup();
2213 return -1;
2214 }
2215 }
2216 goto tracing;
2217 }
2218
2219 if (WSTOPSIG(status) != SIGTRAP) {
2220 if (WSTOPSIG(status) == SIGSTOP &&
2221 (tcp->flags & TCB_SIGTRAPPED)) {
2222 /*
2223 * Trapped attempt to block SIGTRAP
2224 * Hope we are back in control now.
2225 */
2226 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2227 if (ptrace(PTRACE_SYSCALL,
2228 pid, (char *) 1, 0) < 0) {
2229 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2230 cleanup();
2231 return -1;
2232 }
2233 continue;
2234 }
2235 if (!cflag
2236 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002237 unsigned long addr = 0, pc = 0;
2238#ifdef PT_GETSIGINFO
2239# define PSR_RI 41
2240 struct siginfo si;
2241 unsigned long psr;
2242
2243 upeek(pid, PT_CR_IPSR, &psr);
2244 upeek(pid, PT_CR_IIP, &pc);
2245
2246 pc += (psr >> PSR_RI) & 0x3;
2247 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2248 addr = (unsigned long) si.si_addr;
2249#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002250 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002251 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002252 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002253 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002254 printtrailer(tcp);
2255 }
Roland McGrath05690952004-10-20 01:00:27 +00002256 if (((tcp->flags & TCB_ATTACHED) ||
2257 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002258 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002259#ifdef TCB_GROUP_EXITING
2260 handle_group_exit(tcp, WSTOPSIG(status));
2261#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002262 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002263#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002264 continue;
2265 }
2266 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2267 WSTOPSIG(status)) < 0) {
2268 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2269 cleanup();
2270 return -1;
2271 }
2272 tcp->flags &= ~TCB_SUSPENDED;
2273 continue;
2274 }
2275 if (trace_syscall(tcp) < 0) {
2276 if (tcp->flags & TCB_ATTACHED)
2277 detach(tcp, 0);
2278 else {
2279 ptrace(PTRACE_KILL,
2280 tcp->pid, (char *) 1, SIGTERM);
2281 droptcb(tcp);
2282 }
2283 continue;
2284 }
2285 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002286#ifdef TCB_GROUP_EXITING
2287 if (tcp->flags & TCB_GROUP_EXITING) {
2288 if (handle_group_exit(tcp, 0) < 0)
2289 return -1;
2290 continue;
2291 }
2292#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002293 if (tcp->flags & TCB_ATTACHED)
2294 detach(tcp, 0);
2295 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2296 perror("strace: ptrace(PTRACE_CONT, ...)");
2297 cleanup();
2298 return -1;
2299 }
2300 continue;
2301 }
2302 if (tcp->flags & TCB_SUSPENDED) {
2303 if (!qflag)
2304 fprintf(stderr, "Process %u suspended\n", pid);
2305 continue;
2306 }
2307 tracing:
2308 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2309 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2310 cleanup();
2311 return -1;
2312 }
2313 }
2314 return 0;
2315}
2316
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002317#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002318
2319static int curcol;
2320
2321#ifdef __STDC__
2322#include <stdarg.h>
2323#define VA_START(a, b) va_start(a, b)
2324#else
2325#include <varargs.h>
2326#define VA_START(a, b) va_start(a)
2327#endif
2328
2329void
2330#ifdef __STDC__
2331tprintf(const char *fmt, ...)
2332#else
2333tprintf(fmt, va_alist)
2334char *fmt;
2335va_dcl
2336#endif
2337{
2338 va_list args;
2339
2340 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002341 if (outf) {
2342 int n = vfprintf(outf, fmt, args);
2343 if (n < 0 && outf != stderr)
2344 perror(outfname == NULL
2345 ? "<writing to pipe>" : outfname);
2346 else
2347 curcol += n;
2348 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002349 va_end(args);
2350 return;
2351}
2352
2353void
2354printleader(tcp)
2355struct tcb *tcp;
2356{
2357 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2358 tcp_last->flags |= TCB_REPRINT;
2359 tprintf(" <unfinished ...>\n");
2360 }
2361 curcol = 0;
2362 if ((followfork == 1 || pflag_seen > 1) && outfname)
2363 tprintf("%-5d ", tcp->pid);
2364 else if (nprocs > 1 && !outfname)
2365 tprintf("[pid %5u] ", tcp->pid);
2366 if (tflag) {
2367 char str[sizeof("HH:MM:SS")];
2368 struct timeval tv, dtv;
2369 static struct timeval otv;
2370
2371 gettimeofday(&tv, NULL);
2372 if (rflag) {
2373 if (otv.tv_sec == 0)
2374 otv = tv;
2375 tv_sub(&dtv, &tv, &otv);
2376 tprintf("%6ld.%06ld ",
2377 (long) dtv.tv_sec, (long) dtv.tv_usec);
2378 otv = tv;
2379 }
2380 else if (tflag > 2) {
2381 tprintf("%ld.%06ld ",
2382 (long) tv.tv_sec, (long) tv.tv_usec);
2383 }
2384 else {
2385 time_t local = tv.tv_sec;
2386 strftime(str, sizeof(str), "%T", localtime(&local));
2387 if (tflag > 1)
2388 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2389 else
2390 tprintf("%s ", str);
2391 }
2392 }
2393 if (iflag)
2394 printcall(tcp);
2395}
2396
2397void
2398tabto(col)
2399int col;
2400{
2401 if (curcol < col)
2402 tprintf("%*s", col - curcol, "");
2403}
2404
2405void
2406printtrailer(tcp)
2407struct tcb *tcp;
2408{
2409 tprintf("\n");
2410 tcp_last = NULL;
2411}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002412
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002413#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002414
2415int mp_ioctl (int fd, int cmd, void *arg, int size) {
2416
2417 struct iovec iov[2];
2418 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002419
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002420 iov[0].iov_base = &cmd;
2421 iov[0].iov_len = sizeof cmd;
2422 if (arg) {
2423 ++n;
2424 iov[1].iov_base = arg;
2425 iov[1].iov_len = size;
2426 }
Roland McGrath553a6092002-12-16 20:40:39 +00002427
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002428 return writev (fd, iov, n);
2429}
2430
2431#endif