[llvm-dev] Weak symbol/alias semantics

Teresa Johnson via llvm-dev llvm-dev at lists.llvm.org
Wed Jan 18 07:00:34 PST 2017


On Tue, Jan 17, 2017 at 7:24 PM, Rafael Avila de Espindola <
rafael.espindola at gmail.com> wrote:

> Teresa Johnson via llvm-dev <llvm-dev at lists.llvm.org> writes:
>
> > I was wondering though what happens if we have an alias, which may or may
> > not be weak itself, to a non-odr weak symbol that isn't prevailing. In
> that
> > case, do we eventually want references via the alias to go to the
> > prevailing copy (in another module), or to the original copy in the
> alias's
> > module? I looked at some examples without ThinLTO, and am a little
> > confused. Current (non-ThinLTO) behavior in some cases seems to depend on
> > opt level.
> >
> > Example:
> >
> > $ cat weak12main.c
> > extern void test2();
> > int main() {
> >   test2();
> > }
> >
> > $ cat weak1.c
> > #include <stdio.h>
> >
> > void weakalias() __attribute__((weak, alias ("f")));
> > void strongalias() __attribute__((alias ("f")));
> >
> > void f () __attribute__ ((weak));
> > void f()
> > {
> >   printf("In weak1.c:f\n");
> > }
> > void test1() {
> >   printf("Call f() from weak1.c:\n");
> >   f();
> >   printf("Call weakalias() from weak1.c:\n");
> >   weakalias();
> >   printf("Call strongalias() from weak1.c:\n");
> >   strongalias();
> > }
> >
> > $ cat weak2.c
> > #include <stdio.h>
> >
> > void f () __attribute__ ((weak));
> > void f()
> > {
> >   printf("In weak2.c:f\n");
> > }
> > extern void test1();
> > void test2()
> > {
> >   test1();
> >   printf("Call f() from weak2.c\n");
> >   f();
> > }
> >
> > If I link weak1.c before weak2.c, nothing is surprising (we always invoke
> > weak1.c:f at both -O0 and -O2):
> >
> > $ clang weak12main.c weak1.c weak2.c -O0
> > $ a.out
> > Call f() from weak1.c:
> > In weak1.c:f
> > Call weakalias() from weak1.c:
> > In weak1.c:f
> > Call strongalias() from weak1.c:
> > In weak1.c:f
> > Call f() from weak2.c
> > In weak1.c:f
> >
> > $ clang weak12main.c weak1.c weak2.c -O2
> > $ a.out
> > Call f() from weak1.c:
> > In weak1.c:f
> > Call weakalias() from weak1.c:
> > In weak1.c:f
> > Call strongalias() from weak1.c:
> > In weak1.c:f
> > Call f() from weak2.c
> > In weak1.c:f
> >
> > If I instead link weak2.c first, so it's copy of f() is prevailing, I
> still
> > get weak1.c:f for the call via weakalias() (both opt levels), and for
> > strongalias() when building at -O0. At -O2 the compiler replaces the call
> > to strongalias() with a call to f(), so it get's the weak2 copy in that
> > case.
> >
> > $ clang weak12main.c weak2.c weak1.c -O2
> > $ a.out
> > Call f() from weak1.c:
> > In weak2.c:f
> > Call weakalias() from weak1.c:
> > In weak1.c:f
> > Call strongalias() from weak1.c:
> > In weak2.c:f
> > Call f() from weak2.c
> > In weak2.c:f
> >
> > $ clang weak12main.c weak2.c weak1.c -O0
> > $ a.out
> > Call f() from weak1.c:
> > In weak2.c:f
> > Call weakalias() from weak1.c:
> > In weak1.c:f
> > Call strongalias() from weak1.c:
> > In weak1.c:f
> > Call f() from weak2.c
> > In weak2.c:f
> >
> > I'm wondering what the expected/correct behavior is? Depending on what is
> > correct, we need to handle this differently in ThinLTO mode. Let's say
> > weak1.c's copy of f() is not prevailing and I am going to drop it (it
> needs
> > to be removed completely, not turned into available_externally to ensure
> it
> > isn't inlined since weak isInterposable). If we want the aliases in
> weak1.c
> > to reference the original version, then copying is correct (e.g.
> weakalias
> > and strong alias would each become a copy of weak1.c's f()). If we
> however
> > want them to resolve to the prevailing copy of f(), then we need to turn
> > the aliases into declarations (external linkage in the case of
> strongalias
> > and external weak in the case of weakalias?).
> >
> > I also tried the case where f() was in a comdat, because I also need to
> > handle that case in ThinLTO (when f() is not prevailing, drop it from the
> > comdat and remove the comdat from that module). Interestingly, in this
> case
> > when weak2.c is prevailing, I get the following warning when linking and
> > get a seg fault at runtime:
> >
> > weak1.o:weak1.o:function test1: warning: relocation refers to discarded
> > section
> >
> > Presumably the aliases still refer to the copy in weak1.c, which is in
> the
> > comdat that gets dropped by the linker. So is it not legal to have an
> alias
> > to a weak symbol in a comdat (i.e. alias from outside the comdat)? We
> don't
> > complain in the compiler.
>
> The rule should be that the alias to aliasee link is never broken. The
> reason being that an alias at the file level is just another symbol with
> the same value.
>
> So if foo is an alias to bar, accessing that foo will always be the same
> as accessing that bar, regardless of either of them being weak. I say
> *that* foo and *that* bar because symbol resolution may pick another foo
> and another bar.
>

Are you just talking about the comdat case? If this also applies to the
non-comdat case, I'm not sure how this works in the following situation
(copied from an example in my response just now to pcc):

If a module contains the following, and both @x and @y are non-prevailing
in that module:

@x = weak global ...
@y = weak alias @x

and the prevailing def for @x is in moduleX with a different value than the
prevailing def for @y which comes from moduleY. Just because they are
aliased in this module doesn't mean they must be aliased elsewhere, right?
For this case (weak non-prevailing alias to a weak non-prevailing def) I
think it should eventually become:

@x = external global
@y = external global

Trying to understand how this fits with your comment that "The rule should
be that the alias to aliasee link is never broken", unless that is just
referring to the case I mentioned just above about when they are both in
comdats.

Thanks,
Teresa


>
> Cheers,
> Rafael
>



-- 
Teresa Johnson |  Software Engineer |  tejohnson at google.com |  408-460-2413
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170118/a83dffed/attachment.html>


More information about the llvm-dev mailing list