View previous topic :: View next topic |
Author |
Message |
oscarbacho n00b
Joined: 01 Nov 2024 Posts: 1
|
Posted: Fri Nov 01, 2024 11:15 pm Post subject: dlopen does not respect RTLD_LAZY |
|
|
Hello guys
I am trying to run truffleruby on Gentoo, it builds successfully and also the C based extensions but the thing is that I am getting an error when it tries to load the shared library.
I reached out to the trufffleruby development team and they said that they are using dlopen with the RTKD_LAZY which it seems it not working on Gentoo.
We did some basic test to rule out any truffleruby particularities
Code: |
lib.c
cat lib.c
void bar();
void foo()
{
bar();
}
cat lazy.c
#include <dlfcn.h>
#include <stdio.h>
int
main(int argc, char **argv)
{
void *lib = dlopen("./libtest.so", RTLD_LAZY);
if (!lib) {
printf("error: %s\n", dlerror());
return 0;
}
int (*a)() = dlsym(lib, "foo");
printf("a: %p\n", a);
(*a)();
dlclose(lib);
return 1;
}
now.c
#include <dlfcn.h>
#include <stdio.h>
int
main(int argc, char **argv)
{
void *lib = dlopen("./libtest.so", RTLD_NOW);
if (!lib) {
printf("error: %s\n", dlerror());
return 0;
}
int (*a)() = dlsym(lib, "foo");
printf("a: %p\n", a);
(*a)();
dlclose(lib);
return 1;
}
./lazy
error: ./libtest.so: undefined symbol: bar
./now
error: ./libtest.so: undefined symbol: bar
|
We were expecting ./lazy: symbol lookup error:
dlopen() and RTLD_LAZY are POSIX so IMO this shows Gentoo is incompatible with POSIX for dlopen(), which does sound like a bug (or if intentional it should be clearly documented, still sounds bad to not be POSIX-compliant). |
|
Back to top |
|
|
pingtoo Veteran
Joined: 10 Sep 2021 Posts: 1219 Location: Richmond Hill, Canada
|
Posted: Fri Nov 01, 2024 11:59 pm Post subject: |
|
|
oscarbacho,
Your example code have one problem and it is showed in the execution result.
The "bar" function only declared in lib.c as in "vold bar();" There is no function implementation code in lib.c.
The missing "bar" function implementation code actually exist and you just not showing?
It would be better you also share how you "link" everything together. Something it matter what link flag(s) were used. |
|
Back to top |
|
|
Ionen Developer
Joined: 06 Dec 2018 Posts: 2840
|
Posted: Sat Nov 02, 2024 12:10 am Post subject: |
|
|
Note that Gentoo defaults to -Wl,-z,now in 23.0 profiles for security reasons (like many other distros), and with gcc and clang this is done regardless of LDFLAGS to ensure it's used (for clang this is done in /etc/clang, for gcc this is USE=default-znow on gcc).
Lazy bindings are becoming somewhat abandoned due to security reasons, and not many packages need it to function (best known exception is Xorg and its modules, which is broken without it and passed -Wl,-z,lazy in xorg-3.eclass to override that, don't know about your example but Xorg does work fine on Gentoo that way). |
|
Back to top |
|
|
GDH-gentoo Veteran
Joined: 20 Jul 2019 Posts: 1675 Location: South America
|
Posted: Sat Nov 02, 2024 5:14 pm Post subject: |
|
|
In other words, RTLD_LAZY can be overridden, including, for example, by passing the -z now linker option (which Gentoo's compilers implicitly do when using 23.0 profiles), which marks the resulting ELF shared object file in a special way. Here are complete examples:
lib.c
Code: | void bar();
void foo()
{
bar();
} | lazy.c
Code: | #include <dlfcn.h>
#include <stdio.h>
int main() {
void *lib = dlopen("./libtest.so", RTLD_LAZY);
if (!lib) {
fprintf(stderr, "dlopen(): %s\n", dlerror());
return 1;
}
int (*a)() = dlsym(lib, "foo");
if (!a) {
fprintf(stderr, "dlsym(): %s\n", dlerror());
return 1;
}
a();
printf("Everything is OK\n");
return 0;
} | now.c
Code: | #include <dlfcn.h>
#include <stdio.h>
int main() {
void *lib = dlopen("./libtest.so", RTLD_NOW);
if (!lib) {
fprintf(stderr, "dlopen(): %s\n", dlerror());
return 1;
}
int (*a)() = dlsym(lib, "foo");
if (!a) {
fprintf(stderr, "dlsym(): %s\n", dlerror());
return 1;
}
a();
printf("Everything is OK\n");
return 0;
} |
Code: | $ diff lazy.c now.c
5c5
< void *lib = dlopen("./libtest.so", RTLD_LAZY);
---
> void *lib = dlopen("./libtest.so", RTLD_NOW);
$ gcc -o lazy lazy.c
$ gcc -o now now.c
$ gcc -shared -Wl,-z,lazy -o libtest.so lib.c
$ readelf -d libtest.so | grep FLAGS
$ ./lazy
./lazy: symbol lookup error: ./libtest.so: undefined symbol: bar
$ ./now
dlopen(): ./libtest.so: undefined symbol: bar
$ gcc -shared -Wl,-z,now -o libtest.so lib.c
$ readelf -d libtest.so | grep FLAGS
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW
$ ./lazy
dlopen(): ./libtest.so: undefined symbol: bar
$ ./now
dlopen(): ./libtest.so: undefined symbol: bar |
_________________
NeddySeagoon wrote: | I'm not a witch, I'm a retired electronics engineer |
Ionen wrote: | As a packager I just don't want things to get messier with weird build systems and multiple toolchains requirements though |
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|