我知道 dlsym() 返回的符号值可以为 NULL 的一种特殊情况,即在使用GNU 间接函数(IFUNC) 时。但是,可能还有其他情况,因为dlsym(3) 手册页中的文本早于 IFUNC 的发明。
这是一个使用 IFUNC 的示例。首先,将用于创建共享库的文件:
$ cat foo.c
/* foo.c */
#include <stdio.h>
/* This is a 'GNU indirect function' (IFUNC) that will be called by
dlsym() to resolve the symbol "foo" to an address. Typically, such
a function would return the address of an actual function, but it
can also just return NULL. For some background on IFUNCs, see
https://willnewton.name/uncategorized/using-gnu-indirect-functions/ */
asm (".type foo, @gnu_indirect_function");
void *
foo(void)
{
fprintf(stderr, "foo called\n");
return NULL;
}
现在是主程序,它将foo
在共享库中查找符号:
$ cat main.c
/* main.c */
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
void *handle;
void (*funcp)(void);
handle = dlopen("./foo.so", RTLD_LAZY);
if (handle == NULL) {
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any outstanding error */
funcp = dlsym(handle, "foo");
printf("Results after dlsym(): funcp = %p; dlerror = %s\n",
(void *) funcp, dlerror());
exit(EXIT_SUCCESS);
}
现在构建并运行以查看dlsym()
返回的情况NULL
,同时dlerror()
也返回NULL
:
$ cc -Wall -fPIC -shared -o libfoo.so foo.c
$ cc -Wall -o main main.c libfoo.so -ldl
$ LD_LIBRARY_PATH=. ./main
foo called
Results after dlsym(): funcp = (nil); dlerror = (null)