由于librpmio.so导致Lua API符号冲突



如果我还必须链接到RPM库,特别是librpmio.so,那么我很难让一个使用Lua(5.2版)的程序正常工作。这是一个大型应用程序的一部分,该应用程序有几个共享库,也使用Lua。

潜在的问题是,我们使用的librpmio.so版本(4.4.X)中嵌入了一个Lua解释器,并且它没有隐藏Lua代码中包含的全局符号。rpmio版本的Lua比我们使用的Lua(5.2.x)旧(5.0.2),所以它们不能完全互换。

到目前为止,我还无法让我们自己的Lua代码和RPM API调用都工作起来。Lua_pushlstring()等LuaAPI将绑定到liblua.so或librpmio.so中最先出现在加载模块链中的任何一个。如果我早些时候在链接器命令行上指定-lua,那么我们所有的代码都可以正常工作,但对RPM API的调用最终会崩溃。如果-lrpmio早于我们的代码,那么最终会崩溃,因为一些Lua调用最终会使用librpmio的Lua副本。

我试着对liblua.so中的符号进行版本控制,我们使用这样的版本脚本构建:

LUA_5.2 {
    global:
            lua_*;
            luaL_*;
    local: *;
};

然而,这还不够,因为librpmio.so使用未转换的符号,并且上面的版本脚本创建了符号的LUA_5.2版本和"默认"版本。运行时绑定似乎更喜欢liblua.so中的未转换符号,而不是librpmio.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的绑定。

我可以通过在librpmio.so上设置-B符号标志来解决这个问题,但这是一个我们无法控制的系统库,谁知道还会导致什么其他问题。我想,如果我能在liblua.so中消除每个Lua符号的默认版本的创建,我可能会解决这个问题,但我还没能从版本脚本中找到如何做到这一点。GNU版本的脚本文档只展示了如何通过__asm__指令来实现这一点。

除了创建一个包含如下行的文件并将其与我的Lua构建链接外,还有人有其他想法吗?

__asm__(".symver lua_pushlstring,lua_pushlstring@LUA_5.2");

为了那些在搜索中遇到我的问题的人,我能够在不对Lua源代码副本进行大量更改的情况下解决问题的唯一方法是动态加载所有RPM库。

__asm__技术用于对所有Lua符号进行版本控制,而不让它们与未版本的符号匹配,这需要__asm__指令位于定义符号的源模块中,这意味着要对许多Lua文件进行修补。

我们只需要12-15个RPM API,所以我提出的解决方案是使用dlopen()动态加载librpmio、librpm和librpmdb(后者仅存在于RPM<=4.5中)共享库。调用dlopen()时,我为标志指定RTLD_NOW|RTLD_LOCAL|RTLD_DEEPBIND。这导致RPM库中的Lua(和其他)符号被内部解析。

我必须使用dlsym()来获取我们使用的任何RPM API的地址,但至少这可以防止librpmio的Lua与我们新的Lua发生冲突。

最新更新