动态链接库可以覆盖静态库吗?

Can a dynamically linked library override a static one?

nokogori gem 带有自己的 libxml2 版本。此外,它 warns 关于 libxml2.so 在需要之前加载了不同的版本:

      if compiled_parser_version != loaded_parser_version
        ["Nokogiri was built against LibXML version #{compiled_parser_version}, but has dynamically loaded #{loaded_parser_version}"]

它基本上compares LIBXML_DOTTED_VERSION macro and xmlParserVersion全局变量:

  rb_const_set( mNokogiri,
                rb_intern("LIBXML_VERSION"),
                NOKOGIRI_STR_NEW2(LIBXML_DOTTED_VERSION)
              );
  rb_const_set( mNokogiri,
                rb_intern("LIBXML_PARSER_VERSION"),
                NOKOGIRI_STR_NEW2(xmlParserVersion)
              );

而且我正在亲身体验。当 rmagick(动态链接到 libxml2.soldd 确认)在 nokogiri 之前被要求时,后者会抱怨。

据我所知,nokogiri 静态链接到 libxml2。首先是 the default (supposedly). Then when rmagick is not required I can't see libxml2.so in /proc/PID/maps. I neither can see another version of libxml2.so. ldd doesn't list libxml2.so as a nokogiri.so's dependency. objdump lists xmlReadMemory(和朋友)作为 nokogori.so 的符号(可能是静态链接的标志)。

那么nokogiri怎么能访问libxml2.so的变量呢?这是否意味着加载 libxml2.so 会覆盖任何静态链接版本?这会发生在代码执行过程中吗?

So how come can nokogiri access libxml2.so's variables?

这是设计使然(并且由于 nokogiri 构建不正确)。

UNIX 共享库设计用于模拟存档库。这意味着第一个导出给定符号的 ELF 图像获胜(与 -Bstatic 标志链接的库有一些复杂性,但我们现在将忽略它们)。

Does that mean that loading libxml2.so overrides any statically linked versions?

是的,如果还导出静态链接版本并通过 PLT 调用它。

Can that happen in the middle of code execution?

使用惰性符号解析(这是默认设置,除非 LD_BIND_NOW-z now 生效)它将 总是 发生在代码中间执行。

现在的问题是,如果 nokogiri 链接到 libxml.a 的静态副本中,它应该 隐藏 通过在自身内部本地化该副本来隐藏该事实并且不导出其任何符号。这将避免最终用户不得不处理符号冲突。

你最好的选择是构建你自己的 nokogiri 编译并将其链接到相同版本的 libxml,或者联系 nokogiri 维护者并要求他们修复他们的构建。