我试图编写一个抽象来加载Windows和Linux上的dynamic库。 在Windows平台上一切正常,当我打电话给dlopen时,我得到一个SIGSEGV: // File: Main.cs using System; using System.Runtime.InteropServices; namespace DlopenTest { class MainClass { const int RTLD_NOW = 2; [DllImport("dl")] static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPTStr)] string filename, int flags); [DllImport("dl")] static extern IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPTStr)] string symbol); public static void Main (string[] args) { IntPtr libraryHandle = dlopen("libc.so.6", RTLD_NOW); Console.WriteLine ("Success!"); } } } […]
在我的Linux应用程序中,我通过dlopen使用插件体系结构。 共享对象正在打开 dlopen(path,RTLD_GLOBAL | RTLD_LAZY)` 选项RTLD_GLOBAL是必要的,因为插件需要访问常见的RTTI信息。 有些插件偶尔会导出相同的符号。 这通常不会发生,但是当它发生时会导致随机段错误,并且很难debugging。 所以我想在dlopen中检测重复的符号并警告它们。 有没有办法做到这一点? 这是一个简单的例子来说明这一点。 主要可执行文件的代码是 #include <string> #include <dlfcn.h> #include <iostream> #include <cassert> typedef void (*Function)(); void open(const std::string& soname) { void* so = dlopen(soname.c_str(), RTLD_LAZY | RTLD_GLOBAL); if (!so) { std::cout << dlerror() << std::endl; } else { Function function = reinterpret_cast<Function>(dlsym(so, "f")); assert(function); function(); } } […]
有没有办法find一个过程中dynamic库的引用数量? 即在一个应用程序中,许多模块可能使用dlopen加载了相同的库,而当模块执行dlclose时,我们可以知道该库是否真的被卸载,或者它的引用正在减less?
我认为Linux中的一个主要的devise缺陷是共享对象地狱,当涉及到二进制代码分发程序,而不是源代码forms。 这里是我的具体问题:我想发布一个ELF二进制forms的Linux程序,它应该在尽可能多的发行版本上运行,所以我的强制性依赖性如此低:在任何情况下,唯一需要的库是libpthread,libX11,librt和libm(当然还有glibc)。 当我使用gcc构build我的程序时,我正在dynamic链接这些库。 但是,我的程序也可以select支持ALSA(声音接口),Xcursor,Xfixes和Xxf86vm扩展以及GTK。 但是这些只能在用户的系统上使用,否则我的程序仍然可以运行,但function有限。 例如,如果GTK不在那里,我的程序将回退到terminal模式。 因为我的程序应该仍然可以在没有ALSA,Xcursor,Xfixes等的情况下运行,所以我不能dynamic链接这些库,因为如果其中一个库不存在,那么程序根本无法启动。 所以我需要手动检查库是否存在,然后使用dlopen()逐个打开它们,并使用dlsym()导入必要的函数符号。 但是,这会导致各种问题: 1)库命名约定:共享对象通常不是简单地称为“libXcursor.so”,而是具有某种版本的扩展名,比如“libXcursor.so.1”,甚至像“libXcursor.so.0.2000”这样的有趣的东西。 这些扩展名似乎因系统而异。 所以调用dlopen()时应该select哪一个? 在这里使用硬编码名称似乎是一个非常糟糕的主意,因为名称因系统而异。 所以我想到的唯一解决方法是扫描整个库path,查找以“libXcursor.so”前缀开头的文件名,然后执行一些自定义版本匹配。 但是,我怎么知道他们真的兼容? 2)库searchpath:我应该在哪里查找* .so文件? 这也是不同的系统。 有一些默认path,如/ usr / lib和/ lib,但* .so文件也可能在很多其他path。 所以我不得不打开/etc/ld.so.conf并parsing这个来找出所有的库searchpath。 这不是一件小事,因为/etc/ld.so.conf文件也可以使用某种include指令,这意味着我必须parsing更多的.conf文件,对由循环include指令引起的可能的无限循环进行一些检查等等。真的没有更简单的方法来找出* .so的searchpath吗? 所以,我的实际问题是:是不是有一个更方便,不太方便的方法来实现我想要做的事情? 创build一个有ALSA,GTK,libXcursor等一些可选依赖项的Linux程序真的太复杂了,但是也应该在没有它的情况下运行! 有什么样的标准做我想做的事情? 还是我注定要这样做的黑客方式? 感谢您的意见/解决scheme!
是否有可能在发生时捕获未parsing的符号引用,以便根据需要调用函数来尝试parsing符号? 还是有可能在运行时将新符号添加到dynamic符号表中,而不创build库文件并将其删除? 我在GNU / Linux上使用GCC。 (可移植到其他Unix将是不错的,但不是一个关键的问题。) 提前致谢! 编辑:我应该给我更多的细节,我想要做的。 我想为编程语言编写一个解释器,这个编程语言预计支持编译(dlopen)和解释模块。 我想要从编译模块调用其他地方定义的函数来由链接器parsing,以避免在每次调用时查找函数,但调用解释的代码将不会被parsing。 我想拦截这些调用,以便在需要时调用相应的解释函数(或者如果函数不存在,则发出错误信号)。
我正在研究一个在CentOS上使用dlopen加载用户创build的插件的程序。 我遇到了一个插件的问题,这个插件依赖于也有依赖关系的共享库: libplugin.so – > libservices.so – > libconfig.so 我们的程序首先将依赖关系加载到内存中,从依赖关系树的叶子开始,然后移动到插件(本例中省略了错误检查): dlopen("/path_to_plugin/libconfig.so", RTLD_NOW | RTLD_GLOBAL) dlopen("/path_to_plugin/libservices.so", RTLD_NOW | RTLD_GLOBAL) dlopen("/path_to_plugin/libplugin.so", RTLD_NOW | RTLD_GLOBAL) 我们使用这种方法,所以最终用户不必修改它们的LD_LIBRARY_PATH来指向带有插件的目录。 这种方法已经成功地为几个不同的插件。 我们最近收到一个新的插件,这种方法不起作用。 我们能够成功加载libconfig.so,但是当我们尝试加载libservices.so时,我们得到以下错误信息: Exception libconfig.so: cannot open shared object file: No such file or directory 我知道库之间的符号依赖关系都是满足的,因为当我设置LD_LIBRARY_PATH来包含插件path时,插件加载并正确执行。 当我在程序上运行strace时,我可以看到系统正在按照dlopen手册页中的描述执行对libconfig.so的search。 所以看来,出于某种原因,dlopen没有检测到libconfig.so已经被加载。 什么样的情况会导致这种行为?
考虑一个简单的C程序: #include <stdio.h> int main() { puts("Hello"); return 0; } 使用GDB运行它,为简单起见,设置了LD_BIND_NOW=1 ,我可以观察到以下情况: $ gdb -q ./test -ex 'b main' -ex r Reading symbols from ./test…done. Breakpoint 1 at 0x8048420 Starting program: /tmp/test Breakpoint 1, 0x08048420 in main () (gdb) disas Dump of assembler code for function main: 0x0804841d <+0>: push ebp 0x0804841e <+1>: mov ebp,esp […]
现在我有3个共享对象,A.so,B.so,C.so Ac void libA() { common(); } Bc void common() { printf("COME HERE B\n"); } Cc void common() { printf("COME HERE C\n"); } (just ingore the .h files) test.c int main() { libA(); return 1; } complie: gcc -fPIC -shared libB.so libB.c gcc -fPIC -shared libA.so libA.c ./libB.so gcc -o test test.c libC.so libA.so 我希望结果是“来这里B”,我可以用RTLD_DEEPBIND标志使用dlopen […]
我有一个linux共享库foo.so,它使用dlopen("foo.so", RTLD_NOW | RTLD_LOCAL)从可执行文件加载。 从foo.so我想dlopen另一个库,bar.so,其中引用符号在foo.so中定义,但链接器无法find它们。 我无法将RTLD_LOCAL更改为RTLD_GLOBAL,因为我没有执行加载的可执行文件的源代码。 我想-Wl,–export-dynamic链接foo.so时的-Wl,–export-dynamic可能会有所帮助,但不会覆盖到dlopen的本地标志。 GCC的新属性可见性function看起来并不像它提供的答案。 有没有一种方法可以指示链接器将bar.so中的未定义符号的引用parsing为foo.so中的那些定义,而无需将链接栏与-lfoo或相似性移动到第三个库中,并将foo和bar链接到它? 唯一发生在我身上的是,用foo.so本身的RTLD_GLOBAL把doopen foo.so,然后dlopen bar.so,但是这让我觉得有点乱。 谢谢。
我想让我的可执行文件“可选地依赖于”其他共享对象。 因此,如果DSO不存在,它将能够运行没有一些符号。 我可以用dlopen/dlsym调用来实现这一点,但我必须手动加载每个符号并为它们添加包装器,如下所示: void *my_lib = dlopen("my_lib.so", RTLD_LAZY); if (!my_lib) { // ok, I promise not to touch my_lib symbols } else { my_foo_ptr = dlsym(my_lib, "my_foo"); my_bar_ptr = dlsym(my_lib, "my_bar"); } … my_foo(…) { assert(my_foo_ptr); return (*my_foo_ptr)(…); } … my_bar(…) { assert(my_foo_ptr); return (*my_bar_ptr)(…); } 这是一个愚蠢的代码,它直接依赖于“my_lib.so”ABI,这意味着我必须在每次更新库时更新它。 我正在寻找一些方法来使ld.so为我做到这一点。 所以理想是: void *my_lib = dlopen("my_lib.so", /* bring […]