https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88805

Florian Weimer <fw at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |NEW
                 CC|                            |fw at gcc dot gnu.org

--- Comment #5 from Florian Weimer <fw at gcc dot gnu.org> ---
I can reproduce this using g++ and gcc-8.3.1-2.fc29.x86_64, with this test
file:

static int
implementation_avx2 (void)
{
  return 1;
}

static int
implementation (void)
{
  return 0;
}

static __typeof__ (implementation) * resolver (void) __asm__ ("resolver");

static __typeof__ (implementation) *
resolver (void)
{
  __builtin_cpu_init ();
  if (__builtin_cpu_supports ("avx2"))
    return implementation_avx2;
  else
    return implementation;
}

int magic (void) __attribute__ ((ifunc ("resolver")));

Compile with:

g++ -O2 -fpic -shared

The assembler output contains a reference to __cpu_model:

resolver:
        subq    $8, %rsp
        call    __cpu_indicator_init
        movl    $_ZL19implementation_avx2v, %eax
        movl    $_ZL14implementationv, %edx
        testb   $4, __cpu_model+13(%rip)
        cmove   %rdx, %rax
        addq    $8, %rsp
        ret

__cpu_model is a compat symbol in libgcc_s.so.1 (with a single @ in the
version):

$ eu-readelf -s /usr/lib64/libgcc_s.so.1  | grep cpu_model
  151: 000000000001a190     16 OBJECT  GLOBAL DEFAULT       27
__cpu_model@GCC_4.8.0

This means that the link editor will not use this symbol and leave it
unversioned and undefined:

$ eu-readelf -s a.out | grep cpu_model
    3: 0000000000000000      0 NOTYPE  GLOBAL DEFAULT    UNDEF __cpu_model
   49: 0000000000000000      0 NOTYPE  GLOBAL DEFAULT    UNDEF __cpu_model

I think the expectation is that the definition from libgcc.a is used instead: A
local definition has to be used because relocations in IFUNC resolvers are
invalid (see bug 70082).

But g++ (and presumably gfortran) do not link against libgcc.a.

gcc links against libgcc.a and does not have this problem:

$ eu-readelf -s a.out | grep cpu_model
   44: 0000000000004030     16 OBJECT  LOCAL  DEFAULT       22 __cpu_model

Reply via email to