Yury Khrustalev <[email protected]> writes:
> From: Szabolcs Nagy <[email protected]>
>
> Tail calls of indirect_return functions from non-indirect_return
> functions are disallowed even if BTI is disabled, since the call
> site may have BTI enabled.
>
> Following x86, mismatching attribute on function pointers is not
> a type error even though this can lead to bugs.
Is that still true? I would have expected the aarch64_comp_type_attributes
part of the patch to reject mismatches.
> Needed for swapcontext within the same function when GCS is enabled.
>
> gcc/ChangeLog:
>
> * config/aarch64/aarch64.cc (aarch64_gnu_attributes): Add
> indirect_return.
> (aarch64_function_ok_for_sibcall): Disallow tail calls if caller
> is non-indirect_return but callee is indirect_return.
> (aarch64_comp_type_attributes): Check indirect_return attribute.
> * config/arm/aarch-bti-insert.cc (call_needs_bti_j): New.
> (rest_of_insert_bti): Use call_needs_bti_j.
>
> ---
> gcc/config/aarch64/aarch64.cc | 11 +++++++++
> gcc/config/arm/aarch-bti-insert.cc | 36 ++++++++++++++++++++++++++----
> 2 files changed, 43 insertions(+), 4 deletions(-)
>
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index a89a30113b9..9bfc9a1dbba 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -853,6 +853,7 @@ static const attribute_spec aarch64_gnu_attributes[] =
> affects_type_identity, handler, exclude } */
> { "aarch64_vector_pcs", 0, 0, false, true, true, true,
> handle_aarch64_vector_pcs_attribute, NULL },
> + { "indirect_return", 0, 0, false, true, true, false, NULL, NULL },
> { "arm_sve_vector_bits", 1, 1, false, true, false, true,
> aarch64_sve::handle_arm_sve_vector_bits_attribute,
> NULL },
> @@ -6429,6 +6430,14 @@ aarch64_function_ok_for_sibcall (tree, tree exp)
> if (bool (aarch64_cfun_shared_flags (state))
> != bool (aarch64_fntype_shared_flags (fntype, state)))
> return false;
> +
> + /* BTI J is needed where indirect_return functions may return
> + if bti is enabled there. */
> + if (lookup_attribute ("indirect_return", TYPE_ATTRIBUTES (fntype))
> + && !lookup_attribute ("indirect_return",
> + TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl))))
> + return false;
> +
> return true;
> }
>
> @@ -29118,6 +29127,8 @@ aarch64_comp_type_attributes (const_tree type1,
> const_tree type2)
>
> if (!check_attr ("gnu", "aarch64_vector_pcs"))
> return 0;
> + if (!check_attr ("gnu", "indirect_return"))
> + return 0;
> if (!check_attr ("gnu", "Advanced SIMD type"))
> return 0;
> if (!check_attr ("gnu", "SVE type"))
> diff --git a/gcc/config/arm/aarch-bti-insert.cc
> b/gcc/config/arm/aarch-bti-insert.cc
> index 14d36971cd4..403afff9120 100644
> --- a/gcc/config/arm/aarch-bti-insert.cc
> +++ b/gcc/config/arm/aarch-bti-insert.cc
> @@ -92,6 +92,35 @@ const pass_data pass_data_insert_bti =
> 0, /* todo_flags_finish. */
> };
>
> +/* Decide if BTI J is needed after a call instruction. */
> +static bool
> +call_needs_bti_j (rtx_insn *insn)
> +{
> + /* Call returns twice, one of which may be indirect. */
> + if (find_reg_note (insn, REG_SETJMP, NULL))
> + return true;
> +
> + /* Tail call does not return. */
> + if (SIBLING_CALL_P (insn))
> + return false;
> +
> + /* Check if the function is marked to return indirectly. */
> + rtx call = get_call_rtx_from (insn);
> + rtx fnaddr = XEXP (call, 0);
> + tree fndecl = NULL_TREE;
> + if (GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
> + fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
> + if (fndecl == NULL_TREE)
> + fndecl = MEM_EXPR (fnaddr);
> + if (!fndecl)
> + return false;
> + if (TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
> + && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
> + return false;
> + tree fntype = TREE_TYPE (fndecl);
> + return lookup_attribute ("indirect_return", TYPE_ATTRIBUTES (fntype));
I think it would be safer/more robust to encode the indirect_return status
in the call insn "cookie", like we do for some other ABI properties.
The information would be recorded in CUMULATIVE_ARGS by
aarch64_init_cumulative_args, then aarch64_function_arg would
add it to the cookie.
Thanks,
Richard
> +}
> +
> /* Insert the BTI instruction. */
> /* This is implemented as a late RTL pass that runs before branch
> shortening and does the following. */
> @@ -147,10 +176,9 @@ rest_of_insert_bti (void)
> }
> }
>
> - /* Also look for calls to setjmp () which would be marked with
> - REG_SETJMP note and put a BTI J after. This is where longjump ()
> - will return. */
> - if (CALL_P (insn) && (find_reg_note (insn, REG_SETJMP, NULL)))
> + /* Also look for calls that may return indirectly, such as setjmp,
> + and put a BTI J after them. */
> + if (CALL_P (insn) && call_needs_bti_j (insn))
> {
> bti_insn = aarch_gen_bti_j ();
> emit_insn_after (bti_insn, insn);