]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_fslog.c
xnu-4903.231.4.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_fslog.c
index b13faa434a0fc8c8945d1d7059dcf2974134424f..87db6067f5470105291a4f7c0dc84e26a2936029 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2006-2017 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -40,7 +40,8 @@
 #include <sys/mount_internal.h>
 #include <sys/kasl.h>
 
-#include <dev/random/randomdev.h>
+#include <sys/queue.h>
+#include <kern/kalloc.h>
 
 #include <uuid/uuid.h>
 
@@ -74,7 +75,7 @@ fslog_extmod_msgtracer(proc_t caller, proc_t target)
                strlcat(c_name, "(", sizeof(c_name));
                strlcat(c_name, uuidstr, sizeof(c_name));
                strlcat(c_name, ")", sizeof(c_name));
-               if (0 != escape_str(c_name, strlen(c_name), sizeof(c_name))) {
+               if (0 != escape_str(c_name, strlen(c_name) + 1, sizeof(c_name))) {
                        return;
                }
 
@@ -83,7 +84,7 @@ fslog_extmod_msgtracer(proc_t caller, proc_t target)
                strlcat(t_name, "(", sizeof(t_name));
                strlcat(t_name, uuidstr, sizeof(t_name));
                strlcat(t_name, ")", sizeof(t_name));
-               if (0 != escape_str(t_name, strlen(t_name), sizeof(t_name))) {
+               if (0 != escape_str(t_name, strlen(t_name) + 1, sizeof(t_name))) {
                        return;
                }
 #if DEBUG
@@ -105,3 +106,170 @@ fslog_extmod_msgtracer(proc_t caller, proc_t target)
        }
 }
 
