strace.c revision 558e5127fb68a7ab5c5ba6d8e976efd77e396cc2
1/* 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> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 6 * 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 35#include <sys/types.h> 36#include <stdarg.h> 37#include <signal.h> 38#include <errno.h> 39#include <sys/param.h> 40#include <fcntl.h> 41#include <sys/resource.h> 42#include <sys/wait.h> 43#include <sys/stat.h> 44#include <pwd.h> 45#include <grp.h> 46#include <string.h> 47#include <dirent.h> 48#include <sys/utsname.h> 49 50# include <asm/unistd.h> 51# if defined __NR_tkill 52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig)) 53# else 54 /* kill() may choose arbitrarily the target task of the process group 55 while we later wait on a that specific TID. PID process waits become 56 TID task specific waits for a process under ptrace(2). */ 57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!" 58# define my_tkill(tid, sig) kill((tid), (sig)) 59# endif 60 61#if defined(IA64) 62# include <asm/ptrace_offsets.h> 63#endif 64 65extern char **environ; 66extern int optind; 67extern char *optarg; 68 69int debug = 0, followfork = 0; 70unsigned int ptrace_setoptions = 0; 71/* Which WSTOPSIG(status) value marks syscall traps? */ 72static unsigned int syscall_trap_sig = SIGTRAP; 73int dtime = 0, xflag = 0, qflag = 0; 74cflag_t cflag = CFLAG_NONE; 75static int iflag = 0, rflag = 0, tflag = 0; 76static int print_pid_pfx = 0; 77 78/* -I n */ 79enum { 80 INTR_NOT_SET = 0, 81 INTR_ANYWHERE = 1, /* don't block/ignore any signals */ 82 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */ 83 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */ 84 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */ 85 NUM_INTR_OPTS 86}; 87static int opt_intr; 88/* We play with signal mask only if this mode is active: */ 89#define interactive (opt_intr == INTR_WHILE_WAIT) 90 91/* 92 * daemonized_tracer supports -D option. 93 * With this option, strace forks twice. 94 * Unlike normal case, with -D *grandparent* process exec's, 95 * becoming a traced process. Child exits (this prevents traced process 96 * from having children it doesn't expect to have), and grandchild 97 * attaches to grandparent similarly to strace -p PID. 98 * This allows for more transparent interaction in cases 99 * when process and its parent are communicating via signals, 100 * wait() etc. Without -D, strace process gets lodged in between, 101 * disrupting parent<->child link. 102 */ 103static bool daemonized_tracer = 0; 104 105#ifdef USE_SEIZE 106static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; 107# define use_seize (post_attach_sigstop == 0) 108#else 109# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP 110# define use_seize 0 111#endif 112 113/* Sometimes we want to print only succeeding syscalls. */ 114int not_failing_only = 0; 115 116/* Show path associated with fd arguments */ 117int show_fd_path = 0; 118 119/* are we filtering traces based on paths? */ 120int tracing_paths = 0; 121 122static int exit_code = 0; 123static int strace_child = 0; 124static int strace_tracer_pid = 0; 125 126static char *username = NULL; 127static uid_t run_uid; 128static gid_t run_gid; 129 130int max_strlen = DEFAULT_STRLEN; 131static int acolumn = DEFAULT_ACOLUMN; 132static char *acolumn_spaces; 133static char *outfname = NULL; 134static FILE *outf; 135struct tcb *printing_tcp = NULL; 136static int curcol; 137static struct tcb **tcbtab; 138static unsigned int nprocs, tcbtabsize; 139static const char *progname; 140 141static char *os_release; /* from uname() */ 142 143static int detach(struct tcb *tcp); 144static int trace(void); 145static void cleanup(void); 146static void interrupt(int sig); 147static sigset_t empty_set, blocked_set; 148 149#ifdef HAVE_SIG_ATOMIC_T 150static volatile sig_atomic_t interrupted; 151#else 152static volatile int interrupted; 153#endif 154 155static void 156usage(FILE *ofp, int exitval) 157{ 158 fprintf(ofp, "\ 159usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\ 160 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\ 161 [-P path] [PROG [ARGS]]\n\ 162 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\ 163 [PROG [ARGS]]\n\ 164-c -- count time, calls, and errors for each syscall and report summary\n\ 165-C -- like -c but also print regular output while processes are running\n\ 166-D -- run tracer process as a detached grandchild, not as parent\n\ 167-f -- follow forks, -ff -- with output into separate files\n\ 168-F -- attempt to follow vforks\n\ 169-i -- print instruction pointer at time of syscall\n\ 170-I interruptible\n\ 171 1: no signals are blocked\n\ 172 2: fatal signals are blocked while decoding syscall (default)\n\ 173 3: fatal signals are always blocked (default if '-o FILE PROG')\n\ 174 4: fatal signals and SIGTSTP (^Z) are always blocked\n\ 175 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\ 176-q -- suppress messages about attaching, detaching, etc.\n\ 177-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 178-T -- print time spent in each syscall\n\ 179-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\ 180-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 181-y -- print paths associated with file descriptor arguments\n\ 182-h -- print help message\n\ 183-V -- print version\n\ 184-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 185-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 186 options: trace, abbrev, verbose, raw, signal, read, or write\n\ 187-o file -- send trace output to FILE instead of stderr\n\ 188-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 189-p pid -- trace process with process id PID, may be repeated\n\ 190-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 191-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 192-u username -- run command as username handling setuid and/or setgid\n\ 193-E var=val -- put var=val in the environment for command\n\ 194-E var -- remove var from the environment for command\n\ 195-P path -- trace accesses to path\n\ 196" /* this is broken, so don't document it 197-z -- print only succeeding syscalls\n\ 198 */ 199, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 200 exit(exitval); 201} 202 203static void die(void) __attribute__ ((noreturn)); 204static void die(void) 205{ 206 if (strace_tracer_pid == getpid()) { 207 cflag = 0; 208 cleanup(); 209 } 210 exit(1); 211} 212 213static void verror_msg(int err_no, const char *fmt, va_list p) 214{ 215 char *msg; 216 217 fflush(NULL); 218 219 /* We want to print entire message with single fprintf to ensure 220 * message integrity if stderr is shared with other programs. 221 * Thus we use vasprintf + single fprintf. 222 */ 223 msg = NULL; 224 if (vasprintf(&msg, fmt, p) >= 0) { 225 if (err_no) 226 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no)); 227 else 228 fprintf(stderr, "%s: %s\n", progname, msg); 229 free(msg); 230 } else { 231 /* malloc in vasprintf failed, try it without malloc */ 232 fprintf(stderr, "%s: ", progname); 233 vfprintf(stderr, fmt, p); 234 if (err_no) 235 fprintf(stderr, ": %s\n", strerror(err_no)); 236 else 237 putc('\n', stderr); 238 } 239 /* We don't switch stderr to buffered, thus fprintf(stderr) 240 * always flushes its output and this is not necessary: */ 241 /* fflush(stderr); */ 242} 243 244void error_msg(const char *fmt, ...) 245{ 246 va_list p; 247 va_start(p, fmt); 248 verror_msg(0, fmt, p); 249 va_end(p); 250} 251 252void error_msg_and_die(const char *fmt, ...) 253{ 254 va_list p; 255 va_start(p, fmt); 256 verror_msg(0, fmt, p); 257 die(); 258} 259 260void perror_msg(const char *fmt, ...) 261{ 262 va_list p; 263 va_start(p, fmt); 264 verror_msg(errno, fmt, p); 265 va_end(p); 266} 267 268void perror_msg_and_die(const char *fmt, ...) 269{ 270 va_list p; 271 va_start(p, fmt); 272 verror_msg(errno, fmt, p); 273 die(); 274} 275 276void die_out_of_memory(void) 277{ 278 static bool recursed = 0; 279 if (recursed) 280 exit(1); 281 recursed = 1; 282 error_msg_and_die("Out of memory"); 283} 284 285/* Glue for systems without a MMU that cannot provide fork() */ 286#ifdef HAVE_FORK 287# define strace_vforked 0 288#else 289# define strace_vforked 1 290# define fork() vfork() 291#endif 292 293#ifdef USE_SEIZE 294static int 295ptrace_attach_or_seize(int pid) 296{ 297 int r; 298 if (!use_seize) 299 return ptrace(PTRACE_ATTACH, pid, 0, 0); 300 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL); 301 if (r) 302 return r; 303 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0); 304 return r; 305} 306#else 307# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0) 308#endif 309 310static void 311set_cloexec_flag(int fd) 312{ 313 int flags, newflags; 314 315 flags = fcntl(fd, F_GETFD); 316 if (flags < 0) { 317 /* Can happen only if fd is bad. 318 * Should never happen: if it does, we have a bug 319 * in the caller. Therefore we just abort 320 * instead of propagating the error. 321 */ 322 perror_msg_and_die("fcntl(%d, F_GETFD)", fd); 323 } 324 325 newflags = flags | FD_CLOEXEC; 326 if (flags == newflags) 327 return; 328 329 fcntl(fd, F_SETFD, newflags); /* never fails */ 330} 331 332static void kill_save_errno(pid_t pid, int sig) 333{ 334 int saved_errno = errno; 335 336 (void) kill(pid, sig); 337 errno = saved_errno; 338} 339 340void 341tprintf(const char *fmt, ...) 342{ 343 va_list args; 344 345 va_start(args, fmt); 346 if (outf) { 347 int n = vfprintf(outf, fmt, args); 348 if (n < 0) { 349 if (outf != stderr) 350 perror(outfname == NULL 351 ? "<writing to pipe>" : outfname); 352 } else 353 curcol += n; 354 } 355 va_end(args); 356} 357 358void 359tprints(const char *str) 360{ 361 if (outf) { 362 int n = fputs(str, outf); 363 if (n >= 0) { 364 curcol += strlen(str); 365 return; 366 } 367 if (outf != stderr) 368 perror(outfname == NULL 369 ? "<writing to pipe>" : outfname); 370 } 371} 372 373void 374printleader(struct tcb *tcp) 375{ 376 if (printing_tcp) { 377 if (printing_tcp->ptrace_errno) { 378 if (printing_tcp->flags & TCB_INSYSCALL) { 379 tprints(" <unavailable>) "); 380 tabto(); 381 } 382 tprints("= ? <unavailable>\n"); 383 printing_tcp->ptrace_errno = 0; 384 } else if (!outfname || followfork < 2 || printing_tcp == tcp) { 385 printing_tcp->flags |= TCB_REPRINT; 386 tprints(" <unfinished ...>\n"); 387 } 388 } 389 390 printing_tcp = tcp; 391 curcol = 0; 392 393 if (print_pid_pfx) 394 tprintf("%-5d ", tcp->pid); 395 else if (nprocs > 1 && !outfname) 396 tprintf("[pid %5u] ", tcp->pid); 397 398 if (tflag) { 399 char str[sizeof("HH:MM:SS")]; 400 struct timeval tv, dtv; 401 static struct timeval otv; 402 403 gettimeofday(&tv, NULL); 404 if (rflag) { 405 if (otv.tv_sec == 0) 406 otv = tv; 407 tv_sub(&dtv, &tv, &otv); 408 tprintf("%6ld.%06ld ", 409 (long) dtv.tv_sec, (long) dtv.tv_usec); 410 otv = tv; 411 } 412 else if (tflag > 2) { 413 tprintf("%ld.%06ld ", 414 (long) tv.tv_sec, (long) tv.tv_usec); 415 } 416 else { 417 time_t local = tv.tv_sec; 418 strftime(str, sizeof(str), "%T", localtime(&local)); 419 if (tflag > 1) 420 tprintf("%s.%06ld ", str, (long) tv.tv_usec); 421 else 422 tprintf("%s ", str); 423 } 424 } 425 if (iflag) 426 printcall(tcp); 427} 428 429void 430tabto(void) 431{ 432 if (curcol < acolumn) 433 tprints(acolumn_spaces + curcol); 434} 435 436/* 437 * When strace is setuid executable, we have to swap uids 438 * before and after filesystem and process management operations. 439 */ 440static void 441swap_uid(void) 442{ 443 int euid = geteuid(), uid = getuid(); 444 445 if (euid != uid && setreuid(euid, uid) < 0) { 446 perror_msg_and_die("setreuid"); 447 } 448} 449 450#if _LFS64_LARGEFILE 451# define fopen_for_output fopen64 452#else 453# define fopen_for_output fopen 454#endif 455 456static FILE * 457strace_fopen(const char *path) 458{ 459 FILE *fp; 460 461 swap_uid(); 462 fp = fopen_for_output(path, "w"); 463 if (!fp) 464 perror_msg_and_die("Can't fopen '%s'", path); 465 swap_uid(); 466 set_cloexec_flag(fileno(fp)); 467 return fp; 468} 469 470static int popen_pid = 0; 471 472#ifndef _PATH_BSHELL 473# define _PATH_BSHELL "/bin/sh" 474#endif 475 476/* 477 * We cannot use standard popen(3) here because we have to distinguish 478 * popen child process from other processes we trace, and standard popen(3) 479 * does not export its child's pid. 480 */ 481static FILE * 482strace_popen(const char *command) 483{ 484 FILE *fp; 485 int fds[2]; 486 487 swap_uid(); 488 if (pipe(fds) < 0) 489 perror_msg_and_die("pipe"); 490 491 set_cloexec_flag(fds[1]); /* never fails */ 492 493 popen_pid = vfork(); 494 if (popen_pid == -1) 495 perror_msg_and_die("vfork"); 496 497 if (popen_pid == 0) { 498 /* child */ 499 close(fds[1]); 500 if (fds[0] != 0) { 501 if (dup2(fds[0], 0)) 502 perror_msg_and_die("dup2"); 503 close(fds[0]); 504 } 505 execl(_PATH_BSHELL, "sh", "-c", command, NULL); 506 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL); 507 } 508 509 /* parent */ 510 close(fds[0]); 511 swap_uid(); 512 fp = fdopen(fds[1], "w"); 513 if (!fp) 514 die_out_of_memory(); 515 return fp; 516} 517 518static void 519newoutf(struct tcb *tcp) 520{ 521 if (outfname && followfork > 1) { 522 char name[520 + sizeof(int) * 3]; 523 sprintf(name, "%.512s.%u", outfname, tcp->pid); 524 tcp->outf = strace_fopen(name); 525 } 526} 527 528static void 529process_opt_p_list(char *opt) 530{ 531 while (*opt) { 532 /* 533 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`". 534 * pidof uses space as delim, pgrep uses newline. :( 535 */ 536 int pid; 537 char *delim = opt + strcspn(opt, ", \n\t"); 538 char c = *delim; 539 540 *delim = '\0'; 541 pid = atoi(opt); /* TODO: stricter parsing of the number? */ 542 if (pid <= 0) { 543 error_msg("Invalid process id: '%s'", opt); 544 *delim = c; 545 return; 546 } 547 if (pid == strace_tracer_pid) { 548 error_msg("I'm sorry, I can't let you do that, Dave."); 549 *delim = c; 550 return; 551 } 552 *delim = c; 553 alloc_tcb(pid, 0); 554 if (c == '\0') 555 break; 556 opt = delim + 1; 557 } 558} 559 560static void 561startup_attach(void) 562{ 563 int tcbi; 564 struct tcb *tcp; 565 566 /* 567 * Block user interruptions as we would leave the traced 568 * process stopped (process state T) if we would terminate in 569 * between PTRACE_ATTACH and wait4() on SIGSTOP. 570 * We rely on cleanup() from this point on. 571 */ 572 if (interactive) 573 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 574 575 if (daemonized_tracer) { 576 pid_t pid = fork(); 577 if (pid < 0) { 578 perror_msg_and_die("fork"); 579 } 580 if (pid) { /* parent */ 581 /* 582 * Wait for grandchild to attach to straced process 583 * (grandparent). Grandchild SIGKILLs us after it attached. 584 * Grandparent's wait() is unblocked by our death, 585 * it proceeds to exec the straced program. 586 */ 587 pause(); 588 _exit(0); /* paranoia */ 589 } 590 /* grandchild */ 591 /* We will be the tracer process. Remember our new pid: */ 592 strace_tracer_pid = getpid(); 593 } 594 595 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 596 tcp = tcbtab[tcbi]; 597 598 if (!(tcp->flags & TCB_INUSE)) 599 continue; 600 601 /* Is this a process we should attach to, but not yet attached? */ 602 if (tcp->flags & TCB_ATTACHED) 603 continue; /* no, we already attached it */ 604 605 /* Reinitialize the output since it may have changed */ 606 tcp->outf = outf; 607 newoutf(tcp); 608 609 if (followfork && !daemonized_tracer) { 610 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3]; 611 DIR *dir; 612 613 sprintf(procdir, "/proc/%d/task", tcp->pid); 614 dir = opendir(procdir); 615 if (dir != NULL) { 616 unsigned int ntid = 0, nerr = 0; 617 struct dirent *de; 618 619 while ((de = readdir(dir)) != NULL) { 620 struct tcb *cur_tcp; 621 int tid; 622 623 if (de->d_fileno == 0) 624 continue; 625 tid = atoi(de->d_name); 626 if (tid <= 0) 627 continue; 628 ++ntid; 629 if (ptrace_attach_or_seize(tid) < 0) { 630 ++nerr; 631 if (debug) 632 fprintf(stderr, "attach to pid %d failed\n", tid); 633 continue; 634 } 635 if (debug) 636 fprintf(stderr, "attach to pid %d succeeded\n", tid); 637 cur_tcp = tcp; 638 if (tid != tcp->pid) 639 cur_tcp = alloctcb(tid); 640 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop; 641 } 642 closedir(dir); 643 if (interactive) { 644 sigprocmask(SIG_SETMASK, &empty_set, NULL); 645 if (interrupted) 646 goto ret; 647 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 648 } 649 ntid -= nerr; 650 if (ntid == 0) { 651 perror("attach: ptrace(PTRACE_ATTACH, ...)"); 652 droptcb(tcp); 653 continue; 654 } 655 if (!qflag) { 656 fprintf(stderr, ntid > 1 657? "Process %u attached with %u threads - interrupt to quit\n" 658: "Process %u attached - interrupt to quit\n", 659 tcp->pid, ntid); 660 } 661 if (!(tcp->flags & TCB_ATTACHED)) { 662 /* -p PID, we failed to attach to PID itself 663 * but did attach to some of its sibling threads. 664 * Drop PID's tcp. 665 */ 666 droptcb(tcp); 667 } 668 continue; 669 } /* if (opendir worked) */ 670 } /* if (-f) */ 671 if (ptrace_attach_or_seize(tcp->pid) < 0) { 672 perror("attach: ptrace(PTRACE_ATTACH, ...)"); 673 droptcb(tcp); 674 continue; 675 } 676 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop; 677 if (debug) 678 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid); 679 680 if (daemonized_tracer) { 681 /* 682 * Make parent go away. 683 * Also makes grandparent's wait() unblock. 684 */ 685 kill(getppid(), SIGKILL); 686 } 687 688 if (!qflag) 689 fprintf(stderr, 690 "Process %u attached - interrupt to quit\n", 691 tcp->pid); 692 } /* for each tcbtab[] */ 693 694 ret: 695 if (interactive) 696 sigprocmask(SIG_SETMASK, &empty_set, NULL); 697} 698 699static void 700startup_child(char **argv) 701{ 702 struct stat statbuf; 703 const char *filename; 704 char pathname[MAXPATHLEN]; 705 int pid = 0; 706 struct tcb *tcp; 707 708 filename = argv[0]; 709 if (strchr(filename, '/')) { 710 if (strlen(filename) > sizeof pathname - 1) { 711 errno = ENAMETOOLONG; 712 perror_msg_and_die("exec"); 713 } 714 strcpy(pathname, filename); 715 } 716#ifdef USE_DEBUGGING_EXEC 717 /* 718 * Debuggers customarily check the current directory 719 * first regardless of the path but doing that gives 720 * security geeks a panic attack. 721 */ 722 else if (stat(filename, &statbuf) == 0) 723 strcpy(pathname, filename); 724#endif /* USE_DEBUGGING_EXEC */ 725 else { 726 const char *path; 727 int m, n, len; 728 729 for (path = getenv("PATH"); path && *path; path += m) { 730 const char *colon = strchr(path, ':'); 731 if (colon) { 732 n = colon - path; 733 m = n + 1; 734 } 735 else 736 m = n = strlen(path); 737 if (n == 0) { 738 if (!getcwd(pathname, MAXPATHLEN)) 739 continue; 740 len = strlen(pathname); 741 } 742 else if (n > sizeof pathname - 1) 743 continue; 744 else { 745 strncpy(pathname, path, n); 746 len = n; 747 } 748 if (len && pathname[len - 1] != '/') 749 pathname[len++] = '/'; 750 strcpy(pathname + len, filename); 751 if (stat(pathname, &statbuf) == 0 && 752 /* Accept only regular files 753 with some execute bits set. 754 XXX not perfect, might still fail */ 755 S_ISREG(statbuf.st_mode) && 756 (statbuf.st_mode & 0111)) 757 break; 758 } 759 } 760 if (stat(pathname, &statbuf) < 0) { 761 perror_msg_and_die("Can't stat '%s'", filename); 762 } 763 strace_child = pid = fork(); 764 if (pid < 0) { 765 perror_msg_and_die("fork"); 766 } 767 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */ 768 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */ 769 ) { 770 pid = getpid(); 771 if (outf != stderr) 772 close(fileno(outf)); 773 if (!daemonized_tracer && !use_seize) { 774 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) { 775 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)"); 776 } 777 } 778 779 if (username != NULL) { 780 uid_t run_euid = run_uid; 781 gid_t run_egid = run_gid; 782 783 if (statbuf.st_mode & S_ISUID) 784 run_euid = statbuf.st_uid; 785 if (statbuf.st_mode & S_ISGID) 786 run_egid = statbuf.st_gid; 787 /* 788 * It is important to set groups before we 789 * lose privileges on setuid. 790 */ 791 if (initgroups(username, run_gid) < 0) { 792 perror_msg_and_die("initgroups"); 793 } 794 if (setregid(run_gid, run_egid) < 0) { 795 perror_msg_and_die("setregid"); 796 } 797 if (setreuid(run_uid, run_euid) < 0) { 798 perror_msg_and_die("setreuid"); 799 } 800 } 801 else if (geteuid() != 0) 802 setreuid(run_uid, run_uid); 803 804 if (!daemonized_tracer) { 805 /* 806 * Induce a ptrace stop. Tracer (our parent) 807 * will resume us with PTRACE_SYSCALL and display 808 * the immediately following execve syscall. 809 * Can't do this on NOMMU systems, we are after 810 * vfork: parent is blocked, stopping would deadlock. 811 */ 812 if (!strace_vforked) 813 kill(pid, SIGSTOP); 814 } else { 815 struct sigaction sv_sigchld; 816 sigaction(SIGCHLD, NULL, &sv_sigchld); 817 /* 818 * Make sure it is not SIG_IGN, otherwise wait 819 * will not block. 820 */ 821 signal(SIGCHLD, SIG_DFL); 822 /* 823 * Wait for grandchild to attach to us. 824 * It kills child after that, and wait() unblocks. 825 */ 826 alarm(3); 827 wait(NULL); 828 alarm(0); 829 sigaction(SIGCHLD, &sv_sigchld, NULL); 830 } 831 832 execv(pathname, argv); 833 perror_msg_and_die("exec"); 834 } 835 836 /* We are the tracer */ 837 838 if (!daemonized_tracer) { 839 if (!use_seize) { 840 /* child did PTRACE_TRACEME, nothing to do in parent */ 841 } else { 842 if (!strace_vforked) { 843 /* Wait until child stopped itself */ 844 int status; 845 while (waitpid(pid, &status, WSTOPPED) < 0) { 846 if (errno == EINTR) 847 continue; 848 perror_msg_and_die("waitpid"); 849 } 850 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) { 851 kill_save_errno(pid, SIGKILL); 852 perror_msg_and_die("Unexpected wait status %x", status); 853 } 854 } 855 /* Else: vforked case, we have no way to sync. 856 * Just attach to it as soon as possible. 857 * This means that we may miss a few first syscalls... 858 */ 859 860 if (ptrace_attach_or_seize(pid)) { 861 kill_save_errno(pid, SIGKILL); 862 perror_msg_and_die("Can't attach to %d", pid); 863 } 864 if (!strace_vforked) 865 kill(pid, SIGCONT); 866 } 867 tcp = alloctcb(pid); 868 if (!strace_vforked) 869 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop; 870 else 871 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP; 872 } 873 else { 874 /* With -D, *we* are child here, IOW: different pid. Fetch it: */ 875 strace_tracer_pid = getpid(); 876 /* The tracee is our parent: */ 877 pid = getppid(); 878 alloctcb(pid); 879 /* attaching will be done later, by startup_attach */ 880 } 881} 882 883/* 884 * Test whether the kernel support PTRACE_O_TRACECLONE et al options. 885 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it, 886 * and then see which options are supported by the kernel. 887 */ 888static void 889test_ptrace_setoptions_followfork(void) 890{ 891 int pid, expected_grandchild = 0, found_grandchild = 0; 892 const unsigned int test_options = PTRACE_O_TRACECLONE | 893 PTRACE_O_TRACEFORK | 894 PTRACE_O_TRACEVFORK; 895 896 pid = fork(); 897 if (pid < 0) 898 perror_msg_and_die("fork"); 899 if (pid == 0) { 900 pid = getpid(); 901 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) 902 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", 903 __func__); 904 kill_save_errno(pid, SIGSTOP); 905 if (fork() < 0) 906 perror_msg_and_die("fork"); 907 _exit(0); 908 } 909 910 while (1) { 911 int status, tracee_pid; 912 913 errno = 0; 914 tracee_pid = wait(&status); 915 if (tracee_pid <= 0) { 916 if (errno == EINTR) 917 continue; 918 if (errno == ECHILD) 919 break; 920 kill_save_errno(pid, SIGKILL); 921 perror_msg_and_die("%s: unexpected wait result %d", 922 __func__, tracee_pid); 923 } 924 if (WIFEXITED(status)) { 925 if (WEXITSTATUS(status)) { 926 if (tracee_pid != pid) 927 kill_save_errno(pid, SIGKILL); 928 error_msg_and_die("%s: unexpected exit status %u", 929 __func__, WEXITSTATUS(status)); 930 } 931 continue; 932 } 933 if (WIFSIGNALED(status)) { 934 if (tracee_pid != pid) 935 kill_save_errno(pid, SIGKILL); 936 error_msg_and_die("%s: unexpected signal %u", 937 __func__, WTERMSIG(status)); 938 } 939 if (!WIFSTOPPED(status)) { 940 if (tracee_pid != pid) 941 kill_save_errno(tracee_pid, SIGKILL); 942 kill_save_errno(pid, SIGKILL); 943 error_msg_and_die("%s: unexpected wait status %x", 944 __func__, status); 945 } 946 if (tracee_pid != pid) { 947 found_grandchild = tracee_pid; 948 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) { 949 kill_save_errno(tracee_pid, SIGKILL); 950 kill_save_errno(pid, SIGKILL); 951 perror_msg_and_die("PTRACE_CONT doesn't work"); 952 } 953 continue; 954 } 955 switch (WSTOPSIG(status)) { 956 case SIGSTOP: 957 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0 958 && errno != EINVAL && errno != EIO) 959 perror_msg("PTRACE_SETOPTIONS"); 960 break; 961 case SIGTRAP: 962 if (status >> 16 == PTRACE_EVENT_FORK) { 963 long msg = 0; 964 965 if (ptrace(PTRACE_GETEVENTMSG, pid, 966 NULL, (long) &msg) == 0) 967 expected_grandchild = msg; 968 } 969 break; 970 } 971 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { 972 kill_save_errno(pid, SIGKILL); 973 perror_msg_and_die("PTRACE_SYSCALL doesn't work"); 974 } 975 } 976 if (expected_grandchild && expected_grandchild == found_grandchild) { 977 ptrace_setoptions |= test_options; 978 if (debug) 979 fprintf(stderr, "ptrace_setoptions = %#x\n", 980 ptrace_setoptions); 981 return; 982 } 983 error_msg("Test for PTRACE_O_TRACECLONE failed, " 984 "giving up using this feature."); 985} 986 987/* 988 * Test whether the kernel support PTRACE_O_TRACESYSGOOD. 989 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it, 990 * and then see whether it will stop with (SIGTRAP | 0x80). 991 * 992 * Use of this option enables correct handling of user-generated SIGTRAPs, 993 * and SIGTRAPs generated by special instructions such as int3 on x86: 994 * _start: .globl _start 995 * int3 996 * movl $42, %ebx 997 * movl $1, %eax 998 * int $0x80 999 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S") 1000 */ 1001static void 1002test_ptrace_setoptions_for_all(void) 1003{ 1004 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | 1005 PTRACE_O_TRACEEXEC; 1006 int pid; 1007 int it_worked = 0; 1008 1009 pid = fork(); 1010 if (pid < 0) 1011 perror_msg_and_die("fork"); 1012 1013 if (pid == 0) { 1014 pid = getpid(); 1015 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) 1016 /* Note: exits with exitcode 1 */ 1017 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", 1018 __func__); 1019 kill(pid, SIGSTOP); 1020 _exit(0); /* parent should see entry into this syscall */ 1021 } 1022 1023 while (1) { 1024 int status, tracee_pid; 1025 1026 errno = 0; 1027 tracee_pid = wait(&status); 1028 if (tracee_pid <= 0) { 1029 if (errno == EINTR) 1030 continue; 1031 kill_save_errno(pid, SIGKILL); 1032 perror_msg_and_die("%s: unexpected wait result %d", 1033 __func__, tracee_pid); 1034 } 1035 if (WIFEXITED(status)) { 1036 if (WEXITSTATUS(status) == 0) 1037 break; 1038 error_msg_and_die("%s: unexpected exit status %u", 1039 __func__, WEXITSTATUS(status)); 1040 } 1041 if (WIFSIGNALED(status)) { 1042 error_msg_and_die("%s: unexpected signal %u", 1043 __func__, WTERMSIG(status)); 1044 } 1045 if (!WIFSTOPPED(status)) { 1046 kill(pid, SIGKILL); 1047 error_msg_and_die("%s: unexpected wait status %x", 1048 __func__, status); 1049 } 1050 if (WSTOPSIG(status) == SIGSTOP) { 1051 /* 1052 * We don't check "options aren't accepted" error. 1053 * If it happens, we'll never get (SIGTRAP | 0x80), 1054 * and thus will decide to not use the option. 1055 * IOW: the outcome of the test will be correct. 1056 */ 1057 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0 1058 && errno != EINVAL && errno != EIO) 1059 perror_msg("PTRACE_SETOPTIONS"); 1060 } 1061 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) { 1062 it_worked = 1; 1063 } 1064 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) { 1065 kill_save_errno(pid, SIGKILL); 1066 perror_msg_and_die("PTRACE_SYSCALL doesn't work"); 1067 } 1068 } 1069 1070 if (it_worked) { 1071 syscall_trap_sig = (SIGTRAP | 0x80); 1072 ptrace_setoptions |= test_options; 1073 if (debug) 1074 fprintf(stderr, "ptrace_setoptions = %#x\n", 1075 ptrace_setoptions); 1076 return; 1077 } 1078 1079 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, " 1080 "giving up using this feature."); 1081} 1082 1083# ifdef USE_SEIZE 1084static void 1085test_ptrace_seize(void) 1086{ 1087 int pid; 1088 1089 pid = fork(); 1090 if (pid < 0) 1091 perror_msg_and_die("fork"); 1092 1093 if (pid == 0) { 1094 pause(); 1095 _exit(0); 1096 } 1097 1098 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After 1099 * attaching tracee continues to run unless a trap condition occurs. 1100 * PTRACE_SEIZE doesn't affect signal or group stop state. 1101 */ 1102 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) { 1103 post_attach_sigstop = 0; /* this sets use_seize to 1 */ 1104 } else if (debug) { 1105 fprintf(stderr, "PTRACE_SEIZE doesn't work\n"); 1106 } 1107 1108 kill(pid, SIGKILL); 1109 1110 while (1) { 1111 int status, tracee_pid; 1112 1113 errno = 0; 1114 tracee_pid = waitpid(pid, &status, 0); 1115 if (tracee_pid <= 0) { 1116 if (errno == EINTR) 1117 continue; 1118 perror_msg_and_die("%s: unexpected wait result %d", 1119 __func__, tracee_pid); 1120 } 1121 if (WIFSIGNALED(status)) { 1122 return; 1123 } 1124 error_msg_and_die("%s: unexpected wait status %x", 1125 __func__, status); 1126 } 1127} 1128# else /* !USE_SEIZE */ 1129# define test_ptrace_seize() ((void)0) 1130# endif 1131 1132static void 1133get_os_release(void) 1134{ 1135 struct utsname u; 1136 if (uname(&u) < 0) 1137 perror_msg_and_die("uname"); 1138 os_release = strdup(u.release); 1139 if (!os_release) 1140 die_out_of_memory(); 1141} 1142 1143/* 1144 * Initialization part of main() was eating much stack (~0.5k), 1145 * which was unused after init. 1146 * We can reuse it if we move init code into a separate function. 1147 * 1148 * Don't want main() to inline us and defeat the reason 1149 * we have a separate function. 1150 */ 1151static void __attribute__ ((noinline)) 1152init(int argc, char *argv[]) 1153{ 1154 struct tcb *tcp; 1155 int c; 1156 int optF = 0; 1157 struct sigaction sa; 1158 1159 progname = argv[0] ? argv[0] : "strace"; 1160 1161 strace_tracer_pid = getpid(); 1162 1163 get_os_release(); 1164 1165 /* Allocate the initial tcbtab. */ 1166 tcbtabsize = argc; /* Surely enough for all -p args. */ 1167 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0])); 1168 if (!tcbtab) 1169 die_out_of_memory(); 1170 tcp = calloc(tcbtabsize, sizeof(*tcp)); 1171 if (!tcp) 1172 die_out_of_memory(); 1173 for (c = 0; c < tcbtabsize; c++) 1174 tcbtab[c] = tcp++; 1175 1176 outf = stderr; 1177 set_sortby(DEFAULT_SORTBY); 1178 set_personality(DEFAULT_PERSONALITY); 1179 qualify("trace=all"); 1180 qualify("abbrev=all"); 1181 qualify("verbose=all"); 1182 qualify("signal=all"); 1183 while ((c = getopt(argc, argv, 1184 "+cCdfFhiqrtTvVxyz" 1185 "D" 1186 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) { 1187 switch (c) { 1188 case 'c': 1189 if (cflag == CFLAG_BOTH) { 1190 error_msg_and_die("-c and -C are mutually exclusive options"); 1191 } 1192 cflag = CFLAG_ONLY_STATS; 1193 break; 1194 case 'C': 1195 if (cflag == CFLAG_ONLY_STATS) { 1196 error_msg_and_die("-c and -C are mutually exclusive options"); 1197 } 1198 cflag = CFLAG_BOTH; 1199 break; 1200 case 'd': 1201 debug++; 1202 break; 1203 case 'D': 1204 daemonized_tracer = 1; 1205 break; 1206 case 'F': 1207 optF = 1; 1208 break; 1209 case 'f': 1210 followfork++; 1211 break; 1212 case 'h': 1213 usage(stdout, 0); 1214 break; 1215 case 'i': 1216 iflag++; 1217 break; 1218 case 'q': 1219 qflag++; 1220 break; 1221 case 'r': 1222 rflag++; 1223 tflag++; 1224 break; 1225 case 't': 1226 tflag++; 1227 break; 1228 case 'T': 1229 dtime++; 1230 break; 1231 case 'x': 1232 xflag++; 1233 break; 1234 case 'y': 1235 show_fd_path = 1; 1236 break; 1237 case 'v': 1238 qualify("abbrev=none"); 1239 break; 1240 case 'V': 1241 printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 1242 exit(0); 1243 break; 1244 case 'z': 1245 not_failing_only = 1; 1246 break; 1247 case 'a': 1248 acolumn = atoi(optarg); 1249 if (acolumn < 0) 1250 error_msg_and_die("Bad column width '%s'", optarg); 1251 break; 1252 case 'e': 1253 qualify(optarg); 1254 break; 1255 case 'o': 1256 outfname = strdup(optarg); 1257 break; 1258 case 'O': 1259 set_overhead(atoi(optarg)); 1260 break; 1261 case 'p': 1262 process_opt_p_list(optarg); 1263 break; 1264 case 'P': 1265 tracing_paths = 1; 1266 if (pathtrace_select(optarg)) { 1267 error_msg_and_die("Failed to select path '%s'", optarg); 1268 } 1269 break; 1270 case 's': 1271 max_strlen = atoi(optarg); 1272 if (max_strlen < 0) { 1273 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg); 1274 } 1275 break; 1276 case 'S': 1277 set_sortby(optarg); 1278 break; 1279 case 'u': 1280 username = strdup(optarg); 1281 break; 1282 case 'E': 1283 if (putenv(optarg) < 0) 1284 die_out_of_memory(); 1285 break; 1286 case 'I': 1287 opt_intr = atoi(optarg); 1288 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) { 1289 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg); 1290 } 1291 break; 1292 default: 1293 usage(stderr, 1); 1294 break; 1295 } 1296 } 1297 argv += optind; 1298 /* argc -= optind; - no need, argc is not used below */ 1299 1300 acolumn_spaces = malloc(acolumn + 1); 1301 if (!acolumn_spaces) 1302 die_out_of_memory(); 1303 memset(acolumn_spaces, ' ', acolumn); 1304 acolumn_spaces[acolumn] = '\0'; 1305 1306 /* Must have PROG [ARGS], or -p PID. Not both. */ 1307 if (!argv[0] == !nprocs) 1308 usage(stderr, 1); 1309 1310 if (nprocs != 0 && daemonized_tracer) { 1311 error_msg_and_die("-D and -p are mutually exclusive options"); 1312 } 1313 1314 if (!followfork) 1315 followfork = optF; 1316 1317 if (followfork > 1 && cflag) { 1318 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options"); 1319 } 1320 1321 /* See if they want to run as another user. */ 1322 if (username != NULL) { 1323 struct passwd *pent; 1324 1325 if (getuid() != 0 || geteuid() != 0) { 1326 error_msg_and_die("You must be root to use the -u option"); 1327 } 1328 pent = getpwnam(username); 1329 if (pent == NULL) { 1330 error_msg_and_die("Cannot find user '%s'", username); 1331 } 1332 run_uid = pent->pw_uid; 1333 run_gid = pent->pw_gid; 1334 } 1335 else { 1336 run_uid = getuid(); 1337 run_gid = getgid(); 1338 } 1339 1340 if (followfork) 1341 test_ptrace_setoptions_followfork(); 1342 test_ptrace_setoptions_for_all(); 1343 test_ptrace_seize(); 1344 1345 /* Check if they want to redirect the output. */ 1346 if (outfname) { 1347 /* See if they want to pipe the output. */ 1348 if (outfname[0] == '|' || outfname[0] == '!') { 1349 /* 1350 * We can't do the <outfname>.PID funny business 1351 * when using popen, so prohibit it. 1352 */ 1353 if (followfork > 1) 1354 error_msg_and_die("Piping the output and -ff are mutually exclusive"); 1355 outf = strace_popen(outfname + 1); 1356 } 1357 else if (followfork <= 1) 1358 outf = strace_fopen(outfname); 1359 } 1360 1361 if (!outfname || outfname[0] == '|' || outfname[0] == '!') { 1362 char *buf = malloc(BUFSIZ); 1363 if (!buf) 1364 die_out_of_memory(); 1365 setvbuf(outf, buf, _IOLBF, BUFSIZ); 1366 } 1367 if (outfname && argv[0]) { 1368 if (!opt_intr) 1369 opt_intr = INTR_NEVER; 1370 qflag = 1; 1371 } 1372 if (!opt_intr) 1373 opt_intr = INTR_WHILE_WAIT; 1374 1375 /* argv[0] -pPID -oFILE Default interactive setting 1376 * yes 0 0 INTR_WHILE_WAIT 1377 * no 1 0 INTR_WHILE_WAIT 1378 * yes 0 1 INTR_NEVER 1379 * no 1 1 INTR_WHILE_WAIT 1380 */ 1381 1382 /* STARTUP_CHILD must be called before the signal handlers get 1383 installed below as they are inherited into the spawned process. 1384 Also we do not need to be protected by them as during interruption 1385 in the STARTUP_CHILD mode we kill the spawned process anyway. */ 1386 if (argv[0]) 1387 startup_child(argv); 1388 1389 sigemptyset(&empty_set); 1390 sigemptyset(&blocked_set); 1391 sa.sa_handler = SIG_IGN; 1392 sigemptyset(&sa.sa_mask); 1393 sa.sa_flags = 0; 1394 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */ 1395 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */ 1396 if (opt_intr != INTR_ANYWHERE) { 1397 if (opt_intr == INTR_BLOCK_TSTP_TOO) 1398 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */ 1399 /* 1400 * In interactive mode (if no -o OUTFILE, or -p PID is used), 1401 * fatal signals are blocked while syscall stop is processed, 1402 * and acted on in between, when waiting for new syscall stops. 1403 * In non-interactive mode, signals are ignored. 1404 */ 1405 if (opt_intr == INTR_WHILE_WAIT) { 1406 sigaddset(&blocked_set, SIGHUP); 1407 sigaddset(&blocked_set, SIGINT); 1408 sigaddset(&blocked_set, SIGQUIT); 1409 sigaddset(&blocked_set, SIGPIPE); 1410 sigaddset(&blocked_set, SIGTERM); 1411 sa.sa_handler = interrupt; 1412 } 1413 /* SIG_IGN, or set handler for these */ 1414 sigaction(SIGHUP, &sa, NULL); 1415 sigaction(SIGINT, &sa, NULL); 1416 sigaction(SIGQUIT, &sa, NULL); 1417 sigaction(SIGPIPE, &sa, NULL); 1418 sigaction(SIGTERM, &sa, NULL); 1419 } 1420 /* Make sure SIGCHLD has the default action so that waitpid 1421 definitely works without losing track of children. The user 1422 should not have given us a bogus state to inherit, but he might 1423 have. Arguably we should detect SIG_IGN here and pass it on 1424 to children, but probably noone really needs that. */ 1425 sa.sa_handler = SIG_DFL; 1426 sigaction(SIGCHLD, &sa, NULL); 1427 1428 if (nprocs != 0 || daemonized_tracer) 1429 startup_attach(); 1430 1431 /* Do we want pids printed in our -o OUTFILE? 1432 * -ff: no (every pid has its own file); or 1433 * -f: yes (there can be more pids in the future); or 1434 * -p PID1,PID2: yes (there are already more than one pid) 1435 */ 1436 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1)); 1437} 1438 1439static void 1440expand_tcbtab(void) 1441{ 1442 /* Allocate some more TCBs and expand the table. 1443 We don't want to relocate the TCBs because our 1444 callers have pointers and it would be a pain. 1445 So tcbtab is a table of pointers. Since we never 1446 free the TCBs, we allocate a single chunk of many. */ 1447 int i = tcbtabsize; 1448 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0])); 1449 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0])); 1450 if (!newtab || !newtcbs) 1451 die_out_of_memory(); 1452 tcbtabsize *= 2; 1453 tcbtab = newtab; 1454 while (i < tcbtabsize) 1455 tcbtab[i++] = newtcbs++; 1456} 1457 1458struct tcb * 1459alloc_tcb(int pid, int command_options_parsed) 1460{ 1461 int i; 1462 struct tcb *tcp; 1463 1464 if (nprocs == tcbtabsize) 1465 expand_tcbtab(); 1466 1467 for (i = 0; i < tcbtabsize; i++) { 1468 tcp = tcbtab[i]; 1469 if ((tcp->flags & TCB_INUSE) == 0) { 1470 memset(tcp, 0, sizeof(*tcp)); 1471 tcp->pid = pid; 1472 tcp->flags = TCB_INUSE; 1473 tcp->outf = outf; /* Initialise to current out file */ 1474#if SUPPORTED_PERSONALITIES > 1 1475 tcp->currpers = current_personality; 1476#endif 1477 nprocs++; 1478 if (debug) 1479 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs); 1480 if (command_options_parsed) 1481 newoutf(tcp); 1482 return tcp; 1483 } 1484 } 1485 error_msg_and_die("bug in alloc_tcb"); 1486} 1487 1488static struct tcb * 1489pid2tcb(int pid) 1490{ 1491 int i; 1492 1493 if (pid <= 0) 1494 return NULL; 1495 1496 for (i = 0; i < tcbtabsize; i++) { 1497 struct tcb *tcp = tcbtab[i]; 1498 if (tcp->pid == pid && (tcp->flags & TCB_INUSE)) 1499 return tcp; 1500 } 1501 1502 return NULL; 1503} 1504 1505void 1506droptcb(struct tcb *tcp) 1507{ 1508 if (tcp->pid == 0) 1509 return; 1510 1511 nprocs--; 1512 if (debug) 1513 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs); 1514 1515 if (outfname && followfork > 1 && tcp->outf) 1516 fclose(tcp->outf); 1517 1518 memset(tcp, 0, sizeof(*tcp)); 1519} 1520 1521/* detach traced process; continue with sig 1522 * Never call DETACH twice on the same process as both unattached and 1523 * attached-unstopped processes give the same ESRCH. For unattached process we 1524 * would SIGSTOP it and wait for its SIGSTOP notification forever. 1525 */ 1526static int 1527detach(struct tcb *tcp) 1528{ 1529 int error; 1530 int status, sigstop_expected; 1531 1532 if (tcp->flags & TCB_BPTSET) 1533 clearbpt(tcp); 1534 1535 /* 1536 * Linux wrongly insists the child be stopped 1537 * before detaching. Arghh. We go through hoops 1538 * to make a clean break of things. 1539 */ 1540#if defined(SPARC) 1541#undef PTRACE_DETACH 1542#define PTRACE_DETACH PTRACE_SUNDETACH 1543#endif 1544 1545 sigstop_expected = 0; 1546 if (tcp->flags & TCB_ATTACHED) { 1547 /* 1548 * We attached but possibly didn't see the expected SIGSTOP. 1549 * We must catch exactly one as otherwise the detached process 1550 * would be left stopped (process state T). 1551 */ 1552 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP); 1553 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0); 1554 if (error == 0) { 1555 /* On a clear day, you can see forever. */ 1556 } 1557 else if (errno != ESRCH) { 1558 /* Shouldn't happen. */ 1559 perror("detach: ptrace(PTRACE_DETACH, ...)"); 1560 } 1561 else if (my_tkill(tcp->pid, 0) < 0) { 1562 if (errno != ESRCH) 1563 perror("detach: checking sanity"); 1564 } 1565 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) { 1566 if (errno != ESRCH) 1567 perror("detach: stopping child"); 1568 } 1569 else 1570 sigstop_expected = 1; 1571 } 1572 1573 if (sigstop_expected) { 1574 for (;;) { 1575#ifdef __WALL 1576 if (waitpid(tcp->pid, &status, __WALL) < 0) { 1577 if (errno == ECHILD) /* Already gone. */ 1578 break; 1579 if (errno != EINVAL) { 1580 perror("detach: waiting"); 1581 break; 1582 } 1583#endif /* __WALL */ 1584 /* No __WALL here. */ 1585 if (waitpid(tcp->pid, &status, 0) < 0) { 1586 if (errno != ECHILD) { 1587 perror("detach: waiting"); 1588 break; 1589 } 1590#ifdef __WCLONE 1591 /* If no processes, try clones. */ 1592 if (waitpid(tcp->pid, &status, __WCLONE) < 0) { 1593 if (errno != ECHILD) 1594 perror("detach: waiting"); 1595 break; 1596 } 1597#endif /* __WCLONE */ 1598 } 1599#ifdef __WALL 1600 } 1601#endif 1602 if (!WIFSTOPPED(status)) { 1603 /* Au revoir, mon ami. */ 1604 break; 1605 } 1606 if (WSTOPSIG(status) == SIGSTOP) { 1607 ptrace_restart(PTRACE_DETACH, tcp, 0); 1608 break; 1609 } 1610 error = ptrace_restart(PTRACE_CONT, tcp, 1611 WSTOPSIG(status) == syscall_trap_sig ? 0 1612 : WSTOPSIG(status)); 1613 if (error < 0) 1614 break; 1615 } 1616 } 1617 1618 if (!qflag && (tcp->flags & TCB_ATTACHED)) 1619 fprintf(stderr, "Process %u detached\n", tcp->pid); 1620 1621 droptcb(tcp); 1622 1623 return error; 1624} 1625 1626static void 1627cleanup(void) 1628{ 1629 int i; 1630 struct tcb *tcp; 1631 int fatal_sig; 1632 1633 /* 'interrupted' is a volatile object, fetch it only once */ 1634 fatal_sig = interrupted; 1635 if (!fatal_sig) 1636 fatal_sig = SIGTERM; 1637 1638 for (i = 0; i < tcbtabsize; i++) { 1639 tcp = tcbtab[i]; 1640 if (!(tcp->flags & TCB_INUSE)) 1641 continue; 1642 if (debug) 1643 fprintf(stderr, 1644 "cleanup: looking at pid %u\n", tcp->pid); 1645 if (printing_tcp && 1646 (!outfname || followfork < 2 || printing_tcp == tcp)) { 1647 tprints(" <unfinished ...>\n"); 1648 printing_tcp = NULL; 1649 } 1650 if (!(tcp->flags & TCB_STRACE_CHILD)) 1651 detach(tcp); 1652 else { 1653 kill(tcp->pid, SIGCONT); 1654 kill(tcp->pid, fatal_sig); 1655 } 1656 } 1657 if (cflag) 1658 call_summary(outf); 1659} 1660 1661static void 1662interrupt(int sig) 1663{ 1664 interrupted = sig; 1665} 1666 1667#ifndef HAVE_STRERROR 1668 1669#if !HAVE_DECL_SYS_ERRLIST 1670extern int sys_nerr; 1671extern char *sys_errlist[]; 1672#endif /* HAVE_DECL_SYS_ERRLIST */ 1673 1674const char * 1675strerror(int err_no) 1676{ 1677 static char buf[sizeof("Unknown error %d") + sizeof(int)*3]; 1678 1679 if (err_no < 1 || err_no >= sys_nerr) { 1680 sprintf(buf, "Unknown error %d", err_no); 1681 return buf; 1682 } 1683 return sys_errlist[err_no]; 1684} 1685 1686#endif /* HAVE_STERRROR */ 1687 1688#ifndef HAVE_STRSIGNAL 1689 1690#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 1691extern char *sys_siglist[]; 1692#endif 1693#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 1694extern char *_sys_siglist[]; 1695#endif 1696 1697const char * 1698strsignal(int sig) 1699{ 1700 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3]; 1701 1702 if (sig < 1 || sig >= NSIG) { 1703 sprintf(buf, "Unknown signal %d", sig); 1704 return buf; 1705 } 1706#ifdef HAVE__SYS_SIGLIST 1707 return _sys_siglist[sig]; 1708#else 1709 return sys_siglist[sig]; 1710#endif 1711} 1712 1713#endif /* HAVE_STRSIGNAL */ 1714 1715static int 1716trace(void) 1717{ 1718 struct rusage ru; 1719 struct rusage *rup = cflag ? &ru : NULL; 1720# ifdef __WALL 1721 static int wait4_options = __WALL; 1722# endif 1723 1724 while (nprocs != 0) { 1725 int pid; 1726 int wait_errno; 1727 int status, sig; 1728 int stopped; 1729 struct tcb *tcp; 1730 unsigned event; 1731 1732 if (interrupted) 1733 return 0; 1734 if (interactive) 1735 sigprocmask(SIG_SETMASK, &empty_set, NULL); 1736# ifdef __WALL 1737 pid = wait4(-1, &status, wait4_options, rup); 1738 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 1739 /* this kernel does not support __WALL */ 1740 wait4_options &= ~__WALL; 1741 pid = wait4(-1, &status, wait4_options, rup); 1742 } 1743 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 1744 /* most likely a "cloned" process */ 1745 pid = wait4(-1, &status, __WCLONE, rup); 1746 if (pid < 0) { 1747 perror_msg("wait4(__WCLONE) failed"); 1748 } 1749 } 1750# else 1751 pid = wait4(-1, &status, 0, rup); 1752# endif /* __WALL */ 1753 wait_errno = errno; 1754 if (interactive) 1755 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 1756 1757 if (pid < 0) { 1758 switch (wait_errno) { 1759 case EINTR: 1760 continue; 1761 case ECHILD: 1762 /* 1763 * We would like to verify this case 1764 * but sometimes a race in Solbourne's 1765 * version of SunOS sometimes reports 1766 * ECHILD before sending us SIGCHILD. 1767 */ 1768 return 0; 1769 default: 1770 errno = wait_errno; 1771 perror_msg("wait"); 1772 return -1; 1773 } 1774 } 1775 if (pid == popen_pid) { 1776 if (WIFEXITED(status) || WIFSIGNALED(status)) 1777 popen_pid = 0; 1778 continue; 1779 } 1780 1781 event = ((unsigned)status >> 16); 1782 if (debug) { 1783 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16]; 1784 if (event != 0) { 1785 static const char *const event_names[] = { 1786 [PTRACE_EVENT_CLONE] = "CLONE", 1787 [PTRACE_EVENT_FORK] = "FORK", 1788 [PTRACE_EVENT_VFORK] = "VFORK", 1789 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE", 1790 [PTRACE_EVENT_EXEC] = "EXEC", 1791 [PTRACE_EVENT_EXIT] = "EXIT", 1792 }; 1793 const char *e; 1794 if (event < ARRAY_SIZE(event_names)) 1795 e = event_names[event]; 1796 else { 1797 sprintf(buf, "?? (%u)", event); 1798 e = buf; 1799 } 1800 fprintf(stderr, " PTRACE_EVENT_%s", e); 1801 } 1802 strcpy(buf, "???"); 1803 if (WIFSIGNALED(status)) 1804#ifdef WCOREDUMP 1805 sprintf(buf, "WIFSIGNALED,%ssig=%s", 1806 WCOREDUMP(status) ? "core," : "", 1807 signame(WTERMSIG(status))); 1808#else 1809 sprintf(buf, "WIFSIGNALED,sig=%s", 1810 signame(WTERMSIG(status))); 1811#endif 1812 if (WIFEXITED(status)) 1813 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status)); 1814 if (WIFSTOPPED(status)) 1815 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status))); 1816#ifdef WIFCONTINUED 1817 if (WIFCONTINUED(status)) 1818 strcpy(buf, "WIFCONTINUED"); 1819#endif 1820 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf); 1821 } 1822 1823 /* Look up 'pid' in our table. */ 1824 tcp = pid2tcb(pid); 1825 1826 /* Under Linux, execve changes pid to thread leader's pid, 1827 * and we see this changed pid on EVENT_EXEC and later, 1828 * execve sysexit. Leader "disappears" without exit 1829 * notification. Let user know that, drop leader's tcb, 1830 * and fix up pid in execve thread's tcb. 1831 * Effectively, execve thread's tcb replaces leader's tcb. 1832 * 1833 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED 1834 * on exit syscall) in multithreaded programs exactly 1835 * in order to handle this case. 1836 * 1837 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0. 1838 * On 2.6 and earlier, it can return garbage. 1839 */ 1840 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') { 1841 long old_pid = 0; 1842 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0 1843 && old_pid > 0 1844 && old_pid != pid 1845 ) { 1846 struct tcb *execve_thread = pid2tcb(old_pid); 1847 if (tcp) { 1848 outf = tcp->outf; 1849 curcol = tcp->curcol; 1850 if (!cflag) { 1851 if (printing_tcp) 1852 tprints(" <unfinished ...>\n"); 1853 printleader(tcp); 1854 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid); 1855 printing_tcp = NULL; 1856 fflush(outf); 1857 } 1858 if (execve_thread) { 1859 /* swap output FILEs (needed for -ff) */ 1860 tcp->outf = execve_thread->outf; 1861 execve_thread->outf = outf; 1862 } 1863 droptcb(tcp); 1864 } 1865 tcp = execve_thread; 1866 if (tcp) { 1867 tcp->pid = pid; 1868 tcp->flags |= TCB_REPRINT; 1869 } 1870 } 1871 } 1872 1873 if (tcp == NULL) { 1874 if (followfork) { 1875 /* This is needed to go with the CLONE_PTRACE 1876 changes in process.c/util.c: we might see 1877 the child's initial trap before we see the 1878 parent return from the clone syscall. 1879 Leave the child suspended until the parent 1880 returns from its system call. Only then 1881 will we have the association of parent and 1882 child so that we know how to do clearbpt 1883 in the child. */ 1884 tcp = alloctcb(pid); 1885 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop; 1886 if (!qflag) 1887 fprintf(stderr, "Process %d attached\n", 1888 pid); 1889 } 1890 else 1891 /* This can happen if a clone call used 1892 CLONE_PTRACE itself. */ 1893 { 1894 if (WIFSTOPPED(status)) 1895 ptrace(PTRACE_CONT, pid, (char *) 0, 0); 1896 error_msg_and_die("Unknown pid: %u", pid); 1897 } 1898 } 1899 /* set current output file */ 1900 outf = tcp->outf; 1901 curcol = tcp->curcol; 1902 if (cflag) { 1903 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 1904 tcp->stime = ru.ru_stime; 1905 } 1906 1907 if (WIFSIGNALED(status)) { 1908 if (pid == strace_child) 1909 exit_code = 0x100 | WTERMSIG(status); 1910 if (cflag != CFLAG_ONLY_STATS 1911 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 1912 printleader(tcp); 1913#ifdef WCOREDUMP 1914 tprintf("+++ killed by %s %s+++\n", 1915 signame(WTERMSIG(status)), 1916 WCOREDUMP(status) ? "(core dumped) " : ""); 1917#else 1918 tprintf("+++ killed by %s +++\n", 1919 signame(WTERMSIG(status))); 1920#endif 1921 printing_tcp = NULL; 1922 } 1923 fflush(tcp->outf); 1924 droptcb(tcp); 1925 continue; 1926 } 1927 if (WIFEXITED(status)) { 1928 if (pid == strace_child) 1929 exit_code = WEXITSTATUS(status); 1930 if (tcp == printing_tcp) { 1931 tprints(" <unfinished ...>\n"); 1932 printing_tcp = NULL; 1933 } 1934 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) { 1935 printleader(tcp); 1936 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status)); 1937 printing_tcp = NULL; 1938 } 1939 fflush(tcp->outf); 1940 droptcb(tcp); 1941 continue; 1942 } 1943 if (!WIFSTOPPED(status)) { 1944 fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 1945 droptcb(tcp); 1946 continue; 1947 } 1948 1949 /* Is this the very first time we see this tracee stopped? */ 1950 if (tcp->flags & TCB_STARTUP) { 1951 if (debug) 1952 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid); 1953 tcp->flags &= ~TCB_STARTUP; 1954 if (tcp->flags & TCB_BPTSET) { 1955 /* 1956 * One example is a breakpoint inherited from 1957 * parent through fork(). 1958 */ 1959 if (clearbpt(tcp) < 0) { 1960 /* Pretty fatal */ 1961 droptcb(tcp); 1962 cleanup(); 1963 return -1; 1964 } 1965 } 1966 if (ptrace_setoptions) { 1967 if (debug) 1968 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid); 1969 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) { 1970 if (errno != ESRCH) { 1971 /* Should never happen, really */ 1972 perror_msg_and_die("PTRACE_SETOPTIONS"); 1973 } 1974 } 1975 } 1976 } 1977 1978 sig = WSTOPSIG(status); 1979 1980 if (event != 0) { 1981 /* Ptrace event */ 1982#ifdef USE_SEIZE 1983 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) { 1984 /* 1985 * PTRACE_INTERRUPT-stop or group-stop. 1986 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here. 1987 */ 1988 if (sig == SIGSTOP 1989 || sig == SIGTSTP 1990 || sig == SIGTTIN 1991 || sig == SIGTTOU 1992 ) { 1993 stopped = 1; 1994 goto show_stopsig; 1995 } 1996 } 1997#endif 1998 goto restart_tracee_with_sig_0; 1999 } 2000 2001 /* Is this post-attach SIGSTOP? 2002 * Interestingly, the process may stop 2003 * with STOPSIG equal to some other signal 2004 * than SIGSTOP if we happend to attach 2005 * just before the process takes a signal. 2006 */ 2007 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) { 2008 if (debug) 2009 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid); 2010 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP; 2011 goto restart_tracee_with_sig_0; 2012 } 2013 2014 if (sig != syscall_trap_sig) { 2015 siginfo_t si; 2016 2017 /* Nonzero (true) if tracee is stopped by signal 2018 * (as opposed to "tracee received signal"). 2019 */ 2020 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0); 2021#ifdef USE_SEIZE 2022 show_stopsig: 2023#endif 2024 if (cflag != CFLAG_ONLY_STATS 2025 && (qual_flags[sig] & QUAL_SIGNAL)) { 2026#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) 2027 long pc = 0; 2028 long psr = 0; 2029 2030 upeek(tcp, PT_CR_IPSR, &psr); 2031 upeek(tcp, PT_CR_IIP, &pc); 2032 2033# define PSR_RI 41 2034 pc += (psr >> PSR_RI) & 0x3; 2035# define PC_FORMAT_STR " @ %lx" 2036# define PC_FORMAT_ARG , pc 2037#else 2038# define PC_FORMAT_STR "" 2039# define PC_FORMAT_ARG /* nothing */ 2040#endif 2041 printleader(tcp); 2042 if (!stopped) { 2043 tprints("--- "); 2044 printsiginfo(&si, verbose(tcp)); 2045 tprintf(" (%s)" PC_FORMAT_STR " ---\n", 2046 strsignal(sig) 2047 PC_FORMAT_ARG); 2048 } else 2049 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n", 2050 strsignal(sig), 2051 signame(sig) 2052 PC_FORMAT_ARG); 2053 printing_tcp = NULL; 2054 fflush(tcp->outf); 2055 } 2056 2057 if (!stopped) 2058 /* It's signal-delivery-stop. Inject the signal */ 2059 goto restart_tracee; 2060 2061 /* It's group-stop */ 2062#ifdef USE_SEIZE 2063 if (use_seize) { 2064 /* 2065 * This ends ptrace-stop, but does *not* end group-stop. 2066 * This makes stopping signals work properly on straced process 2067 * (that is, process really stops. It used to continue to run). 2068 */ 2069 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) { 2070 cleanup(); 2071 return -1; 2072 } 2073 continue; 2074 } 2075 /* We don't have PTRACE_LISTEN support... */ 2076#endif 2077 goto restart_tracee; 2078 } 2079 2080 /* We handled quick cases, we are permitted to interrupt now. */ 2081 if (interrupted) 2082 return 0; 2083 2084 /* This should be syscall entry or exit. 2085 * (Or it still can be that pesky post-execve SIGTRAP!) 2086 * Handle it. 2087 */ 2088 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) { 2089 /* ptrace() failed in trace_syscall() with ESRCH. 2090 * Likely a result of process disappearing mid-flight. 2091 * Observed case: exit_group() terminating 2092 * all processes in thread group. 2093 */ 2094 if (printing_tcp) { 2095 /* Do we have dangling line "syscall(param, param"? 2096 * Finish the line then. 2097 */ 2098 printing_tcp->flags |= TCB_REPRINT; 2099 tprints(" <unfinished ...>\n"); 2100 printing_tcp = NULL; 2101 fflush(tcp->outf); 2102 } 2103 /* We assume that ptrace error was caused by process death. 2104 * We used to detach(tcp) here, but since we no longer 2105 * implement "detach before death" policy/hack, 2106 * we can let this process to report its death to us 2107 * normally, via WIFEXITED or WIFSIGNALED wait status. 2108 */ 2109 continue; 2110 } 2111 restart_tracee_with_sig_0: 2112 sig = 0; 2113 restart_tracee: 2114 /* Remember current print column before continuing. */ 2115 tcp->curcol = curcol; 2116 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) { 2117 cleanup(); 2118 return -1; 2119 } 2120 } 2121 return 0; 2122} 2123 2124int 2125main(int argc, char *argv[]) 2126{ 2127 init(argc, argv); 2128 2129 /* Run main tracing loop */ 2130 if (trace() < 0) 2131 return 1; 2132 2133 cleanup(); 2134 fflush(NULL); 2135 if (exit_code > 0xff) { 2136 /* Avoid potential core file clobbering. */ 2137 struct rlimit rlim = {0, 0}; 2138 setrlimit(RLIMIT_CORE, &rlim); 2139 2140 /* Child was killed by a signal, mimic that. */ 2141 exit_code &= 0xff; 2142 signal(exit_code, SIG_DFL); 2143 raise(exit_code); 2144 /* Paranoia - what if this signal is not fatal? 2145 Exit with 128 + signo then. */ 2146 exit_code += 128; 2147 } 2148 2149 return exit_code; 2150} 2151