> Would it be equivalent to:
> 1) output foo_v2 local
> 2) producing static alias with local name (.L1)
> 3) do .symver .L1,foo@@@VERS_2
> That is somewhat more systematic and would not lead to false
> visibilities.

I spent some time playing with this.  An in order to 
1) be able to handle foo_v2 according to the resolution info
   (so it behaves like a regular symbol and can be called dirrectly,
    localized and optimized)
2) get intended objdump -T relocations
3) do not polute global symbol tables

I ended up with the following codegen:

        .type   foo_v2, @function
foo_v2:
.LFB1:
        .cfi_startproc
        movl    $2, %eax
        ret
        .cfi_endproc
.LFE1:
        .size   foo_v2, .-foo_v2
        .globl  .LSYMVER0
        .set    .LSYMVER0,foo_v2
        .symver .LSYMVER0, foo@@@VERS_2

This uses @@@ symver version of gas which seems to have odd semantics of
requiring to be passed global symbol name which it then tkes away and
produces foo@@VERS_2.

So the nm outoutp of the ltrans unit is:
0000000000000000 T foo_v1
0000000000000010 t foo_v2
0000000000000000 T foo@VERS_1
0000000000000010 T foo@@VERS_2

So the difference to your patch is that foo_v2 is static which enables
normal optimizations.

Since additional symbol alias is produced this would also make it
possible to attach multiple symver attributes with @@ string.

Does somehting like this make sense to you? Modulo the obvious buffer
overflow issue?
Honza

Index: lto/lto-common.c
===================================================================
--- lto/lto-common.c    (revision 279178)
+++ lto/lto-common.c    (working copy)
@@ -2818,6 +2818,10 @@ 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.  */
+       else if (snode->symver && *res == LDPR_PREVAILING_DEF_IRONLY)
+         snode->resolution = LDPR_PREVAILING_DEF_IRONLY_EXP;
        else
          snode->resolution = *res;
       }
Index: varasm.c
===================================================================
--- varasm.c    (revision 279178)
+++ varasm.c    (working copy)
@@ -5970,9 +5970,47 @@ do_assemble_symver (tree decl, tree targ
   ultimate_transparent_alias_target (&id);
   ultimate_transparent_alias_target (&target);
 #ifdef ASM_OUTPUT_SYMVER_DIRECTIVE
-  ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
-                              IDENTIFIER_POINTER (target),
-                              IDENTIFIER_POINTER (id));
+  if (TREE_PUBLIC (target) && DECL_VISIBILITY (target) == VISIBILITY_DEFAULT)
+    ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
+                                IDENTIFIER_POINTER
+                                  (DECL_ASSEMBLER_NAME (target)),
+                                IDENTIFIER_POINTER (id));
+  else
+    {
+      int nameend;
+      for (nameend = 0; IDENTIFIER_POINTER (id)[nameend] != '@'; nameend++)
+       ;
+      if (IDENTIFIER_POINTER (id)[nameend + 1] != '@'
+         || IDENTIFIER_POINTER (id)[nameend + 2] == '@')
+       {
+         sorry_at (DECL_SOURCE_LOCATION (target),
+                   "can not produce %<symver%> of a symbol that is "
+                   "not exported with default visibility");
+         return;
+       }
+      tree tmpdecl = copy_node (decl);
+      char buf[256];
+      static int symver_labelno;
+      targetm.asm_out.generate_internal_label (buf,
+                                              "LSYMVER", symver_labelno++);
+      SET_DECL_ASSEMBLER_NAME (tmpdecl, get_identifier (buf));
+      globalize_decl (tmpdecl);
+#ifdef ASM_OUTPUT_DEF_FROM_DECLS
+      ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, tmpdecl,
+                                DECL_ASSEMBLER_NAME (target));
+#else
+      ASM_OUTPUT_DEF (asm_out_file,
+                     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tmpdecl)),
+                     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
+#endif
+      memcpy (buf, IDENTIFIER_POINTER (id), nameend + 2);
+      buf[nameend + 2] = '@';
+      strcpy (buf + nameend + 3, IDENTIFIER_POINTER (id) + nameend + 2);
+      ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
+                                  IDENTIFIER_POINTER
+                                        (DECL_ASSEMBLER_NAME (tmpdecl)),
+                                  buf);
+    }
 #else
   error ("symver is only supported on ELF platforms");
 #endif

Reply via email to