在我自己的过程中找到一个符号

时间:2013-09-15 10:41:34

标签: c linux dynamic-library

以下是设置:

  1. 有一个应用程序A加载liba.so(在编译时链接)
  2. liba.so导出符号expA
  3. 我无法控制Aliba.so
  4. 应用程序A可以通过libmine.so将我指定的库dlopen加载到同一进程中(想想插件架构)
  5. 我需要使用expA中的libmine.so但不知道如何在没有明确链接liba.so的情况下找到它,这是我到目前为止所做的。我认为这在现实世界中不起作用,因为该符号不能保证与我liba.so本地副本中的符号相同(或者是它?)。 libmine.so将是封闭源代码,无法使用A重新编译。
  6. 我从未做过这样的事情,所以对库加载的细节有点不清楚。例如,如果我在dlopen("liba.so")内尝试libmine.so,我是否会获得已加载的库或新副本的句柄?

    libmine.so的加载方式而言,我所知道的是它将加载RTLD_LAZY(并没有其他内容)。

    非常感谢任何帮助和指示!

1 个答案:

答案 0 :(得分:3)

如果所有liba.so库都使用dlopen RTLD_GLOBAL编辑,那么您可以使用dlsym(RTLD_DEFAULT, "expA")查找该符号,而无需重新打开该库。

如果liba.sodlopen使用RTLD_LOCAL,那么您需要在自己dlopen内再次使用libmine.so来获取库的句柄。请注意以下事项:

  

如果使用dlopen()再次加载相同的库,则返回相同的文件句柄。 dl库维护库句柄的引用计数,因此在dlpen()成功调用dlclose()之前,不会释放动态库。 _init()例程(如果存在)仅被调用一次。但随后使用RTLD_NOW进行的调用可能会强制对早先使用RTLD_LAZY加载的库进行符号解析。

即。它与图书馆的副本相同。

机制是(伪),假设expA是一个函数:int expA(int value)

int (*fpointer)(int) = NULL;

void *handle = dlopen("liba.so", RTLD_LAZY | RTLD_LOCAL);
if (handle != NULL) {
    void *symbol = dlsym(handle, "expA");
    if (symbol != NULL) {
        fpointer = (int (*)(int ))symbol;
    }
}

这是伪代码,几乎没有错误处理。