@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/ftrace.h>
+#include <linux/kallsyms.h>
#include <linux/sched.h>
#include <linux/stacktrace.h>
@@ -322,5 +323,56 @@ void save_stack_trace_sp(struct stack_trace *trace,
{
__save_stack_trace_tsk(current, trace, stack_dump_sp);
}
+
+static int start_analyzer_test __initdata;
+
+static int __init enable_analyzer_test(char *str)
+{
+ get_option(&str, &start_analyzer_test);
+ return 0;
+}
+early_param("function_prologue_analyzer_test", enable_analyzer_test);
+
+static void __init do_test_function_prologue_analyzer(void)
+{
+ extern unsigned long __start_mcount_loc[];
+ extern unsigned long __stop_mcount_loc[];
+ unsigned long count, i, errors;
+ int print_once;
+
+ count = __stop_mcount_loc - __start_mcount_loc;
+ errors = print_once = 0;
+ for (i = 0; i < count; i++) {
+ unsigned long addr, sp_off, fp_off;
+ int pos;
+ bool check;
+ char buf[60];
+
+ addr = __start_mcount_loc[i];
+ pos = analyze_function_prologue(addr, &sp_off, &fp_off);
+ check = ((pos != 0) || !sp_off || (sp_off <= fp_off));
+ if (check)
+ errors++;
+ if (check || (start_analyzer_test > 1)) {
+ if (!print_once) {
+ pr_debug(" po sp fp symbol\n");
+ pr_debug(" == == == ======\n");
+ print_once++;
+ }
+ sprint_symbol(buf, addr);
+ pr_debug("%5ld: %d 0x%03lx 0x%03lx %s\n",
+ i, pos, sp_off, fp_off, buf);
+ }
+ }
+ pr_debug("function prologue analyzer test: %ld errors\n", errors);
+}
+
+static int __init test_function_prologue_analyzer(void)
+{
+ if (start_analyzer_test)
+ do_test_function_prologue_analyzer();
+ return 0;
+}
+late_initcall(test_function_prologue_analyzer);
#endif /* CONFIG_STACK_TRACER */
#endif
The patch ("arm64: ftrace: add arch-specific stack tracer") introduced a function prologue analyzer. Given that there is no fixed template for a function prologue, at least on gcc for aarch64, a function prologue analyzer may be rather heuristic. So this patch adds a kernel command line option, function_prologue_analyzer_test, in order to run a basic test at startup by executing an analyzer against all the *traceable* functions. For function_prologue_analyzer_test=2, the output looks like: po sp fp symbol == == == ====== 0: 0 0x040 0x000 gic_handle_irq+0x20/0xa4 1: 0 0x040 0x000 gic_handle_irq+0x34/0x114 2: 0 0x030 0x000 run_init_process+0x14/0x48 3: 0 0x020 0x000 try_to_run_init_process+0x14/0x58 4: 0 0x080 0x000 do_one_initcall+0x1c/0x194 ... 22959: 0 0x020 0x000 tty_lock_slave+0x14/0x3c 22960: 0 0x020 0x000 tty_unlock_slave+0x14/0x3c function prologue analyzer test: 0 errors "po" indicates a position of callsite of mcount(), and should be zero if an analyzer has parsed a function prologue successfully and reached a location where fp is properly updated. "sp" is a final offset to a parent's fp at the exit of function prologue. "fp" is also an ofset against sp at the exit of function prologue. So normally, <new sp> = <old fp> + <"sp"> <new fp> = <new sp> - <"fp"> And the last line shows the number of possible errors in the result. For function_prologue_analyzer_test=1, only the last line will be shown. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> --- arch/arm64/kernel/stacktrace.c | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/