1

如果我还必须链接到 RPM 库(特别是 librpmio.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 将绑定到 liblua.so 或 librpmio.so 中首先出现在加载模块链中的任何一个。如果我早先在链接器命令行上指定 -llua,那么我们所有的代码都可以正常工作,但对 RPM API 的调用最终会崩溃。如果 -lrpmio 早于我们的代码最终会崩溃,因为某些 Lua 调用最终会使用 librpmio 的 Lua 副本。

我尝试对 liblua.中的符号进行版本控制,以便我们使用如下版本脚本构建:

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'

请注意最后一行 - 它正在解析 librpmio 中的 lua_pushlstring 与我的 liblua 的绑定。

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

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

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

1 回答 1

1

为了那些在搜索中遇到我的问题的人,我能够在不对我们的 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 发生冲突。

于 2013-02-27T13:19:10.487 回答