假设我有一个共享对象加载时间依赖图,符号foo
在其中一个.so中引用。假设这个符号foo
也在其他几个共享对象中定义。我的问题是:会找到哪个定义,什么是查找顺序,在哪里定义(在什么标准中,手册页)?
示例:考虑依赖关系图https://i.stack.imgur.com/aRwFM.png
其中以ldd顺序列出的库,例如
ldd a.so
b.so
d.so
让我们假设foo
在c.so和d.so中定义,并在f.so中首次引用。我的实验表明,链接器将从d.so实现。看起来库是按bfs顺序搜索的。这是对的吗?这与库的加载顺序一致吗?我在任何文档中都找不到这一点,必须确保它不是由实现定义的。
谢谢!
解析符号引用时,动态链接器会使用广度优先搜索来检查符号表。也就是说,它首先查看可执行程序本身的符号表,然后查看
DT_NEEDED
条目的符号表(按顺序),然后查看第二级DT_NEEDED
条目,依此类推
(有各种扩展可以改变这种行为。ELF规范本身定义了DF_SYMBOLIC
标志。)
这意味着你的问题无法回答,因为你的图没有显示主要的可执行文件,也不清楚搜索多个依赖项的顺序(从上到下或从下到上)。
查找顺序是否与对象加载顺序匹配是实现定义的,因为根据ELF规范,仅仅加载对象(而不执行其初始化函数)并不是具有可观察效果的东西。
初始化顺序(执行初始化函数的顺序)比符号查找顺序约束更小,因为DT_NEEDED
条目的顺序与此无关。因此,理论上,实现可能在b.so
之前加载并初始化d.so
,但来自b.so
的符号插入d.so
的符号,因为它在符号搜索顺序中排名第一(由于DT_NEEDED
条目的排序方式)。