Articles of dlopen

当你有重复的符号时如何可靠地使用dlsym?

晚上好,我现在正在基于Plux.net模型在C ++ / Linux上开发一个插件系统。 为了简单起见,我用extern C(unmangle)基本上声明了一个符号(让它叫做pluginInformation),我的插件pipe理器在预configuration的导入(.so)中查找这个符号。 事情是,主要的应用程序声明相同的符号,不仅如此,但它的任何依赖也可能有符号。 (因为在这个插件信息中,模块可以发布插件和/或插槽)。 所以当我的PluginManager启动时,它首先尝试在主程序中find符号(将NULL传递给dlopen ),然后尝试在它的任何依赖关系中find符号(使用dl_iterate_phdr )。 最后,它将打开一组configuration导入(它将读取用户configuration的.so的path,将它们打开,最后使用pluginInformation符号)。 在所有模块中find的pluginInformation的集合被用来构build扩展名三。 如果我在主程序中声明符号并使用dlopen加载导入,它将起作用(只要在导入导入时通过标记RTLD_DEEPBIND)。 但是对于应用程序的依赖关系,我没有select传递标志(我可以,但它没有做任何事情),因为这个.sos是在应用程序启动时加载的。 现在,当我尝试使用从依赖关系获得的任何符号(启动时加载的符号)时,出现了分段错误。 我假设问题是我在符号表中有几个同名的符号,奇怪的是,它似乎正确地识别出有几个符号,它甚至给我正确的.so符号的path声明,但只要我访问符号分段错误发生。 如果我只在主程序或其中一个依赖关系中声明符号,那么所有东西都可以正常工作。 我如何pipe理主程序之间的重复符号和使用dlsym?进行导入? 我一直在考虑保持mangling,然后试图find符号表符号,但我不知道这甚至可能(以编程方式列出模块中的所有符号)。 PD:对不起,我没有发布任何代码,但我现在不在家,我希望我所做的努力的描述足够清楚,如果不是,我明天可以发布一些代码。

dlclose并不真正卸载共享对象,无论它被调用了多less次

我的程序使用dlopen来加载一个共享对象,然后dlclose卸载它。 有时这个共享对象再次加载。 我注意到静态variables没有重新初始化(这对我的程序是至关重要的),所以我在dlclose后添加了一个testing(使用RTLD_NOLOAD dlopen )来查看库是否真的被卸载。 果然,这仍然是在记忆中。 然后我试着重复调用dlclose直到这个库真的被卸载,但是我得到的是一个无限循环。 这是我用来检查库是否卸载的代码: dlclose(handles[name]); do { void *handle = dlopen(filenames[name], RTLD_NOW | RTLD_NOLOAD); if (!handle) break; dlclose(handle); } while (true); 我的问题是, dlclose后,我的共享对象没有被卸载的可能原因是什么,因为我的dlopen调用是唯一加载的地方。 你能提出一个行动路线来追踪问题的根源吗? 另外,为什么重复调用dlclose没有任何作用,它们都是递减引用计数,不是吗? 编辑:刚刚发现这只发生在我用gcc编译时。 随着叮当 ,一切都很好。

Linux上的RTLD_LOCAL和dynamic_cast

我们有一个插件,它是由我们的应用程序中的一些共享库构build而成的,我们需要在应用程序运行时进行更新。 出于性能方面的原因,我们在卸载旧插件之前加载并开始使用新插件,并且只有在使用旧插件完成所有线程时,我们才能卸载它。 由于新插件和旧插件的库在它们中具有相同的符号,我们使用RTLD_LOCAL进行dlopen()。 如果我们不把新的插件从内部函数偶然调用到旧插件的符号。 插件的一个库执行dynamic_cast()到由另一个插件库创build的对象。 这适用于HP-UX,AIX,Solaris和Windows,但不适用于Linux。 据我所知,这是因为所有这些操作系统(编译器)都使用类的名称来比较types(在dynamic_cast()中),但是Linux使用type_info对象地址来进行比较(以提高性能),并且由于每个库有它自己的type_info对象(因为它是用RTLD_LOCAL加载的)地址是不同的,因此相同的types似乎不等于dynamic_cast()。 有没有办法做到以下一种: 只提供类似信息对象,就好像提供了RTLD_GLOBAL一样。 使编译器使用类名比较而不是type_info地址来比较types。 ? 我们正在使用的编译器是: $ icpc -V英特尔(R)C ++英特尔(R)64编译器XE,适用于在英特尔(R)64版本12.0.0.084版本20101006上运行的应用程序版权所有(C)1985-2010英特尔公司。 版权所有。

dlopen()searchpath

