ftrace: Add test to make sure compiled time sorts work
authorSteven Rostedt (VMware) <rostedt@goodmis.org>
Mon, 6 Dec 2021 20:18:58 +0000 (15:18 -0500)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 13 Jan 2022 21:23:05 +0000 (16:23 -0500)
Now that ftrace function pointers are sorted at compile time, add a test
that makes sure they are sorted at run time. This test is only run if it is
configured in.

Link: https://lkml.kernel.org/r/20211206151858.4d21a24d@gandalf.local.home
Cc: Yinan Liu <yinan@linux.alibaba.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
kernel/trace/Kconfig
kernel/trace/ftrace.c

index 420ff4b..f468767 100644 (file)
@@ -915,6 +915,20 @@ config EVENT_TRACE_TEST_SYSCALLS
         TBD - enable a way to actually call the syscalls as we test their
               events
 
+config FTRACE_SORT_STARTUP_TEST
+       bool "Verify compile time sorting of ftrace functions"
+       depends on DYNAMIC_FTRACE
+       depends on BUILDTIME_TABLE_SORT
+       help
+        Sorting of the mcount_loc sections that is used to find the
+        where the ftrace knows where to patch functions for tracing
+        and other callbacks is done at compile time. But if the sort
+        is not done correctly, it will cause non-deterministic failures.
+        When this is set, the sorted sections will be verified that they
+        are in deed sorted and will warn if they are not.
+
+        If unsure, say N
+
 config RING_BUFFER_STARTUP_TEST
        bool "Ring buffer startup self test"
        depends on RING_BUFFER
index 9ca63df..403e485 100644 (file)
@@ -6388,6 +6388,27 @@ static int ftrace_cmp_ips(const void *a, const void *b)
        return 0;
 }
 
+#ifdef CONFIG_FTRACE_SORT_STARTUP_TEST
+static void test_is_sorted(unsigned long *start, unsigned long count)
+{
+       int i;
+
+       for (i = 1; i < count; i++) {
+               if (WARN(start[i - 1] > start[i],
+                        "[%d] %pS at %lx is not sorted with %pS at %lx\n", i,
+                        (void *)start[i - 1], start[i - 1],
+                        (void *)start[i], start[i]))
+                       break;
+       }
+       if (i == count)
+               pr_info("ftrace section at %px sorted properly\n", start);
+}
+#else
+static void test_is_sorted(unsigned long *start, unsigned long count)
+{
+}
+#endif
+
 static int ftrace_process_locs(struct module *mod,
                               unsigned long *start,
                               unsigned long *end)
@@ -6414,6 +6435,8 @@ static int ftrace_process_locs(struct module *mod,
        if (!IS_ENABLED(CONFIG_BUILDTIME_TABLE_SORT) || mod) {
                sort(start, count, sizeof(*start),
                     ftrace_cmp_ips, NULL);
+       } else {
+               test_is_sorted(start, count);
        }
 
        start_pg = ftrace_allocate_pages(count);