使用 LLVM 链接到动态库中的外部函数

Linking to external functions in dynamic libraries with LLVM

在我的项目中,我正在发出 LLVM IR,它调用动态库中的外部函数。

我这样声明我的外部函数:

declare %"my_type"* @"my_function"()

在外部库中,函数声明如下:

extern "C" {
    my_type* my_function();
}

当我编译 IR 并 运行 时,进程立即崩溃。如果我声明并调用一个我知道不存在的无意义函数,也会发生同样的行为,所以我假设发生的事情是外部函数不是 found/linked。 (我不认为函数本身会崩溃)。

我正在使用 Python 的 llvmlite 库来完成这项任务,并且在我 JIT 和调用我的 LLVM IR 的同一进程中,我导入了另一个 python 库需要外部动态库;所以我假设库已加载并在内存中。

我用来编译和执行我的 LLVM 代码的过程与 this document, except that the IR declares and invokes an external function. I have tried invoking cos(), as in the Kaleidoscope tutorial 中的基本相同并且成功了,所以我不确定我自己的库函数有什么不同。

我尝试在函数名的开头添加下划线,但我得到了相同的结果。 (需要在LLVM函数声明中加下划线吗?)


编辑:似乎确实很难将函数指针获取到我的外部函数。如果我尝试通过用 %"foo" = ptrtoint %"my_type"* ()* @"my_function" to i64 和 return/print 结果替换我的调用来仅打印函数地址,它仍然会出现段错误。仅仅试图获取指针就足以导致崩溃!为什么会这样,我该如何解决?

编辑:还忘了说——这是在 Ubuntu 上(在 Docker 容器中,在 OSX 上)。


我想通了——我想念我需要调用 llvmlite.binding.load_library_permanently(filename) 才能使外部符号可用。即使库已经在内存中,函数仍然需要被调用。 (这对应于 LLVM 原生函数 llvm::sys::DynamicLibrary::LoadLibraryPermanently())。

开始,使用 nullptr 调用上述函数似乎将导入进程可用的所有符号。

奇怪的是,在 OSX 上,我发现即使没有明确调用 load_library_permanently() 也可以使用外部符号——我不确定这是为什么(也许是 OSX llvmlite 的构建本身碰巧用 nullptr 调用函数,如上所述?)。