有没有办法find编程的dlopen()search共享对象的path? 我一直以为dlopen()只会在/ lib和/ usr / lib中看到,但现在我已经看到,在Linux Mint上,像libglib-2.0.so这样的几个核心组件在一个完全不同的文件夹中,即在/ rofs / lib / i386-gnu-linux等等。 有没有办法去了解所有这些dlopen()将search共享对象的path? 我已经检查了环境variablesLD_LIBRARY_PATH,但是根本没有定义它。

dlopen – 未定义的符号错误

我正在使用dlopen在运行时加载共享库 dlopen("SharedLibarary1.so", RTLD_NOW | RTLD_GLOBAL); 在该共享对象中,我指的是在另一个共享库“SharedLibarary2.so”中定义的const char *。 可执行文件和两个库都是使用-rdynamic构build的。 但是,当使用dlopen时,我仍然遇到运行时错误:“/usr/lib/SharedLibarary1.so:undefined symbol”,并指向mangled的const char *有未定义的符号。 whith GDB的“信息共享”我可以看到,第二个库没有加载的错误点。 如果我在第一个图书馆做第二个图书馆之前做了一个dlopen,那么这个问题怎么会消失呢? 有没有更好的方法来强制加载器加载第二个库的未解决符号?

dlopen vs连接开销

假设我有一个库–foo.so。 在构build我的二进制文件(需要这个库)时,我可以(1)链接foo.so,或者(2)在程序源代码中,dlopen这个库,然后调用这个库提供的函数 当我从库中调用函数时,(1)和(2)之间是否有任何性能差异? 请注意,我知道会有不同的初始化特性(如dlopen的开销,第一次使用符号的开销等),但是在稳定状态下,两种select都同样快,还是更快? 谢谢。

无法使用静态TLS加载更多对象

我有一个应用程序使用dlopen()来加载额外的模块。 应用程序和模块是在Ubuntu 12.04 x86_64上使用gcc 4.6而构build的,但是为了i386 arch。 然后将二进制文件复制到具有完全相同的操作系统的另一台机器,并正常工作 但是,如果它们被复制到Ubuntu 12.04 i386,则一些(但不是全部)模块将无法加载以下消息: dlopen: cannot load any more object with static TLS 我怀疑这是由__threadvariables的使用引起的。 但是,这些variables不会在加载的模块中使用 – 只能在加载器模块本身中使用。 有人可以提供任何额外的信息,可以是什么原因? 我正在减less__threadvariables的数量并优化它们(使用-ftls-model等),我只是好奇它为什么不能在几乎相同的系统上工作。

如何在Linux上基于CPU能力进行运行时绑定

是否有可能有一个Linux库(例如“libloader.so”)加载另一个库来解决任何外部符号? 我有一大堆的代码被有条件编译为支持SIMD级别(SSE2,AVX,AVX2)。 如果构build平台与运行时平台相同,此工作正常。 但它妨碍了不同处理器世代的重用。 一个想法是有一个调用function链接到libloader.so executable ,它不直接实现function 。 相反,它parsing(绑定?)该符号从另一个加载的库,例如libimpl_sse2.so , libimpl_avx2.so等取决于cpuflags。 有数百个函数需要以这种方式进行dynamic绑定,因此更改声明或调用代码是不现实的。 程序链接相当容易改变。 运行时环境variables也可以改变,但我不想。 我已经得到尽可能做一个可执行文件,并通过ld标志 – –unresolved-symbols=ignore-allbuild立并开始与未parsing的外部符号(UES)。 但是随后的impl lib的加载不会将UES函数的值从NULL改变。

获取一个ELF二进制文件的加载地址,dlopen不能正常工作

我试图得到一个ELF二进制文件的加载地址, 但是dlopen不能按预期工作: void *elf = (char *)dlopen (0, RTLD_NOW); printf ("%p\n", elf); sleep (100); 它打印0xb772d918 ,但是从/proc/1510/maps可以0xb772d918 ,它并不指向dlfn二进制文件的加载地址,而是ld-2.15.so , 08048000-08049000 r-xp 00000000 fc:00 1379 /root/dlfn 08049000-0804a000 r–p 00000000 fc:00 1379 /root/dlfn 0804a000-0804b000 rw-p 00001000 fc:00 1379 /root/dlfn b7550000-b7552000 rw-p 00000000 00:00 0 b7552000-b76f5000 r-xp 00000000 fc:00 9275 /lib/i386-linux-gnu/libc-2.15.so b76f5000-b76f7000 r–p 001a3000 fc:00 9275 /lib/i386-linux-gnu/libc-2.15.so b76f7000-b76f8000 rw-p […]

Linux的dlopen:一个库可以“加载时通知”?

有没有办法让共享库在加载时被“通知”? 换句话说,假设我在共享库上使用dlopen ,是否有共享库中自动调用的函数(如果存在)(例如main?)