blob: 368eb860d48ed4f6c49a8f2c246d391d8454b78f [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
Wichert Akkerman2ee6e452000-02-18 15:36:12 +000033#include <sys/types.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000034#include "defs.h"
35
36#include <signal.h>
37#include <errno.h>
38#include <sys/param.h>
39#include <fcntl.h>
40#include <sys/resource.h>
41#include <sys/wait.h>
42#include <sys/stat.h>
43#include <pwd.h>
44#include <grp.h>
45#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000046#include <limits.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000047
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000048#if defined(IA64) && defined(LINUX)
49# include <asm/ptrace_offsets.h>
50#endif
51
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000052#ifdef USE_PROCFS
53#include <poll.h>
54#endif
55
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000056#ifdef SVR4
57#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000058#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000059#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000060#include <sys/uio.h>
61#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000062#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000063#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000064
65int debug = 0, followfork = 0, followvfork = 0, interactive = 0;
66int rflag = 0, tflag = 0, dtime = 0, cflag = 0;
67int iflag = 0, xflag = 0, qflag = 0;
68int pflag_seen = 0;
69
Michal Ludvig17f8fb32002-11-06 13:17:21 +000070/* Sometimes we want to print only succeeding syscalls. */
71int not_failing_only = 0;
72
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073char *username = NULL;
74uid_t run_uid;
75gid_t run_gid;
76
77int acolumn = DEFAULT_ACOLUMN;
78int max_strlen = DEFAULT_STRLEN;
79char *outfname = NULL;
80FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +000081struct tcb **tcbtab;
82unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084extern char **environ;
85
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086static int trace P((void));
87static void cleanup P((void));
88static void interrupt P((int sig));
89static sigset_t empty_set, blocked_set;
90
91#ifdef HAVE_SIG_ATOMIC_T
92static volatile sig_atomic_t interrupted;
93#else /* !HAVE_SIG_ATOMIC_T */
94#ifdef __STDC__
95static volatile int interrupted;
96#else /* !__STDC__ */
97static int interrupted;
98#endif /* !__STDC__ */
99#endif /* !HAVE_SIG_ATOMIC_T */
100
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000101#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
103static struct tcb *pfd2tcb P((int pfd));
104static void reaper P((int sig));
105static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000106static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
108#ifndef HAVE_POLLABLE_PROCFS
109
110static void proc_poll_open P((void));
111static void proc_poller P((int pfd));
112
113struct proc_pollfd {
114 int fd;
115 int revents;
116 int pid;
117};
118
119static int poller_pid;
120static int proc_poll_pipe[2] = { -1, -1 };
121
122#endif /* !HAVE_POLLABLE_PROCFS */
123
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000124#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000125#define POLLWANT POLLWRNORM
126#else
127#define POLLWANT POLLPRI
128#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000129#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
131static void
132usage(ofp, exitval)
133FILE *ofp;
134int exitval;
135{
136 fprintf(ofp, "\
137usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000138 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
139 [command [arg ...]]\n\
140 or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
141 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142-c -- count time, calls, and errors for each syscall and report summary\n\
143-f -- follow forks, -ff -- with output into separate files\n\
144-F -- attempt to follow vforks, -h -- print help message\n\
145-i -- print instruction pointer at time of syscall\n\
146-q -- suppress messages about attaching, detaching, etc.\n\
147-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
148-T -- print time spent in each syscall, -V -- print version\n\
149-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
150-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
151-a column -- alignment COLUMN for printing syscall results (default %d)\n\
152-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
153 options: trace, abbrev, verbose, raw, signal, read, or write\n\
154-o file -- send trace output to FILE instead of stderr\n\
155-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
156-p pid -- trace process with process id PID, may be repeated\n\
157-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
158-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
159-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000160-E var=val -- put var=val in the environment for command\n\
161-E var -- remove var from the environment for command\n\
162" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000163-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000164 */
165, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166 exit(exitval);
167}
168
169#ifdef SVR4
170#ifdef MIPS
171void
172foobar()
173{
174}
175#endif /* MIPS */
176#endif /* SVR4 */
177
178int
179main(argc, argv)
180int argc;
181char *argv[];
182{
183 extern int optind;
184 extern char *optarg;
185 struct tcb *tcp;
186 int c, pid = 0;
187 struct sigaction sa;
188
189 static char buf[BUFSIZ];
190
Roland McGrathee9d4352002-12-18 04:16:10 +0000191 /* Allocate the initial tcbtab. */
192 tcbtabsize = argc; /* Surely enough for all -p args. */
193 tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
194 tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
195 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
196 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
197
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198 progname = argv[0];
199 outf = stderr;
200 interactive = 1;
201 qualify("trace=all");
202 qualify("abbrev=all");
203 qualify("verbose=all");
204 qualify("signal=all");
205 set_sortby(DEFAULT_SORTBY);
206 set_personality(DEFAULT_PERSONALITY);
207 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000208 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209 switch (c) {
210 case 'c':
211 cflag++;
212 dtime++;
213 break;
214 case 'd':
215 debug++;
216 break;
217 case 'f':
218 followfork++;
219 break;
220 case 'F':
221 followvfork++;
222 break;
223 case 'h':
224 usage(stdout, 0);
225 break;
226 case 'i':
227 iflag++;
228 break;
229 case 'q':
230 qflag++;
231 break;
232 case 'r':
233 rflag++;
234 tflag++;
235 break;
236 case 't':
237 tflag++;
238 break;
239 case 'T':
240 dtime++;
241 break;
242 case 'x':
243 xflag++;
244 break;
245 case 'v':
246 qualify("abbrev=none");
247 break;
248 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000249 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250 exit(0);
251 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000252 case 'z':
253 not_failing_only = 1;
254 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000255 case 'a':
256 acolumn = atoi(optarg);
257 break;
258 case 'e':
259 qualify(optarg);
260 break;
261 case 'o':
262 outfname = strdup(optarg);
263 break;
264 case 'O':
265 set_overhead(atoi(optarg));
266 break;
267 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000268 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000269 fprintf(stderr, "%s: Invalid process id: %s\n",
270 progname, optarg);
271 break;
272 }
273 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000274 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000275 break;
276 }
277 if ((tcp = alloctcb(pid)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000278 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000279 progname);
280 exit(1);
281 }
282 tcp->flags |= TCB_ATTACHED;
283 pflag_seen++;
284 break;
285 case 's':
286 max_strlen = atoi(optarg);
287 break;
288 case 'S':
289 set_sortby(optarg);
290 break;
291 case 'u':
292 username = strdup(optarg);
293 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000294 case 'E':
295 if (putenv(optarg) < 0) {
296 fprintf(stderr, "%s: out of memory\n",
297 progname);
298 exit(1);
299 }
300 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301 default:
302 usage(stderr, 1);
303 break;
304 }
305 }
306
307 /* See if they want to run as another user. */
308 if (username != NULL) {
309 struct passwd *pent;
310
311 if (getuid() != 0 || geteuid() != 0) {
312 fprintf(stderr,
313 "%s: you must be root to use the -u option\n",
314 progname);
315 exit(1);
316 }
317 if ((pent = getpwnam(username)) == NULL) {
318 fprintf(stderr, "%s: cannot find user `%s'\n",
319 progname, optarg);
320 exit(1);
321 }
322 run_uid = pent->pw_uid;
323 run_gid = pent->pw_gid;
324 }
325 else {
326 run_uid = getuid();
327 run_gid = getgid();
328 }
329
330#ifndef SVR4
331 setreuid(geteuid(), getuid());
332#endif
333
334 /* See if they want to pipe the output. */
335 if (outfname && (outfname[0] == '|' || outfname[0] == '!')) {
336 if ((outf = popen(outfname + 1, "w")) == NULL) {
337 fprintf(stderr, "%s: can't popen '%s': %s\n",
338 progname, outfname + 1, strerror(errno));
339 exit(1);
340 }
341 free(outfname);
342 outfname = NULL;
343 }
344
345 /* Check if they want to redirect the output. */
346 if (outfname) {
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000347 long f;
348
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000349 if ((outf = fopen(outfname, "w")) == NULL) {
350 fprintf(stderr, "%s: can't fopen '%s': %s\n",
351 progname, outfname, strerror(errno));
352 exit(1);
353 }
Wichert Akkerman54b4f792001-08-03 11:43:35 +0000354
355 if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
356 perror("failed to get flags for outputfile");
357 exit(1);
358 }
359
360 if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
361 perror("failed to set flags for outputfile");
362 exit(1);
363 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364 }
365
366#ifndef SVR4
367 setreuid(geteuid(), getuid());
368#endif
369
370 if (!outfname) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000371 setvbuf(outf, buf, _IOLBF, BUFSIZ);
372 }
Roland McGrath36931052003-06-03 01:35:20 +0000373 else if (optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000374 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000375 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000376 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000377
Roland McGrathee9d4352002-12-18 04:16:10 +0000378 for (c = 0; c < tcbtabsize; c++) {
379 tcp = tcbtab[c];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000380 /* Reinitialize the output since it may have changed. */
381 tcp->outf = outf;
382 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
383 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000384#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 if (proc_open(tcp, 1) < 0) {
386 fprintf(stderr, "trouble opening proc file\n");
387 droptcb(tcp);
388 continue;
389 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000390#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
392 perror("attach: ptrace(PTRACE_ATTACH, ...)");
393 droptcb(tcp);
394 continue;
395 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000396#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397 if (!qflag)
398 fprintf(stderr,
399 "Process %u attached - interrupt to quit\n",
400 pid);
401 }
402
403 if (optind < argc) {
404 struct stat statbuf;
405 char *filename;
406 char pathname[MAXPATHLEN];
407
408 filename = argv[optind];
409 if (strchr(filename, '/'))
410 strcpy(pathname, filename);
411#ifdef USE_DEBUGGING_EXEC
412 /*
413 * Debuggers customarily check the current directory
414 * first regardless of the path but doing that gives
415 * security geeks a panic attack.
416 */
417 else if (stat(filename, &statbuf) == 0)
418 strcpy(pathname, filename);
419#endif /* USE_DEBUGGING_EXEC */
420 else {
421 char *path;
422 int m, n, len;
423
424 for (path = getenv("PATH"); path && *path; path += m) {
425 if (strchr(path, ':')) {
426 n = strchr(path, ':') - path;
427 m = n + 1;
428 }
429 else
430 m = n = strlen(path);
431 if (n == 0) {
432 getcwd(pathname, MAXPATHLEN);
433 len = strlen(pathname);
434 }
435 else {
436 strncpy(pathname, path, n);
437 len = n;
438 }
439 if (len && pathname[len - 1] != '/')
440 pathname[len++] = '/';
441 strcpy(pathname + len, filename);
442 if (stat(pathname, &statbuf) == 0)
443 break;
444 }
445 }
446 if (stat(pathname, &statbuf) < 0) {
447 fprintf(stderr, "%s: %s: command not found\n",
448 progname, filename);
449 exit(1);
450 }
451 switch (pid = fork()) {
452 case -1:
453 perror("strace: fork");
454 cleanup();
455 exit(1);
456 break;
457 case 0: {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000458#ifdef USE_PROCFS
459 if (outf != stderr) close (fileno (outf));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000460#ifdef MIPS
461 /* Kludge for SGI, see proc_open for details. */
462 sa.sa_handler = foobar;
463 sa.sa_flags = 0;
464 sigemptyset(&sa.sa_mask);
465 sigaction(SIGINT, &sa, NULL);
466#endif /* MIPS */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000467#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000468 pause();
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000469#else /* FREEBSD */
470 kill(getpid(), SIGSTOP); /* stop HERE */
Roland McGrath553a6092002-12-16 20:40:39 +0000471#endif /* FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000472#else /* !USE_PROCFS */
Roland McGrath553a6092002-12-16 20:40:39 +0000473 if (outf!=stderr)
Wichert Akkerman7987cdf2000-07-05 16:05:39 +0000474 close(fileno (outf));
Wichert Akkermanbd4125c2000-06-27 17:28:06 +0000475
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000476 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
477 perror("strace: ptrace(PTRACE_TRACEME, ...)");
478 return -1;
479 }
480 if (debug)
481 kill(getpid(), SIGSTOP);
482
483 if (username != NULL || geteuid() == 0) {
484 uid_t run_euid = run_uid;
485 gid_t run_egid = run_gid;
486
487 if (statbuf.st_mode & S_ISUID)
488 run_euid = statbuf.st_uid;
489 if (statbuf.st_mode & S_ISGID)
490 run_egid = statbuf.st_gid;
491
492 /*
493 * It is important to set groups before we
494 * lose privileges on setuid.
495 */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +0000496 if (username != NULL) {
497 if (initgroups(username, run_gid) < 0) {
498 perror("initgroups");
499 exit(1);
500 }
501 if (setregid(run_gid, run_egid) < 0) {
502 perror("setregid");
503 exit(1);
504 }
505 if (setreuid(run_uid, run_euid) < 0) {
506 perror("setreuid");
507 exit(1);
508 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509 }
510 }
511 else
512 setreuid(run_uid, run_uid);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000513#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514
515 execv(pathname, &argv[optind]);
516 perror("strace: exec");
517 _exit(1);
518 break;
519 }
520 default:
521 if ((tcp = alloctcb(pid)) == NULL) {
522 fprintf(stderr, "tcb table full\n");
523 cleanup();
524 exit(1);
525 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000526#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527 if (proc_open(tcp, 0) < 0) {
528 fprintf(stderr, "trouble opening proc file\n");
529 cleanup();
530 exit(1);
531 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000532#endif /* USE_PROCFS */
533#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534 fake_execve(tcp, pathname, &argv[optind], environ);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000535#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536 break;
537 }
538 }
539 else if (pflag_seen == 0)
540 usage(stderr, 1);
541
542 sigemptyset(&empty_set);
543 sigemptyset(&blocked_set);
544 sa.sa_handler = SIG_IGN;
545 sigemptyset(&sa.sa_mask);
546 sa.sa_flags = 0;
547 sigaction(SIGTTOU, &sa, NULL);
548 sigaction(SIGTTIN, &sa, NULL);
549 if (interactive) {
550 sigaddset(&blocked_set, SIGHUP);
551 sigaddset(&blocked_set, SIGINT);
552 sigaddset(&blocked_set, SIGQUIT);
553 sigaddset(&blocked_set, SIGPIPE);
554 sigaddset(&blocked_set, SIGTERM);
555 sa.sa_handler = interrupt;
556#ifdef SUNOS4
557 /* POSIX signals on sunos4.1 are a little broken. */
558 sa.sa_flags = SA_INTERRUPT;
559#endif /* SUNOS4 */
560 }
561 sigaction(SIGHUP, &sa, NULL);
562 sigaction(SIGINT, &sa, NULL);
563 sigaction(SIGQUIT, &sa, NULL);
564 sigaction(SIGPIPE, &sa, NULL);
565 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000566#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567 sa.sa_handler = reaper;
568 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000569#else
570 /* Make sure SIGCHLD has the default action so that waitpid
571 definitely works without losing track of children. The user
572 should not have given us a bogus state to inherit, but he might
573 have. Arguably we should detect SIG_IGN here and pass it on
574 to children, but probably noone really needs that. */
575 sa.sa_handler = SIG_DFL;
576 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000577#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578
579 if (trace() < 0)
580 exit(1);
581 cleanup();
582 exit(0);
583}
584
585void
586newoutf(tcp)
587struct tcb *tcp;
588{
589 char name[MAXPATHLEN];
590 FILE *fp;
591
592 if (outfname && followfork > 1) {
593 sprintf(name, "%s.%u", outfname, tcp->pid);
594#ifndef SVR4
595 setreuid(geteuid(), getuid());
596#endif
597 fp = fopen(name, "w");
598#ifndef SVR4
599 setreuid(geteuid(), getuid());
600#endif
601 if (fp == NULL) {
602 perror("fopen");
603 return;
604 }
605 tcp->outf = fp;
606 }
607 return;
608}
609
610struct tcb *
611alloctcb(pid)
612int pid;
613{
614 int i;
615 struct tcb *tcp;
616
Roland McGrathee9d4352002-12-18 04:16:10 +0000617 for (i = 0; i < tcbtabsize; i++) {
618 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619 if ((tcp->flags & TCB_INUSE) == 0) {
620 tcp->pid = pid;
621 tcp->parent = NULL;
622 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000623 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000624#ifdef TCB_CLONE_THREAD
625 tcp->nclone_threads = tcp->nclone_detached = 0;
626 tcp->nclone_waiting = 0;
627#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000628 tcp->flags = TCB_INUSE | TCB_STARTUP;
629 tcp->outf = outf; /* Initialise to current out file */
630 tcp->stime.tv_sec = 0;
631 tcp->stime.tv_usec = 0;
632 tcp->pfd = -1;
633 nprocs++;
634 return tcp;
635 }
636 }
637 return NULL;
638}
639
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000640#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000641int
642proc_open(tcp, attaching)
643struct tcb *tcp;
644int attaching;
645{
646 char proc[32];
647 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000648#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000649 int i;
650 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651 sigset_t signals;
652 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000653#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000654#ifndef HAVE_POLLABLE_PROCFS
655 static int last_pfd;
656#endif
657
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000658#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000659 /* Open the process pseudo-files in /proc. */
660 sprintf(proc, "/proc/%d/ctl", tcp->pid);
661 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000662 perror("strace: open(\"/proc/...\", ...)");
663 return -1;
664 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000665 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
666 perror("F_GETFD");
667 return -1;
668 }
669 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
670 perror("F_SETFD");
671 return -1;
672 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000673 sprintf(proc, "/proc/%d/status", tcp->pid);
674 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
675 perror("strace: open(\"/proc/...\", ...)");
676 return -1;
677 }
678 if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
679 perror("F_GETFD");
680 return -1;
681 }
682 if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
683 perror("F_SETFD");
684 return -1;
685 }
686 sprintf(proc, "/proc/%d/as", tcp->pid);
687 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
688 perror("strace: open(\"/proc/...\", ...)");
689 return -1;
690 }
691 if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
692 perror("F_GETFD");
693 return -1;
694 }
695 if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
696 perror("F_SETFD");
697 return -1;
698 }
699#else
700 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000701#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000702 sprintf(proc, "/proc/%d", tcp->pid);
703 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000704#else /* FREEBSD */
705 sprintf(proc, "/proc/%d/mem", tcp->pid);
706 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
707#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000708 perror("strace: open(\"/proc/...\", ...)");
709 return -1;
710 }
711 if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
712 perror("F_GETFD");
713 return -1;
714 }
715 if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
716 perror("F_SETFD");
717 return -1;
718 }
719#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000720#ifdef FREEBSD
721 sprintf(proc, "/proc/%d/regs", tcp->pid);
722 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
723 perror("strace: open(\"/proc/.../regs\", ...)");
724 return -1;
725 }
726 if (cflag) {
727 sprintf(proc, "/proc/%d/status", tcp->pid);
728 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
729 perror("strace: open(\"/proc/.../status\", ...)");
730 return -1;
731 }
732 } else
733 tcp->pfd_status = -1;
734#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000735 rebuild_pollv();
736 if (!attaching) {
737 /*
738 * Wait for the child to pause. Because of a race
739 * condition we have to poll for the event.
740 */
741 for (;;) {
742 if (IOCTL_STATUS (tcp) < 0) {
743 perror("strace: PIOCSTATUS");
744 return -1;
745 }
746 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000747 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000748 }
749 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000750#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000751 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000752 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000753 perror("strace: PIOCSTOP");
754 return -1;
755 }
Roland McGrath553a6092002-12-16 20:40:39 +0000756#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757#ifdef PIOCSET
758 /* Set Run-on-Last-Close. */
759 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000760 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000761 perror("PIOCSET PR_RLC");
762 return -1;
763 }
764 /* Set or Reset Inherit-on-Fork. */
765 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000766 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 perror("PIOC{SET,RESET} PR_FORK");
768 return -1;
769 }
770#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +0000771#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000772 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
773 perror("PIOCSRLC");
774 return -1;
775 }
776 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
777 perror("PIOC{S,R}FORK");
778 return -1;
779 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000780#else /* FREEBSD */
781 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
782 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
783 perror("PIOCGFL");
784 return -1;
785 }
786 arg &= ~PF_LINGER;
787 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
788 perror("PIOCSFL");
789 return -1;
790 }
791#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000793#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +0000794 /* Enable all syscall entries we care about. */
795 premptyset(&syscalls);
796 for (i = 1; i < MAX_QUALS; ++i) {
797 if (i > (sizeof syscalls) * CHAR_BIT) break;
798 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
799 }
800 praddset (&syscalls, SYS_execve);
801 if (followfork) {
802 praddset (&syscalls, SYS_fork);
803#ifdef SYS_forkall
804 praddset (&syscalls, SYS_forkall);
805#endif
Roland McGrath553a6092002-12-16 20:40:39 +0000806#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +0000807 praddset (&syscalls, SYS_fork1);
808#endif
809#ifdef SYS_rfork1
810 praddset (&syscalls, SYS_rfork1);
811#endif
812#ifdef SYS_rforkall
813 praddset (&syscalls, SYS_rforkall);
814#endif
815 }
816 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000817 perror("PIOCSENTRY");
818 return -1;
819 }
John Hughes19e49982001-10-19 08:59:12 +0000820 /* Enable the syscall exits. */
821 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000822 perror("PIOSEXIT");
823 return -1;
824 }
John Hughes19e49982001-10-19 08:59:12 +0000825 /* Enable signals we care about. */
826 premptyset(&signals);
827 for (i = 1; i < MAX_QUALS; ++i) {
828 if (i > (sizeof signals) * CHAR_BIT) break;
829 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
830 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000831 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000832 perror("PIOCSTRACE");
833 return -1;
834 }
John Hughes19e49982001-10-19 08:59:12 +0000835 /* Enable faults we care about */
836 premptyset(&faults);
837 for (i = 1; i < MAX_QUALS; ++i) {
838 if (i > (sizeof faults) * CHAR_BIT) break;
839 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
840 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000841 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000842 perror("PIOCSFAULT");
843 return -1;
844 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000845#else /* FREEBSD */
846 /* set events flags. */
847 arg = S_SIG | S_SCE | S_SCX ;
848 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
849 perror("PIOCBIS");
850 return -1;
851 }
852#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000853 if (!attaching) {
854#ifdef MIPS
855 /*
856 * The SGI PRSABORT doesn't work for pause() so
857 * we send it a caught signal to wake it up.
858 */
859 kill(tcp->pid, SIGINT);
860#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +0000861#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000862 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000863 arg = PRSABORT;
864 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000865 perror("PIOCRUN");
866 return -1;
867 }
Roland McGrath553a6092002-12-16 20:40:39 +0000868#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000869#endif /* !MIPS*/
870#ifdef FREEBSD
871 /* wake up the child if it received the SIGSTOP */
872 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +0000873#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000874 for (;;) {
875 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000876 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000877 perror("PIOCWSTOP");
878 return -1;
879 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000880 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000881 tcp->flags &= ~TCB_INSYSCALL;
882 get_scno(tcp);
883 if (tcp->scno == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884 break;
885 }
886 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000887#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000888 arg = 0;
889 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000890#else /* FREEBSD */
891 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +0000892#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 perror("PIOCRUN");
894 return -1;
895 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000896#ifdef FREEBSD
897 /* handle the case where we "opened" the child before
898 it did the kill -STOP */
899 if (tcp->status.PR_WHY == PR_SIGNALLED &&
900 tcp->status.PR_WHAT == SIGSTOP)
901 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +0000902#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000904#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000906#else /* FREEBSD */
907 } else {
Roland McGrath553a6092002-12-16 20:40:39 +0000908 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +0000909 /* We are attaching to an already running process.
910 * Try to figure out the state of the process in syscalls,
911 * to handle the first event well.
912 * This is done by having a look at the "wchan" property of the
913 * process, which tells where it is stopped (if it is). */
914 FILE * status;
915 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +0000916
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +0000917 sprintf(proc, "/proc/%d/status", tcp->pid);
918 status = fopen(proc, "r");
919 if (status &&
920 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
921 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
922 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
923 strcmp(wchan, "stopevent")) {
924 /* The process is asleep in the middle of a syscall.
925 Fake the syscall entry event */
926 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
927 tcp->status.PR_WHY = PR_SYSENTRY;
928 trace_syscall(tcp);
929 }
930 if (status)
931 fclose(status);
932 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000933 }
934#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000935#ifndef HAVE_POLLABLE_PROCFS
936 if (proc_poll_pipe[0] != -1)
937 proc_poller(tcp->pfd);
938 else if (nprocs > 1) {
939 proc_poll_open();
940 proc_poller(last_pfd);
941 proc_poller(tcp->pfd);
942 }
943 last_pfd = tcp->pfd;
944#endif /* !HAVE_POLLABLE_PROCFS */
945 return 0;
946}
947
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000948#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000950struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951pid2tcb(pid)
952int pid;
953{
954 int i;
955 struct tcb *tcp;
956
Roland McGrathee9d4352002-12-18 04:16:10 +0000957 for (i = 0; i < tcbtabsize; i++) {
958 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000959 if (pid && tcp->pid != pid)
960 continue;
961 if (tcp->flags & TCB_INUSE)
962 return tcp;
963 }
964 return NULL;
965}
966
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000967#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968
969static struct tcb *
970pfd2tcb(pfd)
971int pfd;
972{
973 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974
Roland McGrathca16be82003-01-10 19:55:28 +0000975 for (i = 0; i < tcbtabsize; i++) {
976 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977 if (tcp->pfd != pfd)
978 continue;
979 if (tcp->flags & TCB_INUSE)
980 return tcp;
981 }
982 return NULL;
983}
984
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000985#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986
987void
988droptcb(tcp)
989struct tcb *tcp;
990{
991 if (tcp->pid == 0)
992 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000993#ifdef TCB_CLONE_THREAD
994 if (tcp->nclone_threads > 0) {
995 /* There are other threads left in this process, but this
996 is the one whose PID represents the whole process.
997 We need to keep this record around as a zombie until
998 all the threads die. */
999 tcp->flags |= TCB_EXITING;
1000 return;
1001 }
1002#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003 nprocs--;
1004 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001005
Roland McGrathe29341c2003-01-10 20:14:20 +00001006 if (tcp->parent != NULL) {
1007 tcp->parent->nchildren--;
1008#ifdef TCB_CLONE_THREAD
1009 if (tcp->flags & TCB_CLONE_DETACHED)
1010 tcp->parent->nclone_detached--;
1011 if (tcp->flags & TCB_CLONE_THREAD)
1012 tcp->parent->nclone_threads--;
1013#endif
Roland McGrath09623452003-05-23 02:27:13 +00001014#ifdef TCB_CLONE_DETACHED
1015 if (!(tcp->flags & TCB_CLONE_DETACHED))
1016#endif
1017 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001018 tcp->parent = NULL;
1019 }
1020
1021 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 if (tcp->pfd != -1) {
1023 close(tcp->pfd);
1024 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001025#ifdef FREEBSD
1026 if (tcp->pfd_reg != -1) {
1027 close(tcp->pfd_reg);
1028 tcp->pfd_reg = -1;
1029 }
1030 if (tcp->pfd_status != -1) {
1031 close(tcp->pfd_status);
1032 tcp->pfd_status = -1;
1033 }
Roland McGrath553a6092002-12-16 20:40:39 +00001034#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001035#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001036 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037#endif
1038 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001039
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001040 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001042
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 tcp->outf = 0;
1044}
1045
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001046#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047
1048static int
1049resume(tcp)
1050struct tcb *tcp;
1051{
1052 if (tcp == NULL)
1053 return -1;
1054
1055 if (!(tcp->flags & TCB_SUSPENDED)) {
1056 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1057 return -1;
1058 }
1059 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001060#ifdef TCB_CLONE_THREAD
1061 if (tcp->flags & TCB_CLONE_THREAD)
1062 tcp->parent->nclone_waiting--;
1063#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064
1065 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1066 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1067 return -1;
1068 }
1069
1070 if (!qflag)
1071 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1072 return 0;
1073}
1074
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001075#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076
1077/* detach traced process; continue with sig */
1078
1079static int
1080detach(tcp, sig)
1081struct tcb *tcp;
1082int sig;
1083{
1084 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001085#ifdef LINUX
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001086 int status, resumed;
Roland McGrathca16be82003-01-10 19:55:28 +00001087#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088
1089 if (tcp->flags & TCB_BPTSET)
1090 sig = SIGKILL;
1091
1092#ifdef LINUX
1093 /*
1094 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001095 * before detaching. Arghh. We go through hoops
1096 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001098#if defined(SPARC)
1099#undef PTRACE_DETACH
1100#define PTRACE_DETACH PTRACE_SUNDETACH
1101#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001102 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1103 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001104 }
1105 else if (errno != ESRCH) {
1106 /* Shouldn't happen. */
1107 perror("detach: ptrace(PTRACE_DETACH, ...)");
1108 }
1109 else if (kill(tcp->pid, 0) < 0) {
1110 if (errno != ESRCH)
1111 perror("detach: checking sanity");
1112 }
1113 else if (kill(tcp->pid, SIGSTOP) < 0) {
1114 if (errno != ESRCH)
1115 perror("detach: stopping child");
1116 }
1117 else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001119#ifdef __WALL
1120 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1121 if (errno == ECHILD) /* Already gone. */
1122 break;
1123 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001124 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001125 break;
1126 }
1127#endif /* __WALL */
1128 /* No __WALL here. */
1129 if (waitpid(tcp->pid, &status, 0) < 0) {
1130 if (errno != ECHILD) {
1131 perror("detach: waiting");
1132 break;
1133 }
1134#ifdef __WCLONE
1135 /* If no processes, try clones. */
1136 if (wait4(tcp->pid, &status, __WCLONE,
1137 NULL) < 0) {
1138 if (errno != ECHILD)
1139 perror("detach: waiting");
1140 break;
1141 }
1142#endif /* __WCLONE */
1143 }
1144#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001145 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001146#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 if (!WIFSTOPPED(status)) {
1148 /* Au revoir, mon ami. */
1149 break;
1150 }
1151 if (WSTOPSIG(status) == SIGSTOP) {
1152 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001153 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 if (errno != ESRCH)
1155 perror("detach: ptrace(PTRACE_DETACH, ...)");
1156 /* I died trying. */
1157 }
1158 break;
1159 }
1160 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001161 WSTOPSIG(status) == SIGTRAP ?
1162 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 if (errno != ESRCH)
1164 perror("detach: ptrace(PTRACE_CONT, ...)");
1165 break;
1166 }
1167 }
1168 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001169#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170
1171#if defined(SUNOS4)
1172 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1173 if (sig && kill(tcp->pid, sig) < 0)
1174 perror("detach: kill");
1175 sig = 0;
1176 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1177 perror("detach: ptrace(PTRACE_DETACH, ...)");
1178#endif /* SUNOS4 */
1179
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001180#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001181 resumed = 0;
1182
1183 /* XXX This won't always be quite right (but it never was).
1184 A waiter with argument 0 or < -1 is waiting for any pid in
1185 a particular pgrp, which this child might or might not be
1186 in. The waiter will only wake up if it's argument is -1
1187 or if it's waiting for tcp->pid's pgrp. It makes a
1188 difference to wake up a waiter when there might be more
1189 traced children, because it could get a false ECHILD
1190 error. OTOH, if this was the last child in the pgrp, then
1191 it ought to wake up and get ECHILD. We would have to
1192 search the system for all pid's in the pgrp to be sure.
1193
1194 && (t->waitpid == -1 ||
1195 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1196 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1197 */
1198
1199 if (tcp->parent &&
1200 (tcp->parent->flags & TCB_SUSPENDED) &&
1201 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1202 error = resume(tcp->parent);
1203 ++resumed;
1204 }
1205#ifdef TCB_CLONE_THREAD
1206 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1207 /* Some other threads of our parent are waiting too. */
1208 unsigned int i;
1209
1210 /* Resume all the threads that were waiting for this PID. */
1211 for (i = 0; i < tcbtabsize; i++) {
1212 struct tcb *t = tcbtab[i];
1213 if (t->parent == tcp->parent && t != tcp
1214 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1215 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1216 && t->waitpid == tcp->pid) {
1217 error |= resume (t);
1218 ++resumed;
1219 }
1220 }
1221 if (resumed == 0)
1222 /* Noone was waiting for this PID in particular,
1223 so now we might need to resume some wildcarders. */
1224 for (i = 0; i < tcbtabsize; i++) {
1225 struct tcb *t = tcbtab[i];
1226 if (t->parent == tcp->parent && t != tcp
1227 && ((t->flags
1228 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1229 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1230 && t->waitpid <= 0
1231 ) {
1232 error |= resume (t);
1233 break;
1234 }
1235 }
1236 }
1237#endif
1238
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001239#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001240
1241 if (!qflag)
1242 fprintf(stderr, "Process %u detached\n", tcp->pid);
1243
1244 droptcb(tcp);
1245 return error;
1246}
1247
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001248#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249
1250static void
1251reaper(sig)
1252int sig;
1253{
1254 int pid;
1255 int status;
1256
1257 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1258#if 0
1259 struct tcb *tcp;
1260
1261 tcp = pid2tcb(pid);
1262 if (tcp)
1263 droptcb(tcp);
1264#endif
1265 }
1266}
1267
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001268#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269
1270static void
1271cleanup()
1272{
1273 int i;
1274 struct tcb *tcp;
1275
Roland McGrathee9d4352002-12-18 04:16:10 +00001276 for (i = 0; i < tcbtabsize; i++) {
1277 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001278 if (!(tcp->flags & TCB_INUSE))
1279 continue;
1280 if (debug)
1281 fprintf(stderr,
1282 "cleanup: looking at pid %u\n", tcp->pid);
1283 if (tcp_last &&
1284 (!outfname || followfork < 2 || tcp_last == tcp)) {
1285 tprintf(" <unfinished ...>\n");
1286 tcp_last = NULL;
1287 }
1288 if (tcp->flags & TCB_ATTACHED)
1289 detach(tcp, 0);
1290 else {
1291 kill(tcp->pid, SIGCONT);
1292 kill(tcp->pid, SIGTERM);
1293 }
1294 }
1295 if (cflag)
1296 call_summary(outf);
1297}
1298
1299static void
1300interrupt(sig)
1301int sig;
1302{
1303 interrupted = 1;
1304}
1305
1306#ifndef HAVE_STRERROR
1307
Roland McGrath6d2b3492002-12-30 00:51:30 +00001308#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309extern int sys_nerr;
1310extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001311#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001312
1313const char *
1314strerror(errno)
1315int errno;
1316{
1317 static char buf[64];
1318
1319 if (errno < 1 || errno >= sys_nerr) {
1320 sprintf(buf, "Unknown error %d", errno);
1321 return buf;
1322 }
1323 return sys_errlist[errno];
1324}
1325
1326#endif /* HAVE_STERRROR */
1327
1328#ifndef HAVE_STRSIGNAL
1329
Roland McGrath8f474e02003-01-14 07:53:33 +00001330#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001331extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001333#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1334extern char *_sys_siglist[];
1335#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336
1337const char *
1338strsignal(sig)
1339int sig;
1340{
1341 static char buf[64];
1342
1343 if (sig < 1 || sig >= NSIG) {
1344 sprintf(buf, "Unknown signal %d", sig);
1345 return buf;
1346 }
1347#ifdef HAVE__SYS_SIGLIST
1348 return _sys_siglist[sig];
1349#else
1350 return sys_siglist[sig];
1351#endif
1352}
1353
1354#endif /* HAVE_STRSIGNAL */
1355
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001356#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001357
1358static void
1359rebuild_pollv()
1360{
1361 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001362
Roland McGrathee9d4352002-12-18 04:16:10 +00001363 if (pollv != NULL)
1364 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001365 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001366 if (pollv == NULL) {
1367 fprintf(stderr, "strace: out of memory for poll vector\n");
1368 exit(1);
1369 }
1370
Roland McGrathca16be82003-01-10 19:55:28 +00001371 for (i = j = 0; i < tcbtabsize; i++) {
1372 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001373 if (!(tcp->flags & TCB_INUSE))
1374 continue;
1375 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001376 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377 j++;
1378 }
1379 if (j != nprocs) {
1380 fprintf(stderr, "strace: proc miscount\n");
1381 exit(1);
1382 }
1383}
1384
1385#ifndef HAVE_POLLABLE_PROCFS
1386
1387static void
1388proc_poll_open()
1389{
1390 int arg;
1391 int i;
1392
1393 if (pipe(proc_poll_pipe) < 0) {
1394 perror("pipe");
1395 exit(1);
1396 }
1397 for (i = 0; i < 2; i++) {
1398 if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
1399 perror("F_GETFD");
1400 exit(1);
1401 }
1402 if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
1403 perror("F_SETFD");
1404 exit(1);
1405 }
1406 }
1407}
1408
1409static int
1410proc_poll(pollv, nfds, timeout)
1411struct pollfd *pollv;
1412int nfds;
1413int timeout;
1414{
1415 int i;
1416 int n;
1417 struct proc_pollfd pollinfo;
1418
1419 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1420 return n;
1421 if (n != sizeof(struct proc_pollfd)) {
1422 fprintf(stderr, "panic: short read: %d\n", n);
1423 exit(1);
1424 }
1425 for (i = 0; i < nprocs; i++) {
1426 if (pollv[i].fd == pollinfo.fd)
1427 pollv[i].revents = pollinfo.revents;
1428 else
1429 pollv[i].revents = 0;
1430 }
1431 poller_pid = pollinfo.pid;
1432 return 1;
1433}
1434
1435static void
1436wakeup_handler(sig)
1437int sig;
1438{
1439}
1440
1441static void
1442proc_poller(pfd)
1443int pfd;
1444{
1445 struct proc_pollfd pollinfo;
1446 struct sigaction sa;
1447 sigset_t blocked_set, empty_set;
1448 int i;
1449 int n;
1450 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001451#ifdef FREEBSD
1452 struct procfs_status pfs;
1453#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454
1455 switch (fork()) {
1456 case -1:
1457 perror("fork");
1458 _exit(0);
1459 case 0:
1460 break;
1461 default:
1462 return;
1463 }
1464
1465 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1466 sa.sa_flags = 0;
1467 sigemptyset(&sa.sa_mask);
1468 sigaction(SIGHUP, &sa, NULL);
1469 sigaction(SIGINT, &sa, NULL);
1470 sigaction(SIGQUIT, &sa, NULL);
1471 sigaction(SIGPIPE, &sa, NULL);
1472 sigaction(SIGTERM, &sa, NULL);
1473 sa.sa_handler = wakeup_handler;
1474 sigaction(SIGUSR1, &sa, NULL);
1475 sigemptyset(&blocked_set);
1476 sigaddset(&blocked_set, SIGUSR1);
1477 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1478 sigemptyset(&empty_set);
1479
1480 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1481 perror("getrlimit(RLIMIT_NOFILE, ...)");
1482 _exit(0);
1483 }
1484 n = rl.rlim_cur;
1485 for (i = 0; i < n; i++) {
1486 if (i != pfd && i != proc_poll_pipe[1])
1487 close(i);
1488 }
1489
1490 pollinfo.fd = pfd;
1491 pollinfo.pid = getpid();
1492 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001493#ifndef FREEBSD
1494 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1495#else /* FREEBSD */
1496 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1497#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001498 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 switch (errno) {
1500 case EINTR:
1501 continue;
1502 case EBADF:
1503 pollinfo.revents = POLLERR;
1504 break;
1505 case ENOENT:
1506 pollinfo.revents = POLLHUP;
1507 break;
1508 default:
1509 perror("proc_poller: PIOCWSTOP");
1510 }
1511 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1512 _exit(0);
1513 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001514 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1516 sigsuspend(&empty_set);
1517 }
1518}
1519
1520#endif /* !HAVE_POLLABLE_PROCFS */
1521
1522static int
1523choose_pfd()
1524{
1525 int i, j;
1526 struct tcb *tcp;
1527
1528 static int last;
1529
1530 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001531 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532 /*
1533 * The previous process is ready to run again. We'll
1534 * let it do so if it is currently in a syscall. This
1535 * heuristic improves the readability of the trace.
1536 */
1537 tcp = pfd2tcb(pollv[last].fd);
1538 if (tcp && (tcp->flags & TCB_INSYSCALL))
1539 return pollv[last].fd;
1540 }
1541
1542 for (i = 0; i < nprocs; i++) {
1543 /* Let competing children run round robin. */
1544 j = (i + last + 1) % nprocs;
1545 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1546 tcp = pfd2tcb(pollv[j].fd);
1547 if (!tcp) {
1548 fprintf(stderr, "strace: lost proc\n");
1549 exit(1);
1550 }
1551 droptcb(tcp);
1552 return -1;
1553 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001554 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555 last = j;
1556 return pollv[j].fd;
1557 }
1558 }
1559 fprintf(stderr, "strace: nothing ready\n");
1560 exit(1);
1561}
1562
1563static int
1564trace()
1565{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001566#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001567 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001568#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569 struct tcb *tcp;
1570 int pfd;
1571 int what;
1572 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001573 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574
1575 for (;;) {
1576 if (interactive)
1577 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1578
1579 if (nprocs == 0)
1580 break;
1581
1582 switch (nprocs) {
1583 case 1:
1584#ifndef HAVE_POLLABLE_PROCFS
1585 if (proc_poll_pipe[0] == -1) {
1586#endif
1587 tcp = pid2tcb(0);
1588 if (!tcp)
1589 continue;
1590 pfd = tcp->pfd;
1591 if (pfd == -1)
1592 continue;
1593 break;
1594#ifndef HAVE_POLLABLE_PROCFS
1595 }
1596 /* fall through ... */
1597#endif /* !HAVE_POLLABLE_PROCFS */
1598 default:
1599#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001600#ifdef POLL_HACK
1601 /* On some systems (e.g. UnixWare) we get too much ugly
1602 "unfinished..." stuff when multiple proceses are in
1603 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001604
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001605 if (in_syscall) {
1606 struct pollfd pv;
1607 tcp = in_syscall;
1608 in_syscall = NULL;
1609 pv.fd = tcp->pfd;
1610 pv.events = POLLWANT;
1611 if ((what = poll (&pv, 1, 1)) < 0) {
1612 if (interrupted)
1613 return 0;
1614 continue;
1615 }
1616 else if (what == 1 && pv.revents & POLLWANT) {
1617 goto FOUND;
1618 }
1619 }
1620#endif
1621
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 if (poll(pollv, nprocs, INFTIM) < 0) {
1623 if (interrupted)
1624 return 0;
1625 continue;
1626 }
1627#else /* !HAVE_POLLABLE_PROCFS */
1628 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1629 if (interrupted)
1630 return 0;
1631 continue;
1632 }
1633#endif /* !HAVE_POLLABLE_PROCFS */
1634 pfd = choose_pfd();
1635 if (pfd == -1)
1636 continue;
1637 break;
1638 }
1639
1640 /* Look up `pfd' in our table. */
1641 if ((tcp = pfd2tcb(pfd)) == NULL) {
1642 fprintf(stderr, "unknown pfd: %u\n", pfd);
1643 exit(1);
1644 }
John Hughesb6643082002-05-23 11:02:22 +00001645#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001646 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001647#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 /* Get the status of the process. */
1649 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001650#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001651 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001652#else /* FREEBSD */
1653 /* Thanks to some scheduling mystery, the first poller
1654 sometimes waits for the already processed end of fork
1655 event. Doing a non blocking poll here solves the problem. */
1656 if (proc_poll_pipe[0] != -1)
1657 ioctl_result = IOCTL_STATUS (tcp);
1658 else
1659 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001660#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661 ioctl_errno = errno;
1662#ifndef HAVE_POLLABLE_PROCFS
1663 if (proc_poll_pipe[0] != -1) {
1664 if (ioctl_result < 0)
1665 kill(poller_pid, SIGKILL);
1666 else
1667 kill(poller_pid, SIGUSR1);
1668 }
1669#endif /* !HAVE_POLLABLE_PROCFS */
1670 }
1671 if (interrupted)
1672 return 0;
1673
1674 if (interactive)
1675 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1676
1677 if (ioctl_result < 0) {
1678 /* Find out what happened if it failed. */
1679 switch (ioctl_errno) {
1680 case EINTR:
1681 case EBADF:
1682 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001683#ifdef FREEBSD
1684 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001685#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686 case ENOENT:
1687 droptcb(tcp);
1688 continue;
1689 default:
1690 perror("PIOCWSTOP");
1691 exit(1);
1692 }
1693 }
1694
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001695#ifdef FREEBSD
1696 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1697 /* discard first event for a syscall we never entered */
1698 IOCTL (tcp->pfd, PIOCRUN, 0);
1699 continue;
1700 }
Roland McGrath553a6092002-12-16 20:40:39 +00001701#endif
1702
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 /* clear the just started flag */
1704 tcp->flags &= ~TCB_STARTUP;
1705
1706 /* set current output file */
1707 outf = tcp->outf;
1708
1709 if (cflag) {
1710 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001711#ifdef FREEBSD
1712 char buf[1024];
1713 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001715 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1716 buf[len] = '\0';
1717 sscanf(buf,
1718 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1719 &stime.tv_sec, &stime.tv_usec);
1720 } else
1721 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001722#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723 stime.tv_sec = tcp->status.pr_stime.tv_sec;
1724 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001725#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001726 tv_sub(&tcp->dtime, &stime, &tcp->stime);
1727 tcp->stime = stime;
1728 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001729 what = tcp->status.PR_WHAT;
1730 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001731#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001733 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
1734 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735 if (trace_syscall(tcp) < 0) {
1736 fprintf(stderr, "syscall trouble\n");
1737 exit(1);
1738 }
1739 }
1740 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001741#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001743#ifdef POLL_HACK
1744 in_syscall = tcp;
1745#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 case PR_SYSEXIT:
1747 if (trace_syscall(tcp) < 0) {
1748 fprintf(stderr, "syscall trouble\n");
1749 exit(1);
1750 }
1751 break;
1752 case PR_SIGNALLED:
1753 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
1754 printleader(tcp);
1755 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00001756 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00001758#ifdef PR_INFO
1759 if (tcp->status.PR_INFO.si_signo == what) {
1760 printleader(tcp);
1761 tprintf(" siginfo=");
1762 printsiginfo(&tcp->status.PR_INFO, 1);
1763 printtrailer(tcp);
1764 }
1765#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766 }
1767 break;
1768 case PR_FAULTED:
1769 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
1770 printleader(tcp);
1771 tprintf("=== FAULT %d ===", what);
1772 printtrailer(tcp);
1773 }
1774 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001775#ifdef FREEBSD
1776 case 0: /* handle case we polled for nothing */
1777 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00001778#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001780 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 exit(1);
1782 break;
1783 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001784 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001785#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001786 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001787#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001788 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001789#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 perror("PIOCRUN");
1791 exit(1);
1792 }
1793 }
1794 return 0;
1795}
1796
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001797#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001799#ifdef TCB_GROUP_EXITING
1800/* Handle an exit detach or death signal that is taking all the
1801 related clone threads with it. This is called in three circumstances:
1802 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
1803 SIG == 0 Continuing TCP will perform an exit_group syscall.
1804 SIG == other Continuing TCP with SIG will kill the process.
1805*/
1806static int
1807handle_group_exit(struct tcb *tcp, int sig)
1808{
1809 /* We need to locate our records of all the clone threads
1810 related to TCP, either its children or siblings. */
1811 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1812 ? tcp->parent
1813 : tcp->nclone_detached > 0
1814 ? tcp : NULL);
1815
1816 if (sig < 0) {
1817 if (leader != NULL && leader != tcp)
1818 fprintf(stderr,
1819 "PANIC: handle_group_exit: %d leader %d\n",
1820 tcp->pid, leader ? leader->pid : -1);
1821 droptcb(tcp); /* Already died. */
1822 }
1823 else {
1824 if (tcp->flags & TCB_ATTACHED) {
1825 if (leader != NULL && leader != tcp) {
1826 /* We need to detach the leader so that the
1827 process death will be reported to its real
1828 parent. But we kill it first to prevent
1829 it doing anything before we kill the whole
1830 process in a moment. We can use
1831 PTRACE_KILL on a thread that's not already
1832 stopped. Then the value we pass in
1833 PTRACE_DETACH just sets the death
1834 signal reported to the real parent. */
1835 ptrace(PTRACE_KILL, leader->pid, 0, 0);
1836 if (debug)
1837 fprintf(stderr,
1838 " [%d exit %d kills %d]\n",
1839 tcp->pid, sig, leader->pid);
1840 detach(leader, sig);
1841 }
1842 detach(tcp, sig);
1843 }
1844 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1845 perror("strace: ptrace(PTRACE_CONT, ...)");
1846 cleanup();
1847 return -1;
1848 }
1849 else {
1850 if (leader != NULL && leader != tcp)
1851 droptcb(tcp);
1852 /* The leader will report to us as parent now,
1853 and then we'll get to the SIG==-1 case. */
1854 return 0;
1855 }
1856 }
1857
1858 /* Note that TCP and LEADER are no longer valid,
1859 but we can still compare against them. */
1860 if (leader != NULL) {
1861 unsigned int i;
1862 for (i = 0; i < tcbtabsize; i++) {
1863 struct tcb *t = tcbtab[i];
1864 if (t != tcp && (t->flags & TCB_CLONE_DETACHED)
1865 && t->parent == leader)
1866 droptcb(t);
1867 }
1868 }
1869
1870 return 0;
1871}
1872#endif
1873
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874static int
1875trace()
1876{
1877 int pid;
1878 int wait_errno;
1879 int status;
1880 struct tcb *tcp;
1881#ifdef LINUX
1882 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001883#ifdef __WALL
1884 static int wait4_options = __WALL;
1885#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886#endif /* LINUX */
1887
1888 while (nprocs != 0) {
1889 if (interactive)
1890 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1891#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001892#ifdef __WALL
1893 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00001894 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001895 /* this kernel does not support __WALL */
1896 wait4_options &= ~__WALL;
1897 errno = 0;
1898 pid = wait4(-1, &status, wait4_options,
1899 cflag ? &ru : NULL);
1900 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001901 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001902 /* most likely a "cloned" process */
1903 pid = wait4(-1, &status, __WCLONE,
1904 cflag ? &ru : NULL);
1905 if (pid == -1) {
1906 fprintf(stderr, "strace: clone wait4 "
1907 "failed: %s\n", strerror(errno));
1908 }
1909 }
1910#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001912#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001913#endif /* LINUX */
1914#ifdef SUNOS4
1915 pid = wait(&status);
1916#endif /* SUNOS4 */
1917 wait_errno = errno;
1918 if (interactive)
1919 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1920
1921 if (interrupted)
1922 return 0;
1923
1924 if (pid == -1) {
1925 switch (wait_errno) {
1926 case EINTR:
1927 continue;
1928 case ECHILD:
1929 /*
1930 * We would like to verify this case
1931 * but sometimes a race in Solbourne's
1932 * version of SunOS sometimes reports
1933 * ECHILD before sending us SIGCHILD.
1934 */
1935#if 0
1936 if (nprocs == 0)
1937 return 0;
1938 fprintf(stderr, "strace: proc miscount\n");
1939 exit(1);
1940#endif
1941 return 0;
1942 default:
1943 errno = wait_errno;
1944 perror("strace: wait");
1945 return -1;
1946 }
1947 }
1948 if (debug)
1949 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
1950
1951 /* Look up `pid' in our table. */
1952 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001953#ifdef LINUX
1954 if (followfork || followvfork) {
1955 /* This is needed to go with the CLONE_PTRACE
1956 changes in process.c/util.c: we might see
1957 the child's initial trap before we see the
1958 parent return from the clone syscall.
1959 Leave the child suspended until the parent
1960 returns from its system call. Only then
1961 will we have the association of parent and
1962 child so that we know how to do clearbpt
1963 in the child. */
1964 if ((tcp = alloctcb(pid)) == NULL) {
1965 fprintf(stderr, " [tcb table full]\n");
1966 kill(pid, SIGKILL); /* XXX */
1967 return 0;
1968 }
1969 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
1970 newoutf(tcp);
1971 if (!qflag)
1972 fprintf(stderr, "\
1973Process %d attached (waiting for parent)\n",
1974 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001975 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001976 else
1977 /* This can happen if a clone call used
1978 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001979#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001980 {
1981 fprintf(stderr, "unknown pid: %u\n", pid);
1982 if (WIFSTOPPED(status))
1983 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
1984 exit(1);
1985 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986 }
1987 /* set current output file */
1988 outf = tcp->outf;
1989 if (cflag) {
1990#ifdef LINUX
1991 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1992 tcp->stime = ru.ru_stime;
1993#endif /* !LINUX */
1994 }
1995
1996 if (tcp->flags & TCB_SUSPENDED) {
1997 /*
1998 * Apparently, doing any ptrace() call on a stopped
1999 * process, provokes the kernel to report the process
2000 * status again on a subsequent wait(), even if the
2001 * process has not been actually restarted.
2002 * Since we have inspected the arguments of suspended
2003 * processes we end up here testing for this case.
2004 */
2005 continue;
2006 }
2007 if (WIFSIGNALED(status)) {
2008 if (!cflag
2009 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2010 printleader(tcp);
2011 tprintf("+++ killed by %s +++",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002012 signame(WTERMSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002013 printtrailer(tcp);
2014 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002015#ifdef TCB_GROUP_EXITING
2016 handle_group_exit(tcp, -1);
2017#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002018 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002019#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002020 continue;
2021 }
2022 if (WIFEXITED(status)) {
2023 if (debug)
2024 fprintf(stderr, "pid %u exited\n", pid);
2025 if (tcp->flags & TCB_ATTACHED)
2026 fprintf(stderr,
2027 "PANIC: attached pid %u exited\n",
2028 pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002029#ifdef TCB_GROUP_EXITING
2030 handle_group_exit(tcp, -1);
2031#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002032 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002033#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 continue;
2035 }
2036 if (!WIFSTOPPED(status)) {
2037 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2038 droptcb(tcp);
2039 continue;
2040 }
2041 if (debug)
2042 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002043 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044
2045 if (tcp->flags & TCB_STARTUP) {
2046 /*
2047 * This flag is there to keep us in sync.
2048 * Next time this process stops it should
2049 * really be entering a system call.
2050 */
2051 tcp->flags &= ~TCB_STARTUP;
2052 if (tcp->flags & TCB_ATTACHED) {
2053 /*
2054 * Interestingly, the process may stop
2055 * with STOPSIG equal to some other signal
2056 * than SIGSTOP if we happend to attach
2057 * just before the process takes a signal.
2058 */
2059 if (!WIFSTOPPED(status)) {
2060 fprintf(stderr,
2061 "pid %u not stopped\n", pid);
2062 detach(tcp, WSTOPSIG(status));
2063 continue;
2064 }
2065 }
2066 else {
2067#ifdef SUNOS4
2068 /* A child of us stopped at exec */
2069 if (WSTOPSIG(status) == SIGTRAP && followvfork)
2070 fixvfork(tcp);
2071#endif /* SUNOS4 */
2072 }
2073 if (tcp->flags & TCB_BPTSET) {
2074 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2075 droptcb(tcp);
2076 cleanup();
2077 return -1;
2078 }
2079 }
2080 goto tracing;
2081 }
2082
2083 if (WSTOPSIG(status) != SIGTRAP) {
2084 if (WSTOPSIG(status) == SIGSTOP &&
2085 (tcp->flags & TCB_SIGTRAPPED)) {
2086 /*
2087 * Trapped attempt to block SIGTRAP
2088 * Hope we are back in control now.
2089 */
2090 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2091 if (ptrace(PTRACE_SYSCALL,
2092 pid, (char *) 1, 0) < 0) {
2093 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2094 cleanup();
2095 return -1;
2096 }
2097 continue;
2098 }
2099 if (!cflag
2100 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002101 unsigned long addr = 0, pc = 0;
2102#ifdef PT_GETSIGINFO
2103# define PSR_RI 41
2104 struct siginfo si;
2105 unsigned long psr;
2106
2107 upeek(pid, PT_CR_IPSR, &psr);
2108 upeek(pid, PT_CR_IIP, &pc);
2109
2110 pc += (psr >> PSR_RI) & 0x3;
2111 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2112 addr = (unsigned long) si.si_addr;
2113#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002115 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002116 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002117 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002118 printtrailer(tcp);
2119 }
2120 if ((tcp->flags & TCB_ATTACHED) &&
2121 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002122#ifdef TCB_GROUP_EXITING
2123 handle_group_exit(tcp, WSTOPSIG(status));
2124#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002125 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002126#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127 continue;
2128 }
2129 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2130 WSTOPSIG(status)) < 0) {
2131 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2132 cleanup();
2133 return -1;
2134 }
2135 tcp->flags &= ~TCB_SUSPENDED;
2136 continue;
2137 }
2138 if (trace_syscall(tcp) < 0) {
2139 if (tcp->flags & TCB_ATTACHED)
2140 detach(tcp, 0);
2141 else {
2142 ptrace(PTRACE_KILL,
2143 tcp->pid, (char *) 1, SIGTERM);
2144 droptcb(tcp);
2145 }
2146 continue;
2147 }
2148 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002149#ifdef TCB_GROUP_EXITING
2150 if (tcp->flags & TCB_GROUP_EXITING) {
2151 if (handle_group_exit(tcp, 0) < 0)
2152 return -1;
2153 continue;
2154 }
2155#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002156 if (tcp->flags & TCB_ATTACHED)
2157 detach(tcp, 0);
2158 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2159 perror("strace: ptrace(PTRACE_CONT, ...)");
2160 cleanup();
2161 return -1;
2162 }
2163 continue;
2164 }
2165 if (tcp->flags & TCB_SUSPENDED) {
2166 if (!qflag)
2167 fprintf(stderr, "Process %u suspended\n", pid);
2168 continue;
2169 }
2170 tracing:
2171 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2172 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2173 cleanup();
2174 return -1;
2175 }
2176 }
2177 return 0;
2178}
2179
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002180#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002181
2182static int curcol;
2183
2184#ifdef __STDC__
2185#include <stdarg.h>
2186#define VA_START(a, b) va_start(a, b)
2187#else
2188#include <varargs.h>
2189#define VA_START(a, b) va_start(a)
2190#endif
2191
2192void
2193#ifdef __STDC__
2194tprintf(const char *fmt, ...)
2195#else
2196tprintf(fmt, va_alist)
2197char *fmt;
2198va_dcl
2199#endif
2200{
2201 va_list args;
2202
2203 VA_START(args, fmt);
2204 if (outf)
2205 curcol += vfprintf(outf, fmt, args);
2206 va_end(args);
2207 return;
2208}
2209
2210void
2211printleader(tcp)
2212struct tcb *tcp;
2213{
2214 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2215 tcp_last->flags |= TCB_REPRINT;
2216 tprintf(" <unfinished ...>\n");
2217 }
2218 curcol = 0;
2219 if ((followfork == 1 || pflag_seen > 1) && outfname)
2220 tprintf("%-5d ", tcp->pid);
2221 else if (nprocs > 1 && !outfname)
2222 tprintf("[pid %5u] ", tcp->pid);
2223 if (tflag) {
2224 char str[sizeof("HH:MM:SS")];
2225 struct timeval tv, dtv;
2226 static struct timeval otv;
2227
2228 gettimeofday(&tv, NULL);
2229 if (rflag) {
2230 if (otv.tv_sec == 0)
2231 otv = tv;
2232 tv_sub(&dtv, &tv, &otv);
2233 tprintf("%6ld.%06ld ",
2234 (long) dtv.tv_sec, (long) dtv.tv_usec);
2235 otv = tv;
2236 }
2237 else if (tflag > 2) {
2238 tprintf("%ld.%06ld ",
2239 (long) tv.tv_sec, (long) tv.tv_usec);
2240 }
2241 else {
2242 time_t local = tv.tv_sec;
2243 strftime(str, sizeof(str), "%T", localtime(&local));
2244 if (tflag > 1)
2245 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2246 else
2247 tprintf("%s ", str);
2248 }
2249 }
2250 if (iflag)
2251 printcall(tcp);
2252}
2253
2254void
2255tabto(col)
2256int col;
2257{
2258 if (curcol < col)
2259 tprintf("%*s", col - curcol, "");
2260}
2261
2262void
2263printtrailer(tcp)
2264struct tcb *tcp;
2265{
2266 tprintf("\n");
2267 tcp_last = NULL;
2268}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002269
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002270#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002271
2272int mp_ioctl (int fd, int cmd, void *arg, int size) {
2273
2274 struct iovec iov[2];
2275 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002276
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002277 iov[0].iov_base = &cmd;
2278 iov[0].iov_len = sizeof cmd;
2279 if (arg) {
2280 ++n;
2281 iov[1].iov_base = arg;
2282 iov[1].iov_len = size;
2283 }
Roland McGrath553a6092002-12-16 20:40:39 +00002284
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002285 return writev (fd, iov, n);
2286}
2287
2288#endif