LD_LIBRARY_PATH对LibXML.so无效

时间:2018-09-08 10:33:30

标签: c perl ld libxml2 dynamic-loading

flutter clean 是一个Perl库。 XML::LibXML是库的一部分。我正在尝试使LibXML.so使用定制的XML::LibXML。但是提供libxml2并没有什么不同:

LD_LIBRARY_PATH

我在做什么错?有办法处理吗?目的是使Perl脚本使用定制的$ 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) (以调查某些问题)。

UPD

libxml2

2 个答案:

答案 0 :(得分: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

引擎盖下

ExtUtils::Liblist::ext()获取一个要链接的库列表,例如-lxml2 -lz -llzma -licui18n -licuuc -licudata -lm -ldl,并将它们转换为fourfive variables,进入生成的Makefile中。其中之一是LD_RUN_PATH。它包含找到库的所有路径。

如果库是动态的(不是ends.a),则

$is_dyna为true。如果Perl不是builtit,则$is_perl是正确的,并且%ld_run_path_seen不能重复LD_RUN_PATH中的值。

calculates LD_RUN_PATH的一部分与variable一起生成Makefile的一部分,并将其传递给linker的一部分。

后果

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-显示所有标题。

解决方案

一种补救方法是预加载所需的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)

旁注

如果您想调试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 :(得分:-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链接,则可能是问题所在。