SFrame V3 represents the assembler directive .cfi_signal_frame using a SFrame FDE flag. Note that a SFrame FDE with this particular flag set may have no SFrame FREs. Introduce a SFRAME_V3_FDE_SIGNAL_P() helper macro. Use it in __find_fre() to populate the signal flag in struct unwind_user_frame, even if there are no FREs. Signed-off-by: Jens Remus --- kernel/unwind/sframe.c | 8 +++++++- kernel/unwind/sframe.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index 21283e3bda42..9fd2fc1572cc 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -446,6 +446,7 @@ static __always_inline int __find_fre(struct sframe_section *sec, struct unwind_user_frame *frame) { unsigned char fde_pctype = SFRAME_V3_FDE_PCTYPE(fde->info); + bool signal = SFRAME_V3_FDE_SIGNAL_P(fde->info); struct sframe_fre_internal *fre, *prev_fre = NULL; struct sframe_fre_internal fres[2]; unsigned long fre_addr; @@ -486,8 +487,11 @@ static __always_inline int __find_fre(struct sframe_section *sec, prev_fre = fre; } - if (!prev_fre) + if (!prev_fre) { + if (signal) + goto signal; return -EINVAL; + } fre = prev_fre; ret = __read_fre_datawords(sec, fde, fre); @@ -500,6 +504,8 @@ static __always_inline int __find_fre(struct sframe_section *sec, sframe_init_rule_data(&frame->fp, fre->fp_ctl, fre->fp_off); frame->sp_off = SFRAME_SP_OFFSET; frame->outermost = SFRAME_V3_FRE_RA_UNDEFINED_P(fre->info); +signal: + frame->signal = signal; return 0; } diff --git a/kernel/unwind/sframe.h b/kernel/unwind/sframe.h index 8a5322e95403..78432857f84c 100644 --- a/kernel/unwind/sframe.h +++ b/kernel/unwind/sframe.h @@ -65,6 +65,7 @@ struct sframe_fda_v3 { #define SFRAME_V3_FDE_FRE_TYPE(info) ((info) & 0xf) #define SFRAME_V3_FDE_PCTYPE(info) (((info) >> 4) & 0x1) #define SFRAME_V3_AARCH64_FDE_PAUTH_KEY(info) (((info) >> 5) & 0x1) +#define SFRAME_V3_FDE_SIGNAL_P(info) (((info) >> 7) & 0x1) #define SFRAME_FDE_TYPE_REGULAR 0 #define SFRAME_FDE_TYPE_FLEXIBLE 1 -- 2.51.0