This is https://bugs.llvm.org/show_bug.cgi?id=38074. This simple reproducible is below.
Imagine the following code:
user.cpp:
extern "C" int myfunc(); int main() { int (*p)() = &myfunc; return p(); }
library.cpp:
int myfunc2() { return 2; } extern "C" int myfunc(); __asm__ (".type myfunc, @gnu_indirect_function"); typeof(myfunc) * myfunc_dispatch (void) __asm__ ("myfunc"); typeof(myfunc) * myfunc_dispatch (void) { return myfunc2; }
If you run the application linked with gold, the output will be correct:
> clang library.o user.o -fPIC -static -o test > ./test > echo $? 2
The application linked with LLD (-fuse-ld=lld) shows 32 for me instead.
The issue is that when calling a function, for example,
LLD generates a .got entry that points to the IFUNC resolver function when
instead, it should use the PLT entries properly for handling the IFUNC.
So we should create a got entry that points to PLT entry, which itself loads the value from
.got.plt, relocated with R_X86_64_IRELATIVE to make things work. Patch do that.
Can you add a comment as to what this enum value represents?