LD_LIBRARY_PATH对LibXML.so不起作用

问题描述 投票:2回答:2

XML::LibXML是一个Perl库。 LibXML.so是图书馆的一部分。我想让XML::LibXML使用定制的libxml2。但提供LD_LIBRARY_PATH没有任何区别:

$ ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
    libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f66af5e9000)

$ LD_LIBRARY_PATH=/home/yuri/_/libxml2/.libs ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
    libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f2d26ae3000)

$ ldd /usr/lib/python3.7/site-packages/libxml2mod.so | grep libxml2
    libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f878cbc8000)

$ LD_LIBRARY_PATH=/home/yuri/_/libxml2/.libs ldd /usr/lib/python3.7/site-packages/libxml2mod.so | grep libxml2
    libxml2.so.2 => /home/yuri/_/libxml2/.libs/libxml2.so.2 (0x00007f6f8f5d8000)

我究竟做错了什么?有办法处理吗?目标是使Perl脚本使用自定义构建的libxml2(以调查某些问题)。

UPD

$ find /usr/lib -name libxml2.so.2
/usr/lib/libxml2.so.2
/usr/lib/vmware-installer/2.1.0/lib/lib/libxml2.so.2
/usr/lib/vmware-installer/2.1.0/lib/lib/libxml2.so.2/libxml2.so.2
/usr/lib/vmware-vmrc/5.5/lib/libxml2.so.2
/usr/lib/vmware-vmrc/5.5/lib/libxml2.so.2/libxml2.so.2

$ find /usr/local/lib -name libxml2.so.2
c perl ld libxml2 dynamic-loading
2个回答
3
投票

tl;dr

ExtUtils::MakeMaker通过RPATH部分中的.dynamic条目硬编码二进制文件中共享库的路径。但是你可以预加载所需的库,

$ LD_PRELOAD=path/to/custom/libxml2/.libs/libxml2.so.2 ldd ./blib/arch/auto/XML/LibXML/LibXML.so

或使加载程序忽略RPATH条目,

$ LD_LIBRARY_PATH=path/to/custom/libxml2/.libs /usr/lib/ld-linux-x86-64.so.2 --inhibit-rpath /abs/path/to/LibXML.so /abs/path/to/perl ./1.pl

或者将RPATH条目转换为RUNPATH

$ chrpath --convert blib/arch/auto/XML/LibXML/LibXML.so

或删除RPATH条目,

$ chrpath --delete blib/arch/auto/XML/LibXML/LibXML.so

或指定XMLPREFIX变量,

$ perl Makefile.PL XMLPREFIX=path/to/custom/libxml2/build

Under the hood

ExtUtils::Liblist::ext()列出了与-lxml2 -lz -llzma -licui18n -licuuc -licudata -lm -ldl相关联的库,并将它们转换为fourfive variables,它们将进入生成的Makefile。其中之一是LD_RUN_PATH。它包含找到库的所有路径。

如果图书馆是动态的,$is_dyna是真的(不是ends.a)。如果Perl与$is_perl不是built,则it是真的,而%ld_run_path_seenLD_RUN_PATH中不重复值。

calculates LD_RUN_PATH,用variable生成Makefile的一部分,以及将它传递给linker的部分。

Consequences

LD_RUN_PATH以及二进制文件中的RPATH条目使加载程序在找到它们的目录(在编译时)搜索库(在运行时)。

-rpath = dir将目录添加到运行时库搜索路径。将ELF可执行文件与共享对象链接时使用此方法。所有-rpath参数都连接在一起并传递给运行时链接程序,后者使用它们在运行时查找共享对象。在定位链接中明确包含的共享对象所需的共享对象时,也会使用-rpath选项;请参阅-rpath-link选项的说明。如果在链接ELF可执行文件时未使用-rpath,则在定义环境变量“LD_RUN_PATH”的内容时将使用该内容。

https://jlk.fjfi.cvut.cz/arch/manpages/man/core/binutils/ld.1.en

如果共享对象依赖项不包含斜杠,则按以下顺序搜索它:

o使用二进制文件的DT_RPATH动态部分属性中指定的目录(如果存在)和DT_RUNPATH属性不存在。不推荐使用DT_RPATH。

o使用环境变量LD_LIBRARY_PATH,除非可执行文件以安全执行模式运行(参见下文),在这种情况下,此变量将被忽略。

https://jlk.fjfi.cvut.cz/arch/manpages/man/core/man-pages/ld.so.8.en

$ perl Makefile.PL
$ make

结果,

$ readelf --dynamic ./blib/arch/auto/XML/LibXML/LibXML.so | grep RPATH
 0x000000000000000f (RPATH)              Library rpath: [/usr/lib]

$ objdump -x ./blib/arch/auto/XML/LibXML/LibXML.so | egrep RPATH
  RPATH                /usr/lib

$ LD_LIBRARY_PATH=path/to/custom/libxml2/.libs ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
    libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f6cfabb2000)

--dynamic - 显示.dynamic部分的内容,-x - 显示所有标题。

Solution

解决这个问题的一种方法是预加载所需的libxml2实例,

$ LD_PRELOAD=path/to/custom/libxml2/.libs/libxml2.so.2 ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
    path/to/custom/libxml2/build/lib/libxml2.so.2 (0x00007fe183aeb000)

另一种方法是告诉Makefile.PL在所需位置(编译时)搜索libxml2

$ perl Makefile.PL XMLPREFIX=path/to/custom/libxml2/build
$ make

结果,

$ readelf --dynamic ./blib/arch/auto/XML/LibXML/LibXML.so | grep RPATH
 0x000000000000000f (RPATH)              Library rpath: [path/to/custom/libxml2/build/lib:/usr/lib]

$ objdump -x ./blib/arch/auto/XML/LibXML/LibXML.so | egrep RPATH
  RPATH                path/to/custom/libxml2/build/lib:/usr/lib

$ ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
    libxml2.so.2 => path/to/custom/libxml2/build/lib/libxml2.so.2 (0x00007fe183aeb000)

On a side note

如果您想调试XML::LibXML,可以使用OPTIMIZE变量运行make(添加-B以使make重建所有内容,以防已经构建了库),

$ make OPTIMIZE='-g3 -O0'

还有-O2-g没有LDDLFLAGS,但不确定这是否重要。

或者,WriteMakeFile采用OPTIMIZE参数,所以你可以添加一行here

'OPTIMIZE' => '-g3 -O0'

或者你可以添加变量here,并将其传递给Makefile.PL

$ perl Makefile.PL OPTIMIZE='-g3 -O0'

-1
投票

如果你在/usr/local/lib中安装自定义版本的libxml,我认为XML :: LibXML模块应该加载自定义版本而不是/usr/lib中的那个(假设你有sudoers或root权限来安装它)。

我不确定为什么Python似乎使用不同的库查找路径而不是Perl。也许libxml库的完整路径是在XML :: LibXML的LibXML.so中硬编码的?如果XML :: LibXML模块与-l / usr / lib / libxml2.so而不是-lxml2链接,那将是问题。

© www.soinside.com 2019 - 2024. All rights reserved.