]> git.saurik.com Git - apple/xnu.git/blobdiff - tools/tests/darwintests/kdebug.c
xnu-4570.41.2.tar.gz
[apple/xnu.git] / tools / tests / darwintests / kdebug.c
index ea1f049e57aeb92f2d9538f4135056534b3d4eea..3cc0e22003b9d2957e8a4f00a3dfb23f958e1502 100644 (file)
@@ -1,8 +1,8 @@
 #include <darwintest.h>
 #include <dispatch/dispatch.h>
 #include <inttypes.h>
-#include <ktrace.h>
-#include <ktrace_private.h>
+#include <ktrace/session.h>
+#include <ktrace/private.h>
 #include <mach/dyld_kernel.h>
 #include <mach/host_info.h>
 #include <mach/mach.h>
 #include <sys/kdebug_signpost.h>
 #include <sys/sysctl.h>
 
-#define KTRACE_WAIT_TIMEOUT_S (10)
+#define KDBG_TEST_MACROS    1
+#define KDBG_TEST_OLD_TIMES 2
+
+static void
+assert_kdebug_test(unsigned int flavor)
+{
+    size_t size = flavor;
+    int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDTEST };
+    T_ASSERT_POSIX_SUCCESS(
+        sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &size, NULL, 0),
+        "KERN_KDTEST sysctl");
+}
+
+#pragma mark kdebug syscalls
 
 #define TRACE_DEBUGID (0xfedfed00U)
 
 T_DECL(kdebug_trace_syscall, "test that kdebug_trace(2) emits correct events",
-       T_META_ASROOT(YES))
+       T_META_ASROOT(true))
 {
     ktrace_session_t s;
-    dispatch_time_t timeout;
     __block int events_seen = 0;
 
     s = ktrace_session_create();
@@ -60,12 +72,11 @@ T_DECL(kdebug_trace_syscall, "test that kdebug_trace(2) emits correct events",
 
 T_DECL(kdebug_signpost_syscall,
     "test that kdebug_signpost(2) emits correct events",
-    T_META_ASROOT(YES))
+    T_META_ASROOT(true))
 {
     ktrace_session_t s;
     __block int single_seen = 0;
     __block int paired_seen = 0;
-    dispatch_time_t timeout;
 
     s = ktrace_session_create();
     T_ASSERT_NOTNULL(s, NULL);
@@ -134,13 +145,15 @@ T_DECL(kdebug_signpost_syscall,
     dispatch_main();
 }
 
+#pragma mark kdebug behaviors
+
 #define WRAPPING_EVENTS_COUNT     (150000)
 #define TRACE_ITERATIONS          (5000)
 #define WRAPPING_EVENTS_THRESHOLD (100)
 
-T_DECL(kdebug_wrapping,
+T_DECL(wrapping,
     "ensure that wrapping traces lost events and no events prior to the wrap",
-    T_META_ASROOT(YES), T_META_CHECK_LEAKS(NO))
+    T_META_ASROOT(true), T_META_CHECK_LEAKS(false))
 {
     ktrace_session_t s;
     __block int events = 0;
@@ -218,6 +231,91 @@ T_DECL(kdebug_wrapping,
     dispatch_main();
 }
 
+T_DECL(reject_old_events,
+        "ensure that kdebug rejects events from before tracing began",
+        T_META_ASROOT(true), T_META_CHECK_LEAKS(false))
+{
+    __block uint64_t event_horizon_ts;
+    __block int events = 0;
+
+    ktrace_session_t s = ktrace_session_create();
+    T_QUIET; T_ASSERT_NOTNULL(s, "ktrace_session_create");
+
+    ktrace_events_range(s, KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 0),
+        KDBG_EVENTID(DBG_BSD + 1, 0, 0),
+        ^(struct trace_point *tp)
+    {
+        events++;
+        T_EXPECT_GT(tp->timestamp, event_horizon_ts,
+                "events in trace should be from after tracing began");
+    });
+
+    ktrace_set_completion_handler(s, ^{
+        T_EXPECT_EQ(events, 2, "should see only two events");
+        ktrace_session_destroy(s);
+        T_END;
+    });
+
+    event_horizon_ts = mach_absolute_time();
+
+    T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
+    /* first, try an old event at the beginning of trace */
+    assert_kdebug_test(KDBG_TEST_OLD_TIMES);
+    /* after a good event has been traced, old events should be rejected */
+    assert_kdebug_test(KDBG_TEST_OLD_TIMES);
+    ktrace_end(s, 0);
+
+    dispatch_main();
+}
+
+#define ORDERING_TIMEOUT_SEC 5
+
+T_DECL(ascending_time_order,
+        "ensure that kdebug events are in ascending order based on time",
+        T_META_ASROOT(true), T_META_CHECK_LEAKS(false))
+{
+    __block uint64_t prev_ts = 0;
+    __block uint32_t prev_debugid = 0;
+    __block unsigned int prev_cpu = 0;
+    __block bool in_order = true;
+
+    ktrace_session_t s = ktrace_session_create();
+    T_QUIET; T_ASSERT_NOTNULL(s, "ktrace_session_create");
+
+    ktrace_events_all(s, ^(struct trace_point *tp) {
+        if (tp->timestamp < prev_ts) {
+            in_order = false;
+            T_FAIL("found timestamps out of order");
+            T_LOG("%" PRIu64 ": %#" PRIx32 " (cpu %d)",
+                    prev_ts, prev_debugid, prev_cpu);
+            T_LOG("%" PRIu64 ": %#" PRIx32 " (cpu %d)",
+                    tp->timestamp, tp->debugid, tp->cpuid);
+        }
+    });
+
+    ktrace_set_completion_handler(s, ^{
+        ktrace_session_destroy(s);
+        T_EXPECT_TRUE(in_order, "event timestamps were in-order");
+        T_END;
+    });
+
+    T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
+
+    /* try to inject old timestamps into trace */
+    assert_kdebug_test(KDBG_TEST_OLD_TIMES);
+
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, ORDERING_TIMEOUT_SEC * NSEC_PER_SEC),
+            dispatch_get_main_queue(), ^{
+        T_LOG("ending test after timeout");
+        ktrace_end(s, 1);
+    });
+
+    dispatch_main();
+
+}
+
+#pragma mark dyld tracing
+
 __attribute__((aligned(8)))
 static const char map_uuid[16] = "map UUID";
 
