C 如何加载共享库而不加载其依赖项?
假设我有一个库C 如何加载共享库而不加载其依赖项?,c,linux,shared-libraries,elf,C,Linux,Shared Libraries,Elf,假设我有一个库libfoo.so.1,它依赖于libbar.so.1(根据ldd)。但是,libbar.so.1目前不可用。我的应用程序需要调用libfoo.so.1中的函数,该函数根本不需要libbar.so.1 有没有一种方法可以加载libfoo.so.1,解析函数符号,然后在没有libbar.so.1的情况下调用它来满足依赖关系?这是一个“我知道我在做什么,就让我去做吧”的例子。我尝试了RTLD_LAZY标志,但它仍然尝试在不加载符号之前加载libbar.so.1库 编辑 具体情况如下
libfoo.so.1
,它依赖于libbar.so.1
(根据ldd
)。但是,libbar.so.1目前不可用。我的应用程序需要调用libfoo.so.1
中的函数,该函数根本不需要libbar.so.1
有没有一种方法可以加载libfoo.so.1
,解析函数符号,然后在没有libbar.so.1
的情况下调用它来满足依赖关系?这是一个“我知道我在做什么,就让我去做吧”的例子。我尝试了RTLD_LAZY标志,但它仍然尝试在不加载符号之前加载libbar.so.1
库
编辑
具体情况如下
我们有3名球员:
libbar.so.1
,一个位于路径中的共享库,该路径不在LD\u library\u path
或ldconfig
中,并且其依赖关系都已解决
libfoo.so.1
,一个共享库,位于与libbar
不同的目录中,但它依赖于libbar
。在运行时,libfoo
将知道在哪里找到libbar
App
,一个二进制应用程序,需要在运行时的某个点加载libfoo
App
不知道在哪里可以找到libbar
,但知道libfoo
知道。我试图实现的是在libfoo
中有一个init函数,它可以简单地将App
的当前工作目录更改为libbar
所在的位置,从而最终解决所有依赖项,让每个人都满意
libfoo
最终需要在libbar
中调用stuff,而不是在这个init函数中。我认为创建存根是行不通的,因为符号最终需要解析为实际函数。好吧,即使使用RTLD\u LAZY
,变量仍然可以解析,所以一般来说,您确实需要链接所有库。似乎您应该创建一个存根libbar.so.1
,它没有任何功能,可以被链接器找到。只是一个想法,您是否想过插入依赖项-只需创建一个具有相同签名、参数等的相同函数,让链接器解析此函数并忽略libbar。那么。1?既然你没有提到这一点,我想我会提出这个建议
希望这有帮助,
顺致敬意,
Tom。使用dlopen加载库并使用dlsym获取所需的函数。另一个想法是:从libfoo.so.1
中提取(使用ar(1))必要的函数,或者将其加载到.o
或另一个.so
文件中,然后链接到该提取帮助?我假设对libbar.so.1的引用在一个libfoo函数中,而这个函数不是从程序中调用的(甚至是间接调用的)。这里的实际需求是什么?仅仅链接一个库并没有多大作用,而且通常是良性的。你缺少图书馆吗?只需创建一个同名的存根库。是否要控制或抢占库中符号的使用?将它们放在另一个库中(使用正确的版本标记!),然后LD_预加载它
我想这里的元问题是,我看不出能够抢占依赖链接有什么价值。这只是一个帮助函数。很好,你提到了RTLD_LAZY,这表明你已经尝试过了,并且阻止了我走上建议它的歧途。我认为这是行不通的。每个库都有一个在链接时编码到其中的依赖项列表,该列表独立于未定义的符号集。加载程序将尝试查找这些依赖项,无论它们是否实际需要。@Jay:加载程序的路径嵌入到可执行文件中,以便动态加载函数……我想通过指定具有相同签名的重复函数来防止动态加载,从而迫使链接器使用该函数版本改为…@Jay:刚刚看到你对Adam的回答的反应,那是我的想法…一个存根,因为没有更好的词…@tommieb75,那就好了。符号被定义在哪里并不重要,只要它们被定义在某个地方。尽管libbar.so仍然必须存在,即使它是空的。我认为这会起作用,但您需要存根来定义libfoo.so所依赖的所有符号。但是定义本身可以是存根。正如tommieb75指出的,存根实际上不必在libbar中。因此,它们的符号必须在某个地方定义。我认为您不需要定义所有符号,这不是RTLD\u LAZY
所能做的吗?RTLD\u LAZY
仅仅是建议。可能是由于某些事情可能超出了您的控制范围,因此会被忽略(例如,不支持延迟绑定的系统、已启动的程序suid或出于安全或健壮性目的禁用延迟绑定的管理员配置);当库在启动时被链接时,您不需要指定它。实际上,动态库不是ar
chives。