> On 2019-12-18 14:19 +0100, Jan Hubicka wrote:
> > The problem here is that we lie to the compiler (by pretending that
> > foo_v2 is exported from DSO while it is not) and force user to do the
> > same.
> >
> > We support two ways to hide symbol - either at compile time via
> > attribute((visibility("hidden"))) or at link-time via map file. The
> > first produces better code because compiler can do more optimizations
> > knowing that the symbol can not be interposed.
>
> I just get your point: if the library calls foo_v2 it won't be interposed. If
> it supposes a call to be interposed it should call foo() [foo@@VER_2] instead
> of
> foo_v2().
>
> But it seems there is no way we can do this [even with traditional
> __asm__("symver foo, foo@@VER_2")]. For this purpose we should either:
>
> 1. Change GAS (introducing some new syntax like '@@@@' or '.symver_export')
>
> or
>
> 2. Add some mangled symbol name in GCC (like ".LSYMVERx" or
> "foo_v2.symver_export").
I agree. The problem with mangled symbol names is that we will require
users to hide them from map files, so I think it is not best answer
either. I have filled binutils
https://sourceware.org/bugzilla/show_bug.cgi?id=25295
This is variant of your patch I comitted. It also adds verification so
we get ICE rather then wrong code. In addition I moved the checks away
rom used_from_object_file. This function is about non-LTO objects
linked into the DSO and thus does not really fit for the check.
Lastly we can not rely on symver attribute to still be present here.
Regtested x86_64-linux and comitted.
Honza
* cgraph.c (cgraph_node_cannot_be_local_p_1): Prevent targets of
symver attributes to be localized.
* ipa-visibility.c (cgraph_externally_visible_p,
varpool_node::externally_visible_p): Likewise.
* symtab.c (symtab_node::verify_base): Check visibility of symbol
versions.
* lto-common.c (read_cgraph_and_symbols): Work around binutils
PR25424
Index: cgraph.c
===================================================================
--- cgraph.c (revision 279523)
+++ cgraph.c (working copy)
@@ -2226,6 +2226,9 @@ cgraph_node_cannot_be_local_p_1 (cgraph_
{
return !(!node->force_output
&& !node->ifunc_resolver
+ /* Limitation of gas requires us to output targets of symver aliases
+ as global symbols. This is binutils PR 25295. */
+ && !node->symver
&& ((DECL_COMDAT (node->decl)
&& !node->forced_by_abi
&& !node->used_from_object_file_p ()
Index: ipa-visibility.c
===================================================================
--- ipa-visibility.c (revision 279523)
+++ ipa-visibility.c (working copy)
@@ -220,6 +220,14 @@ cgraph_externally_visible_p (struct cgra
&& lookup_attribute ("dllexport",
DECL_ATTRIBUTES (node->decl)))
return true;
+
+ /* Limitation of gas requires us to output targets of symver aliases as
+ global symbols. This is binutils PR 25295. */
+ ipa_ref *ref;
+ FOR_EACH_ALIAS (node, ref)
+ if (ref->referring->symver)
+ return true;
+
if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
return false;
/* When doing LTO or whole program, we can bring COMDAT functoins static.
@@ -284,14 +292,13 @@ varpool_node::externally_visible_p (void
DECL_ATTRIBUTES (decl)))
return true;
- /* See if we have linker information about symbol not being used or
- if we need to make guess based on the declaration.
+ /* Limitation of gas requires us to output targets of symver aliases as
+ global symbols. This is binutils PR 25295. */
+ ipa_ref *ref;
+ FOR_EACH_ALIAS (this, ref)
+ if (ref->referring->symver)
+ return true;
- Even if the linker clams the symbol is unused, never bring internal
- symbols that are declared by user as used or externally visible.
- This is needed for i.e. references from asm statements. */
- if (used_from_object_file_p ())
- return true;
if (resolution == LDPR_PREVAILING_DEF_IRONLY)
return false;
Index: lto/lto-common.c
===================================================================
--- lto/lto-common.c (revision 279523)
+++ lto/lto-common.c (working copy)
@@ -2818,6 +2818,11 @@ read_cgraph_and_symbols (unsigned nfiles
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (snode->decl)));
}
+ /* Symbol versions are always used externally, but linker does not
+ report that correctly.
+ This is binutils PR25924. */
+ else if (snode->symver && *res == LDPR_PREVAILING_DEF_IRONLY)
+ snode->resolution = LDPR_PREVAILING_DEF_IRONLY_EXP;
else
snode->resolution = *res;
}
Index: symtab.c
===================================================================
--- symtab.c (revision 279523)
+++ symtab.c (working copy)
@@ -1156,6 +1156,22 @@ symtab_node::verify_base (void)
error ("node is symver but not alias");
error_found = true;
}
+ /* Limitation of gas requires us to output targets of symver aliases as
+ global symbols. This is binutils PR 25295. */
+ if (symver
+ && (!TREE_PUBLIC (get_alias_target ()->decl)
+ || DECL_VISIBILITY (get_alias_target ()->decl) != VISIBILITY_DEFAULT))
+ {
+ error ("symver target is not exported with default visibility");
+ error_found = true;
+ }
+ if (symver
+ && (!TREE_PUBLIC (decl)
+ || DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT))
+ {
+ error ("symver is not exported with default visibility");
+ error_found = true;
+ }
if (same_comdat_group)
{
symtab_node *n = same_comdat_group;