c - dlopen: detect undefined symbols with cyclic dependencies -
i have handful of shared libraries cyclic dependencies, want load dlopen
. this, call dlopen
rtld_lazy | rtld_global
flags.
this works fine.
now, want check symbols in shared libraries resolved, , therefore call dlopen
again rtld_now
, should fail if symbols can not resolved.
at least, how understand man page:
however, subsequent dlopen() call loads same shared object rtld_now may force symbol resolution shared object earlier loaded rtld_lazy.
here simple example illustrates problem:
main.h
#include <stdio.h> #include <dlfcn.h> #include <stdlib.h> #include "h.h" #define cnt 3 static const char *libs[cnt] = {"./liba.so", "./libb.so", "./libc.so"}; typedef int (*f_ptr)(); int main() { void *h[cnt]; f_ptr f[cnt]; (int = 0; < cnt; i++) { printf("dlopen: %s\n", libs[i]); h[i] = dlopen(libs[i], rtld_lazy | rtld_global); if (!h[i]) { fprintf(stderr, "%d %s: %s\n", __line__, libs[i], dlerror()); exit(exit_failure); } } (int = 0; < cnt; i++) { printf("dlopen again: %s\n", libs[i]); void *xx = dlopen(libs[i], rtld_now | rtld_global); if (!xx) { fprintf(stderr, "%d %s: %s\n", __line__, libs[i], dlerror()); dlclose(h[i]); h[i] = 0; } else { dlclose(xx); } } (int = 0; < cnt; i++) { if (h[i]) { f[i] = (int (*)())dlsym(h[i], "init"); if (!f[i]) { fprintf(stderr, "%d %s: %s\n", __line__, libs[i], dlerror()); exit(exit_failure); } } } (int = 0; < cnt; i++) { if (f[i]) { printf("%s %08d\n", libs[i], f[i]()); } } return 0; }
a.c
#include "h.h" int init() { return 1 + b_(); } int a_() { return 10; }
b.c
#include "h.h" int init() { return 100 + a_(); } int b_() { return 1000; }
c.c
#include "h.h" int init() { return 10000 + x_(); } int c_() { return 100000; }
h.h
int init(); int a_(); int b_(); int x_();
cmakelists.txt
project(xx) add_library(a shared a.c) add_library(b shared b.c) add_library(c shared c.c) add_executable(main main.c) target_link_libraries(main dl)
compile , run:
$ mkdir b && cd b && cmake .. && make && ./main ... [100%] built target b dlopen: ./liba.so dlopen: ./libb.so dlopen: ./libc.so dlopen again: ./liba.so dlopen again: ./libb.so dlopen again: ./libc.so ./liba.so 00001001 ./libb.so 00000110 ./main: symbol lookup error: ./libc.so: undefined symbol: x_
how can detect libc.so not loaded - before calling symbol cause crash?
ideally you'd want put burden of symbol cross-matching on static linker suggested others (via --no-allow-shlib-undefined) rather delaying startup. it's bit complicated cyclic dependencies solaris (of linux shlibs bleak copy) has come clever solution - shlib filters. idea link against dummy shlibs export equally dummy symbols , have same sonames final production libraries. these of course used @ link time verify dependencies.
as side note, i'm pretty sure generation of dummy libs can automated, following:
- build lib without --no-allow-shlib-undefined
- use readelf or whatever extract exported symbols
- generate dummy c (or asm) file defines empty stubs symbols previous item
- build lib , voila - you've built first filter
hm, sounds nice mini-project evening.
Comments
Post a Comment