130 lines
4.5 KiB
Diff
130 lines
4.5 KiB
Diff
From 49fa913a61e7f2941bb59c11d72a1aafa6930162 Mon Sep 17 00:00:00 2001
|
|
From: "Frank Ch. Eigler" <fche@redhat.com>
|
|
Date: Tue, 20 Aug 2019 21:20:40 -0400
|
|
Subject: [PATCH] PR24904: support linux 5.2's stacktrace.c changes
|
|
|
|
The following kernel commit disabled the older struct stack_trace APIs
|
|
on architectures that support the newer stackwalk APIs. Provide an
|
|
adaptation layer to stack_trace_save_regs().
|
|
|
|
commit 214d8ca6ee854f696f75e75511fe66b409e656db
|
|
Author: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Thu Apr 25 11:45:21 2019 +0200
|
|
|
|
stacktrace: Provide common infrastructure
|
|
---
|
|
buildrun.cxx | 2 +
|
|
.../linux/autoconf-stack-trace-save-regs.c | 8 ++++
|
|
runtime/stack.c | 37 +++++++++++++++++--
|
|
3 files changed, 44 insertions(+), 3 deletions(-)
|
|
create mode 100644 runtime/linux/autoconf-stack-trace-save-regs.c
|
|
|
|
diff --git a/buildrun.cxx b/buildrun.cxx
|
|
index 5e8d3b961..6ed744707 100644
|
|
--- a/buildrun.cxx
|
|
+++ b/buildrun.cxx
|
|
@@ -485,6 +485,8 @@ compile_pass (systemtap_session& s)
|
|
output_autoconf(s, o, "autoconf-bio-bi_opf.c", "STAPCONF_BIO_BI_OPF", NULL);
|
|
output_autoconf(s, o, "autoconf-linux-sched_headers.c",
|
|
"STAPCONF_LINUX_SCHED_HEADERS", NULL);
|
|
+ output_autoconf(s, o, "autoconf-stack-trace-save-regs.c",
|
|
+ "STAPCONF_STACK_TRACE_SAVE_REGS", NULL);
|
|
|
|
// used by runtime/linux/netfilter.c
|
|
output_exportconf(s, o, "nf_register_hook", "STAPCONF_NF_REGISTER_HOOK");
|
|
diff --git a/runtime/linux/autoconf-stack-trace-save-regs.c b/runtime/linux/autoconf-stack-trace-save-regs.c
|
|
new file mode 100644
|
|
index 000000000..8bf33391f
|
|
--- /dev/null
|
|
+++ b/runtime/linux/autoconf-stack-trace-save-regs.c
|
|
@@ -0,0 +1,8 @@
|
|
+#include <linux/stacktrace.h>
|
|
+
|
|
+unsigned int foo ()
|
|
+{
|
|
+ unsigned long e[10];
|
|
+ struct pt_regs* r = 0;
|
|
+ return stack_trace_save_regs (r, & e[0], 10, 0);
|
|
+}
|
|
diff --git a/runtime/stack.c b/runtime/stack.c
|
|
index 0f649e8da..bf59b2909 100644
|
|
--- a/runtime/stack.c
|
|
+++ b/runtime/stack.c
|
|
@@ -39,6 +39,7 @@
|
|
#include "linux/uprobes-inc.h"
|
|
|
|
#include <linux/stacktrace.h>
|
|
+
|
|
#if defined(STAPCONF_KERNEL_STACKTRACE) || defined(STAPCONF_KERNEL_STACKTRACE_NO_BP)
|
|
#include <asm/stacktrace.h>
|
|
#endif
|
|
@@ -47,6 +48,20 @@
|
|
#include <asm/unwind.h>
|
|
#endif
|
|
|
|
+#if defined(STAPCONF_STACK_TRACE_SAVE_REGS) /* linux 5.2+ apprx. */
|
|
+static __typeof__(stack_trace_save_regs) (*stack_trace_save_regs_fn); /* not exported */
|
|
+
|
|
+static int
|
|
+_stp_init_stack(void)
|
|
+{
|
|
+ stack_trace_save_regs_fn = (void*) kallsyms_lookup_name("stack_trace_save_regs");
|
|
+ dbug_unwind(1, "stack_trace_saves_regs_fn=%lx for _stp_stack_print_fallback().\n",
|
|
+ (unsigned long) save_trace_save_regs_fn);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#else /* ! STAPCONF_STACK_TRACE_SAVE_REGS */
|
|
+
|
|
static void (*(save_stack_trace_regs_fn))(struct pt_regs *regs,
|
|
struct stack_trace *trace);
|
|
|
|
@@ -60,6 +75,10 @@ _stp_init_stack(void)
|
|
return 0;
|
|
}
|
|
|
|
+#endif /* STAPCONF_STACK_TRACE_SAVE_REGS */
|
|
+
|
|
+
|
|
+
|
|
static void _stp_stack_print_fallback(unsigned long, struct pt_regs*, int, int, int);
|
|
|
|
#ifdef STP_USE_DWARF_UNWINDER
|
|
@@ -168,9 +187,19 @@ static void _stp_stack_print_fallback(unsigned long sp, struct pt_regs *regs,
|
|
int sym_flags,
|
|
int levels, int skip) {
|
|
unsigned long entries[MAXBACKTRACE];
|
|
- struct stack_trace trace;
|
|
- int i;
|
|
+ unsigned i;
|
|
+ unsigned num_entries;
|
|
+
|
|
+#if defined(STAPCONF_STACK_TRACE_SAVE_REGS) /* linux 5.2+ apprx. */
|
|
+ if (!stack_trace_save_regs_fn) {
|
|
+ dbug_unwind(1, "no fallback kernel stacktrace (giving up)\n");
|
|
+ _stp_print_addr(0, sym_flags | _STP_SYM_INEXACT, NULL);
|
|
+ return;
|
|
+ }
|
|
|
|
+ num_entries = (*stack_trace_save_regs_fn)(regs, &entries[0], MAXBACKTRACE, skip);
|
|
+#else
|
|
+ struct stack_trace trace;
|
|
/* If don't have save_stack_trace_regs unwinder, just give up. */
|
|
if (!save_stack_trace_regs_fn) {
|
|
dbug_unwind(1, "no fallback kernel stacktrace (giving up)\n");
|
|
@@ -189,9 +218,11 @@ static void _stp_stack_print_fallback(unsigned long sp, struct pt_regs *regs,
|
|
dbug_unwind(1, "trace.nr_entries: %d\n", trace.nr_entries);
|
|
dbug_unwind(1, "trace.max_entries: %d\n", trace.max_entries);
|
|
dbug_unwind(1, "trace.skip %d\n", trace.skip);
|
|
+ num_entries = trace.nr_entries;
|
|
+#endif
|
|
|
|
/* save_stack_trace_reg() adds a ULONG_MAX after last valid entry. Ignore it. */
|
|
- for (i=0; i<MAXBACKTRACE && i<trace.nr_entries && entries[i]!=ULONG_MAX; ++i) {
|
|
+ for (i=0; i<MAXBACKTRACE && i<num_entries && entries[i]!=ULONG_MAX; ++i) {
|
|
/* When we have frame pointers, the unwind addresses can be
|
|
(mostly) trusted, otherwise it is all guesswork. */
|
|
#ifdef CONFIG_FRAME_POINTER
|
|
--
|
|
2.21.0
|
|
|