On 10/06/2024 15:04, Torbjörn SVENSSON wrote: > Properly handle zero and sign extension for Armv8-M.baseline as > Cortex-M23 can have the security extension active. > Currently, there is an internal compiler error on Cortex-M23 for the > epilog processing of sign extension. > > This patch addresses the following CVE-2024-0151 for Armv8-M.baseline. > > gcc/ChangeLog: > > PR target/115253 > * config/arm/arm.cc (cmse_nonsecure_call_inline_register_clear): > Sign extend for Thumb1. > (thumb1_expand_prologue): Add zero/sign extend. > > Signed-off-by: Torbjörn SVENSSON <torbjorn.svens...@foss.st.com> > Co-authored-by: Yvan ROUX <yvan.r...@foss.st.com> > --- > gcc/config/arm/arm.cc | 71 ++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 63 insertions(+), 8 deletions(-) > > diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc > index ea0c963a4d6..e7b4caf1083 100644 > --- a/gcc/config/arm/arm.cc > +++ b/gcc/config/arm/arm.cc > @@ -19220,17 +19220,22 @@ cmse_nonsecure_call_inline_register_clear (void) > || TREE_CODE (ret_type) == BOOLEAN_TYPE) > && known_lt (GET_MODE_SIZE (TYPE_MODE (ret_type)), 4)) > { > - machine_mode ret_mode = TYPE_MODE (ret_type); > + rtx ret_reg = gen_rtx_REG (TYPE_MODE (ret_type), R0_REGNUM); > + rtx si_reg = gen_rtx_REG (SImode, R0_REGNUM); > rtx extend; > if (TYPE_UNSIGNED (ret_type)) > - extend = gen_rtx_ZERO_EXTEND (SImode, > - gen_rtx_REG (ret_mode, > R0_REGNUM)); > + extend = gen_rtx_SET (si_reg, gen_rtx_ZERO_EXTEND (SImode, > + ret_reg)); > else > - extend = gen_rtx_SIGN_EXTEND (SImode, > - gen_rtx_REG (ret_mode, > R0_REGNUM)); > - emit_insn_after (gen_rtx_SET (gen_rtx_REG (SImode, R0_REGNUM), > - extend), insn); > - > + /* Signed-extension is a special case because of > + thumb1_extendhisi2. */ > + if (TARGET_THUMB1
You effectively have an 'else if' split across a comment here, and the indentation looks weird. Either write 'else if' on one line (and re-indent accordingly) or put this entire block inside braces. > + && known_ge (GET_MODE_SIZE (TYPE_MODE (ret_type)), 2)) You can use known_eq here. We'll never have any value other than 2, given the known_le (4) above and anyway it doesn't make sense to call extendhisi with any other size. > + extend = gen_thumb1_extendhisi2 (si_reg, ret_reg); > + else > + extend = gen_rtx_SET (si_reg, gen_rtx_SIGN_EXTEND (SImode, > + ret_reg)); > + emit_insn_after (extend, insn); > } > > > @@ -27250,6 +27255,56 @@ thumb1_expand_prologue (void) > live_regs_mask = offsets->saved_regs_mask; > lr_needs_saving = live_regs_mask & (1 << LR_REGNUM); > Similar comments to above apply to the hunk below. > + /* The AAPCS requires the callee to widen integral types narrower > + than 32 bits to the full width of the register; but when handling > + calls to non-secure space, we cannot trust the callee to have > + correctly done so. So forcibly re-widen the result here. */ > + if (IS_CMSE_ENTRY (func_type)) > + { > + function_args_iterator args_iter; > + CUMULATIVE_ARGS args_so_far_v; > + cumulative_args_t args_so_far; > + bool first_param = true; > + tree arg_type; > + tree fndecl = current_function_decl; > + tree fntype = TREE_TYPE (fndecl); > + arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, fndecl); > + args_so_far = pack_cumulative_args (&args_so_far_v); > + FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) > + { > + rtx arg_rtx; > + > + if (VOID_TYPE_P (arg_type)) > + break; > + > + function_arg_info arg (arg_type, /*named=*/true); > + if (!first_param) > + /* We should advance after processing the argument and pass > + the argument we're advancing past. */ > + arm_function_arg_advance (args_so_far, arg); > + first_param = false; > + arg_rtx = arm_function_arg (args_so_far, arg); > + gcc_assert (REG_P (arg_rtx)); > + if ((TREE_CODE (arg_type) == INTEGER_TYPE > + || TREE_CODE (arg_type) == ENUMERAL_TYPE > + || TREE_CODE (arg_type) == BOOLEAN_TYPE) > + && known_lt (GET_MODE_SIZE (GET_MODE (arg_rtx)), 4)) > + { > + rtx res_reg = gen_rtx_REG (SImode, REGNO (arg_rtx)); > + if (TYPE_UNSIGNED (arg_type)) > + emit_set_insn (res_reg, gen_rtx_ZERO_EXTEND (SImode, arg_rtx)); > + else > + /* Signed-extension is a special case because of > + thumb1_extendhisi2. */ > + if (known_ge (GET_MODE_SIZE (GET_MODE (arg_rtx)), 2)) > + emit_insn (gen_thumb1_extendhisi2 (res_reg, arg_rtx)); > + else > + emit_set_insn (res_reg, > + gen_rtx_SIGN_EXTEND (SImode, arg_rtx)); > + } > + } > + } > + > /* Extract a mask of the ones we can give to the Thumb's push instruction. > */ > l_mask = live_regs_mask & 0x40ff; > /* Then count how many other high registers will need to be pushed. */ OK with those changes. R.