如何处理在OSX和Linux(通用)中dlsym()的不同行为

3

我最近在一个OSX程序中添加了一些动态插件行为,这个程序按设计工作正常。然而,在Linux(通用)上尝试同样的操作失败了,因为dlsym()库调用未能解析符号,而这种方式在OSX上运行良好。

从阅读man dlsym可以明显看出,两种架构中的系统调用实现非常不同,但我曾认为最基本的情况应该是相同的,但显然不是这样。

以下(虚假的)示例在OSX上正常工作,但在Linux上却无法工作。

是否有某种解决方法,使它在Linux中以相同的方式解析符号?

// Needed to make RTLD_DEFAULT available on GNU/Linux
#define _GNU_SOURCE

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

// Pointer to function returning int
typedef int (*pfi_t)(void);

// "Plugin" dummy function for illustrative purpose
int get_result(void) { return 42; }

int
main(int argc, char **argv) {

    // Resolve "plugin" function using the default handle which should,
    // according to documentation, search in global symbols and dependencies.
    pfi_t res_fnc = (pfi_t) dlsym(RTLD_DEFAULT, "get_result");

    if (NULL == res_fnc) {
        fprintf(stderr, "Cannot resolve symbol 'get_result'.\n");
        return EXIT_FAILURE;
    } else {
        fprintf(stdout, "Resolved symbol 'get_result'. get_result() = %d\n", (*res_fnc)());
    };

    return EXIT_SUCCESS;
}


在OSX(Monteray 12.5,Apple clang版本13.1.6)上运行结果为:
Resolved symbol 'get_result'. get_result() = 42
但是在Linux上(在Ubuntu 22.04.1和Ubuntu 18.04.6上测试),运行结果为:
Cannot resolve symbol 'get_result'。
备注:在Ubuntu 18.x上必须使用-ldl链接以解析dlsym()。

dlerror() 提供了任何有用的信息吗? - G.M.
奇怪的是,nm显示二进制文件中定义了get_result。我甚至添加了export以确保。但dlerror仅显示undefined symbol: get_result - stark
dlopendlsym等不是syscalls,它们只是普通的用户空间库函数。 - datenwolf
1个回答

3
一种解决方法是使用gcc的选项-Wl,-E或者-Wl,--export-dynamic告诉链接器将所有全局符号导出到动态符号表。为了更好的控制,-Wl,--export-dynamic-symbol=get_result告诉链接器只导出单个全局符号get_result。在等号后面的值上使用glob模式匹配。另外,-Wl,--export-dynamic-symbol-list=FILE从包含glob模式的文件FILE中获取需要导出的符号列表。编辑:@yugr指出,GCC选项-rdynamic等效于-Wl,--export-dynamic

2
还有一个选项是-rdynamic,它是-Wl,--export-dynamic的同义词。 - yugr
谢谢!在链接步骤中添加“-rdynamic”可以解析符号! - Johan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接