[PATCH] Fix symver attribute with LTO

Jan Hubicka hubicka@ucw.cz
Tue Dec 17 16:43:00 GMT 2019


> Hi Jan,
> 
> I'm using GNU ld 2.33.1.
> 
> I'll attach a testcase simplified from fuse-3.9 code.  "local: *;" in the
> versioning script triggers the issue.  Without it there would be no problem.

Thanks.
You are right that I did not play with local:. Now I wonder what is the
intended behaviour here.

In resolution file I see:
1
foo.o 4
205 dc8dc21a4ac8d072 PREVAILING_DEF_IRONLY_EXP foo_v1
207 dc8dc21a4ac8d072 PREVAILING_DEF_IRONLY foo@VERS_1
216 dc8dc21a4ac8d072 PREVAILING_DEF_IRONLY foo_v2
218 dc8dc21a4ac8d072 PREVAILING_DEF_IRONLY foo@@VERS_2

If I link the DSO w/o -flto I get with objdump -T:
0000000000001100 g    DF .text  0000000000000006 (VERS_1)     foo
0000000000001100 g    DF .text  0000000000000006  VERS_2      foo_v1
0000000000000000 g    DO *ABS*  0000000000000000  VERS_1      VERS_1
0000000000001110 g    DF .text  0000000000000006  VERS_2      foo
0000000000000000 g    DO *ABS*  0000000000000000  VERS_2      VERS_2

So I think linker is right here that foo_v1 is exported.  I would have
expected PREVAILING_DEF_IRONLY_EXP for foo@VERS_1 and foo@@VERS_2 since
that symbols do get exported even though they land in special way in the
DSO symbol table.  So I think meaingful behaviour would be
 1) make linker plugin interface to not annotate symbol version symbols
    with any resolution at all, since they are "special"
 2) make them PREVAILING_DEF_IRONLY_EXP/PREVAILING_DEF since they always
    get exported to non-LTO land.
We could workaround that on GCC side but if you agree with this
understanding I would fill in binutils PR. Also since we use resolution
info at many places, I would simply add logic working around this at a
time we read resolution rahter than on one of places we use it.

Comparing to objedump -T

0000000000001100 g    DF .text  0000000000000006  VERS_2      foo_v1
0000000000000000 g    DO *ABS*  0000000000000000  VERS_1      VERS_1
0000000000000000 g    DO *ABS*  0000000000000000  VERS_2      VERS_2

Why we also miss
0000000000001100 g    DF .text  0000000000000006 (VERS_1)     foo
and what does it mean?

I am not too happy about forcing GCC to keep foo_v2 exported when it is
not.  For example, calls to foo_v2 will then not be optimized as they
could if GCC knew it is not used by non-LTO world (except for fact that
symver is bound to it).

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.

Honza

> 
> > > 2. The actual function body implementing the symver-ed function is also
> > > marked
> > >    as PREVAILING_DEF_IRONLY and then removed or marked as local.  So no
> > > ".globl"
> > >    directive is outputed for it.
> > 
> > Here is the symver-ed function exported from the DSO (or is it set
> > to have hidden attribute)?
> > Again this was working for me, so it would be good to understand this
> > issue.
> 
> It's also triggered by "local: *;".
> 
> Untar the attachment and use "make" to build it, then "make show-dynamic-syms"
> to dump the dynamic symbol table.  I believe (with 99% chance) you'll see only
> foo (VERS_1) and foo_v1 (because foo_v1 is marked as global in the version
> script).  And foo (VERS_2) would be missing.  With this patch foo (VERS_2) would
> show up.
> 
> We can't mark "foo_v2" to be "global" because it should not be a part of DSO
> ABI.
> 
> The other 1% chance would be a regression in Binutils.
> -- 
> Xi Ruoyao <xry111@mengyan1223.wang>
> School of Aerospace Science and Technology, Xidian University




More information about the Gcc-patches mailing list