Is there an elegant way to avoid dlsym when using dlopen in C?

后端 未结 2 857
我在风中等你
我在风中等你 2020-12-05 12:20

I need to dynamically open a shared library lib.so if a specific condition is met at runtime. The library contains ~700 functions and I need to load all their s

2条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-05 12:53

    You could automatically generate trampoline functions for all symbols in dlopen-ed library. Trampolines would be seen as normal functions in application but would internally redirect to real code in library. Here's a simple 5-minute PoC:

    $ cat lib.h
    // Dynamic library header
    #ifndef LIB_H
    #define LIB_H
    extern void foo(int);
    extern void bar(int);
    extern void baz(int);
    #endif
    
    $ cat lib.c
    // Dynamic library implementation
    #include 
    
    void foo(int x) {
      printf("Called library foo: %d\n", x);
    }
    
    void bar(int x) {
      printf("Called library baz: %d\n", x);
    }
    
    void baz(int x) {
      printf("Called library baz: %d\n", x);
    }
    
    $ cat main.c
    // Main application
    #include 
    #include 
    
    #include 
    
    // Should be autogenerated
    void *fptrs[100];
    void init_trampoline_table(void *h) {
      fptrs[0] = dlsym(h, "foo");
      fptrs[1] = dlsym(h, "bar");
      fptrs[2] = dlsym(h, "baz");
    }
    
    int main() {
      void *h = dlopen("./lib.so", RTLD_LAZY);
      init_trampoline_table(h);
      printf("Calling wrappers\n");
      foo(123);
      bar(456);
      baz(789);
      printf("Returned from wrappers\n");
      return 0;
    }
    
    $ cat trampolines.S
      // Trampoline code.
      // Should be autogenerated. Each wrapper gets its own index in table.
      // TODO: abort if table wasn't initialized.
    
      .text
    
      .globl foo
    foo:
      jmp *fptrs
    
      .globl bar
    bar:
      jmp *fptrs+8
    
      .globl baz
    baz:
      jmp *fptrs+16
    
    $ gcc -fPIC -shared -O2 lib.c -o lib.so
    $ gcc -I. -O2 main.c trampolines.S -ldl
    $ ./a.out
    Calling wrappers
    Called library foo: 123
    Called library baz: 456
    Called library baz: 789
    Returned from wrappers
    

    Note that application code in main.c is using only local functions (which wrap library functions) and does not have to mess with function pointers at all (apart from initializing redirection table at startup which should be autogenerated code anyway).

    EDIT: I've created a standalone tool Implib.so to automate creation of stub libraries like in example above. This turned out to be more or less equivalent to well known Windows DLL import libraries.

提交回复
热议问题