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