如果我还必须链接到 RPM 库——特别是 lirpmio.so,我就很难运行一个使用 Lua(5.2 版)的程序。这是一个大型应用程序的一部分,该应用程序包含多个也使用 Lua 的共享库。
潜在的问题是我们使用的 librpmio.so 版本(4.4.X)中嵌入了一个 Lua 解释器,它没有隐藏 Lua 代码中包含的全局符号。 Lua 的 rpmio 版本 (5.0.2) 比我们使用的 Lua (5.2.x) 旧,因此它们不能完全互换。
到目前为止,我无法让我们自己的 Lua 代码和 RPM API 调用 正常工作。像 lua_pushlstring() 这样的 Lua API 将绑定(bind) liblua.so 或 lirpmio.so 中最先出现在加载模块链中的那个。如果我早些时候在链接器命令行上指定 -llua,那么我们所有的代码都可以正常工作,但对 RPM API 的调用最终会崩溃。如果 -lrpmio 早于我们的代码最终将崩溃,因为一些 Lua 调用最终使用 librpmio 的 Lua 副本。
我尝试对 liblua. 中的符号进行版本控制,以便我们使用这样的版本脚本进行构建:
LUA_5.2 {
global:
lua_*;
luaL_*;
local: *;
};
但这还不够,因为 librpmio.so 使用未版本化的符号,并且上面的版本脚本创建了符号的 LUA_5.2 版本加上“默认”版本。运行时绑定(bind)似乎更倾向于 liblua.so 中的未版本化符号而不是 lirpmio.so,即使前者在链中更早:
19075: symbol=lua_pushlstring; lookup in file=output/Linux64/bin/myapp [0]
19075: symbol=lua_pushlstring; lookup in file=/home/output/Linux64/lib/lib1.so [0]
19075: symbol=lua_pushlstring; lookup in file=/home/output/Linux64/lib/lib2.so [0]
19075: symbol=lua_pushlstring; lookup in file=/home/output/Linux64/lib/lib3.so [0]
19075: symbol=lua_pushlstring; lookup in file=/home/lib/libwx_base-2.8.so.0 [0]
19075: symbol=lua_pushlstring; lookup in file=/home/lib/libsqlite.so [0]
19075: symbol=lua_pushlstring; lookup in file=/home/lib/libssl.so.0.9.8 [0]
19075: symbol=lua_pushlstring; lookup in file=/home/lib/libcrypto.so.0.9.8 [0]
19075: symbol=lua_pushlstring; lookup in file=/lib64/libacl.so.1 [0]
19075: symbol=lua_pushlstring; lookup in file=/usr/lib64/librpm-4.4.so [0]
19075: symbol=lua_pushlstring; lookup in file=/home/lib/liblua.so [0]
19075: binding file /usr/lib64/librpmio-4.4.so [0] to /home/lib/liblua.so [0]: normal symbol `lua_pushlstring'
请注意最后一行 - 它正在针对我的 liblua 解决 librpmio 中 lua_pushlstring 的绑定(bind)。
我可以通过设置 -Bsymbolic 来解决这个问题librpmio.so 上的标志,但这是我们无法控制的系统库,谁知道可能会导致什么其他问题。我想如果我可以在我的 liblua.so 中消除每个 Lua 符号的默认版本的创建,我可能能够解决这个问题,但我一直无法弄清楚如何从版本脚本中做到这一点。 GNU version script文档仅显示如何通过 __asm__
指令执行此操作。
除了创建一个包含如下一堆行的文件并将其与我的 Lua 构建链接之外,还有其他想法吗?
__asm__(".symver lua_pushlstring,lua_pushlstring@LUA_5.2");
最佳答案
为了那些在搜索中遇到我的问题的人,我能够在不对我们的 Lua 源副本进行大量更改的情况下解决问题的唯一方法是动态加载所有 RPM 库。
用于对所有 Lua 符号进行版本控制而不让它们与未版本控制的符号匹配的 __asm__
技术要求 __asm__
指令位于定义符号的源模块中,这意味着需要为大量 Lua 文件打补丁。
我们只需要 12-15 RPM API,所以我想到的解决方案是使用 dlopen() 动态加载 lirpmio、librpm 和 lirpmdb(后者仅存在于 RPM <= 4.5 中)共享库。调用 dlopen() 时,我为标志指定了 RTLD_NOW|RTLD_LOCAL|RTLD_DEEPBIND。这会导致在内部解析 RPM 库中的 Lua(和其他)符号。
我必须使用 dlsym() 来获取我们使用的任何 RPM API 的地址,但至少这可以防止 librpmio 的 Lua 与我们较新的 Lua 发生冲突。
关于linux - 由于 librpmio.so 导致 Lua API 符号冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14901119/