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>
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() ```
--- Dr. Koutheir Attouchi.