From nobody Fri Dec 19 19:19:24 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 355442185B1 for ; Wed, 9 Jul 2025 21:26:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096366; cv=none; b=HkSQj+lBoWsSuBkRrxfjqxybwVFh6UoF4uKX3AmayKFduKcgo73dty+PtOgx2VWWMGHkctlFdwMaKC77CgBvEwLel3B+P9TPC6XwgZH7jbZXPTgpisxPl78h0B7/JALHhznNZgnxUuH8NC8HJXpWPeJjBogKJ9iavlIoKJy4cvc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096366; c=relaxed/simple; bh=cLPgqH2KUraiMJyagQJzNxidnpkhJsY9buyg4sM+lSg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sOFW+cW7caoB68LYsr7trTb1Ky7KX6Ox5pWg5n13PDZE52zS1QDTR/3bX/rDJcvPAFIEdmzpIRE/VpF/mre+ok1h3+WHeyRFsW0IH2QsySB7Ih5VO6E7J+F7qCdXSp8Es4i0+1I5B9wmJu0HffTePLybtcsZExUAFBm+PQuNjBQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=LojVS4EK; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="LojVS4EK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752096362; bh=cLPgqH2KUraiMJyagQJzNxidnpkhJsY9buyg4sM+lSg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LojVS4EKLYmabGbYuUsLwEBtIM76uMKnbb3Ide7fLbo9Rt2w8sdU4aZphq/ivKMvW i3ZxaE2wV9vvKPN4MTP2miUnFqg0J6EfDckL5JrJiCQ7v4K/rD+BduVITu2bY6jBok Ldl9a+H+TczqndLu7bVKQKVghlMQtN483otFo1YSRcdEaEFW7RFumzKGMZUH0fC6kc yBvxhmcMergr/s5jRdJUWktfaeK6sDaSCwcYw39FdPd4VNLyEhb4dSg6ry0dsAX0Vs Y3fB5Tc5UUZKXCs/RPWWNDwZayW4Uq5w8DJqBvDBjyqlChtHYrcaoOAB9fufIWdsEn OaSe+NTVZAgNQ== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bcrcn6BWGzQ0D; Wed, 9 Jul 2025 17:26:01 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton Subject: [RFC PATCH 1/5] unwind_user: Fix userspace unwind iterator 32-bit compat handling Date: Wed, 9 Jul 2025 17:25:48 -0400 Message-ID: <20250709212556.32777-2-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> References: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor the stack unwind iterator to clean the overall design and fix 32-bit compat corner-cases that arise due to confusion over the semantic of the struct unwind_user_state type field. Observed Issue =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Before this refactor, the struct unwind_user_state type field identifies: - Whether sframe is available in the current process, for at least portions of the address space, - Whether frame pointers should be used for stack walk, - Whether frame pointers should be used for stack walk in a 32-bit compat process. It would be natural for the unwind iterator caller to expect the "state->type" to contain the type of stack walk operation performed for the most recent unwind iteration (unwind_user_next()), but it actually acts as an internal cache and is unrelated to the current iteration, which makes this field confusing. It is not only confusing to the caller, but also to the implementation of unwind_user_next(). Is has the following drawbacks: - A 32-bit compat process will favor using frame pointers rather than sframe for its next unwind iterator, which is an unexpected priority order because sframe is more accurate than frame pointers when available. - Because the "UNWIND_USER_TYPE_SFRAME" state type is unaware of 32-bit compat, handling of sframe would be broken on 32-bit compat because compat_fp_state() would return false, thus expecting 64-bit unsigned long types. Moreover, only IA32 compat emulation is supported. x32 support appears to be missing. Cause =3D=3D=3D=3D=3D Associating a semantic to a single enumeration field that consists of: - many orthogonal properties, without listing all those properties (sframe vs frame pointer, compat vs non-compat) within each of the enumeration labels, - an implicit priority, leads to confusion in the unwind iterator implementation. Using ifdef based on CONFIG_IA32_EMULATION and re-implementing a custom "in_compat_mode" rather than using the pre-existing in_compat_syscall() contributes to mishandling of x32 binaries. Solution =3D=3D=3D=3D=3D=3D=3D=3D Split this type field into three fields: - A "current_type" field, which can be queried by the iterator caller and by architecture code to learn which method is used for the current unwind iteration, - An "available_types" field, which is a bitmask of available user types. It is used internally by the iterator implementation. - A "compat" field to track whether the unwind targets a 32-bit compat process. This allows removing the "UNWIND_USER_TYPE_COMPAT_FP" label from the unwind types, since it is now implicitly taken into account by the "compat" field. This approach will also make it easier to introduce new unwind types in the future, such as an unwinder for JIT code. Also use CONFIG_COMPAT ifdef rather than CONFIG_IA32_EMULATION, and remove the in_compat_mode() custom macro in favor of in_compat_syscall(). This aims to fix x32 support. Known Drawbacks =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D None. [ This is based on linux-trace unwind/sframe ] Fixes: 1abc29eeca39 ("unwind_user/sframe: Wire up unwind_user to sframe") Fixes: ce8d69a1a578 ("unwind_user/x86: Enable compat mode frame pointer unw= inding on x86") Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- arch/Kconfig | 4 - arch/x86/Kconfig | 1 - arch/x86/include/asm/unwind_user.h | 9 +- arch/x86/include/asm/unwind_user_types.h | 4 +- arch/x86/kernel/stacktrace.c | 6 +- include/linux/unwind_user.h | 9 -- include/linux/unwind_user_types.h | 25 ++++- kernel/unwind/user.c | 137 +++++++++++++---------- 8 files changed, 109 insertions(+), 86 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 86eec85cb898..c2f12135db92 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -442,10 +442,6 @@ config HAVE_UNWIND_USER_FP bool select UNWIND_USER =20 -config HAVE_UNWIND_USER_COMPAT_FP - bool - depends on HAVE_UNWIND_USER_FP - config HAVE_UNWIND_USER_SFRAME bool select UNWIND_USER diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8a382a6b9be3..05dbfa3eb8ea 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -302,7 +302,6 @@ config X86 select HAVE_SYSCALL_TRACEPOINTS select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL select HAVE_UNSTABLE_SCHED_CLOCK - select HAVE_UNWIND_USER_COMPAT_FP if IA32_EMULATION select HAVE_UNWIND_USER_FP if X86_64 select HAVE_UNWIND_USER_SFRAME if X86_64 select HAVE_USER_RETURN_NOTIFIER diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwi= nd_user.h index 19634a73612d..77f7af37aa82 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -3,6 +3,7 @@ #define _ASM_X86_UNWIND_USER_H =20 #include +#include =20 #define ARCH_INIT_USER_FP_FRAME \ .cfa_off =3D (s32)sizeof(long) * 2, \ @@ -10,7 +11,7 @@ .fp_off =3D (s32)sizeof(long) * -2, \ .use_fp =3D true, =20 -#ifdef CONFIG_IA32_EMULATION +#ifdef CONFIG_COMPAT =20 #define ARCH_INIT_USER_COMPAT_FP_FRAME \ .cfa_off =3D (s32)sizeof(u32) * 2, \ @@ -18,14 +19,12 @@ .fp_off =3D (s32)sizeof(u32) * -2, \ .use_fp =3D true, =20 -#define in_compat_mode(regs) !user_64bit_mode(regs) - void arch_unwind_user_init(struct unwind_user_state *state, struct pt_regs *regs); =20 static inline void arch_unwind_user_next(struct unwind_user_state *state) { - if (state->type !=3D UNWIND_USER_TYPE_COMPAT_FP) + if (!in_compat_syscall()) return; =20 state->ip +=3D state->arch.cs_base; @@ -35,7 +34,7 @@ static inline void arch_unwind_user_next(struct unwind_us= er_state *state) #define arch_unwind_user_init arch_unwind_user_init #define arch_unwind_user_next arch_unwind_user_next =20 -#endif /* CONFIG_IA32_EMULATION */ +#endif /* CONFIG_COMPAT */ =20 #include =20 diff --git a/arch/x86/include/asm/unwind_user_types.h b/arch/x86/include/as= m/unwind_user_types.h index f93d535f900e..7b940520659e 100644 --- a/arch/x86/include/asm/unwind_user_types.h +++ b/arch/x86/include/asm/unwind_user_types.h @@ -2,7 +2,7 @@ #ifndef _ASM_X86_UNWIND_USER_TYPES_H #define _ASM_X86_UNWIND_USER_TYPES_H =20 -#ifdef CONFIG_IA32_EMULATION +#ifdef CONFIG_COMPAT =20 struct arch_unwind_user_state { unsigned long ss_base; @@ -10,7 +10,7 @@ struct arch_unwind_user_state { }; #define arch_unwind_user_state arch_unwind_user_state =20 -#endif /* CONFIG_IA32_EMULATION */ +#endif /* CONFIG_COMPAT */ =20 #include =20 diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index 8ef9d8c71df9..396897851b00 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c @@ -131,13 +131,13 @@ void arch_stack_walk_user(stack_trace_consume_fn cons= ume_entry, void *cookie, } } =20 -#ifdef CONFIG_IA32_EMULATION +#ifdef CONFIG_COMPAT void arch_unwind_user_init(struct unwind_user_state *state, struct pt_regs *regs) { unsigned long cs_base, ss_base; =20 - if (state->type !=3D UNWIND_USER_TYPE_COMPAT_FP) + if (user_64bit_mode(regs)) return; =20 cs_base =3D insn_get_seg_base(regs, INAT_SEG_REG_CS); @@ -155,4 +155,4 @@ void arch_unwind_user_init(struct unwind_user_state *st= ate, state->sp +=3D ss_base; state->fp +=3D ss_base; } -#endif /* CONFIG_IA32_EMULATION */ +#endif /* CONFIG_COMPAT */ diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h index 8a4af0214ecb..0308adb349fc 100644 --- a/include/linux/unwind_user.h +++ b/include/linux/unwind_user.h @@ -5,15 +5,6 @@ #include #include =20 -#ifndef ARCH_INIT_USER_FP_FRAME - #define ARCH_INIT_USER_FP_FRAME -#endif - -#ifndef ARCH_INIT_USER_COMPAT_FP_FRAME - #define ARCH_INIT_USER_COMPAT_FP_FRAME - #define in_compat_mode(regs) false -#endif - /* * If an architecture needs to initialize the state for a specific * reason, for example, it may need to do something different diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 4d50476e950e..fc440ae3a29b 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -9,11 +9,23 @@ struct arch_unwind_user_state {}; #endif =20 + +/* + * unwind types, listed in priority order: lower numbers are attempted fir= st if + * available. + */ +enum unwind_user_type_bits { + UNWIND_USER_TYPE_SFRAME_BIT =3D 0, + UNWIND_USER_TYPE_FP_BIT =3D 1, + + _NR_UNWIND_USER_TYPE_BITS, +}; + enum unwind_user_type { - UNWIND_USER_TYPE_NONE, - UNWIND_USER_TYPE_FP, - UNWIND_USER_TYPE_COMPAT_FP, - UNWIND_USER_TYPE_SFRAME, + /* Type "none" for the start of stack walk iteration. */ + UNWIND_USER_TYPE_NONE =3D 0, + UNWIND_USER_TYPE_SFRAME =3D (1U << UNWIND_USER_TYPE_SFRAME_BIT), + UNWIND_USER_TYPE_FP =3D (1U << UNWIND_USER_TYPE_FP_BIT), }; =20 struct unwind_stacktrace { @@ -33,7 +45,10 @@ struct unwind_user_state { unsigned long sp; unsigned long fp; struct arch_unwind_user_state arch; - enum unwind_user_type type; + /* Unwind time used for the most recent unwind traversal iteration. */ + enum unwind_user_type current_type; + /* Unwind types available in the current context. Bitmask of enum unwind_= user_type. */ + unsigned int available_types; bool done; }; =20 diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 6e7ca9f1293a..349bdd72390b 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -8,75 +8,48 @@ #include #include #include +#include =20 static struct unwind_user_frame fp_frame =3D { ARCH_INIT_USER_FP_FRAME }; =20 +#ifdef CONFIG_COMPAT static struct unwind_user_frame compat_fp_frame =3D { ARCH_INIT_USER_COMPAT_FP_FRAME }; +#endif =20 -static inline bool fp_state(struct unwind_user_state *state) +static struct unwind_user_frame *get_fp_frame(void) { - return IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP) && - state->type =3D=3D UNWIND_USER_TYPE_FP; +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + return &compat_fp_frame; +#endif + return &fp_frame; } =20 #define for_each_user_frame(state) \ for (unwind_user_start(state); !(state)->done; unwind_user_next(state)) =20 -static inline bool compat_fp_state(struct unwind_user_state *state) -{ - return IS_ENABLED(CONFIG_HAVE_UNWIND_USER_COMPAT_FP) && - state->type =3D=3D UNWIND_USER_TYPE_COMPAT_FP; -} - -static inline bool sframe_state(struct unwind_user_state *state) -{ - return IS_ENABLED(CONFIG_HAVE_UNWIND_USER_SFRAME) && - state->type =3D=3D UNWIND_USER_TYPE_SFRAME; -} - -#define unwind_get_user_long(to, from, state) \ +#define unwind_get_user_long(to, from) \ ({ \ int __ret; \ - if (compat_fp_state(state)) \ + if (in_compat_syscall()) \ __ret =3D get_user(to, (u32 __user *)(from)); \ else \ __ret =3D get_user(to, (unsigned long __user *)(from)); \ __ret; \ }) =20 -static int unwind_user_next(struct unwind_user_state *state) +static int unwind_user_next_common(struct unwind_user_state *state, struct= unwind_user_frame *frame) { - struct unwind_user_frame *frame; - struct unwind_user_frame _frame; - unsigned long cfa =3D 0, fp, ra =3D 0; + unsigned long cfa, fp, ra =3D 0; unsigned int shift; =20 - if (state->done) - return -EINVAL; - - if (compat_fp_state(state)) { - frame =3D &compat_fp_frame; - } else if (sframe_state(state)) { - /* sframe expects the frame to be local storage */ - frame =3D &_frame; - if (sframe_find(state->ip, frame)) { - if (!IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) - goto done; - frame =3D &fp_frame; - } - } else if (fp_state(state)) { - frame =3D &fp_frame; - } else { - goto done; - } - if (frame->use_fp) { if (state->fp < state->sp) - goto done; + return -EINVAL; cfa =3D state->fp; } else { cfa =3D state->sp; @@ -87,30 +60,84 @@ static int unwind_user_next(struct unwind_user_state *s= tate) =20 /* stack going in wrong direction? */ if (cfa <=3D state->sp) - goto done; + return -EINVAL; =20 /* Make sure that the address is word aligned */ - shift =3D sizeof(long) =3D=3D 4 || compat_fp_state(state) ? 2 : 3; + shift =3D (sizeof(long) =3D=3D 4 || in_compat_syscall()) ? 2 : 3; if ((cfa + frame->ra_off) & ((1 << shift) - 1)) - goto done; + return -EINVAL; =20 /* Find the Return Address (RA) */ - if (unwind_get_user_long(ra, cfa + frame->ra_off, state)) - goto done; + if (unwind_get_user_long(ra, cfa + frame->ra_off)) + return -EINVAL; =20 - if (frame->fp_off && unwind_get_user_long(fp, cfa + frame->fp_off, state)) - goto done; + if (frame->fp_off && unwind_get_user_long(fp, cfa + frame->fp_off)) + return -EINVAL; =20 state->ip =3D ra; state->sp =3D cfa; if (frame->fp_off) state->fp =3D fp; + return 0; +} =20 - arch_unwind_user_next(state); +static int unwind_user_next_sframe(struct unwind_user_state *state) +{ + struct unwind_user_frame _frame, *frame; + + /* sframe expects the frame to be local storage */ + frame =3D &_frame; + if (sframe_find(state->ip, frame)) + return -ENOENT; + return unwind_user_next_common(state, frame); +} =20 +static int unwind_user_next_fp(struct unwind_user_state *state) +{ + return unwind_user_next_common(state, get_fp_frame()); +} + +static int unwind_user_next(struct unwind_user_state *state) +{ + unsigned long iter_mask =3D state->available_types; + unsigned int bit; + + if (state->done) + return -EINVAL; + + for_each_set_bit(bit, &iter_mask, _NR_UNWIND_USER_TYPE_BITS) { + enum unwind_user_type type =3D 1U << bit; + + state->current_type =3D type; + switch (type) { + case UNWIND_USER_TYPE_SFRAME: + switch (unwind_user_next_sframe(state)) { + case 0: + goto end; + case -ENOENT: + continue; /* Try next method. */ + default: + goto done; + } + case UNWIND_USER_TYPE_FP: + if (!unwind_user_next_fp(state)) + goto end; + else + goto done; + case UNWIND_USER_TYPE_NONE: + break; + } + } + + /* No successful unwind method. */ + goto done; + +end: + arch_unwind_user_next(state); return 0; =20 done: + state->current_type =3D UNWIND_USER_TYPE_NONE; state->done =3D true; return -EINVAL; } @@ -126,14 +153,10 @@ static int unwind_user_start(struct unwind_user_state= *state) return -EINVAL; } =20 - if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_COMPAT_FP) && in_compat_mode(regs)) - state->type =3D UNWIND_USER_TYPE_COMPAT_FP; - else if (current_has_sframe()) - state->type =3D UNWIND_USER_TYPE_SFRAME; - else if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) - state->type =3D UNWIND_USER_TYPE_FP; - else - state->type =3D UNWIND_USER_TYPE_NONE; + if (current_has_sframe()) + state->available_types |=3D UNWIND_USER_TYPE_SFRAME; + if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) + state->available_types |=3D UNWIND_USER_TYPE_FP; =20 state->ip =3D instruction_pointer(regs); state->sp =3D user_stack_pointer(regs); --=20 2.43.0 From nobody Fri Dec 19 19:19:24 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 985E7224AFE for ; Wed, 9 Jul 2025 21:26:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096365; cv=none; b=MAV135Pewp59VFC8djEUb80OZWV70ZnUN+z59BlIxb1eCq0opnZ0ywpGt4ImCyvd8siuZK2vhmLBIbOv6xKWIjkzSAf63ddZtt5pqEOjeOj0JnhmDxcNu4W+40HE913Xlc5xlKGWP2K+NhbsAgfkkBnfhv6jFPwhCophcg1Vz/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096365; c=relaxed/simple; bh=oFxa3EjcmepwUoJqmS6o0GfY5UgZGIQ3GJHwYb45pbw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Nc8TIHJfBHRT4f3wHaO3rAfhebxJkTuaog105xthHkf5MHx5Yt0uZEWMTiKvBabmHaORv7IIsIo1c2DyTdizoA1To3jm2Yv1Q67vlF89UB95svSTo1jozl/YVuP9dmsuulN2p26iO1GDRJl9PTEW8it+dF0xO1OSBBZwZBnD//M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=VFsJbXHf; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="VFsJbXHf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752096362; bh=oFxa3EjcmepwUoJqmS6o0GfY5UgZGIQ3GJHwYb45pbw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VFsJbXHfmkX50tbppWYXx7Y6RL91yRsyRTc9WvtrCWmDIYEVRnGzZ9ZLOG7GW5y4U uuM1IXu2y2h15Rw6vZERbbB6pulM+aFyNPRf2CmP3NAyZdK8j894PW7p151brtjhM/ mjOwm5l/A02u1dERcDr+pFzo3OXf1megs4KFaDfxBI43jYt9c4fIXcxXfuI5q3fvJ2 nYZAIX+4WqDfxEVrbPGxM5/T9Fmm3LoAhvAt8OWbX2EIYw502T7A7m/K4y8tflzg+P 8UqSXBQIIwgDomXZ1O4LqE7egBaj0knb/tj86f7VdMEnOHP/lsSQ0op7WizwB5/n/m +Hi+RPDpmmHGA== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bcrcp1lM6zQ0F; Wed, 9 Jul 2025 17:26:02 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton Subject: [RFC PATCH 2/5] unwind: Export unwind_user symbol to GPL modules Date: Wed, 9 Jul 2025 17:25:49 -0400 Message-ID: <20250709212556.32777-3-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> References: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the unwind_user symbol to be used by GPL modules, for instance LTTng. Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- kernel/unwind/user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 349bdd72390b..9aefbfc8427a 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -187,3 +187,4 @@ int unwind_user(struct unwind_stacktrace *trace, unsign= ed int max_entries) =20 return 0; } +EXPORT_SYMBOL_GPL(unwind_user); --=20 2.43.0 From nobody Fri Dec 19 19:19:24 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B95BD230BC9 for ; Wed, 9 Jul 2025 21:26:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096365; cv=none; b=nwODXVr06kygY5dYdZtJOUUGjKBnVv8s4i8Y6JyT7zzOfxhce6HU2NpaaRQA5n0djqwTU2NBMEUYPcXQG+npKflI4q3ZyOmCbea/P9LalWMrs8TTt/leaK/2Vcig9bioVRab0i0juojUv/hmAdE/8QUn+8PwO4YMoFcjXxhbODU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096365; c=relaxed/simple; bh=iauZL9jmjufsByEqjLynOS/a/I/93HipMuGHw4CkAUk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JZh3binjpqhUlOBoNDnQnWscr2iO/zQ2tqHqYLkC+t5k3aJGpSM/FeLDbvkvjjaxo9Vg9HvTCROA6JfgU7UxqjKDemWTcz4pwLautKTFZn+Y/ernZDccOcU/VALiy6wtBXX5wk/E7ZkVqtryFPgwsIGCRrpTH2F7EdVRN1Kt574= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=fKQgKrKb; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="fKQgKrKb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752096362; bh=iauZL9jmjufsByEqjLynOS/a/I/93HipMuGHw4CkAUk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fKQgKrKbHnseUqsqLWBsQJMsXUQvKuXRe7UYe16qIO7Nq9lmpXwIEHBrc+pqUCB92 CwJ+oEGkRNC2vcfWS+JYsoXSc1kQRKBBoPRoqud0+XGeMQoD5410XhvUF6kdB1AMhk oFaPAmAa0RYJ6IjVi6ojH+qtnT3BtrC2QpSmWCxp9ooWeBjXfL3FctqeRp48Pa4ZiV KWphDqIT1nwUEixM6cQyMLjfL4+Icp4AUkMkDcORVSNO1Aowp/4qoKs7wTk9P8jM+b 9pLDOtWjXbc6ghAHJFTUdq5bUSaXpI3NV/AUvwkSjd6cvve6jl9nbnMPm5pLVkjW8N D9H41DxbioF+g== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bcrcp4QsSzPN5; Wed, 9 Jul 2025 17:26:02 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton Subject: [RFC PATCH 3/5] unwind deferred: Introduce unwind_user_trace_cached Date: Wed, 9 Jul 2025 17:25:50 -0400 Message-ID: <20250709212556.32777-4-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> References: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce unwind_user_trace_cached which copies the stack trace if it was previously stored into the cache since the last reset of the cache. The expected use-case is sampling a stack trace from a faultable context at system call entry (coping it into the cache), and then copying the stack trace from the cache from non-faultable context to a ring buffer. Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- include/linux/unwind_deferred.h | 2 ++ kernel/unwind/deferred.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/linux/unwind_deferred.h b/include/linux/unwind_deferre= d.h index a9d5b100d6b2..ddc985ba982a 100644 --- a/include/linux/unwind_deferred.h +++ b/include/linux/unwind_deferred.h @@ -34,6 +34,7 @@ void unwind_task_init(struct task_struct *task); void unwind_task_free(struct task_struct *task); =20 int unwind_user_faultable(struct unwind_stacktrace *trace); +int unwind_user_trace_cached(struct unwind_stacktrace *trace); =20 int unwind_deferred_init(struct unwind_work *work, unwind_callback_t func); int unwind_deferred_request(struct unwind_work *work, u64 *cookie); @@ -67,6 +68,7 @@ static inline void unwind_task_init(struct task_struct *t= ask) {} static inline void unwind_task_free(struct task_struct *task) {} =20 static inline int unwind_user_faultable(struct unwind_stacktrace *trace) {= return -ENOSYS; } +static inline int unwind_user_trace_cached(struct unwind_stacktrace *trace= ) { return -ENOSYS; } static inline int unwind_deferred_init(struct unwind_work *work, unwind_ca= llback_t func) { return -ENOSYS; } static inline int unwind_deferred_request(struct unwind_work *work, u64 *t= imestamp) { return -ENOSYS; } static inline void unwind_deferred_cancel(struct unwind_work *work) {} diff --git a/kernel/unwind/deferred.c b/kernel/unwind/deferred.c index 039e12700d49..02ab1d2afc21 100644 --- a/kernel/unwind/deferred.c +++ b/kernel/unwind/deferred.c @@ -145,6 +145,37 @@ int unwind_user_faultable(struct unwind_stacktrace *tr= ace) =20 return 0; } +EXPORT_SYMBOL_GPL(unwind_user_faultable); + +/** + * unwind_user_trace_cached - Copy user stack trace from cache + * @trace: The descriptor that will store the user stacktrace + * + * Copy user stack trace from cache if the cache was populated by + * unwind_user_faultable prior to this call. The returned trace + * entries are only valid until the cache is reset. + * + * Return: 0 on success and negative on error + * On success @trace will contain the user space stacktrace + */ +int unwind_user_trace_cached(struct unwind_stacktrace *trace) +{ + struct unwind_task_info *info =3D ¤t->unwind_info; + struct unwind_cache *cache; + + if (!current->mm) + return -EINVAL; + + cache =3D info->cache; + if (!cache || !cache->nr_entries) + return -ENOENT; + + trace->nr =3D cache->nr_entries; + trace->entries =3D cache->entries; + + return 0; +} +EXPORT_SYMBOL_GPL(unwind_user_trace_cached); =20 static void process_unwind_deferred(struct task_struct *task) { --=20 2.43.0 From nobody Fri Dec 19 19:19:24 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6135D23AB86 for ; Wed, 9 Jul 2025 21:26:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096366; cv=none; b=EghNs/fWCzlPi4nzZZkZK+jE0AtaCpEbqpIROeujP3f1jBzn4mOm3bJ7zy7s+jsmeT7gh924sh9tAnNyMyPOz4HA9Os5LQnHv556RGOQL/A7v04uAW+G0Nv+/Y2hHJeEjYn1mqVic55OWhmAqIlJWEKOnXRVqkriiO9LacsBRW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096366; c=relaxed/simple; bh=JN5RMLEHICyZc002MuT4nzGEIbF38xkIf26bUm21Crg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ecQgUvjH9n1NhnbGXKU+sjhGh9QZEME7mwOouD2Viizn6fC608NXqbcHfNQGHQgFztKLbPjpgSxcBEji919rAkw5KAT7v1+6pok/HKcht9rb+5L5nLGuI7fjlPjEULdpkw076gH+eWv25jE03kh3wmi16fBaX4zAbXfi1jbnvsQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=lvpU8+xU; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="lvpU8+xU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752096363; bh=JN5RMLEHICyZc002MuT4nzGEIbF38xkIf26bUm21Crg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lvpU8+xUOBSKkTMNHciLOHamjL6925svjwq4kcre0mVqqgN+xr2DL6eoO7fIWtVQf yK82deWLKMY36usGcisC8XcDNexwEUTdrh2M2zmZcIRP5JZqJLQ6CUSUFNnlZJ2p1J x8x4NFSmQOXEgg5uuv5JNBtUappKTG4/+BxhXUIOuMuc6iMSlOXLh2cJFH9Wz+Z5aH XuAj6nKVypKU/6ppm5tqt2pmwIWNcE1Rj00x9ar8wOZhpfpEOnjvxY8kVLqmMGlmOr wYMMc7QX7nKi4IGLECKaUNmgs1HVlXGZK+wpqOb8QbIqUj2kI+JgfAsegqGBPJnCDH hOKcpZKPlJKXA== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bcrcq03JxzPN6; Wed, 9 Jul 2025 17:26:02 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton Subject: [RFC PATCH 4/5] unwind: Rename unwind_stacktrace to unwind_user_stacktrace Date: Wed, 9 Jul 2025 17:25:51 -0400 Message-ID: <20250709212556.32777-5-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> References: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rename the unwind_stacktrace structure to unwind_user_stacktrace to make it consistent with the rest of the API. Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- include/linux/unwind_deferred.h | 10 +++++----- include/linux/unwind_user.h | 2 +- include/linux/unwind_user_types.h | 2 +- kernel/unwind/deferred.c | 6 +++--- kernel/unwind/user.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/linux/unwind_deferred.h b/include/linux/unwind_deferre= d.h index ddc985ba982a..62f1faf5f2b8 100644 --- a/include/linux/unwind_deferred.h +++ b/include/linux/unwind_deferred.h @@ -8,7 +8,7 @@ =20 struct unwind_work; =20 -typedef void (*unwind_callback_t)(struct unwind_work *work, struct unwind_= stacktrace *trace, u64 cookie); +typedef void (*unwind_callback_t)(struct unwind_work *work, struct unwind_= user_stacktrace *trace, u64 cookie); =20 struct unwind_work { struct list_head list; @@ -33,8 +33,8 @@ enum { void unwind_task_init(struct task_struct *task); void unwind_task_free(struct task_struct *task); =20 -int unwind_user_faultable(struct unwind_stacktrace *trace); -int unwind_user_trace_cached(struct unwind_stacktrace *trace); +int unwind_user_faultable(struct unwind_user_stacktrace *trace); +int unwind_user_trace_cached(struct unwind_user_stacktrace *trace); =20 int unwind_deferred_init(struct unwind_work *work, unwind_callback_t func); int unwind_deferred_request(struct unwind_work *work, u64 *cookie); @@ -67,8 +67,8 @@ static __always_inline void unwind_reset_info(void) static inline void unwind_task_init(struct task_struct *task) {} static inline void unwind_task_free(struct task_struct *task) {} =20 -static inline int unwind_user_faultable(struct unwind_stacktrace *trace) {= return -ENOSYS; } -static inline int unwind_user_trace_cached(struct unwind_stacktrace *trace= ) { return -ENOSYS; } +static inline int unwind_user_faultable(struct unwind_user_stacktrace *tra= ce) { return -ENOSYS; } +static inline int unwind_user_trace_cached(struct unwind_user_stacktrace *= trace) { return -ENOSYS; } static inline int unwind_deferred_init(struct unwind_work *work, unwind_ca= llback_t func) { return -ENOSYS; } static inline int unwind_deferred_request(struct unwind_work *work, u64 *t= imestamp) { return -ENOSYS; } static inline void unwind_deferred_cancel(struct unwind_work *work) {} diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h index 0308adb349fc..6022c77518f3 100644 --- a/include/linux/unwind_user.h +++ b/include/linux/unwind_user.h @@ -25,6 +25,6 @@ static inline void arch_unwind_user_init(struct unwind_us= er_state *state, struct static inline void arch_unwind_user_next(struct unwind_user_state *state) = {} #endif =20 -int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries); +int unwind_user(struct unwind_user_stacktrace *trace, unsigned int max_ent= ries); =20 #endif /* _LINUX_UNWIND_USER_H */ diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index fc440ae3a29b..860f84cd7998 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -28,7 +28,7 @@ enum unwind_user_type { UNWIND_USER_TYPE_FP =3D (1U << UNWIND_USER_TYPE_FP_BIT), }; =20 -struct unwind_stacktrace { +struct unwind_user_stacktrace { unsigned int nr; unsigned long *entries; }; diff --git a/kernel/unwind/deferred.c b/kernel/unwind/deferred.c index 02ab1d2afc21..4006d253c793 100644 --- a/kernel/unwind/deferred.c +++ b/kernel/unwind/deferred.c @@ -105,7 +105,7 @@ static u64 get_cookie(struct unwind_task_info *info) * Return: 0 on success and negative on error * On success @trace will contain the user space stacktrace */ -int unwind_user_faultable(struct unwind_stacktrace *trace) +int unwind_user_faultable(struct unwind_user_stacktrace *trace) { struct unwind_task_info *info =3D ¤t->unwind_info; struct unwind_cache *cache; @@ -158,7 +158,7 @@ EXPORT_SYMBOL_GPL(unwind_user_faultable); * Return: 0 on success and negative on error * On success @trace will contain the user space stacktrace */ -int unwind_user_trace_cached(struct unwind_stacktrace *trace) +int unwind_user_trace_cached(struct unwind_user_stacktrace *trace) { struct unwind_task_info *info =3D ¤t->unwind_info; struct unwind_cache *cache; @@ -180,7 +180,7 @@ EXPORT_SYMBOL_GPL(unwind_user_trace_cached); static void process_unwind_deferred(struct task_struct *task) { struct unwind_task_info *info =3D &task->unwind_info; - struct unwind_stacktrace trace; + struct unwind_user_stacktrace trace; struct unwind_work *work; unsigned long bits; u64 cookie; diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 9aefbfc8427a..dfe7bf50d8f6 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -167,7 +167,7 @@ static int unwind_user_start(struct unwind_user_state *= state) return 0; } =20 -int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries) +int unwind_user(struct unwind_user_stacktrace *trace, unsigned int max_ent= ries) { struct unwind_user_state state; =20 --=20 2.43.0 From nobody Fri Dec 19 19:19:24 2025 Received: from smtpout.efficios.com (smtpout.efficios.com [158.69.130.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 80DEA23E344 for ; Wed, 9 Jul 2025 21:26:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.69.130.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096367; cv=none; b=Y37XzYoJzckJ9OUiXW+x91AgDkBheHhDBfhFOk8oJMK/BaL7Ew1IG43YiHTTpyeVpnI0I9ze3DQZ1Lpn/D2tPynglppdeY178qB0YZhNNo5vMIaBP4dVNSXTb+BzfheSjxFmN9lWaEBEWwdeUvVvse3foho+5H/+oshOzlrkflE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752096367; c=relaxed/simple; bh=fNYzOa+t+y0015VU0hzy4JOUsTLiP1Gd7gv1nGC/GQo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uWvi865P73YpyG2yG6k4yNfhMgZW0+2Xy1H/Pcje67BKDRsQQZEJC/G1x/NvrZo6Z0BEgh+0SobWZN00u0bRNBHiCgZkGQSdoJ0hVBmuLYEw1l/0kXP4/Tm/i6HfBWjZoe0ffCEwmoUHpBbyoKOTQ/Bbn6xa5r6vnftSqsrqvsw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=X+l8f5UO; arc=none smtp.client-ip=158.69.130.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="X+l8f5UO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1752096363; bh=fNYzOa+t+y0015VU0hzy4JOUsTLiP1Gd7gv1nGC/GQo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X+l8f5UOdfFWGRjvK54kUCHSjcGwg8FyZFkR+Na3MCocG/EvQ77Ar2WPRmLLacSrf 1x/tDCip2Snl5lRqDk95MxAPgibfA0Ta469gnlRmXudWQbuA9bPwQuDBxlQjfzOiB3 KMK2TxnE/ewlIOwhWdHai0xeLu1sTB+0OvPi6hmk99qoFmbWymqfS6ei+oDttZt1ZD +whVC8c7OqHtaTuyEo2e0zSMn6Rq8nioCWbGgdQiEuv1kDiisifgRL2rLF3hS3Jhqc HJd5wOaVlH5cWSoh/qh/BkUXpHobEBDgSTvPPkxPd89+ccjWfbssbxQrN8kUoF6ZKz TvKiPmVOdfWbQ== Received: from compudjdev.. (192-222-132-26.qc.cable.ebox.net [192.222.132.26]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4bcrcq2dn7zPtn; Wed, 9 Jul 2025 17:26:03 -0400 (EDT) From: Mathieu Desnoyers To: Steven Rostedt Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers , Josh Poimboeuf , Masami Hiramatsu , Peter Zijlstra , Ingo Molnar , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Andrii Nakryiko , Indu Bhagat , "Jose E. Marchesi" , Beau Belgrave , Jens Remus , Linus Torvalds , Andrew Morton Subject: [RFC PATCH 5/5] unwind: Introduce unwind user entry type Date: Wed, 9 Jul 2025 17:25:52 -0400 Message-ID: <20250709212556.32777-6-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> References: <20250709212556.32777-1-mathieu.desnoyers@efficios.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a unwind user entry type to allow unwind iterator users to know which method was used to obtain each of the stack frames. This allows iterator users to know whether they can trust the information provided by the stack trace. For instance, on a system with binaries built with frame pointers omitted, the stack frames fetched using the frame pointer method should be considered unreliable, whereas those fetched using sframe should be reliable. Note that the "none" entry type denotes the first address (start of iteration), which is present in the pt_regs, and therefore is always reliable. Signed-off-by: Mathieu Desnoyers Cc: Steven Rostedt (Google) Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Thomas Gleixner Cc: Andrii Nakryiko Cc: Indu Bhagat Cc: "Jose E. Marchesi" Cc: Beau Belgrave Cc: Jens Remus Cc: Linus Torvalds Cc: Andrew Morton --- include/linux/unwind_deferred_types.h | 6 ++++-- include/linux/unwind_user_types.h | 9 +++++++-- kernel/unwind/user.c | 7 +++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/linux/unwind_deferred_types.h b/include/linux/unwind_d= eferred_types.h index db6c65daf185..ef9818456fd5 100644 --- a/include/linux/unwind_deferred_types.h +++ b/include/linux/unwind_deferred_types.h @@ -2,9 +2,11 @@ #ifndef _LINUX_UNWIND_USER_DEFERRED_TYPES_H #define _LINUX_UNWIND_USER_DEFERRED_TYPES_H =20 +#include + struct unwind_cache { - unsigned int nr_entries; - unsigned long entries[]; + unsigned int nr_entries; + struct unwind_user_entry entries[]; }; =20 =20 diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 860f84cd7998..ab29c419099c 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -28,9 +28,14 @@ enum unwind_user_type { UNWIND_USER_TYPE_FP =3D (1U << UNWIND_USER_TYPE_FP_BIT), }; =20 +struct unwind_user_entry { + enum unwind_user_type type; + unsigned long ip; +}; + struct unwind_user_stacktrace { - unsigned int nr; - unsigned long *entries; + unsigned int nr; + struct unwind_user_entry *entries; }; =20 struct unwind_user_frame { diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index dfe7bf50d8f6..9a88fe757327 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -180,8 +180,11 @@ int unwind_user(struct unwind_user_stacktrace *trace, = unsigned int max_entries) return 0; =20 for_each_user_frame(&state) { - trace->entries[trace->nr++] =3D state.ip; - if (trace->nr >=3D max_entries) + unsigned int i =3D trace->nr++; + + trace->entries[i].type =3D state.current_type; + trace->entries[i].ip =3D state.ip; + if (i >=3D max_entries) break; } =20 --=20 2.43.0