@@ -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>
@@ -101,7 +102,7 @@ static int analyze_function_prologue(unsigned long pc,
/* exiting a basic block */
goto out;
- if (aarch64_insn_decode_add_sub_imm(insn, &dst, &src,
+ if (!aarch64_insn_extract_add_sub_imm(insn, &dst, &src,
&imm, &variant, &adsb_type)) {
if ((adsb_type == AARCH64_INSN_ADSB_SUB) &&
(dst == AARCH64_INSN_REG_SP) &&
@@ -129,7 +130,7 @@ static int analyze_function_prologue(unsigned long pc,
break;
}
- } else if (aarch64_insn_decode_load_store_pair(insn,
+ } else if (!aarch64_insn_extract_load_store_pair(insn,
®1, ®2, &base, &imm,
&variant, &ldst_type)) {
if ((ldst_type ==
@@ -146,7 +147,7 @@ static int analyze_function_prologue(unsigned long pc,
pos = 3;
*size += -imm;
} else if ((ldst_type ==
- AARCH64_INSN_LDST_STORE_PAIR) &&
+ AARCH64_INSN_LDST_STORE_PAIR_REG_OFFSET) &&
(reg1 == AARCH64_INSN_REG_29) &&
(reg2 == AARCH64_INSN_REG_30) &&
(base == AARCH64_INSN_REG_SP)) {
@@ -348,5 +349,57 @@ 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 %s\n",
+ i, pos, sp_off, fp_off,
+ check ? "NG" : "OK", 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