Hi,

sorry about that.  I'll fix it and resend.


Best regards,

Josef

On 12/1/25 3:42 PM, Jakub Jelinek wrote:
On Mon, Dec 01, 2025 at 03:28:17PM +0100, Josef Melcr wrote:
previously, clones of callback functions had their local flag set.
Because callback edges are direct rather than indirect, GCC falsely
assumes that their callsites are available and that it can change their
ABI, leading to segfaults.  This patch fixes that.  Bootstrapped and
regtested on x86_64-pc-linux-gnu with
RUNTESTFLAGS="--target_board='unix{-m32}'". OK for master?
gcc/ChangeLog:

        PR ipa/122798
        * cgraph.cc (cgraph_edge::redirect_callee): Set address taken
        for new callee.
        (cgraph_node::callback_called_p): New function.
        * cgraph.h (struct cgraph_node): Likewise.
        * cgraphclones.cc (cgraph_node::create_virtual_clone): Set local
        flag to false when cloning a function with a callback call.

Signed-off-by: Josef Melcr <[email protected]>
---
  gcc/cgraph.cc       | 10 ++++++++++
  gcc/cgraph.h        |  3 +++
  gcc/cgraphclones.cc |  4 ++++
  3 files changed, 17 insertions(+)

diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 3c21e174943..64b19b5e5ac 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -1698,6 +1698,7 @@ cgraph_edge::redirect_callee (cgraph_node *n)
        new_ref->lto_stmt_uid = lto_stmt_uid;
        if (!old_callee->referred_to_p ())
        old_callee->address_taken = 0;
+      n->mark_address_taken();
Space before (

      }
if (!inline_failed)
@@ -3575,6 +3576,15 @@ cgraph_node::only_called_directly_p (void)
                                       NULL, true);
  }
Please repeat the cgraph. comment here too.

+bool
+cgraph_node::callback_called_p () const
+{
+  cgraph_edge *e;
+  for (e = callers; e; e = e->next_caller)
+    if (e->callback)
+      return true;
+  return false;
+}
/* Collect all callers of NODE. Worker for collect_callers_of_node. */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 313610fbe2c..b534a470b77 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1278,6 +1278,9 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : 
public symtab_node
       it is not used in any other non-standard way.  */
    bool only_called_directly_p (void);
+ /* Return TRUE if the node has at least one callback edge pointing to it. */
+  bool callback_called_p (void) const;
+
    /* Turn profile to global0.  Walk into inlined functions.  */
    void make_profile_local ();
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index 49f0e58fa1e..3cfbfec4c1a 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -687,6 +687,7 @@ cgraph_node::create_virtual_clone (const vec<cgraph_edge *> 
&redirect_callers,
                           clone_function_name (old_decl, suffix, num_suffix));
    SET_DECL_RTL (new_decl, NULL);
+ bool has_callback_call = callback_called_p ();
    new_node = create_clone (new_decl, count, false,
                           redirect_callers, false, NULL, param_adjustments,
                           suffix);
@@ -697,6 +698,9 @@ cgraph_node::create_virtual_clone (const vec<cgraph_edge *> 
&redirect_callers,
       ??? We cannot use COMDAT linkage because there is no
       ABI support for this.  */
    set_new_clone_decl_and_node_flags (new_node);
+  if (has_callback_call)
+    /* Callback clone can never be local, since it has its address taken.  */
+    new_node->local = false;
    new_node->ipcp_clone = ipcp_clone;
    if (tree_map)
      clone_info::get_create (new_node)->tree_map = tree_map;
        Jakub

Reply via email to