当前位置: 首页 > 面试题库 >

动态加载和弱符号解析度

公孙阳羽
2023-03-14
问题内容

分析这个问题后,我发现了有关dlopen在Linux
上动态加载()上下文中弱符号解析行为的一些信息。现在,我正在寻找管理该规范的规范。

让我们举个例子。假设有一个程序a可以按此顺序动态加载库b.soc.so。如果c.so依赖于其他两个库foo.so(实际上libgcc.so在该示例中)和bar.so(实际上libpthread.so),则通常bar.so使用导出的符号可以满足中的弱符号链接foo.so。但是如果b.so还依赖foo.so但不依赖bar.so,那么这些弱符号显然不会被联系起来bar.so。它好像foo.soinkages只能看从符号ab.so及其所有的依赖关系。

在某种程度上,这是有道理的,因为否则加载c.so可能会foo.sob.so已经使用该库的某个点上改变其行为。另一方面,在让我开始的问题中,这引起了很多麻烦,所以我想知道是否有解决该问题的方法。并且为了找到解决方法,我首先需要对这些情况下如何指定符号分辨率的确切细节有一个很好的了解。

在这些情况下定义正确行为的规范或其他技术文档是什么?


问题答案:

不幸的是,权威文档是源代码。Linux的大多数发行版都使用glibc或其分支,例如eglibc。在两者的源代码中,应记录dlopen()的文件如下所示:

手册/libdl.texi

@c FIXME these are undocumented:
@c dladdr
@c dladdr1
@c dlclose
@c dlerror
@c dlinfo
@c dlmopen
@c dlopen
@c dlsym
@c dlvsym

可以从ELF规范和POSIX标准中获得什么技术规范。ELF规范使弱符号变得有意义。POSIX是dlopen()本身的实际规范。

我发现这是ELF规范中最相关的部分。

链接编辑器搜索存档库时,它将提取包含未定义全局符号定义的存档成员。成员的定义可以是全局符号或弱符号。

ELF规范未提及动态加载,因此本段的其余部分由我自己解释。我发现上述相关的原因是,解析符号出现在单个“时间”处。在您提供的示例中,当程序a动态加载时b.so,动态加载器尝试解析未定义的符号。最终可能会使用全局符号或弱符号来这样做。然后c.so,当程序动态加载时,动态加载器会再次尝试解析未定义的符号。在您描述的方案中,b.so使用弱符号来解析中的符号。一旦解析,这些符号将不再是未定义的。使用全局符号还是弱符号来定义它们都没有关系。在c.so加载时间之前,它们已经不再是未定义的。

ELF规范没有确切定义链接编辑器是什么,或者链接编辑器何时必须组合目标文件。大概是非问题,因为文档考虑了动态链接。

POSIX描述了dlopen()的某些功能,但要留待实现,包括问题的实质。POSIX通常不引用ELF格式或弱符号。对于实现dlopen()的系统,甚至不需要任何弱符号的概念。

http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html

POSIX遵从性是另一个标准Linux标准库的一部分。Linux发行版可能会或可能不会选择遵循这些标准,并且可能会也可能不会通过认证。例如,我知道Open
Group的正式Unix认证非常昂贵-因此有大量的“类Unix”系统。

关于dlopen()的标准合规性的有趣观点在Wikipedia文章上进行了动态加载。根据POSIX的要求,dlopen()返回void
,但是根据ISO的要求,C表示void 是指向对象的指针,并且这种指针不一定与函数指针兼容。

事实仍然是,函数指针和对象指针之间的任何转换都必须被视为(本质上不可移植的)实现扩展,并且不存在直接转换的“正确”方式,因为在这方面POSIX和ISO标准彼此矛盾。其他。

确实存在的标准相互矛盾,并且其中包含哪些标准文件可能并不是特别有意义。这是乌尔里希·德雷珀(Ulrich Drepper)撰写的关于他对Open
Group的鄙视及其“规范”的文章。

http://udrepper.livejournal.com/8511.html

罗德里格(Rodrigo)链接的帖子也表达了类似的观点。

我做出此更改的原因并不是真正符合要求(很好,但没有理由,因为没有人抱怨过时的行为)。

经过仔细研究,我相信您所提问题的正确答案是,dlopen()在这方面没有对或错的行为。可以说,一旦搜索已解析符号,它就不再是未定义的,并且在后续搜索中,动态加载程序将不会尝试解析已经定义的符号。

最后,正如您在评论中指出的那样,您在原始帖子中描述的内容是不正确的。动态加载的共享库可用于解析以前动态加载的共享库中的未定义符号。实际上,这不仅限于动态加载的代码中的未定义符号。这是一个示例,其中可执行文件本身具有未定义的符号,该符号可通过动态加载来解析。

main.c

#include <dlfcn.h>

void say_hi(void);

int main(void) {
    void* symbols_b = dlopen("./dyload.so", RTLD_NOW | RTLD_GLOBAL);
    /* uh-oh, forgot to define this function */
    /* better remember to define it in dyload.so */
    say_hi();
    return 0;
}

dyload.c

#include <stdio.h>
void say_hi(void) {
    puts("dyload.so: hi");
}

编译并运行。

gcc-4.8 main -fpic -ldl -Wl,--unresolved-symbols=ignore-all -o main
gcc-4.8 dyload.c -shared -fpic -o dyload.so
$ ./main
dyload.so: hi

请注意,主要可执行文件本身已编译为PIC。



 类似资料:
  • 正如你在上面看到的,我正试图从https://play . Google . com/store/apps/category/GAME _ ACTION/collection/top selling _ free中抓取一个单词列表 谷歌Play商店页面加载更多的元素,每次你滚动到页面的底部。 我的程序将抓取显示的前40个元素,但由于j汤不会加载动态加载的网页的其余部分,因此我无法抓取前40个元素之

  • 我在下面两个导入语句中遇到错误 Android Studio正在播放无法解析符号的动画

  • 本文向大家介绍浅谈C语言中的强符号、弱符号、强引用和弱引用,包括了浅谈C语言中的强符号、弱符号、强引用和弱引用的使用技巧和注意事项,需要的朋友参考一下 首先我表示很悲剧,在看《程序员的自我修养--链接、装载与库》之前我竟不知道C有强符号、弱符号、强引用和弱引用。在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样感觉的朋友交流也希望高人指点。   首先我们看一下书中关于它

  • 代码运行,但无法获得函数、类等的建议。 谢谢

  • 问题内容: 我正在尝试为我的网站创建页面主题功能。我想使用单独的CSS文件在页面上动态加载相应的主题。 我正在使用此代码: 效果很好,但是如果CSS文件未加载,它不会返回任何信息。 加载时,有什么方法可以捕捉吗?也许通过使用ajax? 问题答案: 加载CSS文件(或其任何其他更改)时,Internet Explorer会触发一个事件。其他浏览器不会触发任何事件,因此您将必须手动检查样式表是否已加载

  •  说明 调用方法: $.f2e.util.getScript(url,cache,fn); 函数说明: 加载js,并提供相关回调 参数说明: 参数名 类型 说明 备注 url string 地址 无 cache boolean 缓存 无 fn function 回调函数 无 脚本 <script> $.f2e.util.getScript(url,true,function(){