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