This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug dynamic-link/24868] New: STT_GNU_IFUNC do not link correctly on RISC-V


https://sourceware.org/bugzilla/show_bug.cgi?id=24868

            Bug ID: 24868
           Summary: STT_GNU_IFUNC do not link correctly on RISC-V
           Product: glibc
           Version: 2.29
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: dynamic-link
          Assignee: unassigned at sourceware dot org
          Reporter: gilles.m.duboscq at gmail dot com
  Target Milestone: ---

Created attachment 11928
  --> https://sourceware.org/bugzilla/attachment.cgi?id=11928&action=edit
patch that solves the issue

On RISC-V, STT_GNU_IFUNC seem to only link correctly when the binary using them
is loaded lazily. When it is loaded eagerly, the result of the relocation is
the resolution function rather than the resolved function.

In turn this means glibc's __riscv_flush_icache does not work in shared
libraries loaded with RTLD_NOW because that symbol is STT_GNU_IFUNC.

To reproduce:
$ cat libtest.c
#include <sys/cachectl.h>
#include <stdio.h>
#include <string.h>
int doit() {
  const char * foo = "ksfghkf";
  int r = __riscv_flush_icache(foo, foo + strlen(foo), 0);
  printf("__riscv_flush_icache: %d", r);
  return r;
}
$ cat testlib.c
#include <dlfcn.h>

int main( int argc, const char* argv[] ) {
  void* l = dlopen("libtest.so", RTLD_NOW);
  int (*f)() = dlsym(l, "doit");
  return f();
}
$ gcc -Wno-discarded-qualifiers -fPIC -g -shared libtest.c -o libtest.so
$ gcc -g -Wl,-ldl testlib.c -o testlib
$ env LD_LIBRARY_PATH=$(pwd) ./testlib
__riscv_flush_icache: 1431779388

- Changing RTLD_NOW to RTLD_LAZY will produce the expected output
(__riscv_flush_icache: 0).
- Some quick debugging shows that the "1431779388" output just comes from the
fact that __riscv_flush_icache return the pointer to the flushing function
rather than doing the flushing.
- My theory is that riscv's elf_machine_rela is missing the STT_GNU_IFUNC
support. This does not impact lazy linking because that goes through some other
path that doesn't need elf_machine_rela.
- The attached patch (ifunc.patch) adds support for STT_GNU_IFUNC to
elf_machine_rela by mimicking what some other architectures do and that fixes
my test case from above.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]