systemtap/PR24904-changes.patch
2019-08-27 15:45:36 -04:00

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