Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
dlopen does not respect RTLD_LAZY
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
oscarbacho
n00b
n00b


Joined: 01 Nov 2024
Posts: 1

PostPosted: Fri Nov 01, 2024 11:15 pm    Post subject: dlopen does not respect RTLD_LAZY Reply with quote

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
View user's profile Send private message
pingtoo
Veteran
Veteran


Joined: 10 Sep 2021
Posts: 1219
Location: Richmond Hill, Canada

PostPosted: Fri Nov 01, 2024 11:59 pm    Post subject: Reply with quote

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
View user's profile Send private message
Ionen
Developer
Developer


Joined: 06 Dec 2018
Posts: 2840

PostPosted: Sat Nov 02, 2024 12:10 am    Post subject: Reply with quote

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
View user's profile Send private message
GDH-gentoo
Veteran
Veteran


Joined: 20 Jul 2019
Posts: 1675
Location: South America

PostPosted: Sat Nov 02, 2024 5:14 pm    Post subject: Reply with quote

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;
   }
   void (*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;
   }
   void (*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 -Wl,-z,lazy -o lazy lazy.c
$ gcc -Wl,-z,lazy -o now now.c
$ gcc -shared -Wl,-z,lazy -fPIC -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 -fPIC -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
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
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