在C中使用dlopen时,有没有一种优雅的方法来避免dlsym? [英] Is there an elegant way to avoid dlsym when using dlopen in C?

查看:142
本文介绍了在C中使用dlopen时,有没有一种优雅的方法来避免dlsym?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果在运行时满足特定条件,我需要动态打开共享库lib.so.该库包含约700个函数,我需要加载它们的所有符号.

一个简单的解决方案是定义指向lib.so中包含的所有符号的函数指针,使用dlopen加载库,最后使用dlsym获取所有符号的地址.但是,鉴于功能的数量,实现此解决方案的代码非常繁琐.

我想知道是否存在一个更优雅,更简洁的解决方案,也许是通过适当地使用宏来定义函数指针.谢谢!

解决方案

您可以为dlopen -ed库中的所有符号自动生成蹦床功能.蹦床将在应用程序中被视为正常功能,但会在内部重定向到库中的实际代码.这是一个简单的5分钟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 <stdio.h>

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 <dlfcn.h>
#include <stdio.h>

#include <lib.h>

// 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

请注意,main.c中的应用程序代码仅使用局部函数(包装库函数),而完全不必弄乱函数指针(除了在启动时初始化重定向表之外,该表无论如何都应该是自动生成的代码). /p>

编辑:我创建了一个独立的工具 Implib.so 像上面的示例一样自动创建存根库.事实证明,这几乎等同于众所周知的Windows DLL导入库.

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 symbols.

A simple solution is to define the function pointers to all symbols contained in lib.so, load the library using dlopen and finally get the addresses of all symbols using dlsym. However, given the number of functions, the code implementing this solution is very cumbersome.

I was wondering if a more elegant and concise solution exists, maybe with an appropriate use of macros for defining the function pointers. Thanks!

解决方案

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 <stdio.h>

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 <dlfcn.h>
#include <stdio.h>

#include <lib.h>

// 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.

这篇关于在C中使用dlopen时,有没有一种优雅的方法来避免dlsym?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