3.2-9 - Add unwind-fallback.patch.
This commit is contained in:
parent
b60bd66c70
commit
a1381b8649
@ -74,7 +74,7 @@
|
||||
|
||||
Name: systemtap
|
||||
Version: 3.2
|
||||
Release: 3%{?dist}
|
||||
Release: 9%{?dist}
|
||||
# for version, see also configure.ac
|
||||
|
||||
Patch10: rhbz1504009.patch
|
||||
@ -83,6 +83,10 @@ Patch10: rhbz1504009.patch
|
||||
# upstream: https://sourceware.org/bugzilla/show_bug.cgi?id=22551
|
||||
Patch11: rhbz1546563.patch
|
||||
|
||||
# Partial fix for backstrace issues. Add a new kernel fallback unwinder.
|
||||
# upstream: commit 553b6df07c9b7ab30ed468a6a4374cbdf73d1c0d
|
||||
Patch13: unwind-fallback.patch
|
||||
|
||||
# Packaging abstract:
|
||||
#
|
||||
# systemtap empty req:-client req:-devel
|
||||
@ -487,6 +491,8 @@ cd ..
|
||||
%patch10 -p1
|
||||
%patch11 -p1
|
||||
|
||||
%patch13 -p1
|
||||
|
||||
%build
|
||||
|
||||
%if %{with_bundled_elfutils}
|
||||
@ -1166,6 +1172,9 @@ done
|
||||
|
||||
# PRERELEASE
|
||||
%changelog
|
||||
* Tue Apr 17 2018 Mark Wielaard <mjw@fedoraproject.org> - 3.2-9
|
||||
- Add unwind-fallback.patch.
|
||||
|
||||
* Thu Feb 22 2018 Sergey Avseyev <sergey.avseyev@gmail.com> - 3.2-3
|
||||
- rhbz1546563 (backport fix for removed timers in kernel 4.15)
|
||||
|
||||
|
249
unwind-fallback.patch
Normal file
249
unwind-fallback.patch
Normal file
@ -0,0 +1,249 @@
|
||||
From 553b6df07c9b7ab30ed468a6a4374cbdf73d1c0d Mon Sep 17 00:00:00 2001
|
||||
From: Mark Wielaard <mark@klomp.org>
|
||||
Date: Tue, 17 Apr 2018 14:36:13 +0200
|
||||
Subject: [PATCH] linux runtime: Add support for new kernel unwind fallback.
|
||||
|
||||
In newer kernels dump_trace got replaced by a new unwind infrastructure.
|
||||
Add a new autoconf-unwind-stack-trace.c to detect whether we can use it.
|
||||
Extend the runtime/stack.c _stp_stack_print_fallback with a new pt_regs*
|
||||
argument. Update all callers and add dbug_unwind output to show which
|
||||
fallback unwinder we are selecting (or if we are just giving up).
|
||||
Rename the struct unwind_state in unwind.c and unwind.h to uw_state
|
||||
because the old name now conflicts with the one used in the kernel.
|
||||
---
|
||||
buildrun.cxx | 2 ++
|
||||
runtime/linux/autoconf-unwind-stack-trace.c | 16 +++++++++
|
||||
runtime/stack.c | 50 ++++++++++++++++++++++++++---
|
||||
runtime/unwind.c | 14 ++++----
|
||||
runtime/unwind/unwind.h | 4 +--
|
||||
5 files changed, 72 insertions(+), 14 deletions(-)
|
||||
create mode 100644 runtime/linux/autoconf-unwind-stack-trace.c
|
||||
|
||||
diff --git a/buildrun.cxx b/buildrun.cxx
|
||||
index 403fa71..59b9e88 100644
|
||||
--- a/buildrun.cxx
|
||||
+++ b/buildrun.cxx
|
||||
@@ -365,6 +365,8 @@ compile_pass (systemtap_session& s)
|
||||
"STAPCONF_KERNEL_STACKTRACE", NULL);
|
||||
output_autoconf(s, o, "autoconf-save-stack-trace-no-bp.c",
|
||||
"STAPCONF_KERNEL_STACKTRACE_NO_BP", NULL);
|
||||
+ output_autoconf(s, o, "autoconf-unwind-stack-trace.c",
|
||||
+ "STAPCONF_KERNEL_UNWIND_STACK", NULL);
|
||||
output_autoconf(s, o, "autoconf-asm-syscall.c",
|
||||
"STAPCONF_ASM_SYSCALL_H", NULL);
|
||||
output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL);
|
||||
diff --git a/runtime/linux/autoconf-unwind-stack-trace.c b/runtime/linux/autoconf-unwind-stack-trace.c
|
||||
new file mode 100644
|
||||
index 0000000..2ec399e
|
||||
--- /dev/null
|
||||
+++ b/runtime/linux/autoconf-unwind-stack-trace.c
|
||||
@@ -0,0 +1,16 @@
|
||||
+#include <linux/sched.h>
|
||||
+#include <asm/unwind.h>
|
||||
+
|
||||
+void unwind_stack_trace (void)
|
||||
+{
|
||||
+ struct unwind_state state;
|
||||
+ unwind_start (&state, current, 0, 0);
|
||||
+ while (! unwind_done (&state))
|
||||
+ {
|
||||
+ unsigned long addr = unwind_get_return_address (&state);
|
||||
+ if (addr == 0)
|
||||
+ break;
|
||||
+ unwind_next_frame (&state);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
diff --git a/runtime/stack.c b/runtime/stack.c
|
||||
index c9d2c0c..43f98ef 100644
|
||||
--- a/runtime/stack.c
|
||||
+++ b/runtime/stack.c
|
||||
@@ -43,7 +43,11 @@
|
||||
#include <asm/stacktrace.h>
|
||||
#endif
|
||||
|
||||
-static void _stp_stack_print_fallback(unsigned long, int, int, int);
|
||||
+#if defined(STAPCONF_KERNEL_UNWIND_STACK)
|
||||
+#include <asm/unwind.h>
|
||||
+#endif
|
||||
+
|
||||
+static void _stp_stack_print_fallback(unsigned long, struct pt_regs*, int, int, int);
|
||||
|
||||
#ifdef STP_USE_DWARF_UNWINDER
|
||||
#ifdef STAPCONF_LINUX_UACCESS_H
|
||||
@@ -128,7 +132,7 @@ static const struct stacktrace_ops print_stack_ops = {
|
||||
};
|
||||
|
||||
/* Used for kernel backtrace printing when other mechanisms fail. */
|
||||
-static void _stp_stack_print_fallback(unsigned long stack,
|
||||
+static void _stp_stack_print_fallback(unsigned long stack, struct pt_regs *regs,
|
||||
int sym_flags, int levels, int skip)
|
||||
{
|
||||
struct print_stack_data print_data;
|
||||
@@ -136,20 +140,55 @@ static void _stp_stack_print_fallback(unsigned long stack,
|
||||
print_data.levels = levels;
|
||||
print_data.skip = skip;
|
||||
#if defined(STAPCONF_KERNEL_STACKTRACE)
|
||||
+ dbug_unwind(1, "fallback kernel stacktrace\n");
|
||||
dump_trace(current, NULL, (long *)stack, 0, &print_stack_ops,
|
||||
&print_data);
|
||||
#else
|
||||
/* STAPCONF_KERNEL_STACKTRACE_NO_BP */
|
||||
+ dbug_unwind(1, "fallback kernel stacktrace (no bp)\n");
|
||||
dump_trace(current, NULL, (long *)stack, &print_stack_ops,
|
||||
&print_data);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
-static void _stp_stack_print_fallback(unsigned long s, int v, int l, int k) {
|
||||
+#if defined(STAPCONF_KERNEL_UNWIND_STACK)
|
||||
+static void _stp_stack_print_fallback(unsigned long sp, struct pt_regs *regs,
|
||||
+ int sym_flags,
|
||||
+ int levels, int skip) {
|
||||
+ struct unwind_state state;
|
||||
+ unwind_start (&state, current, regs, (unsigned long *) sp);
|
||||
+ dbug_unwind(1, "fallback kernel stacktrace (unwind)\n");
|
||||
+ while (levels > 0 && ! unwind_done (&state))
|
||||
+ {
|
||||
+ if (skip == 0)
|
||||
+ {
|
||||
+ unsigned long addr = unwind_get_return_address (&state);
|
||||
+ /* When we have frame pointers, the unwind addresses can be
|
||||
+ (mostly) trusted, otherwise it is all guesswork. */
|
||||
+#ifdef CONFIG_FRAME_POINTER
|
||||
+ _stp_print_addr(addr, sym_flags, NULL);
|
||||
+#else
|
||||
+ _stp_print_addr(addr, sym_flags | _STP_SYM_INEXACT, NULL);
|
||||
+#endif
|
||||
+ if (addr == 0)
|
||||
+ break;
|
||||
+ levels--;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ dbug_unwind(1, "skipping frame\n");
|
||||
+ skip--;
|
||||
+ }
|
||||
+ unwind_next_frame(&state);
|
||||
+ }
|
||||
+}
|
||||
+#else /* no new unwind */
|
||||
+static void _stp_stack_print_fallback(unsigned long s, struct pt_regs *r, int v, int l, int k) {
|
||||
/* Don't guess, just give up. */
|
||||
+ dbug_unwind(1, "no fallback kernel stacktrace (giving up)\n");
|
||||
_stp_print_addr(0, v | _STP_SYM_INEXACT, NULL);
|
||||
}
|
||||
-
|
||||
+#endif /* new unwind */
|
||||
#endif /* defined(STAPCONF_KERNEL_STACKTRACE) || defined(STAPCONF_KERNEL_STACKTRACE_NO_BP) */
|
||||
|
||||
|
||||
@@ -382,6 +421,7 @@ static void _stp_stack_kernel_print(struct context *c, int sym_flags)
|
||||
if (l == 0) {
|
||||
remaining = MAXBACKTRACE - n;
|
||||
_stp_stack_print_fallback(UNW_SP(&c->uwcontext_kernel.info),
|
||||
+ &c->uwcontext_kernel.info.regs,
|
||||
sym_flags, remaining, 0);
|
||||
break;
|
||||
} else {
|
||||
@@ -408,7 +448,7 @@ static void _stp_stack_kernel_print(struct context *c, int sym_flags)
|
||||
sp = 0;
|
||||
skip = 5; /* yes, that many framework frames. */
|
||||
#endif
|
||||
- _stp_stack_print_fallback(sp, sym_flags,
|
||||
+ _stp_stack_print_fallback(sp, NULL, sym_flags,
|
||||
MAXBACKTRACE, skip);
|
||||
#else
|
||||
if (sym_flags & _STP_SYM_SYMBOL)
|
||||
diff --git a/runtime/unwind.c b/runtime/unwind.c
|
||||
index ec7cd58..3a2d991 100644
|
||||
--- a/runtime/unwind.c
|
||||
+++ b/runtime/unwind.c
|
||||
@@ -235,7 +235,7 @@ static int parse_fde_cie(const u32 *fde, const u32 *cie,
|
||||
|
||||
#define REG_STATE state->reg[state->stackDepth]
|
||||
|
||||
-static int advance_loc(unsigned long delta, struct unwind_state *state)
|
||||
+static int advance_loc(unsigned long delta, struct uw_state *state)
|
||||
{
|
||||
state->loc += delta * state->codeAlign;
|
||||
dbug_unwind(1, "state->loc=%lx\n", state->loc);
|
||||
@@ -244,7 +244,7 @@ static int advance_loc(unsigned long delta, struct unwind_state *state)
|
||||
|
||||
/* Set Same or Nowhere rule for register. */
|
||||
static void set_no_state_rule(uleb128_t reg, enum item_location where,
|
||||
- struct unwind_state *state)
|
||||
+ struct uw_state *state)
|
||||
{
|
||||
dbug_unwind(1, "reg=%lx, where=%d\n", reg, where);
|
||||
if (reg < ARRAY_SIZE(REG_STATE.regs)) {
|
||||
@@ -254,7 +254,7 @@ static void set_no_state_rule(uleb128_t reg, enum item_location where,
|
||||
|
||||
/* Memory or Value rule */
|
||||
static void set_offset_rule(uleb128_t reg, enum item_location where,
|
||||
- sleb128_t svalue, struct unwind_state *state)
|
||||
+ sleb128_t svalue, struct uw_state *state)
|
||||
{
|
||||
dbug_unwind(1, "reg=%lx, where=%d, svalue=%lx\n", reg, where, svalue);
|
||||
if (reg < ARRAY_SIZE(REG_STATE.regs)) {
|
||||
@@ -265,7 +265,7 @@ static void set_offset_rule(uleb128_t reg, enum item_location where,
|
||||
|
||||
/* Register rule. */
|
||||
static void set_register_rule(uleb128_t reg, uleb128_t value,
|
||||
- struct unwind_state *state)
|
||||
+ struct uw_state *state)
|
||||
{
|
||||
dbug_unwind(1, "reg=%lx, value=%lx\n", reg, value);
|
||||
if (reg < ARRAY_SIZE(REG_STATE.regs)) {
|
||||
@@ -277,7 +277,7 @@ static void set_register_rule(uleb128_t reg, uleb128_t value,
|
||||
/* Expr or ValExpr rule. */
|
||||
static void set_expr_rule(uleb128_t reg, enum item_location where,
|
||||
const u8 **expr, const u8 *end,
|
||||
- struct unwind_state *state)
|
||||
+ struct uw_state *state)
|
||||
{
|
||||
const u8 *const start = *expr;
|
||||
uleb128_t len = get_uleb128(expr, end);
|
||||
@@ -296,7 +296,7 @@ static void set_expr_rule(uleb128_t reg, enum item_location where,
|
||||
#define MAX_CFI 512
|
||||
|
||||
static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
|
||||
- signed ptrType, int user, struct unwind_state *state, int compat_task)
|
||||
+ signed ptrType, int user, struct uw_state *state, int compat_task)
|
||||
{
|
||||
union {
|
||||
const u8 *p8;
|
||||
@@ -1169,7 +1169,7 @@ static int unwind_frame(struct unwind_context *context,
|
||||
unsigned i;
|
||||
signed ptrType = -1, call_frame = 1;
|
||||
uleb128_t retAddrReg = 0;
|
||||
- struct unwind_state *state = &context->state;
|
||||
+ struct uw_state *state = &context->state;
|
||||
unsigned long addr;
|
||||
|
||||
if (unlikely(table_len == 0)) {
|
||||
diff --git a/runtime/unwind/unwind.h b/runtime/unwind/unwind.h
|
||||
index 9d66732..b3ff786 100644
|
||||
--- a/runtime/unwind/unwind.h
|
||||
+++ b/runtime/unwind/unwind.h
|
||||
@@ -492,7 +492,7 @@ struct unwind_reg_state {
|
||||
unsigned cfa_is_expr:1;
|
||||
};
|
||||
|
||||
-struct unwind_state {
|
||||
+struct uw_state {
|
||||
uleb128_t loc;
|
||||
uleb128_t codeAlign;
|
||||
sleb128_t dataAlign;
|
||||
@@ -503,7 +503,7 @@ struct unwind_state {
|
||||
|
||||
struct unwind_context {
|
||||
struct unwind_frame_info info;
|
||||
- struct unwind_state state;
|
||||
+ struct uw_state state;
|
||||
};
|
||||
|
||||
static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
|
||||
--
|
||||
1.8.3.1
|
||||
|
Loading…
Reference in New Issue
Block a user