How to combine LTO with symbol versioning

WHOPR Driver Design gives some strong hints to what is going on. The function definitions fun1 and fun2 are not exported according to the version script. The LTO plugin is able to use this information, and since GCC does not peek into the asm directives, it knows nothing about the .symver directive, and therefore removes the function definition.

For now, adding __attribute__ ((externally_visible)) is the workaround for this. You also need to build with -flto-partition=none, so that the .symver directives do not land by accident in a different intermediate assembler file than the function definition (where it will not have the desired effect).

GCC PR 48200 tracks an enhancement request for symbol versioning at the compiler level, which would likely address this issue as well.


It looks like my externally_visible fix works. This is:

#define DLLEXPORT __attribute__((visibility("default"),externally_visible))

DLLEXPORT int fun1(void);

Also see: https://gcc.gnu.org/onlinedocs/gccint/WHOPR.html

But I think your versionscript is wrong.

If I take out the visibility overrides and change your versionscript by adding fun1 and fun2 then it works. Like:

v1 {
    global:
        fun; fun1;
    local:
        *;
};
v2 {
    global:
        fun; fun2;
} v1;

The symbol alias targets have to be visible as well as the alias.

Tags:

C

Gcc

Linker

Lto