2013-07-05 43 views
2

我们有一个系统在很大程度上依赖使用dlopen()加载模块。我们的模块是自描述的,带有一个符号,指向与加载模块相关的一些元数据(描述,加载顺序,加载标志等)。如何获取函数地址时的RTLD_LAZY行为?

我们首先加载指定RTLD_LAZY标志模块dlopen的(),让我们从元数据的需要,然后加载模块,真正以后(在我们知道的加载顺序应该是什么,他们如何应加载等)。

这一段时间工作得很好,但我们最近发现,获取函数地址需要在加载时解析函数。我们可以通过哪些方法解决此问题?

我已经把一个相当小的例子演示了这个问题。

/* foo.h */ 
void foo(void); 

/* foo.c */ 
void foo(void) {} 

/* bar.c */ 
#include "foo.h" 
/* Calls foo normally */ 
void bar(void) { foo(); } 

/* bam.c */ 
#include "foo.h" 
static void (*f)(void); 
/* Takes the address of foo */ 
void bam(void) { f = foo; } 

/* rtld_lazy.c */ 
#include <dlfcn.h> 
#include <stdio.h> 

void check(const char *module) { 
    void *mod = dlopen(module, RTLD_LAZY); 
    if (mod) { 
    printf("%s successfully loaded\n", module); 
    dlclose(mod); 
    } else { 
    printf("%s failed to load: %s\n", module, dlerror()); 
    } 
} 

int main() { 
    check("./bar.so"); 
    check("./bam.so"); 
    check("./foo.so"); 
} 

用下面的输出:

./bar.so successfully loaded 
./bam.so failed to load: ./bam.so: undefined symbol: foo 
./foo.so successfully loaded 

回答

0

我们已经想出了两种方法来解决此问题的工作,视情况而定。

第一个是在调用者的模块中,为函数写一个小的静态包装器。静态包装将动态绑定到有问题的函数,并且您可以毫无问题地获取该函数的地址。

/* bam.c */ 
#include "foo.h" 
static void (*f)(void); 
static void foo_wrapper(void) { foo(); } 
/* Takes the address of foo */ 
void bam(void) { f = foo_wrapper; } 

如果你发现自己写很多这个小包装的,可以改为把它返回你需要到提供模块函数指针的函数。

/* foo.h */ 
void foo(void); 
typedef void (*foo_ptr_type)(void); 
foo_ptr_type foo_ptr(void); 

/* foo.c */ 
void foo(void) {} 
foo_ptr_type foo_ptr(void) { return foo; } 

/* bam.c */ 
#include "foo.h" 
static void (*f)(void); 
/* Takes the address of foo */ 
void bam(void) { f = foo_ptr(); }