+#if defined(__x86_64__)
+
+/*
+ * Log information about floating point exception handling
+ */
+
+static lck_mtx_t fpxlock;
+
+void
+fpxlog_init(void)
+{
+       lck_grp_attr_t *lck_grp_attr = lck_grp_attr_alloc_init();
+       lck_grp_t *lck_grp = lck_grp_alloc_init("fpx", lck_grp_attr);
+       lck_mtx_init(&fpxlock, lck_grp, LCK_ATTR_NULL);
+}
+
+struct fpx_event {
+       uuid_t fe_uuid;
+       uint32_t fe_code;
+       uint32_t fe_xcpt;
+       TAILQ_ENTRY(fpx_event) fe_link;
+};
+
+static bool
+match_fpx_event(const struct fpx_event *fe,
+    const uuid_t uuid, const uint32_t code, const uint32_t xcpt)
+{
+       return (code == fe->fe_code && xcpt == fe->fe_xcpt &&
+           0 == memcmp(uuid, fe->fe_uuid, sizeof (uuid_t)));
+}
+
+#if FPX_EVENT_DBG
+static __attribute__((noinline)) void
+print_fpx_event(const char *pfx, const struct fpx_event *fe)
+{
+       uuid_string_t uustr;
+       uuid_unparse_upper(fe->fe_uuid, uustr);
+       printf("%s: code 0x%x xcpt 0x%x uuid '%s'\n",
+           pfx, fe->fe_code, fe->fe_xcpt, uustr);
+}
+#define DPRINTF_FPX_EVENT(pfx, fe)     print_fpx_event(pfx, fe)
+#else
+#define DPRINTF_FPX_EVENT(pfx, fe)     /* nothing */
+#endif
+
+#define MAX_DISTINCT_FPX_EVENTS        101     /* (approx one page of heap) */
+
+/*
+ * Filter to detect "new" <uuid, code, xcpt> tuples.
+ * Uses limited amount of state, managed LRU.
+ * Optimized to ignore repeated invocation with the same tuple.
+ *
+ * Note that there are 6 exception types, two types of FP, and
+ * many binaries, so don't make the list bound too small.
+ * It's also a linear search, so don't make it too large either.
+ * Next level filtering provided by syslogd, and summarization.
+ */
+static bool
+novel_fpx_event(const uuid_t uuid, uint32_t code, uint32_t xcpt)
+{
+       static TAILQ_HEAD(fpx_event_head, fpx_event) fehead =
+               TAILQ_HEAD_INITIALIZER(fehead);
+       struct fpx_event *fe;
+
+       lck_mtx_lock(&fpxlock);
+
+       fe = TAILQ_FIRST(&fehead);
+       if (NULL != fe &&
+           match_fpx_event(fe, uuid, code, xcpt)) {
+               /* seen before and element already at head */
+               lck_mtx_unlock(&fpxlock);
+               DPRINTF_FPX_EVENT("seen, head", fe);
+               return (false);
+       }
+
+       unsigned int count = 0;
+
+       TAILQ_FOREACH(fe, &fehead, fe_link) {
+               if (match_fpx_event(fe, uuid, code, xcpt)) {
+                       /* seen before, now move element to head */
+                       TAILQ_REMOVE(&fehead, fe, fe_link);
+                       TAILQ_INSERT_HEAD(&fehead, fe, fe_link);
+                       lck_mtx_unlock(&fpxlock);
+                       DPRINTF_FPX_EVENT("seen, moved to head", fe);
+                       return (false);
+               }
+               count++;
+       }
+
+       /* not recorded here => novel */
+
+       if (count >= MAX_DISTINCT_FPX_EVENTS) {
+               /* reuse LRU element */
+               fe = TAILQ_LAST(&fehead, fpx_event_head);
+               TAILQ_REMOVE(&fehead, fe, fe_link);
+               DPRINTF_FPX_EVENT("reusing", fe);
+       } else {
+               /* add a new element to the list */
+               fe = kalloc(sizeof (*fe));
+       }
+       memcpy(fe->fe_uuid, uuid, sizeof (uuid_t));
+       fe->fe_code = code;
+       fe->fe_xcpt = xcpt;
+       TAILQ_INSERT_HEAD(&fehead, fe, fe_link);
+       lck_mtx_unlock(&fpxlock);
+
+       DPRINTF_FPX_EVENT("novel", fe);
+
+       return (true);
+}
+
+void
+fpxlog(
+       int code,       /* Mach exception code: e.g. 5 or 8 */
+       uint32_t stat,  /* Full FP status register bits */
+       uint32_t ctrl,  /* Full FP control register bits */
+       uint32_t xcpt)  /* Exception bits from FP status */
+{
+       proc_t p = current_proc();
+       if (PROC_NULL == p)
+               return;
+
+       uuid_t uuid;
+       proc_getexecutableuuid(p, uuid, sizeof (uuid));
+
+       /*
+        * Check to see if an exception with this <uuid, code, xcpt>
+        * has been seen before.  If "novel" then log a message.
+        */
+       if (!novel_fpx_event(uuid, code, xcpt))
+               return;
+
+       const size_t nmlen = 2 * MAXCOMLEN + 1;
+       char nm[nmlen] = {};
+       proc_selfname(nm, nmlen);
+       if (escape_str(nm, strlen(nm) + 1, nmlen))
+               snprintf(nm, nmlen, "(a.out)");
+
+       const size_t slen = 8 + 1 + 8 + 1;
+       char xcptstr[slen], csrstr[slen];
+
+       snprintf(xcptstr, slen, "%x.%x", code, xcpt);
+       if (ctrl == stat)
+               snprintf(csrstr, slen, "%x", ctrl);
+       else
+               snprintf(csrstr, slen, "%x.%x", ctrl, stat);
+
+#if DEVELOPMENT || DEBUG
+       printf("%s[%d]: com.apple.kernel.fpx: %s, %s\n",
+               nm, proc_pid(p), xcptstr, csrstr);
+#endif
+       kern_asl_msg(LOG_DEBUG, "messagetracer", 5,
+       /* 0 */ "com.apple.message.domain", "com.apple.kernel.fpx",
+       /* 1 */ "com.apple.message.signature", nm,
+       /* 2 */ "com.apple.message.signature2", xcptstr,
+       /* 3 */ "com.apple.message.value", csrstr,
+       /* 4 */ "com.apple.message.summarize", "YES",
+               NULL);
+}
+
+#else
+
+void
+fpxlog_init(void)
+{}
+
+#endif /* __x86_64__ */