> 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;

Reply via email to