]> granicus.if.org Git - strace/blobdiff - strace.c
mmap_cache: add function to enable mmap_cache
[strace] / strace.c
index 1fcf7e249718c7175de9ebe6be180d526f0ac7ac..794e9a0d4925e14c75eca13a61f364291202676f 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -3,7 +3,7 @@
  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
- * Copyright (c) 1999-2017 The strace developers.
+ * Copyright (c) 1999-2018 The strace developers.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,9 @@
 
 #include "defs.h"
 #include <stdarg.h>
-#include <sys/param.h>
+#include <limits.h>
 #include <fcntl.h>
+#include "ptrace.h"
 #include <signal.h>
 #include <sys/resource.h>
 #include <sys/wait.h>
@@ -49,9 +50,9 @@
 #endif
 #include <asm/unistd.h>
 
+#include "largefile_wrappers.h"
 #include "number_set.h"
 #include "scno.h"
-#include "ptrace.h"
 #include "printsiginfo.h"
 #include "trace_event.h"
 #include "xstring.h"
@@ -204,6 +205,23 @@ print_version(void)
 #ifdef USE_LIBUNWIND
                " stack-unwind"
 #endif /* USE_LIBUNWIND */
+#ifdef USE_DEMANGLE
+               " stack-demangle"
+#endif /* USE_DEMANGLE */
+#if SUPPORTED_PERSONALITIES > 1
+# if defined HAVE_M32_MPERS
+               " m32-mpers"
+# else
+               " no-m32-mpers"
+# endif
+#endif /* SUPPORTED_PERSONALITIES > 1 */
+#if SUPPORTED_PERSONALITIES > 2
+# if defined HAVE_MX32_MPERS
+               " mx32-mpers"
+# else
+               " no-mx32-mpers"
+# endif
+#endif /* SUPPORTED_PERSONALITIES > 2 */
                "";
 
        printf("%s -- version %s\n"
@@ -430,28 +448,6 @@ swap_uid(void)
        }
 }
 
-#ifdef _LARGEFILE64_SOURCE
-# ifdef HAVE_FOPEN64
-#  define fopen_for_output fopen64
-# else
-#  define fopen_for_output fopen
-# endif
-# define struct_stat struct stat64
-# define stat_file stat64
-# define struct_dirent struct dirent64
-# define read_dir readdir64
-# define struct_rlimit struct rlimit64
-# define set_rlimit setrlimit64
-#else
-# define fopen_for_output fopen
-# define struct_stat struct stat
-# define stat_file stat
-# define struct_dirent struct dirent
-# define read_dir readdir
-# define struct_rlimit struct rlimit
-# define set_rlimit setrlimit
-#endif
-
 static FILE *
 strace_fopen(const char *path)
 {
@@ -516,6 +512,19 @@ strace_popen(const char *command)
        return fp;
 }
 
+static void
+outf_perror(const struct tcb * const tcp)
+{
+       if (tcp->outf == stderr)
+               return;
+
+       /* This is ugly, but we don't store separate file names */
+       if (followfork >= 2)
+               perror_msg("%s.%u", outfname, tcp->pid);
+       else
+               perror_msg("%s", outfname);
+}
+
 ATTRIBUTE_FORMAT((printf, 1, 0))
 static void
 tvprintf(const char *const fmt, va_list args)
@@ -524,8 +533,7 @@ tvprintf(const char *const fmt, va_list args)
                int n = vfprintf(current_tcp->outf, fmt, args);
                if (n < 0) {
                        /* very unlikely due to vfprintf buffering */
-                       if (current_tcp->outf != stderr)
-                               perror_msg("%s", outfname);
+                       outf_perror(current_tcp);
                } else
                        current_tcp->curcol += n;
        }
@@ -554,8 +562,7 @@ tprints(const char *str)
                        return;
                }
                /* very unlikely due to fputs_unlocked buffering */
-               if (current_tcp->outf != stderr)
-                       perror_msg("%s", outfname);
+               outf_perror(current_tcp);
        }
 }
 
@@ -583,8 +590,8 @@ tprintf_comment(const char *fmt, ...)
 static void
 flush_tcp_output(const struct tcb *const tcp)
 {
-       if (fflush(tcp->outf) && tcp->outf != stderr)
-               perror_msg("%s", outfname);
+       if (fflush(tcp->outf))
+               outf_perror(tcp);
 }
 
 void
@@ -600,6 +607,16 @@ line_ended(void)
        }
 }
 
