是否总是再次从符号名称空间的根开始查找不同共享库中的相同符号?

Are same symbols in different shared libs looked up starting from the root of the symbol namespace always again?

根据我收集到的信息,共享库默认可见符号的符号名称查找以呼吸优先顺序遍历共享库依赖树,可执行程序是该搜索树的根。由一个 DT_NEEDED 列表 link 编辑的所有库都位于该树的同一级别。

因此,当查找符号 "foo" 时,在我看来,它的查找确定性地总是在运行时绑定到相同的库或可执行文件。动态 linker 是否利用了这一点并且有一个 "global symbol table" 种类(可能与 link-map 列表相关联),一旦符号是第一个就知道哪个符号属于哪个共享库查找,并在第二次由不同的共享库查找符号时从该库的 GOT 中取出符号的地址?或者该符号是否总是像第一次查找一样被查找?

Thus, when a symbol "foo" is looked up, it seems to me that its lookup is deterministically always bound to the same library or executable at runtime.

此观点方式过于简单化了。有很多并发症,例如在引用 DSO 上存在 DT_SYMBOLIC,在加载定义 DSO 时存在 RTLD_LOCAL(如果它没有直接链接),我确信我不是其他一些并发症此刻想起来。

Does the dynamic linker exploit this and has a "global symbol table" of sorts

GLIBC 加载器不会那样做。

Or will the symbol always be looked up as if this was its first lookup?

是的。您可以使用 LD_DEBUG=symbols,bindings ./a.out

观察这一点