Articles of dlopen

使用dlopen和dlsym使用-fPIC编译C程序

我有一个错误的符号parsing的问题。 我的主程序用dlsym加载了一个dlopen共享库和一个来自它的符号。 程序和库都是用C库代码编写的 int a(int b) { return b+1; } int c(int d) { return a(d)+1; } 为了使它在64位机器上工作,-fPIC在编译时传递给gcc。 该计划是: #include <dlfcn.h> #include <stdio.h> int (*a)(int b); int (*c)(int d); int main() { void* lib=dlopen("./libtest.so",RTLD_LAZY); a=dlsym(lib,"a"); c=dlsym(lib,"c"); int d = c(6); int b = a(5); printf("b is %dd is %d\n",b,d); return 0; } 如果程序不是用-fPIC编译的话,一切运行正常,但是当用-fPIC编译程序时,程序崩溃时会出现分段错误。 调查发现,坠机是由于符号a的错误parsing。 当调用a时会发生崩溃,无论是从库还是主程序(后者通过在主程序中注释掉调用c()的行来获得)。 […]

使用dlopen()dynamic加载共享对象

我正在做一个普通的X11应用程序。 默认情况下,我的应用只需要libX11.so和标准的gcc C和math库。 该应用程序可以扩展Xfixes,Xrender和ALSA声音系统的function。 但是,这些(Xfixes,Xrender和ALSA)function是可选的。 为了实现这种行为,我使用运行时加载,即libXfixes,libXrender和libasound应该是dlopen()。 因此,应用程序可以运行在没有这样的图书馆。 现在我的问题: What library names should I use when calling dlopen()? 我观察到,这些从发行版到发行版有所不同。 例如,在openSUSE 11上,它们被命名为: libXfixes.so libXrender.so libasound.so 然而,在Ubuntu上,这个名字有一个版本号,如下所示: libXfixes.so.3 libXrender.so.1 libasound.so.2 所以试图打开“libXfixes.so”将在Ubuntu上失败,虽然显然在那里。 它只是附有一个版本号。 那么我的应用程序应该如何处理呢? 我应该让我的应用程序扫描/ usr / lib /第一个手动查看我们有哪些库,然后select一个合适的? 还是有没有人有一个更好的主意? 多谢你们, 安迪

当你有重复的符号时如何可靠地使用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改变。