@@ -342,7 +440,7 @@ expect_dyld_events(ktrace_session_t s, const char *name, uint32_t base_code,
 }
 
 T_DECL(dyld_events, "test that dyld registering libraries emits events",
-    T_META_ASROOT(YES))
+    T_META_ASROOT(true))
 {
     ktrace_session_t s;
     dyld_kernel_image_info_t info;
@@ -359,6 +457,7 @@ T_DECL(dyld_events, "test that dyld registering libraries emits events",
 
     s = ktrace_session_create();
     T_ASSERT_NOTNULL(s, NULL);
+    T_ASSERT_POSIX_ZERO(ktrace_filter_pid(s, getpid()), NULL);
 
     expect_dyld_events(s, "mapping", DBG_DYLD_UUID_MAP_A, map_uuid,
         MAP_LOAD_ADDR, &map_fsid, &map_fsobjid, saw_mapping);
@@ -403,6 +502,8 @@ T_DECL(dyld_events, "test that dyld registering libraries emits events",
     dispatch_main();
 }
 
+#pragma mark kdebug kernel macros
+
 #define EXP_KERNEL_EVENTS 5U
 
 static const uint32_t dev_evts[EXP_KERNEL_EVENTS] = {
@@ -436,31 +537,18 @@ is_development_kernel(void)
     static bool is_development;
 
     dispatch_once(&is_development_once, ^(void) {
-        host_debug_info_internal_data_t info;
-        mach_msg_type_number_t count = HOST_DEBUG_INFO_INTERNAL_COUNT;
-        kern_return_t kr;
-
-        kr = host_info(mach_host_self(), HOST_DEBUG_INFO_INTERNAL,
-            (host_info_t)(void *)&info, &count);
-        if (kr != KERN_SUCCESS && kr != KERN_NOT_SUPPORTED) {
-            T_ASSERT_FAIL("check for development kernel failed %d", kr);
-        }
+        int dev;
+        size_t dev_size = sizeof(dev);
 
-        is_development = (kr == KERN_SUCCESS);
+        T_QUIET;
+        T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &dev,
+                                            &dev_size, NULL, 0), NULL);
+        is_development = (dev != 0);
     });
 
     return is_development;
 }
 
