blob: f78458c3183e00c47c18c4a8465e133f82cca757 [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
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);
Roland McGrathdccec722005-05-09 07:45:47 +0000288 if (max_strlen < 0) {
289 fprintf(stderr,
290 "%s: invalid -s argument: %s\n",
291 progname, optarg);
292 exit(1);
293 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000294 break;
295 case 'S':
296 set_sortby(optarg);
297 break;
298 case 'u':
299 username = strdup(optarg);
300 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000301 case 'E':
302 if (putenv(optarg) < 0) {
303 fprintf(stderr, "%s: out of memory\n",
304 progname);
305 exit(1);
306 }
307 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000308 default:
309 usage(stderr, 1);
310 break;
311 }
312 }
313
Roland McGrathce0d1542003-11-11 21:24:23 +0000314 if (optind == argc && !pflag_seen)
315 usage(stderr, 1);
316
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317 /* See if they want to run as another user. */
318 if (username != NULL) {
319 struct passwd *pent;
320
321 if (getuid() != 0 || geteuid() != 0) {
322 fprintf(stderr,
323 "%s: you must be root to use the -u option\n",
324 progname);
325 exit(1);
326 }
327 if ((pent = getpwnam(username)) == NULL) {
328 fprintf(stderr, "%s: cannot find user `%s'\n",
329 progname, optarg);
330 exit(1);
331 }
332 run_uid = pent->pw_uid;
333 run_gid = pent->pw_gid;
334 }
335 else {
336 run_uid = getuid();
337 run_gid = getgid();
338 }
339
340#ifndef SVR4
341 setreuid(geteuid(), getuid());
342#endif
343
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000344 /* Check if they want to redirect the output. */
345 if (outfname) {
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000346 long f;
347
Roland McGrath37b9a662003-11-07 02:26:54 +0000348 /* See if they want to pipe the output. */
349 if (outfname[0] == '|' || outfname[0] == '!') {
350 /*
351 * We can't do the <outfname>.PID funny business
352 * when using popen, so prohibit it.
353 */
354 if (followfork > 1) {
355 fprintf(stderr, "\
356%s: piping the output and -ff are mutually exclusive options\n",
357 progname);
358 exit(1);
359 }
360
361 if ((outf = popen(outfname + 1, "w")) == NULL) {
362 fprintf(stderr, "%s: can't popen '%s': %s\n",
363 progname, outfname + 1,
364 strerror(errno));
365 exit(1);
366 }
367 }
368 else if ((outf = fopen(outfname, "w")) == NULL) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000369 fprintf(stderr, "%s: can't fopen '%s': %s\n",
370 progname, outfname, strerror(errno));
371 exit(1);
372 }
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000373
374 if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
375 perror("failed to get flags for outputfile");
376 exit(1);
377 }
378
379 if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
380 perror("failed to set flags for outputfile");
381 exit(1);
382 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000383 }
384
385#ifndef SVR4
386 setreuid(geteuid(), getuid());
387#endif
388
Roland McGrath37b9a662003-11-07 02:26:54 +0000389 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000391 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000394 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000395
Roland McGrathee9d4352002-12-18 04:16:10 +0000396 for (c = 0; c < tcbtabsize; c++) {
397 tcp = tcbtab[c];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000398 /* Reinitialize the output since it may have changed. */
399 tcp->outf = outf;
400 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
401 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000402#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403 if (proc_open(tcp, 1) < 0) {
404 fprintf(stderr, "trouble opening proc file\n");
405 droptcb(tcp);
406 continue;
407 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000408#else /* !USE_PROCFS */
Roland McGrath70b08532004-04-09 00:25:21 +0000409# ifdef LINUX
410 if (tcp->flags & TCB_CLONE_THREAD)
411 continue;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000412 if (followfork) {
Roland McGrath70b08532004-04-09 00:25:21 +0000413 char procdir[MAXPATHLEN];
414 DIR *dir;
415 sprintf(procdir, "/proc/%d/task", tcp->pid);
416 dir = opendir(procdir);
417 if (dir != NULL) {
418 unsigned int ntid = 0, nerr = 0;
419 struct dirent *de;
420 int tid;
421 while ((de = readdir(dir)) != NULL) {
422 if (de->d_fileno == 0 ||
423 de->d_name[0] == '.')
424 continue;
425 tid = atoi(de->d_name);
426 if (tid <= 0)
427 continue;
428 ++ntid;
429 if (ptrace(PTRACE_ATTACH, tid,
430 (char *) 1, 0) < 0)
431 ++nerr;
432 else if (tid != tcbtab[c]->pid) {
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000433 if (nprocs == tcbtabsize &&
434 expand_tcbtab())
435 tcp = NULL;
436 else
437 tcp = alloctcb(tid);
Roland McGrath70b08532004-04-09 00:25:21 +0000438 if (tcp == NULL) {
439 fprintf(stderr, "%s: out of memory\n",
440 progname);
441 exit(1);
442 }
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000443 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath70b08532004-04-09 00:25:21 +0000444 tcbtab[c]->nchildren++;
445 tcbtab[c]->nclone_threads++;
446 tcbtab[c]->nclone_detached++;
447 tcp->parent = tcbtab[c];
448 }
449 }
450 closedir(dir);
451 if (nerr == ntid) {
452 perror("attach: ptrace(PTRACE_ATTACH, ...)");
453 droptcb(tcp);
454 continue;
455 }
456 if (!qflag) {
457 ntid -= nerr;
458 if (ntid > 1)
459 fprintf(stderr, "\
460Process %u attached with %u threads - interrupt to quit\n",
461 tcp->pid, ntid);
462 else
463 fprintf(stderr, "\
464Process %u attached - interrupt to quit\n",
465 tcp->pid);
466 }
467 continue;
468 }
469 }
470# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000471 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
472 perror("attach: ptrace(PTRACE_ATTACH, ...)");
473 droptcb(tcp);
474 continue;
475 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000476#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000477 if (!qflag)
478 fprintf(stderr,
479 "Process %u attached - interrupt to quit\n",
Roland McGrathc3266d52004-02-20 02:23:52 +0000480 tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000481 }
482
Roland McGrathce0d1542003-11-11 21:24:23 +0000483 if (!pflag_seen) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000484 struct stat statbuf;
485 char *filename;
486 char pathname[MAXPATHLEN];
487
488 filename = argv[optind];
Roland McGrathbdb09df2004-03-02 06:50:04 +0000489 if (strchr(filename, '/')) {
490 if (strlen(filename) > sizeof pathname - 1) {
491 errno = ENAMETOOLONG;
492 perror("strace: exec");
493 exit(1);
494 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000495 strcpy(pathname, filename);
Roland McGrathbdb09df2004-03-02 06:50:04 +0000496 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497#ifdef USE_DEBUGGING_EXEC
498 /*
499 * Debuggers customarily check the current directory
500 * first regardless of the path but doing that gives
501 * security geeks a panic attack.
502 */
503 else if (stat(filename, &statbuf) == 0)
504 strcpy(pathname, filename);
505#endif /* USE_DEBUGGING_EXEC */
506 else {
507 char *path;
508 int m, n, len;
509
510 for (path = getenv("PATH"); path && *path; path += m) {
511 if (strchr(path, ':')) {
512 n = strchr(path, ':') - path;
513 m = n + 1;
514 }
515 else
516 m = n = strlen(path);
517 if (n == 0) {
518 getcwd(pathname, MAXPATHLEN);
519 len = strlen(pathname);
520 }
Roland McGrathbdb09df2004-03-02 06:50:04 +0000521 else if (n > sizeof pathname - 1)
522 continue;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523 else {
524 strncpy(pathname, path, n);
525 len = n;
526 }
527 if (len && pathname[len - 1] != '/')
528 pathname[len++] = '/';
529 strcpy(pathname + len, filename);
Roland McGrathed645162003-06-03 07:18:19 +0000530 if (stat(pathname, &statbuf) == 0 &&
531 /* Accept only regular files
532 with some execute bits set.
533 XXX not perfect, might still fail */
534 S_ISREG(statbuf.st_mode) &&
535 (statbuf.st_mode & 0111))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536 break;
537 }
538 }
539 if (stat(pathname, &statbuf) < 0) {
540 fprintf(stderr, "%s: %s: command not found\n",
541 progname, filename);
542 exit(1);
543 }
544 switch (pid = fork()) {
545 case -1:
546 perror("strace: fork");
547 cleanup();
548 exit(1);
549 break;
550 case 0: {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000551#ifdef USE_PROCFS
552 if (outf != stderr) close (fileno (outf));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000553#ifdef MIPS
554 /* Kludge for SGI, see proc_open for details. */
555 sa.sa_handler = foobar;
556 sa.sa_flags = 0;
557 sigemptyset(&sa.sa_mask);
558 sigaction(SIGINT, &sa, NULL);
559#endif /* MIPS */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000560#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561 pause();
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000562#else /* FREEBSD */
563 kill(getpid(), SIGSTOP); /* stop HERE */
Roland McGrath553a6092002-12-16 20:40:39 +0000564#endif /* FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000565#else /* !USE_PROCFS */
Roland McGrath553a6092002-12-16 20:40:39 +0000566 if (outf!=stderr)
Wichert Akkerman7987cdf2000-07-05 16:05:39 +0000567 close(fileno (outf));
Wichert Akkermanbd4125c2000-06-27 17:28:06 +0000568
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000569 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
570 perror("strace: ptrace(PTRACE_TRACEME, ...)");
571 return -1;
572 }
573 if (debug)
574 kill(getpid(), SIGSTOP);
575
576 if (username != NULL || geteuid() == 0) {
577 uid_t run_euid = run_uid;
578 gid_t run_egid = run_gid;
579
580 if (statbuf.st_mode & S_ISUID)
581 run_euid = statbuf.st_uid;
582 if (statbuf.st_mode & S_ISGID)
583 run_egid = statbuf.st_gid;
584
585 /*
586 * It is important to set groups before we
587 * lose privileges on setuid.
588 */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +0000589 if (username != NULL) {
590 if (initgroups(username, run_gid) < 0) {
591 perror("initgroups");
592 exit(1);
593 }
594 if (setregid(run_gid, run_egid) < 0) {
595 perror("setregid");
596 exit(1);
597 }
598 if (setreuid(run_uid, run_euid) < 0) {
599 perror("setreuid");
600 exit(1);
601 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602 }
603 }
604 else
605 setreuid(run_uid, run_uid);
Roland McGrath15dca8e2005-02-06 01:16:32 +0000606
607 /*
608 * Induce an immediate stop so that the parent
609 * will resume us with PTRACE_SYSCALL and display
610 * this execve call normally.
611 */
612 kill(getpid(), SIGSTOP);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000613#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614
615 execv(pathname, &argv[optind]);
616 perror("strace: exec");
617 _exit(1);
618 break;
619 }
620 default:
621 if ((tcp = alloctcb(pid)) == NULL) {
622 fprintf(stderr, "tcb table full\n");
623 cleanup();
624 exit(1);
625 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000626#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627 if (proc_open(tcp, 0) < 0) {
628 fprintf(stderr, "trouble opening proc file\n");
629 cleanup();
630 exit(1);
631 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000632#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000633 break;
634 }
635 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000636
637 sigemptyset(&empty_set);
638 sigemptyset(&blocked_set);
639 sa.sa_handler = SIG_IGN;
640 sigemptyset(&sa.sa_mask);
641 sa.sa_flags = 0;
642 sigaction(SIGTTOU, &sa, NULL);
643 sigaction(SIGTTIN, &sa, NULL);
644 if (interactive) {
645 sigaddset(&blocked_set, SIGHUP);
646 sigaddset(&blocked_set, SIGINT);
647 sigaddset(&blocked_set, SIGQUIT);
648 sigaddset(&blocked_set, SIGPIPE);
649 sigaddset(&blocked_set, SIGTERM);
650 sa.sa_handler = interrupt;
651#ifdef SUNOS4
652 /* POSIX signals on sunos4.1 are a little broken. */
653 sa.sa_flags = SA_INTERRUPT;
654#endif /* SUNOS4 */
655 }
656 sigaction(SIGHUP, &sa, NULL);
657 sigaction(SIGINT, &sa, NULL);
658 sigaction(SIGQUIT, &sa, NULL);
659 sigaction(SIGPIPE, &sa, NULL);
660 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000661#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000662 sa.sa_handler = reaper;
663 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000664#else
665 /* Make sure SIGCHLD has the default action so that waitpid
666 definitely works without losing track of children. The user
667 should not have given us a bogus state to inherit, but he might
668 have. Arguably we should detect SIG_IGN here and pass it on
669 to children, but probably noone really needs that. */
670 sa.sa_handler = SIG_DFL;
671 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000672#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000673
674 if (trace() < 0)
675 exit(1);
676 cleanup();
677 exit(0);
678}
679
680void
681newoutf(tcp)
682struct tcb *tcp;
683{
684 char name[MAXPATHLEN];
685 FILE *fp;
686
687 if (outfname && followfork > 1) {
688 sprintf(name, "%s.%u", outfname, tcp->pid);
689#ifndef SVR4
690 setreuid(geteuid(), getuid());
691#endif
692 fp = fopen(name, "w");
693#ifndef SVR4
694 setreuid(geteuid(), getuid());
695#endif
696 if (fp == NULL) {
697 perror("fopen");
698 return;
699 }
700 tcp->outf = fp;
701 }
702 return;
703}
704
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000705int
706expand_tcbtab()
707{
708 /* Allocate some more TCBs and expand the table.
709 We don't want to relocate the TCBs because our
710 callers have pointers and it would be a pain.
711 So tcbtab is a table of pointers. Since we never
712 free the TCBs, we allocate a single chunk of many. */
713 struct tcb **newtab = (struct tcb **)
714 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
715 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
716 sizeof *newtcbs);
717 int i;
718 if (newtab == NULL || newtcbs == NULL) {
719 if (newtab != NULL)
720 free(newtab);
721 return 1;
722 }
723 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
724 newtab[i] = &newtcbs[i - tcbtabsize];
725 tcbtabsize *= 2;
726 tcbtab = newtab;
727
728 return 0;
729}
730
731
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732struct tcb *
733alloctcb(pid)
734int pid;
735{
736 int i;
737 struct tcb *tcp;
738
Roland McGrathee9d4352002-12-18 04:16:10 +0000739 for (i = 0; i < tcbtabsize; i++) {
740 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000741 if ((tcp->flags & TCB_INUSE) == 0) {
742 tcp->pid = pid;
743 tcp->parent = NULL;
744 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000745 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000746#ifdef TCB_CLONE_THREAD
747 tcp->nclone_threads = tcp->nclone_detached = 0;
748 tcp->nclone_waiting = 0;
749#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000750 tcp->flags = TCB_INUSE | TCB_STARTUP;
751 tcp->outf = outf; /* Initialise to current out file */
752 tcp->stime.tv_sec = 0;
753 tcp->stime.tv_usec = 0;
754 tcp->pfd = -1;
755 nprocs++;
756 return tcp;
757 }
758 }
759 return NULL;
760}
761
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000762#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000763int
764proc_open(tcp, attaching)
765struct tcb *tcp;
766int attaching;
767{
768 char proc[32];
769 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000770#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000771 int i;
772 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000773 sigset_t signals;
774 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000775#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776#ifndef HAVE_POLLABLE_PROCFS
777 static int last_pfd;
778#endif
779
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000780#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000781 /* Open the process pseudo-files in /proc. */
782 sprintf(proc, "/proc/%d/ctl", tcp->pid);
783 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000784 perror("strace: open(\"/proc/...\", ...)");
785 return -1;
786 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
788 perror("F_GETFD");
789 return -1;
790 }
791 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
792 perror("F_SETFD");
793 return -1;
794 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000795 sprintf(proc, "/proc/%d/status", tcp->pid);
796 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
797 perror("strace: open(\"/proc/...\", ...)");
798 return -1;
799 }
800 if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
801 perror("F_GETFD");
802 return -1;
803 }
804 if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
805 perror("F_SETFD");
806 return -1;
807 }
808 sprintf(proc, "/proc/%d/as", tcp->pid);
809 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
810 perror("strace: open(\"/proc/...\", ...)");
811 return -1;
812 }
813 if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
814 perror("F_GETFD");
815 return -1;
816 }
817 if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
818 perror("F_SETFD");
819 return -1;
820 }
821#else
822 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000823#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000824 sprintf(proc, "/proc/%d", tcp->pid);
825 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000826#else /* FREEBSD */
827 sprintf(proc, "/proc/%d/mem", tcp->pid);
828 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
829#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000830 perror("strace: open(\"/proc/...\", ...)");
831 return -1;
832 }
833 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
834 perror("F_GETFD");
835 return -1;
836 }
837 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
838 perror("F_SETFD");
839 return -1;
840 }
841#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000842#ifdef FREEBSD
843 sprintf(proc, "/proc/%d/regs", tcp->pid);
844 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
845 perror("strace: open(\"/proc/.../regs\", ...)");
846 return -1;
847 }
848 if (cflag) {
849 sprintf(proc, "/proc/%d/status", tcp->pid);
850 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
851 perror("strace: open(\"/proc/.../status\", ...)");
852 return -1;
853 }
854 } else
855 tcp->pfd_status = -1;
856#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000857 rebuild_pollv();
858 if (!attaching) {
859 /*
860 * Wait for the child to pause. Because of a race
861 * condition we have to poll for the event.
862 */
863 for (;;) {
864 if (IOCTL_STATUS (tcp) < 0) {
865 perror("strace: PIOCSTATUS");
866 return -1;
867 }
868 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000869 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000870 }
871 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000872#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000873 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000874 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000875 perror("strace: PIOCSTOP");
876 return -1;
877 }
Roland McGrath553a6092002-12-16 20:40:39 +0000878#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879#ifdef PIOCSET
880 /* Set Run-on-Last-Close. */
881 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000882 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883 perror("PIOCSET PR_RLC");
884 return -1;
885 }
886 /* Set or Reset Inherit-on-Fork. */
887 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000888 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889 perror("PIOC{SET,RESET} PR_FORK");
890 return -1;
891 }
892#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +0000893#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
895 perror("PIOCSRLC");
896 return -1;
897 }
898 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
899 perror("PIOC{S,R}FORK");
900 return -1;
901 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000902#else /* FREEBSD */
903 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
904 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
905 perror("PIOCGFL");
906 return -1;
907 }
908 arg &= ~PF_LINGER;
909 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
910 perror("PIOCSFL");
911 return -1;
912 }
913#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000915#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +0000916 /* Enable all syscall entries we care about. */
917 premptyset(&syscalls);
918 for (i = 1; i < MAX_QUALS; ++i) {
919 if (i > (sizeof syscalls) * CHAR_BIT) break;
920 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
921 }
922 praddset (&syscalls, SYS_execve);
923 if (followfork) {
924 praddset (&syscalls, SYS_fork);
925#ifdef SYS_forkall
926 praddset (&syscalls, SYS_forkall);
927#endif
Roland McGrath553a6092002-12-16 20:40:39 +0000928#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +0000929 praddset (&syscalls, SYS_fork1);
930#endif
931#ifdef SYS_rfork1
932 praddset (&syscalls, SYS_rfork1);
933#endif
934#ifdef SYS_rforkall
935 praddset (&syscalls, SYS_rforkall);
936#endif
937 }
938 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939 perror("PIOCSENTRY");
940 return -1;
941 }
John Hughes19e49982001-10-19 08:59:12 +0000942 /* Enable the syscall exits. */
943 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944 perror("PIOSEXIT");
945 return -1;
946 }
John Hughes19e49982001-10-19 08:59:12 +0000947 /* Enable signals we care about. */
948 premptyset(&signals);
949 for (i = 1; i < MAX_QUALS; ++i) {
950 if (i > (sizeof signals) * CHAR_BIT) break;
951 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
952 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000953 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954 perror("PIOCSTRACE");
955 return -1;
956 }
John Hughes19e49982001-10-19 08:59:12 +0000957 /* Enable faults we care about */
958 premptyset(&faults);
959 for (i = 1; i < MAX_QUALS; ++i) {
960 if (i > (sizeof faults) * CHAR_BIT) break;
961 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
962 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000963 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000964 perror("PIOCSFAULT");
965 return -1;
966 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000967#else /* FREEBSD */
968 /* set events flags. */
969 arg = S_SIG | S_SCE | S_SCX ;
970 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
971 perror("PIOCBIS");
972 return -1;
973 }
974#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 if (!attaching) {
976#ifdef MIPS
977 /*
978 * The SGI PRSABORT doesn't work for pause() so
979 * we send it a caught signal to wake it up.
980 */
981 kill(tcp->pid, SIGINT);
982#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +0000983#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000985 arg = PRSABORT;
986 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 perror("PIOCRUN");
988 return -1;
989 }
Roland McGrath553a6092002-12-16 20:40:39 +0000990#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000991#endif /* !MIPS*/
992#ifdef FREEBSD
993 /* wake up the child if it received the SIGSTOP */
994 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +0000995#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 for (;;) {
997 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000998 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 perror("PIOCWSTOP");
1000 return -1;
1001 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001002 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001003 tcp->flags &= ~TCB_INSYSCALL;
1004 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001005 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 break;
1007 }
1008 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001009#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001010 arg = 0;
1011 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001012#else /* FREEBSD */
1013 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001014#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015 perror("PIOCRUN");
1016 return -1;
1017 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001018#ifdef FREEBSD
1019 /* handle the case where we "opened" the child before
1020 it did the kill -STOP */
1021 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1022 tcp->status.PR_WHAT == SIGSTOP)
1023 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001024#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001026#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001028#else /* FREEBSD */
1029 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001030 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001031 /* We are attaching to an already running process.
1032 * Try to figure out the state of the process in syscalls,
1033 * to handle the first event well.
1034 * This is done by having a look at the "wchan" property of the
1035 * process, which tells where it is stopped (if it is). */
1036 FILE * status;
1037 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001038
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001039 sprintf(proc, "/proc/%d/status", tcp->pid);
1040 status = fopen(proc, "r");
1041 if (status &&
1042 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1043 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1044 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1045 strcmp(wchan, "stopevent")) {
1046 /* The process is asleep in the middle of a syscall.
1047 Fake the syscall entry event */
1048 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1049 tcp->status.PR_WHY = PR_SYSENTRY;
1050 trace_syscall(tcp);
1051 }
1052 if (status)
1053 fclose(status);
1054 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001055 }
1056#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057#ifndef HAVE_POLLABLE_PROCFS
1058 if (proc_poll_pipe[0] != -1)
1059 proc_poller(tcp->pfd);
1060 else if (nprocs > 1) {
1061 proc_poll_open();
1062 proc_poller(last_pfd);
1063 proc_poller(tcp->pfd);
1064 }
1065 last_pfd = tcp->pfd;
1066#endif /* !HAVE_POLLABLE_PROCFS */
1067 return 0;
1068}
1069
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001070#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001072struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073pid2tcb(pid)
1074int pid;
1075{
1076 int i;
1077 struct tcb *tcp;
1078
Roland McGrathee9d4352002-12-18 04:16:10 +00001079 for (i = 0; i < tcbtabsize; i++) {
1080 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081 if (pid && tcp->pid != pid)
1082 continue;
1083 if (tcp->flags & TCB_INUSE)
1084 return tcp;
1085 }
1086 return NULL;
1087}
1088
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001089#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001090
1091static struct tcb *
1092pfd2tcb(pfd)
1093int pfd;
1094{
1095 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001096
Roland McGrathca16be82003-01-10 19:55:28 +00001097 for (i = 0; i < tcbtabsize; i++) {
1098 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 if (tcp->pfd != pfd)
1100 continue;
1101 if (tcp->flags & TCB_INUSE)
1102 return tcp;
1103 }
1104 return NULL;
1105}
1106
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001107#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108
1109void
1110droptcb(tcp)
1111struct tcb *tcp;
1112{
1113 if (tcp->pid == 0)
1114 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001115#ifdef TCB_CLONE_THREAD
1116 if (tcp->nclone_threads > 0) {
1117 /* There are other threads left in this process, but this
1118 is the one whose PID represents the whole process.
1119 We need to keep this record around as a zombie until
1120 all the threads die. */
1121 tcp->flags |= TCB_EXITING;
1122 return;
1123 }
1124#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125 nprocs--;
1126 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001127
Roland McGrathe29341c2003-01-10 20:14:20 +00001128 if (tcp->parent != NULL) {
1129 tcp->parent->nchildren--;
1130#ifdef TCB_CLONE_THREAD
1131 if (tcp->flags & TCB_CLONE_DETACHED)
1132 tcp->parent->nclone_detached--;
1133 if (tcp->flags & TCB_CLONE_THREAD)
1134 tcp->parent->nclone_threads--;
1135#endif
Roland McGrath09623452003-05-23 02:27:13 +00001136#ifdef TCB_CLONE_DETACHED
1137 if (!(tcp->flags & TCB_CLONE_DETACHED))
1138#endif
1139 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001140 tcp->parent = NULL;
1141 }
1142
1143 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 if (tcp->pfd != -1) {
1145 close(tcp->pfd);
1146 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001147#ifdef FREEBSD
1148 if (tcp->pfd_reg != -1) {
1149 close(tcp->pfd_reg);
1150 tcp->pfd_reg = -1;
1151 }
1152 if (tcp->pfd_status != -1) {
1153 close(tcp->pfd_status);
1154 tcp->pfd_status = -1;
1155 }
Roland McGrath553a6092002-12-16 20:40:39 +00001156#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001157#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001158 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159#endif
1160 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001161
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001162 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001164
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 tcp->outf = 0;
1166}
1167
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001168#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169
1170static int
1171resume(tcp)
1172struct tcb *tcp;
1173{
1174 if (tcp == NULL)
1175 return -1;
1176
1177 if (!(tcp->flags & TCB_SUSPENDED)) {
1178 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1179 return -1;
1180 }
1181 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001182#ifdef TCB_CLONE_THREAD
1183 if (tcp->flags & TCB_CLONE_THREAD)
1184 tcp->parent->nclone_waiting--;
1185#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186
1187 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1188 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1189 return -1;
1190 }
1191
1192 if (!qflag)
1193 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1194 return 0;
1195}
1196
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001197#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198
1199/* detach traced process; continue with sig */
1200
1201static int
1202detach(tcp, sig)
1203struct tcb *tcp;
1204int sig;
1205{
1206 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001207#ifdef LINUX
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001208 int status, resumed;
Roland McGratha08a97e2005-08-03 11:23:46 +00001209 struct tcb *zombie = NULL;
1210
1211 /* If the group leader is lingering only because of this other
1212 thread now dying, then detach the leader as well. */
1213 if ((tcp->flags & TCB_CLONE_THREAD) &&
1214 tcp->parent->nclone_threads == 1 &&
1215 (tcp->parent->flags & TCB_EXITING))
1216 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001217#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001218
1219 if (tcp->flags & TCB_BPTSET)
1220 sig = SIGKILL;
1221
1222#ifdef LINUX
1223 /*
1224 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001225 * before detaching. Arghh. We go through hoops
1226 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001228#if defined(SPARC)
1229#undef PTRACE_DETACH
1230#define PTRACE_DETACH PTRACE_SUNDETACH
1231#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1233 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001234 }
1235 else if (errno != ESRCH) {
1236 /* Shouldn't happen. */
1237 perror("detach: ptrace(PTRACE_DETACH, ...)");
1238 }
1239 else if (kill(tcp->pid, 0) < 0) {
1240 if (errno != ESRCH)
1241 perror("detach: checking sanity");
1242 }
1243 else if (kill(tcp->pid, SIGSTOP) < 0) {
1244 if (errno != ESRCH)
1245 perror("detach: stopping child");
1246 }
1247 else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001249#ifdef __WALL
1250 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1251 if (errno == ECHILD) /* Already gone. */
1252 break;
1253 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001254 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001255 break;
1256 }
1257#endif /* __WALL */
1258 /* No __WALL here. */
1259 if (waitpid(tcp->pid, &status, 0) < 0) {
1260 if (errno != ECHILD) {
1261 perror("detach: waiting");
1262 break;
1263 }
1264#ifdef __WCLONE
1265 /* If no processes, try clones. */
1266 if (wait4(tcp->pid, &status, __WCLONE,
1267 NULL) < 0) {
1268 if (errno != ECHILD)
1269 perror("detach: waiting");
1270 break;
1271 }
1272#endif /* __WCLONE */
1273 }
1274#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001275 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001276#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001277 if (!WIFSTOPPED(status)) {
1278 /* Au revoir, mon ami. */
1279 break;
1280 }
1281 if (WSTOPSIG(status) == SIGSTOP) {
1282 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001283 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284 if (errno != ESRCH)
1285 perror("detach: ptrace(PTRACE_DETACH, ...)");
1286 /* I died trying. */
1287 }
1288 break;
1289 }
1290 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001291 WSTOPSIG(status) == SIGTRAP ?
1292 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293 if (errno != ESRCH)
1294 perror("detach: ptrace(PTRACE_CONT, ...)");
1295 break;
1296 }
1297 }
1298 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001299#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001300
1301#if defined(SUNOS4)
1302 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1303 if (sig && kill(tcp->pid, sig) < 0)
1304 perror("detach: kill");
1305 sig = 0;
1306 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1307 perror("detach: ptrace(PTRACE_DETACH, ...)");
1308#endif /* SUNOS4 */
1309
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001310#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001311 resumed = 0;
1312
1313 /* XXX This won't always be quite right (but it never was).
1314 A waiter with argument 0 or < -1 is waiting for any pid in
1315 a particular pgrp, which this child might or might not be
1316 in. The waiter will only wake up if it's argument is -1
1317 or if it's waiting for tcp->pid's pgrp. It makes a
1318 difference to wake up a waiter when there might be more
1319 traced children, because it could get a false ECHILD
1320 error. OTOH, if this was the last child in the pgrp, then
1321 it ought to wake up and get ECHILD. We would have to
1322 search the system for all pid's in the pgrp to be sure.
1323
1324 && (t->waitpid == -1 ||
1325 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1326 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1327 */
1328
1329 if (tcp->parent &&
1330 (tcp->parent->flags & TCB_SUSPENDED) &&
1331 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1332 error = resume(tcp->parent);
1333 ++resumed;
1334 }
1335#ifdef TCB_CLONE_THREAD
1336 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1337 /* Some other threads of our parent are waiting too. */
1338 unsigned int i;
1339
1340 /* Resume all the threads that were waiting for this PID. */
1341 for (i = 0; i < tcbtabsize; i++) {
1342 struct tcb *t = tcbtab[i];
1343 if (t->parent == tcp->parent && t != tcp
1344 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1345 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1346 && t->waitpid == tcp->pid) {
1347 error |= resume (t);
1348 ++resumed;
1349 }
1350 }
1351 if (resumed == 0)
1352 /* Noone was waiting for this PID in particular,
1353 so now we might need to resume some wildcarders. */
1354 for (i = 0; i < tcbtabsize; i++) {
1355 struct tcb *t = tcbtab[i];
1356 if (t->parent == tcp->parent && t != tcp
1357 && ((t->flags
1358 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1359 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1360 && t->waitpid <= 0
1361 ) {
1362 error |= resume (t);
1363 break;
1364 }
1365 }
1366 }
1367#endif
1368
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001369#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001370
1371 if (!qflag)
1372 fprintf(stderr, "Process %u detached\n", tcp->pid);
1373
1374 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001375
1376#ifdef LINUX
1377 if (zombie != NULL)
1378 error = detach(zombie) || error;
1379#endif
1380
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001381 return error;
1382}
1383
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001384#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385
1386static void
1387reaper(sig)
1388int sig;
1389{
1390 int pid;
1391 int status;
1392
1393 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1394#if 0
1395 struct tcb *tcp;
1396
1397 tcp = pid2tcb(pid);
1398 if (tcp)
1399 droptcb(tcp);
1400#endif
1401 }
1402}
1403
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001404#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405
1406static void
1407cleanup()
1408{
1409 int i;
1410 struct tcb *tcp;
1411
Roland McGrathee9d4352002-12-18 04:16:10 +00001412 for (i = 0; i < tcbtabsize; i++) {
1413 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001414 if (!(tcp->flags & TCB_INUSE))
1415 continue;
1416 if (debug)
1417 fprintf(stderr,
1418 "cleanup: looking at pid %u\n", tcp->pid);
1419 if (tcp_last &&
1420 (!outfname || followfork < 2 || tcp_last == tcp)) {
1421 tprintf(" <unfinished ...>\n");
1422 tcp_last = NULL;
1423 }
1424 if (tcp->flags & TCB_ATTACHED)
1425 detach(tcp, 0);
1426 else {
1427 kill(tcp->pid, SIGCONT);
1428 kill(tcp->pid, SIGTERM);
1429 }
1430 }
1431 if (cflag)
1432 call_summary(outf);
1433}
1434
1435static void
1436interrupt(sig)
1437int sig;
1438{
1439 interrupted = 1;
1440}
1441
1442#ifndef HAVE_STRERROR
1443
Roland McGrath6d2b3492002-12-30 00:51:30 +00001444#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445extern int sys_nerr;
1446extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001447#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448
1449const char *
1450strerror(errno)
1451int errno;
1452{
1453 static char buf[64];
1454
1455 if (errno < 1 || errno >= sys_nerr) {
1456 sprintf(buf, "Unknown error %d", errno);
1457 return buf;
1458 }
1459 return sys_errlist[errno];
1460}
1461
1462#endif /* HAVE_STERRROR */
1463
1464#ifndef HAVE_STRSIGNAL
1465
Roland McGrath8f474e02003-01-14 07:53:33 +00001466#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001467extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001468#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001469#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1470extern char *_sys_siglist[];
1471#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001472
1473const char *
1474strsignal(sig)
1475int sig;
1476{
1477 static char buf[64];
1478
1479 if (sig < 1 || sig >= NSIG) {
1480 sprintf(buf, "Unknown signal %d", sig);
1481 return buf;
1482 }
1483#ifdef HAVE__SYS_SIGLIST
1484 return _sys_siglist[sig];
1485#else
1486 return sys_siglist[sig];
1487#endif
1488}
1489
1490#endif /* HAVE_STRSIGNAL */
1491
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001492#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493
1494static void
1495rebuild_pollv()
1496{
1497 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498
Roland McGrathee9d4352002-12-18 04:16:10 +00001499 if (pollv != NULL)
1500 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001501 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001502 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001503 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001504 exit(1);
1505 }
1506
Roland McGrathca16be82003-01-10 19:55:28 +00001507 for (i = j = 0; i < tcbtabsize; i++) {
1508 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 if (!(tcp->flags & TCB_INUSE))
1510 continue;
1511 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001512 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 j++;
1514 }
1515 if (j != nprocs) {
1516 fprintf(stderr, "strace: proc miscount\n");
1517 exit(1);
1518 }
1519}
1520
1521#ifndef HAVE_POLLABLE_PROCFS
1522
1523static void
1524proc_poll_open()
1525{
1526 int arg;
1527 int i;
1528
1529 if (pipe(proc_poll_pipe) < 0) {
1530 perror("pipe");
1531 exit(1);
1532 }
1533 for (i = 0; i < 2; i++) {
1534 if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
1535 perror("F_GETFD");
1536 exit(1);
1537 }
1538 if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
1539 perror("F_SETFD");
1540 exit(1);
1541 }
1542 }
1543}
1544
1545static int
1546proc_poll(pollv, nfds, timeout)
1547struct pollfd *pollv;
1548int nfds;
1549int timeout;
1550{
1551 int i;
1552 int n;
1553 struct proc_pollfd pollinfo;
1554
1555 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1556 return n;
1557 if (n != sizeof(struct proc_pollfd)) {
1558 fprintf(stderr, "panic: short read: %d\n", n);
1559 exit(1);
1560 }
1561 for (i = 0; i < nprocs; i++) {
1562 if (pollv[i].fd == pollinfo.fd)
1563 pollv[i].revents = pollinfo.revents;
1564 else
1565 pollv[i].revents = 0;
1566 }
1567 poller_pid = pollinfo.pid;
1568 return 1;
1569}
1570
1571static void
1572wakeup_handler(sig)
1573int sig;
1574{
1575}
1576
1577static void
1578proc_poller(pfd)
1579int pfd;
1580{
1581 struct proc_pollfd pollinfo;
1582 struct sigaction sa;
1583 sigset_t blocked_set, empty_set;
1584 int i;
1585 int n;
1586 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001587#ifdef FREEBSD
1588 struct procfs_status pfs;
1589#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590
1591 switch (fork()) {
1592 case -1:
1593 perror("fork");
1594 _exit(0);
1595 case 0:
1596 break;
1597 default:
1598 return;
1599 }
1600
1601 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1602 sa.sa_flags = 0;
1603 sigemptyset(&sa.sa_mask);
1604 sigaction(SIGHUP, &sa, NULL);
1605 sigaction(SIGINT, &sa, NULL);
1606 sigaction(SIGQUIT, &sa, NULL);
1607 sigaction(SIGPIPE, &sa, NULL);
1608 sigaction(SIGTERM, &sa, NULL);
1609 sa.sa_handler = wakeup_handler;
1610 sigaction(SIGUSR1, &sa, NULL);
1611 sigemptyset(&blocked_set);
1612 sigaddset(&blocked_set, SIGUSR1);
1613 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1614 sigemptyset(&empty_set);
1615
1616 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1617 perror("getrlimit(RLIMIT_NOFILE, ...)");
1618 _exit(0);
1619 }
1620 n = rl.rlim_cur;
1621 for (i = 0; i < n; i++) {
1622 if (i != pfd && i != proc_poll_pipe[1])
1623 close(i);
1624 }
1625
1626 pollinfo.fd = pfd;
1627 pollinfo.pid = getpid();
1628 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001629#ifndef FREEBSD
1630 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1631#else /* FREEBSD */
1632 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1633#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001634 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 switch (errno) {
1636 case EINTR:
1637 continue;
1638 case EBADF:
1639 pollinfo.revents = POLLERR;
1640 break;
1641 case ENOENT:
1642 pollinfo.revents = POLLHUP;
1643 break;
1644 default:
1645 perror("proc_poller: PIOCWSTOP");
1646 }
1647 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1648 _exit(0);
1649 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001650 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1652 sigsuspend(&empty_set);
1653 }
1654}
1655
1656#endif /* !HAVE_POLLABLE_PROCFS */
1657
1658static int
1659choose_pfd()
1660{
1661 int i, j;
1662 struct tcb *tcp;
1663
1664 static int last;
1665
1666 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001667 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 /*
1669 * The previous process is ready to run again. We'll
1670 * let it do so if it is currently in a syscall. This
1671 * heuristic improves the readability of the trace.
1672 */
1673 tcp = pfd2tcb(pollv[last].fd);
1674 if (tcp && (tcp->flags & TCB_INSYSCALL))
1675 return pollv[last].fd;
1676 }
1677
1678 for (i = 0; i < nprocs; i++) {
1679 /* Let competing children run round robin. */
1680 j = (i + last + 1) % nprocs;
1681 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1682 tcp = pfd2tcb(pollv[j].fd);
1683 if (!tcp) {
1684 fprintf(stderr, "strace: lost proc\n");
1685 exit(1);
1686 }
1687 droptcb(tcp);
1688 return -1;
1689 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001690 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 last = j;
1692 return pollv[j].fd;
1693 }
1694 }
1695 fprintf(stderr, "strace: nothing ready\n");
1696 exit(1);
1697}
1698
1699static int
1700trace()
1701{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001702#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001703 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001704#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705 struct tcb *tcp;
1706 int pfd;
1707 int what;
1708 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001709 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710
1711 for (;;) {
1712 if (interactive)
1713 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1714
1715 if (nprocs == 0)
1716 break;
1717
1718 switch (nprocs) {
1719 case 1:
1720#ifndef HAVE_POLLABLE_PROCFS
1721 if (proc_poll_pipe[0] == -1) {
1722#endif
1723 tcp = pid2tcb(0);
1724 if (!tcp)
1725 continue;
1726 pfd = tcp->pfd;
1727 if (pfd == -1)
1728 continue;
1729 break;
1730#ifndef HAVE_POLLABLE_PROCFS
1731 }
1732 /* fall through ... */
1733#endif /* !HAVE_POLLABLE_PROCFS */
1734 default:
1735#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001736#ifdef POLL_HACK
1737 /* On some systems (e.g. UnixWare) we get too much ugly
1738 "unfinished..." stuff when multiple proceses are in
1739 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001740
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001741 if (in_syscall) {
1742 struct pollfd pv;
1743 tcp = in_syscall;
1744 in_syscall = NULL;
1745 pv.fd = tcp->pfd;
1746 pv.events = POLLWANT;
1747 if ((what = poll (&pv, 1, 1)) < 0) {
1748 if (interrupted)
1749 return 0;
1750 continue;
1751 }
1752 else if (what == 1 && pv.revents & POLLWANT) {
1753 goto FOUND;
1754 }
1755 }
1756#endif
1757
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758 if (poll(pollv, nprocs, INFTIM) < 0) {
1759 if (interrupted)
1760 return 0;
1761 continue;
1762 }
1763#else /* !HAVE_POLLABLE_PROCFS */
1764 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1765 if (interrupted)
1766 return 0;
1767 continue;
1768 }
1769#endif /* !HAVE_POLLABLE_PROCFS */
1770 pfd = choose_pfd();
1771 if (pfd == -1)
1772 continue;
1773 break;
1774 }
1775
1776 /* Look up `pfd' in our table. */
1777 if ((tcp = pfd2tcb(pfd)) == NULL) {
1778 fprintf(stderr, "unknown pfd: %u\n", pfd);
1779 exit(1);
1780 }
John Hughesb6643082002-05-23 11:02:22 +00001781#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001782 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001783#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784 /* Get the status of the process. */
1785 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001786#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001787 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001788#else /* FREEBSD */
1789 /* Thanks to some scheduling mystery, the first poller
1790 sometimes waits for the already processed end of fork
1791 event. Doing a non blocking poll here solves the problem. */
1792 if (proc_poll_pipe[0] != -1)
1793 ioctl_result = IOCTL_STATUS (tcp);
1794 else
1795 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001796#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 ioctl_errno = errno;
1798#ifndef HAVE_POLLABLE_PROCFS
1799 if (proc_poll_pipe[0] != -1) {
1800 if (ioctl_result < 0)
1801 kill(poller_pid, SIGKILL);
1802 else
1803 kill(poller_pid, SIGUSR1);
1804 }
1805#endif /* !HAVE_POLLABLE_PROCFS */
1806 }
1807 if (interrupted)
1808 return 0;
1809
1810 if (interactive)
1811 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1812
1813 if (ioctl_result < 0) {
1814 /* Find out what happened if it failed. */
1815 switch (ioctl_errno) {
1816 case EINTR:
1817 case EBADF:
1818 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001819#ifdef FREEBSD
1820 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001821#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822 case ENOENT:
1823 droptcb(tcp);
1824 continue;
1825 default:
1826 perror("PIOCWSTOP");
1827 exit(1);
1828 }
1829 }
1830
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001831#ifdef FREEBSD
1832 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1833 /* discard first event for a syscall we never entered */
1834 IOCTL (tcp->pfd, PIOCRUN, 0);
1835 continue;
1836 }
Roland McGrath553a6092002-12-16 20:40:39 +00001837#endif
1838
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839 /* clear the just started flag */
1840 tcp->flags &= ~TCB_STARTUP;
1841
1842 /* set current output file */
1843 outf = tcp->outf;
1844
1845 if (cflag) {
1846 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001847#ifdef FREEBSD
1848 char buf[1024];
1849 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001850
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001851 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1852 buf[len] = '\0';
1853 sscanf(buf,
1854 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1855 &stime.tv_sec, &stime.tv_usec);
1856 } else
1857 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001858#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859 stime.tv_sec = tcp->status.pr_stime.tv_sec;
1860 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001861#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001862 tv_sub(&tcp->dtime, &stime, &tcp->stime);
1863 tcp->stime = stime;
1864 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001865 what = tcp->status.PR_WHAT;
1866 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001867#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001869 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
1870 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871 if (trace_syscall(tcp) < 0) {
1872 fprintf(stderr, "syscall trouble\n");
1873 exit(1);
1874 }
1875 }
1876 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001877#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001879#ifdef POLL_HACK
1880 in_syscall = tcp;
1881#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001882 case PR_SYSEXIT:
1883 if (trace_syscall(tcp) < 0) {
1884 fprintf(stderr, "syscall trouble\n");
1885 exit(1);
1886 }
1887 break;
1888 case PR_SIGNALLED:
1889 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
1890 printleader(tcp);
1891 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00001892 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001893 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00001894#ifdef PR_INFO
1895 if (tcp->status.PR_INFO.si_signo == what) {
1896 printleader(tcp);
1897 tprintf(" siginfo=");
1898 printsiginfo(&tcp->status.PR_INFO, 1);
1899 printtrailer(tcp);
1900 }
1901#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902 }
1903 break;
1904 case PR_FAULTED:
1905 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
1906 printleader(tcp);
1907 tprintf("=== FAULT %d ===", what);
1908 printtrailer(tcp);
1909 }
1910 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001911#ifdef FREEBSD
1912 case 0: /* handle case we polled for nothing */
1913 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00001914#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001915 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001916 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917 exit(1);
1918 break;
1919 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001920 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001921#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001922 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001923#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001924 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001925#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001926 perror("PIOCRUN");
1927 exit(1);
1928 }
1929 }
1930 return 0;
1931}
1932
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001933#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001935#ifdef TCB_GROUP_EXITING
1936/* Handle an exit detach or death signal that is taking all the
1937 related clone threads with it. This is called in three circumstances:
1938 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
1939 SIG == 0 Continuing TCP will perform an exit_group syscall.
1940 SIG == other Continuing TCP with SIG will kill the process.
1941*/
1942static int
1943handle_group_exit(struct tcb *tcp, int sig)
1944{
1945 /* We need to locate our records of all the clone threads
1946 related to TCP, either its children or siblings. */
1947 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1948 ? tcp->parent
1949 : tcp->nclone_detached > 0
1950 ? tcp : NULL);
1951
1952 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00001953 if (leader != NULL && leader != tcp &&
1954 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001955 fprintf(stderr,
1956 "PANIC: handle_group_exit: %d leader %d\n",
1957 tcp->pid, leader ? leader->pid : -1);
Roland McGratha08a97e2005-08-03 11:23:46 +00001958 detach(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001959 }
1960 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00001961 /* Mark that we are taking the process down. */
1962 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001963 if (tcp->flags & TCB_ATTACHED) {
Roland McGrath00dc13f2004-10-20 02:04:15 +00001964 if (leader != NULL && leader != tcp) {
1965 if (leader->flags & TCB_ATTACHED) {
1966 /* We need to detach the leader so
1967 that the process death will be
1968 reported to its real parent.
1969 But we kill it first to prevent
1970 it doing anything before we kill
1971 the whole process in a moment.
1972 We can use PTRACE_KILL on a
1973 thread that's not already
1974 stopped. Then the value we pass
1975 in PTRACE_DETACH just sets the
1976 death signal reported to the
1977 real parent. */
1978 ptrace(PTRACE_KILL, leader->pid, 0, 0);
1979 if (debug)
1980 fprintf(stderr,
1981 " [%d exit %d kills %d]\n",
1982 tcp->pid, sig, leader->pid);
1983 detach(leader, sig);
1984 }
1985 else
1986 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001987 }
1988 detach(tcp, sig);
1989 }
1990 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1991 perror("strace: ptrace(PTRACE_CONT, ...)");
1992 cleanup();
1993 return -1;
1994 }
1995 else {
Roland McGrath05690952004-10-20 01:00:27 +00001996 if (leader != NULL)
1997 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001998 if (leader != NULL && leader != tcp)
1999 droptcb(tcp);
2000 /* The leader will report to us as parent now,
2001 and then we'll get to the SIG==-1 case. */
2002 return 0;
2003 }
2004 }
2005
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002006 return 0;
2007}
2008#endif
2009
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010static int
2011trace()
2012{
2013 int pid;
2014 int wait_errno;
2015 int status;
2016 struct tcb *tcp;
2017#ifdef LINUX
2018 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002019#ifdef __WALL
2020 static int wait4_options = __WALL;
2021#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002022#endif /* LINUX */
2023
2024 while (nprocs != 0) {
2025 if (interactive)
2026 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2027#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002028#ifdef __WALL
2029 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002030 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002031 /* this kernel does not support __WALL */
2032 wait4_options &= ~__WALL;
2033 errno = 0;
2034 pid = wait4(-1, &status, wait4_options,
2035 cflag ? &ru : NULL);
2036 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002037 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002038 /* most likely a "cloned" process */
2039 pid = wait4(-1, &status, __WCLONE,
2040 cflag ? &ru : NULL);
2041 if (pid == -1) {
2042 fprintf(stderr, "strace: clone wait4 "
2043 "failed: %s\n", strerror(errno));
2044 }
2045 }
2046#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002048#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049#endif /* LINUX */
2050#ifdef SUNOS4
2051 pid = wait(&status);
2052#endif /* SUNOS4 */
2053 wait_errno = errno;
2054 if (interactive)
2055 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2056
2057 if (interrupted)
2058 return 0;
2059
2060 if (pid == -1) {
2061 switch (wait_errno) {
2062 case EINTR:
2063 continue;
2064 case ECHILD:
2065 /*
2066 * We would like to verify this case
2067 * but sometimes a race in Solbourne's
2068 * version of SunOS sometimes reports
2069 * ECHILD before sending us SIGCHILD.
2070 */
2071#if 0
2072 if (nprocs == 0)
2073 return 0;
2074 fprintf(stderr, "strace: proc miscount\n");
2075 exit(1);
2076#endif
2077 return 0;
2078 default:
2079 errno = wait_errno;
2080 perror("strace: wait");
2081 return -1;
2082 }
2083 }
2084 if (debug)
2085 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2086
2087 /* Look up `pid' in our table. */
2088 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002089#ifdef LINUX
2090 if (followfork || followvfork) {
2091 /* This is needed to go with the CLONE_PTRACE
2092 changes in process.c/util.c: we might see
2093 the child's initial trap before we see the
2094 parent return from the clone syscall.
2095 Leave the child suspended until the parent
2096 returns from its system call. Only then
2097 will we have the association of parent and
2098 child so that we know how to do clearbpt
2099 in the child. */
2100 if ((tcp = alloctcb(pid)) == NULL) {
2101 fprintf(stderr, " [tcb table full]\n");
2102 kill(pid, SIGKILL); /* XXX */
2103 return 0;
2104 }
2105 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2106 newoutf(tcp);
2107 if (!qflag)
2108 fprintf(stderr, "\
2109Process %d attached (waiting for parent)\n",
2110 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002111 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002112 else
2113 /* This can happen if a clone call used
2114 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002115#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002116 {
2117 fprintf(stderr, "unknown pid: %u\n", pid);
2118 if (WIFSTOPPED(status))
2119 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2120 exit(1);
2121 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002122 }
2123 /* set current output file */
2124 outf = tcp->outf;
2125 if (cflag) {
2126#ifdef LINUX
2127 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2128 tcp->stime = ru.ru_stime;
2129#endif /* !LINUX */
2130 }
2131
2132 if (tcp->flags & TCB_SUSPENDED) {
2133 /*
2134 * Apparently, doing any ptrace() call on a stopped
2135 * process, provokes the kernel to report the process
2136 * status again on a subsequent wait(), even if the
2137 * process has not been actually restarted.
2138 * Since we have inspected the arguments of suspended
2139 * processes we end up here testing for this case.
2140 */
2141 continue;
2142 }
2143 if (WIFSIGNALED(status)) {
2144 if (!cflag
2145 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2146 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002147 tprintf("+++ killed by %s %s+++",
2148 signame(WTERMSIG(status)),
2149#ifdef WCOREDUMP
2150 WCOREDUMP(status) ? "(core dumped) " :
2151#endif
2152 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 printtrailer(tcp);
2154 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002155#ifdef TCB_GROUP_EXITING
2156 handle_group_exit(tcp, -1);
2157#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002158 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002159#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002160 continue;
2161 }
2162 if (WIFEXITED(status)) {
2163 if (debug)
2164 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002165 if ((tcp->flags & TCB_ATTACHED)
2166#ifdef TCB_GROUP_EXITING
2167 && !(tcp->parent && (tcp->parent->flags &
2168 TCB_GROUP_EXITING))
2169#endif
2170 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 fprintf(stderr,
2172 "PANIC: attached pid %u exited\n",
2173 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002174 if (tcp == tcp_last) {
2175 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2176 == TCB_INSYSCALL)
2177 tprintf(" <unfinished ... exit status %d>\n",
2178 WEXITSTATUS(status));
2179 tcp_last = NULL;
2180 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002181#ifdef TCB_GROUP_EXITING
2182 handle_group_exit(tcp, -1);
2183#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002185#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 continue;
2187 }
2188 if (!WIFSTOPPED(status)) {
2189 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2190 droptcb(tcp);
2191 continue;
2192 }
2193 if (debug)
2194 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002195 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196
2197 if (tcp->flags & TCB_STARTUP) {
2198 /*
2199 * This flag is there to keep us in sync.
2200 * Next time this process stops it should
2201 * really be entering a system call.
2202 */
2203 tcp->flags &= ~TCB_STARTUP;
2204 if (tcp->flags & TCB_ATTACHED) {
2205 /*
2206 * Interestingly, the process may stop
2207 * with STOPSIG equal to some other signal
2208 * than SIGSTOP if we happend to attach
2209 * just before the process takes a signal.
2210 */
2211 if (!WIFSTOPPED(status)) {
2212 fprintf(stderr,
2213 "pid %u not stopped\n", pid);
2214 detach(tcp, WSTOPSIG(status));
2215 continue;
2216 }
2217 }
2218 else {
2219#ifdef SUNOS4
2220 /* A child of us stopped at exec */
2221 if (WSTOPSIG(status) == SIGTRAP && followvfork)
2222 fixvfork(tcp);
2223#endif /* SUNOS4 */
2224 }
2225 if (tcp->flags & TCB_BPTSET) {
2226 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2227 droptcb(tcp);
2228 cleanup();
2229 return -1;
2230 }
2231 }
2232 goto tracing;
2233 }
2234
2235 if (WSTOPSIG(status) != SIGTRAP) {
2236 if (WSTOPSIG(status) == SIGSTOP &&
2237 (tcp->flags & TCB_SIGTRAPPED)) {
2238 /*
2239 * Trapped attempt to block SIGTRAP
2240 * Hope we are back in control now.
2241 */
2242 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2243 if (ptrace(PTRACE_SYSCALL,
2244 pid, (char *) 1, 0) < 0) {
2245 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2246 cleanup();
2247 return -1;
2248 }
2249 continue;
2250 }
2251 if (!cflag
2252 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002253 unsigned long addr = 0, pc = 0;
2254#ifdef PT_GETSIGINFO
2255# define PSR_RI 41
2256 struct siginfo si;
2257 unsigned long psr;
2258
2259 upeek(pid, PT_CR_IPSR, &psr);
2260 upeek(pid, PT_CR_IIP, &pc);
2261
2262 pc += (psr >> PSR_RI) & 0x3;
2263 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2264 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002265#elif defined PTRACE_GETSIGINFO
2266 if (WSTOPSIG(status) == SIGSEGV ||
2267 WSTOPSIG(status) == SIGBUS) {
2268 siginfo_t si;
2269 if (ptrace(PTRACE_GETSIGINFO, pid,
2270 0, &si) == 0)
2271 addr = (unsigned long)
2272 si.si_addr;
2273 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002274#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002275 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002276 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002277 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002278 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002279 printtrailer(tcp);
2280 }
Roland McGrath05690952004-10-20 01:00:27 +00002281 if (((tcp->flags & TCB_ATTACHED) ||
2282 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002283 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002284#ifdef TCB_GROUP_EXITING
2285 handle_group_exit(tcp, WSTOPSIG(status));
2286#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002288#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002289 continue;
2290 }
2291 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2292 WSTOPSIG(status)) < 0) {
2293 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2294 cleanup();
2295 return -1;
2296 }
2297 tcp->flags &= ~TCB_SUSPENDED;
2298 continue;
2299 }
2300 if (trace_syscall(tcp) < 0) {
2301 if (tcp->flags & TCB_ATTACHED)
2302 detach(tcp, 0);
2303 else {
2304 ptrace(PTRACE_KILL,
2305 tcp->pid, (char *) 1, SIGTERM);
2306 droptcb(tcp);
2307 }
2308 continue;
2309 }
2310 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002311#ifdef TCB_GROUP_EXITING
2312 if (tcp->flags & TCB_GROUP_EXITING) {
2313 if (handle_group_exit(tcp, 0) < 0)
2314 return -1;
2315 continue;
2316 }
2317#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002318 if (tcp->flags & TCB_ATTACHED)
2319 detach(tcp, 0);
2320 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2321 perror("strace: ptrace(PTRACE_CONT, ...)");
2322 cleanup();
2323 return -1;
2324 }
2325 continue;
2326 }
2327 if (tcp->flags & TCB_SUSPENDED) {
2328 if (!qflag)
2329 fprintf(stderr, "Process %u suspended\n", pid);
2330 continue;
2331 }
2332 tracing:
2333 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2334 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2335 cleanup();
2336 return -1;
2337 }
2338 }
2339 return 0;
2340}
2341
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002342#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343
2344static int curcol;
2345
2346#ifdef __STDC__
2347#include <stdarg.h>
2348#define VA_START(a, b) va_start(a, b)
2349#else
2350#include <varargs.h>
2351#define VA_START(a, b) va_start(a)
2352#endif
2353
2354void
2355#ifdef __STDC__
2356tprintf(const char *fmt, ...)
2357#else
2358tprintf(fmt, va_alist)
2359char *fmt;
2360va_dcl
2361#endif
2362{
2363 va_list args;
2364
2365 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002366 if (outf) {
2367 int n = vfprintf(outf, fmt, args);
2368 if (n < 0 && outf != stderr)
2369 perror(outfname == NULL
2370 ? "<writing to pipe>" : outfname);
2371 else
2372 curcol += n;
2373 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374 va_end(args);
2375 return;
2376}
2377
2378void
2379printleader(tcp)
2380struct tcb *tcp;
2381{
2382 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2383 tcp_last->flags |= TCB_REPRINT;
2384 tprintf(" <unfinished ...>\n");
2385 }
2386 curcol = 0;
2387 if ((followfork == 1 || pflag_seen > 1) && outfname)
2388 tprintf("%-5d ", tcp->pid);
2389 else if (nprocs > 1 && !outfname)
2390 tprintf("[pid %5u] ", tcp->pid);
2391 if (tflag) {
2392 char str[sizeof("HH:MM:SS")];
2393 struct timeval tv, dtv;
2394 static struct timeval otv;
2395
2396 gettimeofday(&tv, NULL);
2397 if (rflag) {
2398 if (otv.tv_sec == 0)
2399 otv = tv;
2400 tv_sub(&dtv, &tv, &otv);
2401 tprintf("%6ld.%06ld ",
2402 (long) dtv.tv_sec, (long) dtv.tv_usec);
2403 otv = tv;
2404 }
2405 else if (tflag > 2) {
2406 tprintf("%ld.%06ld ",
2407 (long) tv.tv_sec, (long) tv.tv_usec);
2408 }
2409 else {
2410 time_t local = tv.tv_sec;
2411 strftime(str, sizeof(str), "%T", localtime(&local));
2412 if (tflag > 1)
2413 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2414 else
2415 tprintf("%s ", str);
2416 }
2417 }
2418 if (iflag)
2419 printcall(tcp);
2420}
2421
2422void
2423tabto(col)
2424int col;
2425{
2426 if (curcol < col)
2427 tprintf("%*s", col - curcol, "");
2428}
2429
2430void
2431printtrailer(tcp)
2432struct tcb *tcp;
2433{
2434 tprintf("\n");
2435 tcp_last = NULL;
2436}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002437
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002438#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002439
2440int mp_ioctl (int fd, int cmd, void *arg, int size) {
2441
2442 struct iovec iov[2];
2443 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002444
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002445 iov[0].iov_base = &cmd;
2446 iov[0].iov_len = sizeof cmd;
2447 if (arg) {
2448 ++n;
2449 iov[1].iov_base = arg;
2450 iov[1].iov_len = size;
2451 }
Roland McGrath553a6092002-12-16 20:40:39 +00002452
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002453 return writev (fd, iov, n);
2454}
2455
2456#endif