This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug dynamic-link/24868] New: STT_GNU_IFUNC do not link correctly on RISC-V
- From: "gilles.m.duboscq at gmail dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Thu, 01 Aug 2019 17:28:16 +0000
- Subject: [Bug dynamic-link/24868] New: STT_GNU_IFUNC do not link correctly on RISC-V
- Auto-submitted: auto-generated
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.