Consider 3 libraries: libA, libB and libC. Only library libB implements and exports the function public_function().
A program dlopen()s libA then libB then libC. Then the program calls dlsym(libA, "public_function") then dlsym(libB, "public_function") then dlsym(libC, "public_function").
Expected behavior:
dlsym(libA, "public_function") and dlsym(libC, "public_function") return NULL, and
dlsym(libB, "public_function") returns a non-NULL address.
Erroneous behavior:
dlsym(libC, "public_function") return NULL, and
dlsym(libA, "public_function") and dlsym(libB, "public_function") returns the same non-NULL address.
Program to reproduce this issue:
// dlsym-test1.c#include<stdio.h>#include<dlfcn.h>typedefvoid(*public_function_t)();
intmain(){
int i;
void* lib[3] = {};
void* lib_name[3] = {"liba.so", "libb.so", "libc.so"};
public_function_t public_function[3] = {};
for (i = 0; i < 3; ++i) {
lib[i] = dlopen(lib_name[i], RTLD_NOW | RTLD_LOCAL);
}
for (i = 0; i < 3; ++i) {
if (lib[i] != NULL) {
public_function[i] = dlsym(lib[i], "public_function");
}
}
for (i = 0; i < 3; ++i) {
printf("%s:%#x public_function:%#x.\n", lib_name[i], lib[i], public_function[i]);
}
for (i = 0; i < 3; ++i) {
if (public_function[i] != NULL) {
(public_function[i])();
}
}
return0;
}
Consider 3 libraries:
libA
,libB
andlibC
. Only librarylibB
implements and exports the functionpublic_function()
.A program
dlopen()
slibA
thenlibB
thenlibC
. Then the program callsdlsym(libA, "public_function")
thendlsym(libB, "public_function")
thendlsym(libC, "public_function")
.Expected behavior:
dlsym(libA, "public_function")
anddlsym(libC, "public_function")
returnNULL
, anddlsym(libB, "public_function")
returns a non-NULL
address.Erroneous behavior:
dlsym(libC, "public_function")
returnNULL
, anddlsym(libA, "public_function")
anddlsym(libB, "public_function")
returns the same non-NULL
address.Program to reproduce this issue:
// dlsym-test1.c #include <stdio.h> #include <dlfcn.h> typedef void (*public_function_t)(); int main() { int i; void* lib[3] = {}; void* lib_name[3] = {"liba.so", "libb.so", "libc.so"}; public_function_t public_function[3] = {}; for (i = 0; i < 3; ++i) { lib[i] = dlopen(lib_name[i], RTLD_NOW | RTLD_LOCAL); } for (i = 0; i < 3; ++i) { if (lib[i] != NULL) { public_function[i] = dlsym(lib[i], "public_function"); } } for (i = 0; i < 3; ++i) { printf("%s:%#x public_function:%#x.\n", lib_name[i], lib[i], public_function[i]); } for (i = 0; i < 3; ++i) { if (public_function[i] != NULL) { (public_function[i])(); } } return 0; }
// libb.c #include <stdio.h> void public_function() __attribute__ ((visibility ("default"))); void public_function() { puts("libB::public_function()"); }
#!/bin/bash CROSS_COMPILE=... CC=${CROSS_COMPILE}gcc CFLAGS='-fvisibility=hidden -O0 -g -Wextra -Werror' rm *.so dlsym-test1 $CC $CFLAGS -fPIC -shared -o liba.so empty.c $CC $CFLAGS -fPIC -shared -o libb.so libb.c $CC $CFLAGS -fPIC -shared -o libc.so empty.c $CC $CFLAGS -fPIE -pie '-Wl,-rpath=$ORIGIN' -o dlsym-test1 dlsym-test1.c
$ ./dlsym-test1 liba.so:0x80579160 public_function:0xb6eb9584. libb.so:0x80579348 public_function:0xb6eb9584. libc.so:0x80579520 public_function:0. libB::public_function() libB::public_function()
This project seems dead.