Add a signal flag to struct unwind_user_frame, which indicates whether the frame is a signal frame. If set unwind_user_common_next() uses an architecture-specific unwind_user_signal_next() implementation to unwind the frame. user unwind sframe will make use of the signal flag in a subsequent commit. Signed-off-by: Jens Remus --- arch/x86/include/asm/unwind_user.h | 6 ++++-- include/linux/unwind_user.h | 9 +++++++++ include/linux/unwind_user_types.h | 1 + kernel/unwind/user.c | 4 ++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h index f5e9fbcdae28..21cb9eeb2503 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -67,7 +67,8 @@ static inline int unwind_user_get_reg(unsigned long *val, unsigned int regnum) .offset = -2*(ws), \ }, \ .sp_off = 0, \ - .outermost = false, + .outermost = false, \ + .signal = false, #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws) \ .cfa = { \ @@ -82,7 +83,8 @@ static inline int unwind_user_get_reg(unsigned long *val, unsigned int regnum) .rule = UNWIND_USER_RULE_RETAIN,\ }, \ .sp_off = 0, \ - .outermost = false, + .outermost = false, \ + .signal = false, static inline int unwind_user_fp_get_frame(struct unwind_user_state *state, struct unwind_user_frame *frame) diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h index f65b0573b3a5..eb5de4cb5bd6 100644 --- a/include/linux/unwind_user.h +++ b/include/linux/unwind_user.h @@ -34,6 +34,15 @@ static inline int unwind_user_get_reg(unsigned long *val, unsigned int regnum) #define unwind_user_get_reg unwind_user_get_reg #endif +#ifndef unwind_user_signal_next +static inline int unwind_user_signal_next(struct unwind_user_state *state) +{ + WARN_ON_ONCE(1); + return -EINVAL; +} +#define unwind_user_signal_next unwind_user_signal_next +#endif + int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries); #endif /* _LINUX_UNWIND_USER_H */ diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_types.h index fac8f470b597..3985706d7851 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -68,6 +68,7 @@ struct unwind_user_frame { struct unwind_user_rule_data fp; s32 sp_off; bool outermost; + bool signal; }; struct unwind_user_state { diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index a64ceb4a2bf6..b9a3b59e8282 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -32,6 +32,10 @@ static int unwind_user_next_common(struct unwind_user_state *state, { unsigned long cfa, sp, fp, ra; + /* Use signal frame unwinder for signal frames. */ + if (frame->signal) + return unwind_user_signal_next(state); + /* Stop unwinding when reaching an outermost frame. */ if (frame->outermost) { state->done = true; -- 2.51.0