Verified by experiment:
$ cat prog.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int
callback(struct dl_phdr_info *info, size_t size, void *data)
{
printf("\tName = %s\n", info->dlpi_name);
return 0;
}
int
main(int argc, char *argv[])
{
void *x1Handle, *x2Handle, *yHandle;
void (*funcp)(void);
char *err;
x1Handle = dlopen("./lib_x1.so", RTLD_NOW | RTLD_LOCAL);
if (x1Handle == NULL) {
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE);
}
if (argc > 1) {
x2Handle = dlopen("./lib_x2.so", RTLD_NOW | RTLD_GLOBAL);
if (x2Handle == NULL) {
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE);
}
}
yHandle = dlopen("./lib_y1.so", RTLD_NOW | RTLD_LOCAL);
if (yHandle == NULL) {
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE);
}
(void) dlerror(); /* Clear dlerror() */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
funcp = (void (*)(void)) dlsym(yHandle, "y1_enter");
#pragma GCC diagnostic pop
err = dlerror();
if (err != NULL) {
fprintf(stderr, "dlsym: %s", err);
exit(EXIT_FAILURE);
}
(*funcp)();
exit(EXIT_SUCCESS);
}
$ cat lib_x1.c
#include <stdio.h>
void
x1_enter(void)
{
printf("Called %s::%s\n", __FILE__, __func__);
}
$ cat lib_x2.c
#include <stdio.h>
void
testfunc(void)
{
printf("Called %s::%s\n", __FILE__, __func__);
}
$ cat lib_y1.c
#include <stdio.h>
void
testfunc(void)
{
printf("Called %s::%s\n", __FILE__, __func__);
}
void
y1_enter(void)
{
extern void y2(void);
printf("Called %s\n\n", __func__);
testfunc();
}
$ cat Build.sh
#!/bin/sh
CFLAGS="-Wno-implicit-function-declaration -Wl,--no-as-needed"
cc $CFLAGS -g -fPIC -shared -o lib_x2.so lib_x2.c
cc $CFLAGS -g -fPIC -shared -o lib_x1.so lib_x1.c ./lib_x2.so
cc $CFLAGS -g -fPIC -shared -o lib_y1.so lib_y1.c
cc $CFLAGS -o prog prog.c -ldl
$ sh Build.sh
$ ./prog
Called y1_enter
Called lib_y1.c::testfunc
$ ./prog x
Called y1_enter
Called lib_x2.c::testfunc
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
.B RTLD_NOW
may force symbol resolution for a shared object earlier loaded with
.BR RTLD_LAZY .
+Similarly, an object that was previously opened with
+.BR RTLD_LOCAL
+can be promoted to
+.BR RTLD_GLOBAL
+in a subsequent
+.BR dlopen ().
.PP
If
.BR dlopen ()