问题
nokogori
gem comes with its own version of libxml2
. Moreover it warns about libxml2.so
of a different version being loaded before it was required:
if compiled_parser_version != loaded_parser_version
["Nokogiri was built against LibXML version #{compiled_parser_version}, but has dynamically loaded #{loaded_parser_version}"]
It basically compares LIBXML_DOTTED_VERSION macro and xmlParserVersion global variable:
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)
);
And I'm experiencing it firsthand. When rmagick
(which dynamically links to libxml2.so
, ldd
confirms that) is required before nokogiri
, the latter complains.
From what I can see nokogiri
is linked to libxml2
statically. First that is 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 (and friends) as a nokogori.so
's symbol (probably a sign that it was linked statically).
So how come can nokogiri
access libxml2.so
's variables? Does that mean that loading libxml2.so
overrides any statically linked versions? Can that happen in the middle of code execution?
回答1:
So how come can nokogiri access libxml2.so's variables?
This is by design (and due to the fact that nokogiri
was built incorrectly).
UNIX shared libraries are designed to emulate archive libraries. This means that the first ELF image to export a given symbol wins (there are some complications for libraries linked with -Bstatic
flag, but we'll ignore them for now).
Does that mean that loading libxml2.so overrides any statically linked versions?
Yes, if statically linked version is also exported and calls to it go though PLT.
Can that happen in the middle of code execution?
With lazy symbol resolution (which is default, except when LD_BIND_NOW
or -z now
are in effect) it will always happen in the middle of code execution.
Now, the problem is that if nokogiri
links in a static copy of libxml.a
, it should hide that fact by localizing that copy within itself and not exporting any of its symbols. That would prevent end users from having to deal with symbol conflicts.
Your best bet is to either build your own nokogiri
compiling and linking it against the same version of libxml, or to contact nokogiri
maintainers and ask them to fix their builds.
来源:https://stackoverflow.com/questions/59393918/can-a-dynamically-linked-library-override-a-static-one