blob: fd3f7bd289804e7512bf6af4ea6707d9fcfb14c5 [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;
Roland McGrath138c6a32006-01-12 09:50:49 +0000202 set_sortby(DEFAULT_SORTBY);
203 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204 qualify("trace=all");
205 qualify("abbrev=all");
206 qualify("verbose=all");
207 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000208 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 McGrathd0c4c0c2006-04-25 07:39:40 +0000314 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000315 usage(stderr, 1);
316
Roland McGrathcb9def62006-04-25 07:48:03 +0000317 if (followfork > 1 && cflag) {
318 fprintf(stderr,
319 "%s: -c and -ff are mutually exclusive options\n",
320 progname);
321 exit(1);
322 }
323
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324 /* See if they want to run as another user. */
325 if (username != NULL) {
326 struct passwd *pent;
327
328 if (getuid() != 0 || geteuid() != 0) {
329 fprintf(stderr,
330 "%s: you must be root to use the -u option\n",
331 progname);
332 exit(1);
333 }
334 if ((pent = getpwnam(username)) == NULL) {
335 fprintf(stderr, "%s: cannot find user `%s'\n",
336 progname, optarg);
337 exit(1);
338 }
339 run_uid = pent->pw_uid;
340 run_gid = pent->pw_gid;
341 }
342 else {
343 run_uid = getuid();
344 run_gid = getgid();
345 }
346
347#ifndef SVR4
348 setreuid(geteuid(), getuid());
349#endif
350
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000351 /* Check if they want to redirect the output. */
352 if (outfname) {
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000353 long f;
354
Roland McGrath37b9a662003-11-07 02:26:54 +0000355 /* See if they want to pipe the output. */
356 if (outfname[0] == '|' || outfname[0] == '!') {
357 /*
358 * We can't do the <outfname>.PID funny business
359 * when using popen, so prohibit it.
360 */
361 if (followfork > 1) {
362 fprintf(stderr, "\
363%s: piping the output and -ff are mutually exclusive options\n",
364 progname);
365 exit(1);
366 }
367
368 if ((outf = popen(outfname + 1, "w")) == NULL) {
369 fprintf(stderr, "%s: can't popen '%s': %s\n",
370 progname, outfname + 1,
371 strerror(errno));
372 exit(1);
373 }
374 }
375 else if ((outf = fopen(outfname, "w")) == NULL) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000376 fprintf(stderr, "%s: can't fopen '%s': %s\n",
377 progname, outfname, strerror(errno));
378 exit(1);
379 }
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000380
381 if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
382 perror("failed to get flags for outputfile");
383 exit(1);
384 }
385
386 if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
387 perror("failed to set flags for outputfile");
388 exit(1);
389 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390 }
391
392#ifndef SVR4
393 setreuid(geteuid(), getuid());
394#endif
395
Roland McGrath37b9a662003-11-07 02:26:54 +0000396 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000398 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000399 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000400 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000401 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000402
Roland McGrathee9d4352002-12-18 04:16:10 +0000403 for (c = 0; c < tcbtabsize; c++) {
404 tcp = tcbtab[c];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000405 /* Reinitialize the output since it may have changed. */
406 tcp->outf = outf;
407 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
408 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000409#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000410 if (proc_open(tcp, 1) < 0) {
411 fprintf(stderr, "trouble opening proc file\n");
412 droptcb(tcp);
413 continue;
414 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000415#else /* !USE_PROCFS */
Roland McGrath70b08532004-04-09 00:25:21 +0000416# ifdef LINUX
417 if (tcp->flags & TCB_CLONE_THREAD)
418 continue;
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000419 if (followfork) {
Roland McGrath70b08532004-04-09 00:25:21 +0000420 char procdir[MAXPATHLEN];
421 DIR *dir;
422 sprintf(procdir, "/proc/%d/task", tcp->pid);
423 dir = opendir(procdir);
424 if (dir != NULL) {
425 unsigned int ntid = 0, nerr = 0;
426 struct dirent *de;
427 int tid;
428 while ((de = readdir(dir)) != NULL) {
429 if (de->d_fileno == 0 ||
430 de->d_name[0] == '.')
431 continue;
432 tid = atoi(de->d_name);
433 if (tid <= 0)
434 continue;
435 ++ntid;
436 if (ptrace(PTRACE_ATTACH, tid,
437 (char *) 1, 0) < 0)
438 ++nerr;
439 else if (tid != tcbtab[c]->pid) {
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000440 if (nprocs == tcbtabsize &&
441 expand_tcbtab())
442 tcp = NULL;
443 else
444 tcp = alloctcb(tid);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000445 if (tcp == NULL)
Roland McGrath70b08532004-04-09 00:25:21 +0000446 exit(1);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000447 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
Roland McGrath70b08532004-04-09 00:25:21 +0000448 tcbtab[c]->nchildren++;
449 tcbtab[c]->nclone_threads++;
450 tcbtab[c]->nclone_detached++;
451 tcp->parent = tcbtab[c];
452 }
453 }
454 closedir(dir);
455 if (nerr == ntid) {
456 perror("attach: ptrace(PTRACE_ATTACH, ...)");
457 droptcb(tcp);
458 continue;
459 }
460 if (!qflag) {
461 ntid -= nerr;
462 if (ntid > 1)
463 fprintf(stderr, "\
464Process %u attached with %u threads - interrupt to quit\n",
465 tcp->pid, ntid);
466 else
467 fprintf(stderr, "\
468Process %u attached - interrupt to quit\n",
469 tcp->pid);
470 }
471 continue;
472 }
473 }
474# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000475 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
476 perror("attach: ptrace(PTRACE_ATTACH, ...)");
477 droptcb(tcp);
478 continue;
479 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000480#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000481 if (!qflag)
482 fprintf(stderr,
483 "Process %u attached - interrupt to quit\n",
Roland McGrathc3266d52004-02-20 02:23:52 +0000484 tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000485 }
486
Roland McGrathce0d1542003-11-11 21:24:23 +0000487 if (!pflag_seen) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000488 struct stat statbuf;
489 char *filename;
490 char pathname[MAXPATHLEN];
491
492 filename = argv[optind];
Roland McGrathbdb09df2004-03-02 06:50:04 +0000493 if (strchr(filename, '/')) {
494 if (strlen(filename) > sizeof pathname - 1) {
495 errno = ENAMETOOLONG;
496 perror("strace: exec");
497 exit(1);
498 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000499 strcpy(pathname, filename);
Roland McGrathbdb09df2004-03-02 06:50:04 +0000500 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000501#ifdef USE_DEBUGGING_EXEC
502 /*
503 * Debuggers customarily check the current directory
504 * first regardless of the path but doing that gives
505 * security geeks a panic attack.
506 */
507 else if (stat(filename, &statbuf) == 0)
508 strcpy(pathname, filename);
509#endif /* USE_DEBUGGING_EXEC */
510 else {
511 char *path;
512 int m, n, len;
513
514 for (path = getenv("PATH"); path && *path; path += m) {
515 if (strchr(path, ':')) {
516 n = strchr(path, ':') - path;
517 m = n + 1;
518 }
519 else
520 m = n = strlen(path);
521 if (n == 0) {
Dmitry V. Levincbd470f2006-10-14 14:23:57 +0000522 if (!getcwd(pathname, MAXPATHLEN))
523 continue;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524 len = strlen(pathname);
525 }
Roland McGrathbdb09df2004-03-02 06:50:04 +0000526 else if (n > sizeof pathname - 1)
527 continue;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528 else {
529 strncpy(pathname, path, n);
530 len = n;
531 }
532 if (len && pathname[len - 1] != '/')
533 pathname[len++] = '/';
534 strcpy(pathname + len, filename);
Roland McGrathed645162003-06-03 07:18:19 +0000535 if (stat(pathname, &statbuf) == 0 &&
536 /* Accept only regular files
537 with some execute bits set.
538 XXX not perfect, might still fail */
539 S_ISREG(statbuf.st_mode) &&
540 (statbuf.st_mode & 0111))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000541 break;
542 }
543 }
544 if (stat(pathname, &statbuf) < 0) {
545 fprintf(stderr, "%s: %s: command not found\n",
546 progname, filename);
547 exit(1);
548 }
549 switch (pid = fork()) {
550 case -1:
551 perror("strace: fork");
552 cleanup();
553 exit(1);
554 break;
555 case 0: {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000556#ifdef USE_PROCFS
557 if (outf != stderr) close (fileno (outf));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558#ifdef MIPS
559 /* Kludge for SGI, see proc_open for details. */
560 sa.sa_handler = foobar;
561 sa.sa_flags = 0;
562 sigemptyset(&sa.sa_mask);
563 sigaction(SIGINT, &sa, NULL);
564#endif /* MIPS */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000565#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566 pause();
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000567#else /* FREEBSD */
568 kill(getpid(), SIGSTOP); /* stop HERE */
Roland McGrath553a6092002-12-16 20:40:39 +0000569#endif /* FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000570#else /* !USE_PROCFS */
Roland McGrath553a6092002-12-16 20:40:39 +0000571 if (outf!=stderr)
Wichert Akkerman7987cdf2000-07-05 16:05:39 +0000572 close(fileno (outf));
Wichert Akkermanbd4125c2000-06-27 17:28:06 +0000573
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
575 perror("strace: ptrace(PTRACE_TRACEME, ...)");
576 return -1;
577 }
578 if (debug)
579 kill(getpid(), SIGSTOP);
580
581 if (username != NULL || geteuid() == 0) {
582 uid_t run_euid = run_uid;
583 gid_t run_egid = run_gid;
584
585 if (statbuf.st_mode & S_ISUID)
586 run_euid = statbuf.st_uid;
587 if (statbuf.st_mode & S_ISGID)
588 run_egid = statbuf.st_gid;
589
590 /*
591 * It is important to set groups before we
592 * lose privileges on setuid.
593 */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +0000594 if (username != NULL) {
595 if (initgroups(username, run_gid) < 0) {
596 perror("initgroups");
597 exit(1);
598 }
599 if (setregid(run_gid, run_egid) < 0) {
600 perror("setregid");
601 exit(1);
602 }
603 if (setreuid(run_uid, run_euid) < 0) {
604 perror("setreuid");
605 exit(1);
606 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607 }
608 }
609 else
610 setreuid(run_uid, run_uid);
Roland McGrath15dca8e2005-02-06 01:16:32 +0000611
612 /*
613 * Induce an immediate stop so that the parent
614 * will resume us with PTRACE_SYSCALL and display
615 * this execve call normally.
616 */
617 kill(getpid(), SIGSTOP);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000618#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619
620 execv(pathname, &argv[optind]);
621 perror("strace: exec");
622 _exit(1);
623 break;
624 }
625 default:
626 if ((tcp = alloctcb(pid)) == NULL) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627 cleanup();
628 exit(1);
629 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000630#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 if (proc_open(tcp, 0) < 0) {
632 fprintf(stderr, "trouble opening proc file\n");
633 cleanup();
634 exit(1);
635 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000636#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000637 break;
638 }
639 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000640
641 sigemptyset(&empty_set);
642 sigemptyset(&blocked_set);
643 sa.sa_handler = SIG_IGN;
644 sigemptyset(&sa.sa_mask);
645 sa.sa_flags = 0;
646 sigaction(SIGTTOU, &sa, NULL);
647 sigaction(SIGTTIN, &sa, NULL);
648 if (interactive) {
649 sigaddset(&blocked_set, SIGHUP);
650 sigaddset(&blocked_set, SIGINT);
651 sigaddset(&blocked_set, SIGQUIT);
652 sigaddset(&blocked_set, SIGPIPE);
653 sigaddset(&blocked_set, SIGTERM);
654 sa.sa_handler = interrupt;
655#ifdef SUNOS4
656 /* POSIX signals on sunos4.1 are a little broken. */
657 sa.sa_flags = SA_INTERRUPT;
658#endif /* SUNOS4 */
659 }
660 sigaction(SIGHUP, &sa, NULL);
661 sigaction(SIGINT, &sa, NULL);
662 sigaction(SIGQUIT, &sa, NULL);
663 sigaction(SIGPIPE, &sa, NULL);
664 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000665#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 sa.sa_handler = reaper;
667 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000668#else
669 /* Make sure SIGCHLD has the default action so that waitpid
670 definitely works without losing track of children. The user
671 should not have given us a bogus state to inherit, but he might
672 have. Arguably we should detect SIG_IGN here and pass it on
673 to children, but probably noone really needs that. */
674 sa.sa_handler = SIG_DFL;
675 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000676#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000677
678 if (trace() < 0)
679 exit(1);
680 cleanup();
681 exit(0);
682}
683
684void
685newoutf(tcp)
686struct tcb *tcp;
687{
688 char name[MAXPATHLEN];
689 FILE *fp;
690
691 if (outfname && followfork > 1) {
692 sprintf(name, "%s.%u", outfname, tcp->pid);
693#ifndef SVR4
694 setreuid(geteuid(), getuid());
695#endif
696 fp = fopen(name, "w");
697#ifndef SVR4
698 setreuid(geteuid(), getuid());
699#endif
700 if (fp == NULL) {
701 perror("fopen");
702 return;
703 }
704 tcp->outf = fp;
705 }
706 return;
707}
708
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000709int
710expand_tcbtab()
711{
712 /* Allocate some more TCBs and expand the table.
713 We don't want to relocate the TCBs because our
714 callers have pointers and it would be a pain.
715 So tcbtab is a table of pointers. Since we never
716 free the TCBs, we allocate a single chunk of many. */
717 struct tcb **newtab = (struct tcb **)
718 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
719 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
720 sizeof *newtcbs);
721 int i;
722 if (newtab == NULL || newtcbs == NULL) {
723 if (newtab != NULL)
724 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000725 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
726 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000727 return 1;
728 }
729 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
730 newtab[i] = &newtcbs[i - tcbtabsize];
731 tcbtabsize *= 2;
732 tcbtab = newtab;
733
734 return 0;
735}
736
737
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000738struct tcb *
739alloctcb(pid)
740int pid;
741{
742 int i;
743 struct tcb *tcp;
744
Roland McGrathee9d4352002-12-18 04:16:10 +0000745 for (i = 0; i < tcbtabsize; i++) {
746 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000747 if ((tcp->flags & TCB_INUSE) == 0) {
748 tcp->pid = pid;
749 tcp->parent = NULL;
750 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000751 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000752#ifdef TCB_CLONE_THREAD
753 tcp->nclone_threads = tcp->nclone_detached = 0;
754 tcp->nclone_waiting = 0;
755#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 tcp->flags = TCB_INUSE | TCB_STARTUP;
757 tcp->outf = outf; /* Initialise to current out file */
758 tcp->stime.tv_sec = 0;
759 tcp->stime.tv_usec = 0;
760 tcp->pfd = -1;
761 nprocs++;
762 return tcp;
763 }
764 }
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000765 fprintf(stderr, "%s: alloctcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000766 return NULL;
767}
768
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000769#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000770int
771proc_open(tcp, attaching)
772struct tcb *tcp;
773int attaching;
774{
775 char proc[32];
776 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000777#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000778 int i;
779 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000780 sigset_t signals;
781 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000782#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783#ifndef HAVE_POLLABLE_PROCFS
784 static int last_pfd;
785#endif
786
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000787#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000788 /* Open the process pseudo-files in /proc. */
789 sprintf(proc, "/proc/%d/ctl", tcp->pid);
790 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791 perror("strace: open(\"/proc/...\", ...)");
792 return -1;
793 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
795 perror("F_GETFD");
796 return -1;
797 }
798 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
799 perror("F_SETFD");
800 return -1;
801 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000802 sprintf(proc, "/proc/%d/status", tcp->pid);
803 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
804 perror("strace: open(\"/proc/...\", ...)");
805 return -1;
806 }
807 if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
808 perror("F_GETFD");
809 return -1;
810 }
811 if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
812 perror("F_SETFD");
813 return -1;
814 }
815 sprintf(proc, "/proc/%d/as", tcp->pid);
816 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
817 perror("strace: open(\"/proc/...\", ...)");
818 return -1;
819 }
820 if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
821 perror("F_GETFD");
822 return -1;
823 }
824 if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
825 perror("F_SETFD");
826 return -1;
827 }
828#else
829 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000830#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000831 sprintf(proc, "/proc/%d", tcp->pid);
832 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000833#else /* FREEBSD */
834 sprintf(proc, "/proc/%d/mem", tcp->pid);
835 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
836#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000837 perror("strace: open(\"/proc/...\", ...)");
838 return -1;
839 }
840 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
841 perror("F_GETFD");
842 return -1;
843 }
844 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
845 perror("F_SETFD");
846 return -1;
847 }
848#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000849#ifdef FREEBSD
850 sprintf(proc, "/proc/%d/regs", tcp->pid);
851 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
852 perror("strace: open(\"/proc/.../regs\", ...)");
853 return -1;
854 }
855 if (cflag) {
856 sprintf(proc, "/proc/%d/status", tcp->pid);
857 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
858 perror("strace: open(\"/proc/.../status\", ...)");
859 return -1;
860 }
861 } else
862 tcp->pfd_status = -1;
863#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000864 rebuild_pollv();
865 if (!attaching) {
866 /*
867 * Wait for the child to pause. Because of a race
868 * condition we have to poll for the event.
869 */
870 for (;;) {
871 if (IOCTL_STATUS (tcp) < 0) {
872 perror("strace: PIOCSTATUS");
873 return -1;
874 }
875 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000876 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000877 }
878 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000879#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000880 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000881 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000882 perror("strace: PIOCSTOP");
883 return -1;
884 }
Roland McGrath553a6092002-12-16 20:40:39 +0000885#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886#ifdef PIOCSET
887 /* Set Run-on-Last-Close. */
888 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000889 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 perror("PIOCSET PR_RLC");
891 return -1;
892 }
893 /* Set or Reset Inherit-on-Fork. */
894 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000895 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000896 perror("PIOC{SET,RESET} PR_FORK");
897 return -1;
898 }
899#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +0000900#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
902 perror("PIOCSRLC");
903 return -1;
904 }
905 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
906 perror("PIOC{S,R}FORK");
907 return -1;
908 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000909#else /* FREEBSD */
910 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
911 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
912 perror("PIOCGFL");
913 return -1;
914 }
915 arg &= ~PF_LINGER;
916 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
917 perror("PIOCSFL");
918 return -1;
919 }
920#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000921#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000922#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +0000923 /* Enable all syscall entries we care about. */
924 premptyset(&syscalls);
925 for (i = 1; i < MAX_QUALS; ++i) {
926 if (i > (sizeof syscalls) * CHAR_BIT) break;
927 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
928 }
929 praddset (&syscalls, SYS_execve);
930 if (followfork) {
931 praddset (&syscalls, SYS_fork);
932#ifdef SYS_forkall
933 praddset (&syscalls, SYS_forkall);
934#endif
Roland McGrath553a6092002-12-16 20:40:39 +0000935#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +0000936 praddset (&syscalls, SYS_fork1);
937#endif
938#ifdef SYS_rfork1
939 praddset (&syscalls, SYS_rfork1);
940#endif
941#ifdef SYS_rforkall
942 praddset (&syscalls, SYS_rforkall);
943#endif
944 }
945 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000946 perror("PIOCSENTRY");
947 return -1;
948 }
John Hughes19e49982001-10-19 08:59:12 +0000949 /* Enable the syscall exits. */
950 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 perror("PIOSEXIT");
952 return -1;
953 }
John Hughes19e49982001-10-19 08:59:12 +0000954 /* Enable signals we care about. */
955 premptyset(&signals);
956 for (i = 1; i < MAX_QUALS; ++i) {
957 if (i > (sizeof signals) * CHAR_BIT) break;
958 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
959 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000960 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000961 perror("PIOCSTRACE");
962 return -1;
963 }
John Hughes19e49982001-10-19 08:59:12 +0000964 /* Enable faults we care about */
965 premptyset(&faults);
966 for (i = 1; i < MAX_QUALS; ++i) {
967 if (i > (sizeof faults) * CHAR_BIT) break;
968 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
969 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000970 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 perror("PIOCSFAULT");
972 return -1;
973 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000974#else /* FREEBSD */
975 /* set events flags. */
976 arg = S_SIG | S_SCE | S_SCX ;
977 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
978 perror("PIOCBIS");
979 return -1;
980 }
981#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982 if (!attaching) {
983#ifdef MIPS
984 /*
985 * The SGI PRSABORT doesn't work for pause() so
986 * we send it a caught signal to wake it up.
987 */
988 kill(tcp->pid, SIGINT);
989#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +0000990#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000992 arg = PRSABORT;
993 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 perror("PIOCRUN");
995 return -1;
996 }
Roland McGrath553a6092002-12-16 20:40:39 +0000997#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000998#endif /* !MIPS*/
999#ifdef FREEBSD
1000 /* wake up the child if it received the SIGSTOP */
1001 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001002#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003 for (;;) {
1004 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001005 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 perror("PIOCWSTOP");
1007 return -1;
1008 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001009 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001010 tcp->flags &= ~TCB_INSYSCALL;
1011 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001012 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013 break;
1014 }
1015 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001016#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001017 arg = 0;
1018 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001019#else /* FREEBSD */
1020 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001021#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 perror("PIOCRUN");
1023 return -1;
1024 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001025#ifdef FREEBSD
1026 /* handle the case where we "opened" the child before
1027 it did the kill -STOP */
1028 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1029 tcp->status.PR_WHAT == SIGSTOP)
1030 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001031#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001033#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001035#else /* FREEBSD */
1036 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001037 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001038 /* We are attaching to an already running process.
1039 * Try to figure out the state of the process in syscalls,
1040 * to handle the first event well.
1041 * This is done by having a look at the "wchan" property of the
1042 * process, which tells where it is stopped (if it is). */
1043 FILE * status;
1044 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001045
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001046 sprintf(proc, "/proc/%d/status", tcp->pid);
1047 status = fopen(proc, "r");
1048 if (status &&
1049 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1050 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1051 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1052 strcmp(wchan, "stopevent")) {
1053 /* The process is asleep in the middle of a syscall.
1054 Fake the syscall entry event */
1055 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1056 tcp->status.PR_WHY = PR_SYSENTRY;
1057 trace_syscall(tcp);
1058 }
1059 if (status)
1060 fclose(status);
1061 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001062 }
1063#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064#ifndef HAVE_POLLABLE_PROCFS
1065 if (proc_poll_pipe[0] != -1)
1066 proc_poller(tcp->pfd);
1067 else if (nprocs > 1) {
1068 proc_poll_open();
1069 proc_poller(last_pfd);
1070 proc_poller(tcp->pfd);
1071 }
1072 last_pfd = tcp->pfd;
1073#endif /* !HAVE_POLLABLE_PROCFS */
1074 return 0;
1075}
1076
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001077#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001079struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001080pid2tcb(pid)
1081int pid;
1082{
1083 int i;
1084 struct tcb *tcp;
1085
Roland McGrathee9d4352002-12-18 04:16:10 +00001086 for (i = 0; i < tcbtabsize; i++) {
1087 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 if (pid && tcp->pid != pid)
1089 continue;
1090 if (tcp->flags & TCB_INUSE)
1091 return tcp;
1092 }
1093 return NULL;
1094}
1095
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001096#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097
1098static struct tcb *
1099pfd2tcb(pfd)
1100int pfd;
1101{
1102 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103
Roland McGrathca16be82003-01-10 19:55:28 +00001104 for (i = 0; i < tcbtabsize; i++) {
1105 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106 if (tcp->pfd != pfd)
1107 continue;
1108 if (tcp->flags & TCB_INUSE)
1109 return tcp;
1110 }
1111 return NULL;
1112}
1113
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001114#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001115
1116void
1117droptcb(tcp)
1118struct tcb *tcp;
1119{
1120 if (tcp->pid == 0)
1121 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001122#ifdef TCB_CLONE_THREAD
1123 if (tcp->nclone_threads > 0) {
1124 /* There are other threads left in this process, but this
1125 is the one whose PID represents the whole process.
1126 We need to keep this record around as a zombie until
1127 all the threads die. */
1128 tcp->flags |= TCB_EXITING;
1129 return;
1130 }
1131#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 nprocs--;
1133 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001134
Roland McGrathe29341c2003-01-10 20:14:20 +00001135 if (tcp->parent != NULL) {
1136 tcp->parent->nchildren--;
1137#ifdef TCB_CLONE_THREAD
1138 if (tcp->flags & TCB_CLONE_DETACHED)
1139 tcp->parent->nclone_detached--;
1140 if (tcp->flags & TCB_CLONE_THREAD)
1141 tcp->parent->nclone_threads--;
1142#endif
Roland McGrath09623452003-05-23 02:27:13 +00001143#ifdef TCB_CLONE_DETACHED
1144 if (!(tcp->flags & TCB_CLONE_DETACHED))
1145#endif
1146 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001147 tcp->parent = NULL;
1148 }
1149
1150 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 if (tcp->pfd != -1) {
1152 close(tcp->pfd);
1153 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001154#ifdef FREEBSD
1155 if (tcp->pfd_reg != -1) {
1156 close(tcp->pfd_reg);
1157 tcp->pfd_reg = -1;
1158 }
1159 if (tcp->pfd_status != -1) {
1160 close(tcp->pfd_status);
1161 tcp->pfd_status = -1;
1162 }
Roland McGrath553a6092002-12-16 20:40:39 +00001163#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001164#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001165 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166#endif
1167 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001168
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001169 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001171
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 tcp->outf = 0;
1173}
1174
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001175#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176
1177static int
1178resume(tcp)
1179struct tcb *tcp;
1180{
1181 if (tcp == NULL)
1182 return -1;
1183
1184 if (!(tcp->flags & TCB_SUSPENDED)) {
1185 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1186 return -1;
1187 }
1188 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001189#ifdef TCB_CLONE_THREAD
1190 if (tcp->flags & TCB_CLONE_THREAD)
1191 tcp->parent->nclone_waiting--;
1192#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193
1194 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1195 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1196 return -1;
1197 }
1198
1199 if (!qflag)
1200 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1201 return 0;
1202}
1203
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001204#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205
1206/* detach traced process; continue with sig */
1207
1208static int
1209detach(tcp, sig)
1210struct tcb *tcp;
1211int sig;
1212{
1213 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001214#ifdef LINUX
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001215 int status, resumed;
Roland McGratha08a97e2005-08-03 11:23:46 +00001216 struct tcb *zombie = NULL;
1217
1218 /* If the group leader is lingering only because of this other
1219 thread now dying, then detach the leader as well. */
1220 if ((tcp->flags & TCB_CLONE_THREAD) &&
1221 tcp->parent->nclone_threads == 1 &&
1222 (tcp->parent->flags & TCB_EXITING))
1223 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001224#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225
1226 if (tcp->flags & TCB_BPTSET)
1227 sig = SIGKILL;
1228
1229#ifdef LINUX
1230 /*
1231 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001232 * before detaching. Arghh. We go through hoops
1233 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001235#if defined(SPARC)
1236#undef PTRACE_DETACH
1237#define PTRACE_DETACH PTRACE_SUNDETACH
1238#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1240 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001241 }
1242 else if (errno != ESRCH) {
1243 /* Shouldn't happen. */
1244 perror("detach: ptrace(PTRACE_DETACH, ...)");
1245 }
1246 else if (kill(tcp->pid, 0) < 0) {
1247 if (errno != ESRCH)
1248 perror("detach: checking sanity");
1249 }
1250 else if (kill(tcp->pid, SIGSTOP) < 0) {
1251 if (errno != ESRCH)
1252 perror("detach: stopping child");
1253 }
1254 else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001256#ifdef __WALL
1257 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1258 if (errno == ECHILD) /* Already gone. */
1259 break;
1260 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001261 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001262 break;
1263 }
1264#endif /* __WALL */
1265 /* No __WALL here. */
1266 if (waitpid(tcp->pid, &status, 0) < 0) {
1267 if (errno != ECHILD) {
1268 perror("detach: waiting");
1269 break;
1270 }
1271#ifdef __WCLONE
1272 /* If no processes, try clones. */
1273 if (wait4(tcp->pid, &status, __WCLONE,
1274 NULL) < 0) {
1275 if (errno != ECHILD)
1276 perror("detach: waiting");
1277 break;
1278 }
1279#endif /* __WCLONE */
1280 }
1281#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001282 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001283#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284 if (!WIFSTOPPED(status)) {
1285 /* Au revoir, mon ami. */
1286 break;
1287 }
1288 if (WSTOPSIG(status) == SIGSTOP) {
1289 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001290 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001291 if (errno != ESRCH)
1292 perror("detach: ptrace(PTRACE_DETACH, ...)");
1293 /* I died trying. */
1294 }
1295 break;
1296 }
1297 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001298 WSTOPSIG(status) == SIGTRAP ?
1299 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001300 if (errno != ESRCH)
1301 perror("detach: ptrace(PTRACE_CONT, ...)");
1302 break;
1303 }
1304 }
1305 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001306#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307
1308#if defined(SUNOS4)
1309 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1310 if (sig && kill(tcp->pid, sig) < 0)
1311 perror("detach: kill");
1312 sig = 0;
1313 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1314 perror("detach: ptrace(PTRACE_DETACH, ...)");
1315#endif /* SUNOS4 */
1316
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001318 resumed = 0;
1319
1320 /* XXX This won't always be quite right (but it never was).
1321 A waiter with argument 0 or < -1 is waiting for any pid in
1322 a particular pgrp, which this child might or might not be
1323 in. The waiter will only wake up if it's argument is -1
1324 or if it's waiting for tcp->pid's pgrp. It makes a
1325 difference to wake up a waiter when there might be more
1326 traced children, because it could get a false ECHILD
1327 error. OTOH, if this was the last child in the pgrp, then
1328 it ought to wake up and get ECHILD. We would have to
1329 search the system for all pid's in the pgrp to be sure.
1330
1331 && (t->waitpid == -1 ||
1332 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1333 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1334 */
1335
1336 if (tcp->parent &&
1337 (tcp->parent->flags & TCB_SUSPENDED) &&
1338 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1339 error = resume(tcp->parent);
1340 ++resumed;
1341 }
1342#ifdef TCB_CLONE_THREAD
1343 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1344 /* Some other threads of our parent are waiting too. */
1345 unsigned int i;
1346
1347 /* Resume all the threads that were waiting for this PID. */
1348 for (i = 0; i < tcbtabsize; i++) {
1349 struct tcb *t = tcbtab[i];
1350 if (t->parent == tcp->parent && t != tcp
1351 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1352 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1353 && t->waitpid == tcp->pid) {
1354 error |= resume (t);
1355 ++resumed;
1356 }
1357 }
1358 if (resumed == 0)
1359 /* Noone was waiting for this PID in particular,
1360 so now we might need to resume some wildcarders. */
1361 for (i = 0; i < tcbtabsize; i++) {
1362 struct tcb *t = tcbtab[i];
1363 if (t->parent == tcp->parent && t != tcp
1364 && ((t->flags
1365 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1366 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1367 && t->waitpid <= 0
1368 ) {
1369 error |= resume (t);
1370 break;
1371 }
1372 }
1373 }
1374#endif
1375
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001376#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377
1378 if (!qflag)
1379 fprintf(stderr, "Process %u detached\n", tcp->pid);
1380
1381 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001382
1383#ifdef LINUX
1384 if (zombie != NULL)
1385 error = detach(zombie) || error;
1386#endif
1387
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001388 return error;
1389}
1390
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001391#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392
1393static void
1394reaper(sig)
1395int sig;
1396{
1397 int pid;
1398 int status;
1399
1400 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1401#if 0
1402 struct tcb *tcp;
1403
1404 tcp = pid2tcb(pid);
1405 if (tcp)
1406 droptcb(tcp);
1407#endif
1408 }
1409}
1410
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001411#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001412
1413static void
1414cleanup()
1415{
1416 int i;
1417 struct tcb *tcp;
1418
Roland McGrathee9d4352002-12-18 04:16:10 +00001419 for (i = 0; i < tcbtabsize; i++) {
1420 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421 if (!(tcp->flags & TCB_INUSE))
1422 continue;
1423 if (debug)
1424 fprintf(stderr,
1425 "cleanup: looking at pid %u\n", tcp->pid);
1426 if (tcp_last &&
1427 (!outfname || followfork < 2 || tcp_last == tcp)) {
1428 tprintf(" <unfinished ...>\n");
1429 tcp_last = NULL;
1430 }
1431 if (tcp->flags & TCB_ATTACHED)
1432 detach(tcp, 0);
1433 else {
1434 kill(tcp->pid, SIGCONT);
1435 kill(tcp->pid, SIGTERM);
1436 }
1437 }
1438 if (cflag)
1439 call_summary(outf);
1440}
1441
1442static void
1443interrupt(sig)
1444int sig;
1445{
1446 interrupted = 1;
1447}
1448
1449#ifndef HAVE_STRERROR
1450
Roland McGrath6d2b3492002-12-30 00:51:30 +00001451#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001452extern int sys_nerr;
1453extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001454#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455
1456const char *
1457strerror(errno)
1458int errno;
1459{
1460 static char buf[64];
1461
1462 if (errno < 1 || errno >= sys_nerr) {
1463 sprintf(buf, "Unknown error %d", errno);
1464 return buf;
1465 }
1466 return sys_errlist[errno];
1467}
1468
1469#endif /* HAVE_STERRROR */
1470
1471#ifndef HAVE_STRSIGNAL
1472
Roland McGrath8f474e02003-01-14 07:53:33 +00001473#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001474extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001476#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1477extern char *_sys_siglist[];
1478#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479
1480const char *
1481strsignal(sig)
1482int sig;
1483{
1484 static char buf[64];
1485
1486 if (sig < 1 || sig >= NSIG) {
1487 sprintf(buf, "Unknown signal %d", sig);
1488 return buf;
1489 }
1490#ifdef HAVE__SYS_SIGLIST
1491 return _sys_siglist[sig];
1492#else
1493 return sys_siglist[sig];
1494#endif
1495}
1496
1497#endif /* HAVE_STRSIGNAL */
1498
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001499#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500
1501static void
1502rebuild_pollv()
1503{
1504 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505
Roland McGrathee9d4352002-12-18 04:16:10 +00001506 if (pollv != NULL)
1507 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001508 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001509 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001510 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001511 exit(1);
1512 }
1513
Roland McGrathca16be82003-01-10 19:55:28 +00001514 for (i = j = 0; i < tcbtabsize; i++) {
1515 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001516 if (!(tcp->flags & TCB_INUSE))
1517 continue;
1518 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001519 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001520 j++;
1521 }
1522 if (j != nprocs) {
1523 fprintf(stderr, "strace: proc miscount\n");
1524 exit(1);
1525 }
1526}
1527
1528#ifndef HAVE_POLLABLE_PROCFS
1529
1530static void
1531proc_poll_open()
1532{
1533 int arg;
1534 int i;
1535
1536 if (pipe(proc_poll_pipe) < 0) {
1537 perror("pipe");
1538 exit(1);
1539 }
1540 for (i = 0; i < 2; i++) {
1541 if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
1542 perror("F_GETFD");
1543 exit(1);
1544 }
1545 if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
1546 perror("F_SETFD");
1547 exit(1);
1548 }
1549 }
1550}
1551
1552static int
1553proc_poll(pollv, nfds, timeout)
1554struct pollfd *pollv;
1555int nfds;
1556int timeout;
1557{
1558 int i;
1559 int n;
1560 struct proc_pollfd pollinfo;
1561
1562 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1563 return n;
1564 if (n != sizeof(struct proc_pollfd)) {
1565 fprintf(stderr, "panic: short read: %d\n", n);
1566 exit(1);
1567 }
1568 for (i = 0; i < nprocs; i++) {
1569 if (pollv[i].fd == pollinfo.fd)
1570 pollv[i].revents = pollinfo.revents;
1571 else
1572 pollv[i].revents = 0;
1573 }
1574 poller_pid = pollinfo.pid;
1575 return 1;
1576}
1577
1578static void
1579wakeup_handler(sig)
1580int sig;
1581{
1582}
1583
1584static void
1585proc_poller(pfd)
1586int pfd;
1587{
1588 struct proc_pollfd pollinfo;
1589 struct sigaction sa;
1590 sigset_t blocked_set, empty_set;
1591 int i;
1592 int n;
1593 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001594#ifdef FREEBSD
1595 struct procfs_status pfs;
1596#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597
1598 switch (fork()) {
1599 case -1:
1600 perror("fork");
1601 _exit(0);
1602 case 0:
1603 break;
1604 default:
1605 return;
1606 }
1607
1608 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1609 sa.sa_flags = 0;
1610 sigemptyset(&sa.sa_mask);
1611 sigaction(SIGHUP, &sa, NULL);
1612 sigaction(SIGINT, &sa, NULL);
1613 sigaction(SIGQUIT, &sa, NULL);
1614 sigaction(SIGPIPE, &sa, NULL);
1615 sigaction(SIGTERM, &sa, NULL);
1616 sa.sa_handler = wakeup_handler;
1617 sigaction(SIGUSR1, &sa, NULL);
1618 sigemptyset(&blocked_set);
1619 sigaddset(&blocked_set, SIGUSR1);
1620 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1621 sigemptyset(&empty_set);
1622
1623 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1624 perror("getrlimit(RLIMIT_NOFILE, ...)");
1625 _exit(0);
1626 }
1627 n = rl.rlim_cur;
1628 for (i = 0; i < n; i++) {
1629 if (i != pfd && i != proc_poll_pipe[1])
1630 close(i);
1631 }
1632
1633 pollinfo.fd = pfd;
1634 pollinfo.pid = getpid();
1635 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001636#ifndef FREEBSD
1637 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1638#else /* FREEBSD */
1639 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1640#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001641 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 switch (errno) {
1643 case EINTR:
1644 continue;
1645 case EBADF:
1646 pollinfo.revents = POLLERR;
1647 break;
1648 case ENOENT:
1649 pollinfo.revents = POLLHUP;
1650 break;
1651 default:
1652 perror("proc_poller: PIOCWSTOP");
1653 }
1654 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1655 _exit(0);
1656 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001657 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1659 sigsuspend(&empty_set);
1660 }
1661}
1662
1663#endif /* !HAVE_POLLABLE_PROCFS */
1664
1665static int
1666choose_pfd()
1667{
1668 int i, j;
1669 struct tcb *tcp;
1670
1671 static int last;
1672
1673 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001674 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675 /*
1676 * The previous process is ready to run again. We'll
1677 * let it do so if it is currently in a syscall. This
1678 * heuristic improves the readability of the trace.
1679 */
1680 tcp = pfd2tcb(pollv[last].fd);
1681 if (tcp && (tcp->flags & TCB_INSYSCALL))
1682 return pollv[last].fd;
1683 }
1684
1685 for (i = 0; i < nprocs; i++) {
1686 /* Let competing children run round robin. */
1687 j = (i + last + 1) % nprocs;
1688 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1689 tcp = pfd2tcb(pollv[j].fd);
1690 if (!tcp) {
1691 fprintf(stderr, "strace: lost proc\n");
1692 exit(1);
1693 }
1694 droptcb(tcp);
1695 return -1;
1696 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001697 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698 last = j;
1699 return pollv[j].fd;
1700 }
1701 }
1702 fprintf(stderr, "strace: nothing ready\n");
1703 exit(1);
1704}
1705
1706static int
1707trace()
1708{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001709#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001710 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001711#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 struct tcb *tcp;
1713 int pfd;
1714 int what;
1715 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001716 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717
1718 for (;;) {
1719 if (interactive)
1720 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1721
1722 if (nprocs == 0)
1723 break;
1724
1725 switch (nprocs) {
1726 case 1:
1727#ifndef HAVE_POLLABLE_PROCFS
1728 if (proc_poll_pipe[0] == -1) {
1729#endif
1730 tcp = pid2tcb(0);
1731 if (!tcp)
1732 continue;
1733 pfd = tcp->pfd;
1734 if (pfd == -1)
1735 continue;
1736 break;
1737#ifndef HAVE_POLLABLE_PROCFS
1738 }
1739 /* fall through ... */
1740#endif /* !HAVE_POLLABLE_PROCFS */
1741 default:
1742#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001743#ifdef POLL_HACK
1744 /* On some systems (e.g. UnixWare) we get too much ugly
1745 "unfinished..." stuff when multiple proceses are in
1746 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001747
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001748 if (in_syscall) {
1749 struct pollfd pv;
1750 tcp = in_syscall;
1751 in_syscall = NULL;
1752 pv.fd = tcp->pfd;
1753 pv.events = POLLWANT;
1754 if ((what = poll (&pv, 1, 1)) < 0) {
1755 if (interrupted)
1756 return 0;
1757 continue;
1758 }
1759 else if (what == 1 && pv.revents & POLLWANT) {
1760 goto FOUND;
1761 }
1762 }
1763#endif
1764
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765 if (poll(pollv, nprocs, INFTIM) < 0) {
1766 if (interrupted)
1767 return 0;
1768 continue;
1769 }
1770#else /* !HAVE_POLLABLE_PROCFS */
1771 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1772 if (interrupted)
1773 return 0;
1774 continue;
1775 }
1776#endif /* !HAVE_POLLABLE_PROCFS */
1777 pfd = choose_pfd();
1778 if (pfd == -1)
1779 continue;
1780 break;
1781 }
1782
1783 /* Look up `pfd' in our table. */
1784 if ((tcp = pfd2tcb(pfd)) == NULL) {
1785 fprintf(stderr, "unknown pfd: %u\n", pfd);
1786 exit(1);
1787 }
John Hughesb6643082002-05-23 11:02:22 +00001788#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001789 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001790#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791 /* Get the status of the process. */
1792 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001793#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001794 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001795#else /* FREEBSD */
1796 /* Thanks to some scheduling mystery, the first poller
1797 sometimes waits for the already processed end of fork
1798 event. Doing a non blocking poll here solves the problem. */
1799 if (proc_poll_pipe[0] != -1)
1800 ioctl_result = IOCTL_STATUS (tcp);
1801 else
1802 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001803#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 ioctl_errno = errno;
1805#ifndef HAVE_POLLABLE_PROCFS
1806 if (proc_poll_pipe[0] != -1) {
1807 if (ioctl_result < 0)
1808 kill(poller_pid, SIGKILL);
1809 else
1810 kill(poller_pid, SIGUSR1);
1811 }
1812#endif /* !HAVE_POLLABLE_PROCFS */
1813 }
1814 if (interrupted)
1815 return 0;
1816
1817 if (interactive)
1818 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1819
1820 if (ioctl_result < 0) {
1821 /* Find out what happened if it failed. */
1822 switch (ioctl_errno) {
1823 case EINTR:
1824 case EBADF:
1825 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001826#ifdef FREEBSD
1827 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001828#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829 case ENOENT:
1830 droptcb(tcp);
1831 continue;
1832 default:
1833 perror("PIOCWSTOP");
1834 exit(1);
1835 }
1836 }
1837
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001838#ifdef FREEBSD
1839 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1840 /* discard first event for a syscall we never entered */
1841 IOCTL (tcp->pfd, PIOCRUN, 0);
1842 continue;
1843 }
Roland McGrath553a6092002-12-16 20:40:39 +00001844#endif
1845
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846 /* clear the just started flag */
1847 tcp->flags &= ~TCB_STARTUP;
1848
1849 /* set current output file */
1850 outf = tcp->outf;
1851
1852 if (cflag) {
1853 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001854#ifdef FREEBSD
1855 char buf[1024];
1856 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001858 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1859 buf[len] = '\0';
1860 sscanf(buf,
1861 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1862 &stime.tv_sec, &stime.tv_usec);
1863 } else
1864 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001865#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866 stime.tv_sec = tcp->status.pr_stime.tv_sec;
1867 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001868#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869 tv_sub(&tcp->dtime, &stime, &tcp->stime);
1870 tcp->stime = stime;
1871 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001872 what = tcp->status.PR_WHAT;
1873 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001874#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001876 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
1877 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878 if (trace_syscall(tcp) < 0) {
1879 fprintf(stderr, "syscall trouble\n");
1880 exit(1);
1881 }
1882 }
1883 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001884#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001886#ifdef POLL_HACK
1887 in_syscall = tcp;
1888#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001889 case PR_SYSEXIT:
1890 if (trace_syscall(tcp) < 0) {
1891 fprintf(stderr, "syscall trouble\n");
1892 exit(1);
1893 }
1894 break;
1895 case PR_SIGNALLED:
1896 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
1897 printleader(tcp);
1898 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00001899 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001900 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00001901#ifdef PR_INFO
1902 if (tcp->status.PR_INFO.si_signo == what) {
1903 printleader(tcp);
1904 tprintf(" siginfo=");
1905 printsiginfo(&tcp->status.PR_INFO, 1);
1906 printtrailer(tcp);
1907 }
1908#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909 }
1910 break;
1911 case PR_FAULTED:
1912 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
1913 printleader(tcp);
1914 tprintf("=== FAULT %d ===", what);
1915 printtrailer(tcp);
1916 }
1917 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001918#ifdef FREEBSD
1919 case 0: /* handle case we polled for nothing */
1920 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00001921#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001923 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924 exit(1);
1925 break;
1926 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001927 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001928#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001929 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001930#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001931 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001932#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001933 perror("PIOCRUN");
1934 exit(1);
1935 }
1936 }
1937 return 0;
1938}
1939
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001940#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001941
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001942#ifdef TCB_GROUP_EXITING
1943/* Handle an exit detach or death signal that is taking all the
1944 related clone threads with it. This is called in three circumstances:
1945 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
1946 SIG == 0 Continuing TCP will perform an exit_group syscall.
1947 SIG == other Continuing TCP with SIG will kill the process.
1948*/
1949static int
1950handle_group_exit(struct tcb *tcp, int sig)
1951{
1952 /* We need to locate our records of all the clone threads
1953 related to TCP, either its children or siblings. */
1954 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1955 ? tcp->parent
1956 : tcp->nclone_detached > 0
1957 ? tcp : NULL);
1958
1959 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00001960 if (leader != NULL && leader != tcp &&
1961 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001962 fprintf(stderr,
1963 "PANIC: handle_group_exit: %d leader %d\n",
1964 tcp->pid, leader ? leader->pid : -1);
Roland McGratha08a97e2005-08-03 11:23:46 +00001965 detach(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001966 }
1967 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00001968 /* Mark that we are taking the process down. */
1969 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001970 if (tcp->flags & TCB_ATTACHED) {
Roland McGrath00dc13f2004-10-20 02:04:15 +00001971 if (leader != NULL && leader != tcp) {
1972 if (leader->flags & TCB_ATTACHED) {
1973 /* We need to detach the leader so
1974 that the process death will be
1975 reported to its real parent.
1976 But we kill it first to prevent
1977 it doing anything before we kill
1978 the whole process in a moment.
1979 We can use PTRACE_KILL on a
1980 thread that's not already
1981 stopped. Then the value we pass
1982 in PTRACE_DETACH just sets the
1983 death signal reported to the
1984 real parent. */
1985 ptrace(PTRACE_KILL, leader->pid, 0, 0);
1986 if (debug)
1987 fprintf(stderr,
1988 " [%d exit %d kills %d]\n",
1989 tcp->pid, sig, leader->pid);
1990 detach(leader, sig);
1991 }
1992 else
1993 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001994 }
1995 detach(tcp, sig);
1996 }
1997 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1998 perror("strace: ptrace(PTRACE_CONT, ...)");
1999 cleanup();
2000 return -1;
2001 }
2002 else {
Roland McGrath05690952004-10-20 01:00:27 +00002003 if (leader != NULL)
2004 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002005 if (leader != NULL && leader != tcp)
2006 droptcb(tcp);
2007 /* The leader will report to us as parent now,
2008 and then we'll get to the SIG==-1 case. */
2009 return 0;
2010 }
2011 }
2012
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002013 return 0;
2014}
2015#endif
2016
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017static int
2018trace()
2019{
2020 int pid;
2021 int wait_errno;
2022 int status;
2023 struct tcb *tcp;
2024#ifdef LINUX
2025 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002026#ifdef __WALL
2027 static int wait4_options = __WALL;
2028#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029#endif /* LINUX */
2030
2031 while (nprocs != 0) {
2032 if (interactive)
2033 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2034#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002035#ifdef __WALL
2036 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002037 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002038 /* this kernel does not support __WALL */
2039 wait4_options &= ~__WALL;
2040 errno = 0;
2041 pid = wait4(-1, &status, wait4_options,
2042 cflag ? &ru : NULL);
2043 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002044 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002045 /* most likely a "cloned" process */
2046 pid = wait4(-1, &status, __WCLONE,
2047 cflag ? &ru : NULL);
2048 if (pid == -1) {
2049 fprintf(stderr, "strace: clone wait4 "
2050 "failed: %s\n", strerror(errno));
2051 }
2052 }
2053#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002055#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056#endif /* LINUX */
2057#ifdef SUNOS4
2058 pid = wait(&status);
2059#endif /* SUNOS4 */
2060 wait_errno = errno;
2061 if (interactive)
2062 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2063
2064 if (interrupted)
2065 return 0;
2066
2067 if (pid == -1) {
2068 switch (wait_errno) {
2069 case EINTR:
2070 continue;
2071 case ECHILD:
2072 /*
2073 * We would like to verify this case
2074 * but sometimes a race in Solbourne's
2075 * version of SunOS sometimes reports
2076 * ECHILD before sending us SIGCHILD.
2077 */
2078#if 0
2079 if (nprocs == 0)
2080 return 0;
2081 fprintf(stderr, "strace: proc miscount\n");
2082 exit(1);
2083#endif
2084 return 0;
2085 default:
2086 errno = wait_errno;
2087 perror("strace: wait");
2088 return -1;
2089 }
2090 }
2091 if (debug)
2092 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2093
2094 /* Look up `pid' in our table. */
2095 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002096#ifdef LINUX
2097 if (followfork || followvfork) {
2098 /* This is needed to go with the CLONE_PTRACE
2099 changes in process.c/util.c: we might see
2100 the child's initial trap before we see the
2101 parent return from the clone syscall.
2102 Leave the child suspended until the parent
2103 returns from its system call. Only then
2104 will we have the association of parent and
2105 child so that we know how to do clearbpt
2106 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002107 if (nprocs == tcbtabsize &&
2108 expand_tcbtab())
2109 tcp = NULL;
2110 else
2111 tcp = alloctcb(pid);
2112 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002113 kill(pid, SIGKILL); /* XXX */
2114 return 0;
2115 }
2116 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2117 newoutf(tcp);
2118 if (!qflag)
2119 fprintf(stderr, "\
2120Process %d attached (waiting for parent)\n",
2121 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002122 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002123 else
2124 /* This can happen if a clone call used
2125 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002126#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002127 {
2128 fprintf(stderr, "unknown pid: %u\n", pid);
2129 if (WIFSTOPPED(status))
2130 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2131 exit(1);
2132 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002133 }
2134 /* set current output file */
2135 outf = tcp->outf;
2136 if (cflag) {
2137#ifdef LINUX
2138 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2139 tcp->stime = ru.ru_stime;
2140#endif /* !LINUX */
2141 }
2142
2143 if (tcp->flags & TCB_SUSPENDED) {
2144 /*
2145 * Apparently, doing any ptrace() call on a stopped
2146 * process, provokes the kernel to report the process
2147 * status again on a subsequent wait(), even if the
2148 * process has not been actually restarted.
2149 * Since we have inspected the arguments of suspended
2150 * processes we end up here testing for this case.
2151 */
2152 continue;
2153 }
2154 if (WIFSIGNALED(status)) {
2155 if (!cflag
2156 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2157 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002158 tprintf("+++ killed by %s %s+++",
2159 signame(WTERMSIG(status)),
2160#ifdef WCOREDUMP
2161 WCOREDUMP(status) ? "(core dumped) " :
2162#endif
2163 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002164 printtrailer(tcp);
2165 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002166#ifdef TCB_GROUP_EXITING
2167 handle_group_exit(tcp, -1);
2168#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002169 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002170#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 continue;
2172 }
2173 if (WIFEXITED(status)) {
2174 if (debug)
2175 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002176 if ((tcp->flags & TCB_ATTACHED)
2177#ifdef TCB_GROUP_EXITING
2178 && !(tcp->parent && (tcp->parent->flags &
2179 TCB_GROUP_EXITING))
2180#endif
2181 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182 fprintf(stderr,
2183 "PANIC: attached pid %u exited\n",
2184 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002185 if (tcp == tcp_last) {
2186 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2187 == TCB_INSYSCALL)
2188 tprintf(" <unfinished ... exit status %d>\n",
2189 WEXITSTATUS(status));
2190 tcp_last = NULL;
2191 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002192#ifdef TCB_GROUP_EXITING
2193 handle_group_exit(tcp, -1);
2194#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002196#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 continue;
2198 }
2199 if (!WIFSTOPPED(status)) {
2200 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2201 droptcb(tcp);
2202 continue;
2203 }
2204 if (debug)
2205 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002206 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207
2208 if (tcp->flags & TCB_STARTUP) {
2209 /*
2210 * This flag is there to keep us in sync.
2211 * Next time this process stops it should
2212 * really be entering a system call.
2213 */
2214 tcp->flags &= ~TCB_STARTUP;
2215 if (tcp->flags & TCB_ATTACHED) {
2216 /*
2217 * Interestingly, the process may stop
2218 * with STOPSIG equal to some other signal
2219 * than SIGSTOP if we happend to attach
2220 * just before the process takes a signal.
2221 */
2222 if (!WIFSTOPPED(status)) {
2223 fprintf(stderr,
2224 "pid %u not stopped\n", pid);
2225 detach(tcp, WSTOPSIG(status));
2226 continue;
2227 }
2228 }
2229 else {
2230#ifdef SUNOS4
2231 /* A child of us stopped at exec */
2232 if (WSTOPSIG(status) == SIGTRAP && followvfork)
2233 fixvfork(tcp);
2234#endif /* SUNOS4 */
2235 }
2236 if (tcp->flags & TCB_BPTSET) {
2237 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2238 droptcb(tcp);
2239 cleanup();
2240 return -1;
2241 }
2242 }
2243 goto tracing;
2244 }
2245
2246 if (WSTOPSIG(status) != SIGTRAP) {
2247 if (WSTOPSIG(status) == SIGSTOP &&
2248 (tcp->flags & TCB_SIGTRAPPED)) {
2249 /*
2250 * Trapped attempt to block SIGTRAP
2251 * Hope we are back in control now.
2252 */
2253 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2254 if (ptrace(PTRACE_SYSCALL,
2255 pid, (char *) 1, 0) < 0) {
2256 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2257 cleanup();
2258 return -1;
2259 }
2260 continue;
2261 }
2262 if (!cflag
2263 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002264 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002265#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002266# define PSR_RI 41
2267 struct siginfo si;
2268 unsigned long psr;
2269
2270 upeek(pid, PT_CR_IPSR, &psr);
2271 upeek(pid, PT_CR_IIP, &pc);
2272
2273 pc += (psr >> PSR_RI) & 0x3;
2274 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2275 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002276#elif defined PTRACE_GETSIGINFO
2277 if (WSTOPSIG(status) == SIGSEGV ||
2278 WSTOPSIG(status) == SIGBUS) {
2279 siginfo_t si;
2280 if (ptrace(PTRACE_GETSIGINFO, pid,
2281 0, &si) == 0)
2282 addr = (unsigned long)
2283 si.si_addr;
2284 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002285#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002286 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002287 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002288 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002289 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002290 printtrailer(tcp);
2291 }
Roland McGrath05690952004-10-20 01:00:27 +00002292 if (((tcp->flags & TCB_ATTACHED) ||
2293 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002295#ifdef TCB_GROUP_EXITING
2296 handle_group_exit(tcp, WSTOPSIG(status));
2297#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002298 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002299#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002300 continue;
2301 }
2302 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2303 WSTOPSIG(status)) < 0) {
2304 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2305 cleanup();
2306 return -1;
2307 }
2308 tcp->flags &= ~TCB_SUSPENDED;
2309 continue;
2310 }
2311 if (trace_syscall(tcp) < 0) {
2312 if (tcp->flags & TCB_ATTACHED)
2313 detach(tcp, 0);
2314 else {
2315 ptrace(PTRACE_KILL,
2316 tcp->pid, (char *) 1, SIGTERM);
2317 droptcb(tcp);
2318 }
2319 continue;
2320 }
2321 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002322#ifdef TCB_GROUP_EXITING
2323 if (tcp->flags & TCB_GROUP_EXITING) {
2324 if (handle_group_exit(tcp, 0) < 0)
2325 return -1;
2326 continue;
2327 }
2328#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 if (tcp->flags & TCB_ATTACHED)
2330 detach(tcp, 0);
2331 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2332 perror("strace: ptrace(PTRACE_CONT, ...)");
2333 cleanup();
2334 return -1;
2335 }
2336 continue;
2337 }
2338 if (tcp->flags & TCB_SUSPENDED) {
2339 if (!qflag)
2340 fprintf(stderr, "Process %u suspended\n", pid);
2341 continue;
2342 }
2343 tracing:
2344 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2345 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2346 cleanup();
2347 return -1;
2348 }
2349 }
2350 return 0;
2351}
2352
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002353#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002354
2355static int curcol;
2356
2357#ifdef __STDC__
2358#include <stdarg.h>
2359#define VA_START(a, b) va_start(a, b)
2360#else
2361#include <varargs.h>
2362#define VA_START(a, b) va_start(a)
2363#endif
2364
2365void
2366#ifdef __STDC__
2367tprintf(const char *fmt, ...)
2368#else
2369tprintf(fmt, va_alist)
2370char *fmt;
2371va_dcl
2372#endif
2373{
2374 va_list args;
2375
2376 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002377 if (outf) {
2378 int n = vfprintf(outf, fmt, args);
2379 if (n < 0 && outf != stderr)
2380 perror(outfname == NULL
2381 ? "<writing to pipe>" : outfname);
2382 else
2383 curcol += n;
2384 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 va_end(args);
2386 return;
2387}
2388
2389void
2390printleader(tcp)
2391struct tcb *tcp;
2392{
2393 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2394 tcp_last->flags |= TCB_REPRINT;
2395 tprintf(" <unfinished ...>\n");
2396 }
2397 curcol = 0;
2398 if ((followfork == 1 || pflag_seen > 1) && outfname)
2399 tprintf("%-5d ", tcp->pid);
2400 else if (nprocs > 1 && !outfname)
2401 tprintf("[pid %5u] ", tcp->pid);
2402 if (tflag) {
2403 char str[sizeof("HH:MM:SS")];
2404 struct timeval tv, dtv;
2405 static struct timeval otv;
2406
2407 gettimeofday(&tv, NULL);
2408 if (rflag) {
2409 if (otv.tv_sec == 0)
2410 otv = tv;
2411 tv_sub(&dtv, &tv, &otv);
2412 tprintf("%6ld.%06ld ",
2413 (long) dtv.tv_sec, (long) dtv.tv_usec);
2414 otv = tv;
2415 }
2416 else if (tflag > 2) {
2417 tprintf("%ld.%06ld ",
2418 (long) tv.tv_sec, (long) tv.tv_usec);
2419 }
2420 else {
2421 time_t local = tv.tv_sec;
2422 strftime(str, sizeof(str), "%T", localtime(&local));
2423 if (tflag > 1)
2424 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2425 else
2426 tprintf("%s ", str);
2427 }
2428 }
2429 if (iflag)
2430 printcall(tcp);
2431}
2432
2433void
2434tabto(col)
2435int col;
2436{
2437 if (curcol < col)
2438 tprintf("%*s", col - curcol, "");
2439}
2440
2441void
2442printtrailer(tcp)
2443struct tcb *tcp;
2444{
2445 tprintf("\n");
2446 tcp_last = NULL;
2447}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002448
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002449#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002450
2451int mp_ioctl (int fd, int cmd, void *arg, int size) {
2452
2453 struct iovec iov[2];
2454 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002455
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002456 iov[0].iov_base = &cmd;
2457 iov[0].iov_len = sizeof cmd;
2458 if (arg) {
2459 ++n;
2460 iov[1].iov_base = arg;
2461 iov[1].iov_len = size;
2462 }
Roland McGrath553a6092002-12-16 20:40:39 +00002463
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002464 return writev (fd, iov, n);
2465}
2466
2467#endif