即使符号存在,dlsym也会返回NULL

我正在使用dlsym在我的程序中查找符号,但它总是返回NULL,这是我不期待的。 根据手册页,如果出现错误,dlsym可能会返回NULL,或者符号确实为NULL。 在我的情况下,我得到一个错误。 我会告诉你我今天晚上做的MCVE。

这里是instr.c的内容:

#include <stdio.h> void * testing(int i) { printf("You called testing(%d)\n", i); return 0; } 

一个非常简单的东西,只包含一个不起眼的示例函数。

这里是test.c的内容:

 #include <dlfcn.h> #include <stdlib.h> #include <stdio.h> typedef void * (*dltest)(int); int main(int argc, char ** argv) { /* Declare and set a pointer to a function in the executable */ void * handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); dlerror(); dltest fn = dlsym(handle, "testing"); if(fn == NULL) { printf("%s\n", dlerror()); dlclose(handle); return 1; } dlclose(handle); return 0; } 

当我用debugging器遍历代码时,我看到dlopen正在返回一个句柄。 根据手册页, If filename is NULL, then the returned handle is for the main program. 所以如果我把一个叫testing的符号链接到主程序中,dlsym应该find它,对吗?

这是我编译和链接程序的方式:

 all: test instr.o: instr.c gcc -ggdb -Wall -c instr.c test.o: test.c gcc -ggdb -Wall -c test.c test: test.o instr.o gcc -ldl -o test test.o instr.o clean: rm -f *.o test 

而当我build立这个程序,然后做objdump -t test | grep testing objdump -t test | grep testing ,我看到符号testing确实存在:

 08048632 g F .text 00000020 testing 

然而我的程序的输出是错误的:

 ./test: undefined symbol: testing 

我不知道我在做什么错。 如果有人能够解决这个问题,我将不胜感激。

我不认为你可以这样做, dlsym在导出的符号上工作。 因为你正在做NULL (当前图像)的dlsym ,即使符号存在于可执行的ELF图像中,它们也不会被导出(因为它不是共享库)。

为什么不直接调用它,让链接器照顾它呢? 使用dlsymdlsym调用中获取同一图像中的符号是毫无意义的。 如果你的testing符号是在你使用dlopen链接或加载的共享库中,那么你将能够检索它。

我相信在构建可执行文件时也有一种导出符号的方法( -Wl,--export-dynamic在Brandon的评论中提到的-Wl,--export-dynamic ),但我不确定为什么要这么做。