7

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;
}
4

1 に答える 1

7

dlopen(NULL、...)を実行し、静的にコンパイルされたバイナリのシンボルを取得する希望はありますか?

いいえ。

-staticほとんどのUNIXでは、-ldl同時にリンクすることさえできません。glibcを使用することはできますが、そうすることの有用性は非常に限られています。基本的に、この機能は/etc/nsswitch.confをサポートするためにのみ存在し、他には何もありません。

また、実行した動的ルックアップを実行しても意味がありません。

のいずれかを許可しようとしている場合foobarまたはbazコマンドライン引数に応じて呼び出される場合は、たとえば、テーブルを挿入します。

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();
}
于 2013-03-18T06:33:53.123 に答える