在静态二进制文件上使用dlsym

时间:2013-01-12 02:12:32

标签: static-linking dlopen dlsym

是否有希望运行dlopen(NULL, ...)并为静态编译的二进制文件获取符号?

例如,如果程序是动态编译的,我可以使用以下代码获取符号,并使用-rdynamic

$ gcc -o foo foo.c -ldl -rdynamic
$ ./foo bar
In bar!

但是-static我收到一条含糊不清的错误信息:

$ gcc -static -o foo foo.c -ldl -rdynamic
/tmp/cc5LSrI5.o: In function `main':
foo.c:(.text+0x3a): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
$ ./foo bar
/lib/x86_64-linux-gnu/: cannot read file data: Is a directory

foo.c的来源如下:

#include <dlfcn.h>
#include <stdio.h>

int foo() { printf("In foo!\n"); }
int bar() { printf("In bar!\n"); }

int main(int argc, char**argv)
{
  void *handle;
  handle = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
  if (handle == NULL) {
    fprintf(stderr, "%s\n", dlerror());
    return 1;
  }

  typedef void (*function)();
  function f = (function) dlsym(handle, argv[1]);
  if (f == NULL) {
    fprintf(stderr, "%s\n", dlerror());
    return 2;
  }
  f();

  return 0;
}

1 个答案:

答案 0 :(得分:5)

  

是否有希望运行dlopen(NULL,...)并获取静态编译二进制文件的符号?

没有

在大多数UNIX上,您甚至无法同时与-static-ldl相关联。你可以使用glibc,但这样做的效用是非常有限。基本上,这种能力只是为了支持/etc/nsswitch.conf,而不是其他任何东西。

在进行动态查找时,还有无点

如果您尝试根据命令行参数调用foobarbaz之一,只需放入一个表格,例如

struct { const char *fname, void (*fn)(void) } table[] =
  { {"foo", &foo}, {"bar", &bar}, ...};

for (int i = 0; i < ...; ++i)
  if (strcmp(argv[1], table[i].fname) == 0)
    // found the entry, call it
    (*table[i].fn)();

如果你试图“或许”调用foo如果它被链接,否则什么都不做,那么使用弱引用:

extern void foo(void) __attribute((weak));

if (&foo != 0) {
  // foo was linked in, call it
  foo();
}