使用 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函数声明中加下划线吗?)
- 如何验证我的假设,即进程因未找到命名函数而崩溃?
- 如何诊断未找到函数的原因?
- 我需要做什么才能从 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
调用函数,如上所述?)。
在我的项目中,我正在发出 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函数声明中加下划线吗?)
- 如何验证我的假设,即进程因未找到命名函数而崩溃?
- 如何诊断未找到函数的原因?
- 我需要做什么才能从 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
调用函数,如上所述?)。