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

Wil*_*son 8 c linux dlsym

我正在使用dlsym在我的程序中查找符号,但它总是返回NULL,这是我没想到的.根据联机帮助页,如果某种方式存在错误,或者符号确实为NULL,则dlsym可能返回NULL.在我的情况下,我收到一个错误.我会告诉你我今晚做的MCVE.

这是instr.c的内容:

#include <stdio.h>

void * testing(int i) {
    printf("You called testing(%d)\n", i);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

这是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;
}
Run Code Online (Sandbox Code Playgroud)

当我使用调试器逐步执行代码时,我看到dlopen正在返回一个句柄.根据联机帮助页,If filename is NULL, then the returned handle is for the main program.如果我将一个符号链接testing到主程序中,dlsym应该找到它,对吧?

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

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
Run Code Online (Sandbox Code Playgroud)

当我构建这个程序,然后做objdump -t test | grep testing,我看到符号testing确实在那里:

08048632 g     F .text  00000020              testing
Run Code Online (Sandbox Code Playgroud)

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

./test: undefined symbol: testing
Run Code Online (Sandbox Code Playgroud)

我不确定我做错了什么.如果有人能对这个问题有所了解,我将不胜感激.

Kri*_*oks 5

我不认为你能做到这一点,dlsym适用于导出的符号.因为你正在做dlsymNULL(当前图像),即使符号存在的ELF可执行图像中,他们没有出口(因为它不是一个共享库).

为什么不直接调用它并让链接器来处理呢?使用dlsym从与dlsym调用相同的图像中获取符号是没有意义的.如果您的testing符号位于您使用链接或加载的共享库中,dlopen那么您将能够检索它.

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

  • "使用dlsym从与你的dlsym调用相同的图像中获取符号是没有意义的,并且"我不确定你为什么要这样做.这是非常适得其反的事情.有用例. (2认同)