> honza,
> this is the fix for the partitioned WPA bug I was tracking down.
> 
> We have base and complete dtors sharing a comdat group (one's an alias for
> the other).  The linker tells us the complete dtor is PREVAILING_DEF, as
> it's referenced from some other library.  The base dtor is UNKNOWN.
> 
> We therefore internalize the base dtor, making it PREVAILING_DEF_IRONLY and
> split the comdat group.  But the comdat group splitting also internalizes
> the complete dtor /and/ it does so inconsistently.
> 
> The bug manifested at runtime w/o link error as the complete dtor resolved
> to zero in the final link from wpa partitions that didn't contain its
> definition. (For extra fun, that was via a call to __cxa_at_exit registering
> a null function pointer, and getting the subsequent seg fault at program
> exit.)  When we created WPA partitions node->externally_visible was still
> set, so we thought the now-internalized complete dtor was still externally
> visible -- but varasm looks at the DECL itself and emits an internal one.
> Plus the references to it were weak (& now hidden), so resolved to zero,
> rather than link error.  And the external library either had its own
> definition which then prevailed for it.  All rather 'ew'.
> 
> Anyway, this patch does 3 things
> 1) Moves the next->unique_name adjustment to before make_decl_local for
> members of the comdat group -- that matches the behaviour of the decl of
> interest itself.

That part is OK.
> 
> 2) For LDPR_PREVAILING_DEF members we don't make_decl_local, but instead
> clear DECL_COMDAT and DECL_WEAK.  Thus forcing this decl to be the
> prevailing decl in the final link
> 
> 3) For decls we localize, we also clear node->externally_visible and
> node->force_by_abi.  That matches the behavior for the decl of interest too
> and will clue the wpa partitioning logic into knowing it needs to
> hidden-externalize the decl.

So at the moment it works in a way
 1) we walk first symbol of the comdat and it is LDPR_PREVAILING_DEF and thus
    we set externall visible flag
 2) we walk second symbol of the comdat and it is LDPR_PREVAILING_DEF_IRONLY
    and thus we decide to privatize the whole comdat group, during this
    process we force the first symbol local and clear the externally_visible
    flag?

I think at a time we decide on external visibility of a symbol in a comdat
group, we need to check that the comdat group as a whole is not exporte (i.e.
no LDPR_PREVAILING_DEF_EXP or incremental linking).  Then we know we can 
dissolve
the comdat group (without actually affecting visibility) and then we can
handle each symbol independently.

Honza
> 
> nathan
> 
> -- 
> Nathan Sidwell

> 2017-01-18  Nathan Sidwell  <nat...@acm.org>
> 
>       * ipa-visibility.c (localize_node): Set comdat's unique name
>       before adjusting resolution. Make PREVAILING_DEF members strongly
>       public. Set visibility to false for localized decls.
> 
> Index: ipa-visibility.c
> ===================================================================
> --- ipa-visibility.c  (revision 244546)
> +++ ipa-visibility.c  (working copy)
> @@ -542,16 +542,32 @@ localize_node (bool whole_program, symta
>        for (symtab_node *next = node->same_comdat_group;
>          next != node; next = next->same_comdat_group)
>       {
> -       next->set_comdat_group (NULL);
> -       if (!next->alias)
> -         next->set_section (NULL);
> -       if (!next->transparent_alias)
> -         next->make_decl_local ();
>         next->unique_name
>           |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
>                || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
>               && TREE_PUBLIC (next->decl)
>               && !flag_incremental_link);
> +
> +       next->set_comdat_group (NULL);
> +       if (!next->alias)
> +         next->set_section (NULL);
> +       if (next->transparent_alias)
> +         /* Do nothing.  */;
> +       else if (next->resolution == LDPR_PREVAILING_DEF)
> +         {
> +           /* Make this a strong defn, so the external
> +              users don't mistakenly choose some other
> +              instance.  */
> +           DECL_COMDAT (next->decl) = false;
> +           DECL_WEAK (next->decl) = false;
> +         }
> +       else
> +         {
> +           next->externally_visible = false;
> +           next->forced_by_abi = false;
> +           next->resolution = LDPR_PREVAILING_DEF_IRONLY;
> +           next->make_decl_local ();
> +         }
>       }
>  
>        /* Now everything's localized, the grouping has no meaning, and

Reply via email to