LuaJIT FFI无法从可执行文件中加载符号

3

第一个 Lua 代码:

local ffi = require "ffi"

ffi.cdef[[
void printc(const char *fmt, ...);
]]
ffi.C.printc("Hello world")

无法工作。 错误:

boot.lua:6: /usr/lib64/libluajit-5.1.so.2: undefined symbol: printc

然而,实际上这个符号是在LuaJIT正在运行的可执行文件中定义的(而函数声明是从C语言复制并粘贴来的):

$ nm --defined-only build/a.out | grep printc
00000000000650c1 T printc

我的第一个解决方案是构建一个与可执行文件具有相同符号的共享库,并在LuaJIT中加载它:

$ cc -fPIC -shared $LDFLAGS $OFILES -o build/a.so

新的Lua代码:

local ffi = require "ffi"
lib = ffi.load("./build/a.so")
ffi.cdef[[
void printc(const char *fmt, ...);
]]
lib.printc("Hello world")

这使我能够调用printc函数。然而,有一个很大的问题:已加载库使用与运行程序不同的内存空间。 lib.printc(“Hello world”)正在写入的缓冲区与LuaJIT正在运行的程序所使用的缓冲区不同。它就像与完全不同的进程交互一样。 printc应该打印到LuaJIT内部运行的可执行文件的控制台子系统。控制台缓冲区被存储为一个全局的(外部)字符串数组,printc会向其写入数据。 LuaJIT通过加载a.so得到的全局控制台缓冲区指向与运行a.out程序的全局控制台缓冲区不同的某个内存地址。
因此,这不是可行的解决方案。我不知道现在该怎么办。符号作为我的可执行文件的一部分被导出,但是LuaJIT没有加载它们。我也无法使用ffi.load来加载我的可执行文件:
lib = ffi.load("./build/a.out")

boot.lua:2: ./build/a.out: cannot dynamically load position-independent executable

我该如何让LuaJIT FFI从我的正在运行的可执行文件中加载符号?

不是专家,但可以尝试使用 objdump -t ./build/a.out 命令,查看该符号是否存在于可执行文件中 :) - DarkWiiPlayer
当链接时,您可能需要使用“-Wl,-E”从可执行文件中导出符号。 - lhf
@DarkWiiPlayer 这就是 nm --defined-only 的作用。这里是 objdump -t build/a.out| grep printc 的输出结果:000000000001abd1 g F .text 0000000000000179 printc - Accumulator
使用“-E”选项的建议没有起作用,但是它让我找到了“-rdynamic”标志,这确实解决了问题。 - Accumulator
1个回答

1
-rdynamic标志传递给cc可以解决此问题,允许LuaJIT从程序中运行ffi.C.*函数。

对于这个答案的简短解释,请参阅 https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html 中的 "export-dynamic"。当指定了 -rdynamic 选项时,gcc 在链接过程中将此选项传递给 ld(/collect2)。 - i336_

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