-static void
-assert_kdebug_test(void)
-{
-    int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDTEST };
-    T_ASSERT_POSIX_SUCCESS(
-        sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, NULL, NULL, 0),
-        "KERN_KDTEST");
-}
-
 static void
 expect_event(struct trace_point *tp, unsigned int *events,
     const uint32_t *event_ids, size_t event_ids_len)
@@ -511,10 +599,11 @@ expect_filtered_event(struct trace_point *tp, unsigned int *events)
 }
 
 T_DECL(kernel_events, "ensure kernel macros work",
-    T_META_ASROOT(YES))
+    T_META_ASROOT(true))
 {
     ktrace_session_t s;
 
+
     s = ktrace_session_create();
     T_QUIET; T_ASSERT_NOTNULL(s, NULL);
 
@@ -531,10 +620,21 @@ T_DECL(kernel_events, "ensure kernel macros work",
     });
 
     ktrace_set_completion_handler(s, ^(void) {
-        T_EXPECT_EQ(rel_seen, EXP_KERNEL_EVENTS, NULL);
-        T_EXPECT_EQ(dev_seen, is_development_kernel() ? EXP_KERNEL_EVENTS : 0U,
-            NULL);
-        T_EXPECT_EQ(filt_seen, EXP_KERNEL_EVENTS, NULL);
+        /*
+         * Development-only events are only filtered if running on an embedded
+         * OS.
+         */
+        unsigned int dev_exp;
+#if TARGET_OS_EMBEDDED
+        dev_exp = is_development_kernel() ? EXP_KERNEL_EVENTS : 0U;
+#else
+        dev_exp = EXP_KERNEL_EVENTS;
+#endif
+
+        T_EXPECT_EQ(rel_seen, EXP_KERNEL_EVENTS,
+                "release and development events seen");
+        T_EXPECT_EQ(dev_seen, dev_exp, "development-only events seen/not seen");
+        T_EXPECT_EQ(filt_seen, dev_exp, "filter-only events seen");
         ktrace_session_destroy(s);
         T_END;
     });
@@ -542,7 +642,7 @@ T_DECL(kernel_events, "ensure kernel macros work",
     ktrace_filter_pid(s, getpid());
 
     T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
-    assert_kdebug_test();
+    assert_kdebug_test(KDBG_TEST_MACROS);
 
     ktrace_end(s, 0);
 
@@ -550,7 +650,7 @@ T_DECL(kernel_events, "ensure kernel macros work",
 }
 
 T_DECL(kernel_events_filtered, "ensure that the filtered kernel macros work",
-    T_META_ASROOT(YES))
+    T_META_ASROOT(true))
 {
     ktrace_session_t s;
 
@@ -571,16 +671,20 @@ T_DECL(kernel_events_filtered, "ensure that the filtered kernel macros work",
         ktrace_session_destroy(s);
 
         T_EXPECT_EQ(rel_seen, EXP_KERNEL_EVENTS, NULL);
+#if defined(__arm__) || defined(__arm64__)
+        T_EXPECT_EQ(dev_seen, is_development_kernel() ? EXP_KERNEL_EVENTS : 0U,
+            NULL);
+#else
         T_EXPECT_EQ(dev_seen, EXP_KERNEL_EVENTS, NULL);
+#endif /* defined(__arm__) || defined(__arm64__) */
         T_EXPECT_EQ(filt_seen, 0U, NULL);
         T_END;
     });
 
     T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
-    assert_kdebug_test();
+    assert_kdebug_test(KDBG_TEST_MACROS);
 
     ktrace_end(s, 0);
 
     dispatch_main();
 }
-