2013-01-12 40 views
5

Có hy vọng chạy dlopen(NULL, ...) và nhận biểu tượng cho nhị phân được biên dịch tĩnh không?Sử dụng dlsym trên nhị phân tĩnh

Ví dụ: với mã sau tôi có thể nhận được biểu tượng nếu chương trình được biên dịch động và tôi sử dụng -rdynamic.

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

Nhưng với -static tôi nhận được một thông báo lỗi khó hiểu:

$ 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 

Nguồn cho foo.c sau:

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

Trả lời

4

Không còn hi vọng chạy dlopen (NULL,. ..) và nhận các biểu tượng cho một nhị phân được biên dịch tĩnh?

số

Trên hầu hết các UNIXes bạn thậm chí không thể liên kết với -static-ldl cùng một lúc. Sử dụng glibc bạn có thể, nhưng tiện ích làm như vậy là rất bị giới hạn. Về cơ bản, khả năng này chỉ xuất hiện để hỗ trợ /etc/nsswitch.conf, và không có gì khác.

Ngoài ra còn có không có điểm khi thực hiện tra cứu động bạn đã làm.

Nếu bạn đang cố gắng cho phép một trong số foo, bar hoặc baz được gọi tùy thuộc vào đối số dòng lệnh, chỉ cần đặt bảng vào, ví dụ:

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)(); 

Nếu bạn đang cố gắng để "có thể" gọi foo nếu nó được liên kết trong, và không làm gì khác, sau đó sử dụng tài liệu tham khảo yếu:

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

if (&foo != 0) { 
    // foo was linked in, call it 
    foo(); 
} 
Các vấn đề liên quan