+void
+set_current_tcp(const struct tcb *tcp)
+{
+       current_tcp = (struct tcb *) tcp;
+
+       /* Sync current_personality and stuff */
+       if (current_tcp)
+               set_personality(current_tcp->currpers);
+}
+
 void
 printleader(struct tcb *tcp)
 {
@@ -610,7 +627,7 @@ printleader(struct tcb *tcp)
                printing_tcp = tcp;
 
        if (printing_tcp) {
-               current_tcp = printing_tcp;
+               set_current_tcp(printing_tcp);
                if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
                        /*
                         * case 1: we have a shared log (i.e. not -ff), and last line
@@ -624,7 +641,7 @@ printleader(struct tcb *tcp)
        }
 
        printing_tcp = tcp;
-       current_tcp = tcp;
+       set_current_tcp(tcp);
        current_tcp->curcol = 0;
 
        if (print_pid_pfx)
@@ -786,6 +803,8 @@ droptcb(struct tcb *tcp)
        }
 #endif
 
+       mmap_cache_delete(tcp, __func__);
+
        nprocs--;
        debug_msg("dropped tcb for pid %d, %d remain", tcp->pid, nprocs);
 
@@ -802,7 +821,7 @@ droptcb(struct tcb *tcp)
        }
 
        if (current_tcp == tcp)
-               current_tcp = NULL;
+               set_current_tcp(NULL);
        if (printing_tcp == tcp)
                printing_tcp = NULL;
 
@@ -2173,11 +2192,11 @@ print_event_exit(struct tcb *tcp)
 
        if (followfork < 2 && printing_tcp && printing_tcp != tcp
            && printing_tcp->curcol != 0) {
-               current_tcp = printing_tcp;
+               set_current_tcp(printing_tcp);
                tprints(" <unfinished ...>\n");
                flush_tcp_output(printing_tcp);
                printing_tcp->curcol = 0;
-               current_tcp = tcp;
+               set_current_tcp(tcp);
        }
 
        if ((followfork < 2 && printing_tcp != tcp)
@@ -2194,6 +2213,8 @@ print_event_exit(struct tcb *tcp)
                 */
                tprints(" <unfinished ...>");
        }
+
+       printing_tcp = tcp;
        tprints(") ");
        tabto();
        tprints("= ?\n");
@@ -2273,10 +2294,10 @@ next_event(int *pstatus, siginfo_t *si)
                        return TE_NEXT;
        }
 
-       clear_regs();
+       clear_regs(tcp);
 
        /* Set current output file */
-       current_tcp = tcp;
+       set_current_tcp(tcp);
 
        if (cflag) {
                tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
@@ -2442,6 +2463,31 @@ dispatch_event(enum trace_event ret, int *pstatus, siginfo_t *si)
                return true;
 
        case TE_STOP_BEFORE_EXECVE:
+               /*
+                * Check that we are inside syscall now (next event after
+                * PTRACE_EVENT_EXEC should be for syscall exiting).  If it is
+                * not the case, we might have a situation when we attach to a
+                * process and the first thing we see is a PTRACE_EVENT_EXEC
+                * and all the following syscall state tracking is screwed up
+                * otherwise.
+                */
+               if (entering(current_tcp)) {
+                       int ret;
+
+                       error_msg("Stray PTRACE_EVENT_EXEC from pid %d"
+                                 ", trying to recover...",
+                                 current_tcp->pid);
+
+                       current_tcp->flags |= TCB_RECOVERING;
+                       ret = trace_syscall(current_tcp, &restart_sig);
+                       current_tcp->flags &= ~TCB_RECOVERING;
+
+                       if (ret < 0) {
+                               /* The reason is described in TE_SYSCALL_STOP */
+                               return true;
+                       }
+               }
+
                /*
                 * Under Linux, execve changes pid to thread leader's pid,
                 * and we see this changed pid on EVENT_EXEC and later,
@@ -2458,7 +2504,8 @@ dispatch_event(enum trace_event ret, int *pstatus, siginfo_t *si)
                 * On 2.6 and earlier, it can return garbage.
                 */
                if (os_release >= KERNEL_VERSION(3, 0, 0))
-                       current_tcp = maybe_switch_tcbs(current_tcp, current_tcp->pid);
+                       set_current_tcp(maybe_switch_tcbs(current_tcp,
+                                                         current_tcp->pid));
 
                if (detach_on_execve) {
                        if (current_tcp->flags & TCB_SKIP_DETACH_ON_FIRST_EXEC) {