gpt4 book ai didi

c - dlopen:检测具有循环依赖性的 undefined symbol

转载 作者:行者123 更新时间:2023-11-30 16:54:39 26 4
gpt4 key购买 nike

我有一些具有循环依赖关系的共享库,我想使用 dlopen 加载它们。为此,我使用 RTLD_LAZY | 调用 dlopen RTLD_GLOBAL 标志。

这很好用。

现在,我想检查所有共享库中的所有符号是否都已完全解析,因此我使用 RTLD_NOW 再次调用 dlopen,如果所有符号都可以,这应该会失败无法解决。

至少,这是我对手册页的理解:

However, a subsequent dlopen() call that loads the same shared object with RTLD_NOW may force symbol resolution for a shared object earlier loaded with RTLD_LAZY.

这是一个简单的例子来说明我的问题:

main.h

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

#include "h.h"

#define CNT 3
static const char *libs[CNT] = {"./liba.so", "./libb.so", "./libc.so"};

typedef int (*f_ptr)();

int main() {
void *h[CNT];
f_ptr f[CNT];

for (int i = 0; i < CNT; i++) {
printf("dlopen: %s\n", libs[i]);
h[i] = dlopen(libs[i], RTLD_LAZY | RTLD_GLOBAL);
if (!h[i]) {
fprintf(stderr, "%d %s: %s\n", __LINE__, libs[i], dlerror());
exit(EXIT_FAILURE);
}
}

for (int i = 0; i < CNT; i++) {
printf("dlopen again: %s\n", libs[i]);
void *xx = dlopen(libs[i], RTLD_NOW | RTLD_GLOBAL);
if (!xx) {
fprintf(stderr, "%d %s: %s\n", __LINE__, libs[i], dlerror());
dlclose(h[i]);
h[i] = 0;
} else {
dlclose(xx);
}
}

for (int i = 0; i < CNT; i++) {
if (h[i]) {
f[i] = (int (*)())dlsym(h[i], "init");

if (!f[i]) {
fprintf(stderr, "%d %s: %s\n", __LINE__, libs[i], dlerror());
exit(EXIT_FAILURE);
}
}
}

for (int i = 0; i < CNT; i++) {
if (f[i]) {
printf("%s %08d\n", libs[i], f[i]());
}
}

return 0;
}

a.c

#include "h.h"

int init() { return 1 + b_(); }
int a_() { return 10; }

b.c

#include "h.h"

int init() { return 100 + a_(); }
int b_() { return 1000; }

抄送

#include "h.h"

int init() { return 10000 + x_(); }
int c_() { return 100000; }

h.h

int init();
int a_();
int b_();
int x_();

CMakeLists.txt

project(xx)

add_library(a SHARED a.c)
add_library(b SHARED b.c)
add_library(c SHARED c.c)

add_executable(main main.c)
target_link_libraries(main dl)

编译并运行:

$ mkdir b && cd b && cmake .. && make && ./main
...
[100%] Built target b
dlopen: ./liba.so
dlopen: ./libb.so
dlopen: ./libc.so
dlopen again: ./liba.so
dlopen again: ./libb.so
dlopen again: ./libc.so
./liba.so 00001001
./libb.so 00000110
./main: symbol lookup error: ./libc.so: undefined symbol: x_

在调用之前,如何检测 libc.so 无法完全加载导致它崩溃的符号?

最佳答案

理想情况下,您希望按照其他人的建议(通过 --no-allow-shlib-undefined)将符号交叉匹配的负担放在静态链接器上,而不是延迟其启动。现在循环依赖有点复杂,但是 Solaris(Linux shlib 是一个黯淡的副本)已经提供了一个聪明的解决方案 - shlib filters 。这个想法是,您链接到虚拟 shlib,这些 shlib 导出同样的虚拟符号,并且具有与最终生产库相同的 sonames。这些当然仅在链接时用于验证依赖关系。

顺便说一句,我很确定虚拟库的生成可以自动化,如下所示:

  • 构建 lib 不使用 --no-allow-shlib-undefined
  • 使用readelf或其他方式提取导出的符号
  • 生成一个虚拟 C(或 asm)文件,该文件为前一项中的符号定义空 stub
  • 构建库并瞧 - 您已经构建了第一个过滤器

嗯,这听起来像是今晚的一个不错的迷你项目。

关于c - dlopen:检测具有循环依赖性的 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40484188/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com