【问题标题】:Executable cannot find dynamically linked mkl library, but ldd does可执行文件找不到动态链接的 mkl 库,但 ldd 可以
【发布时间】:2013-07-23 21:39:02
【问题描述】:

我有一个与 mkl 库动态链接的代码。运行代码时,报mkl not found。

./bmdl
/g/software/EMTO/5.7/intel_12.1/ser/bin/bmdl: error while loading shared libraries: libmkl_intel_lp64.so: cannot open shared object file: No such file or directory

但是当我使用 ldd 检查可执行文件中的动态链接库时,它显示找到了 mkl 库

ldd bmdl
libmkl_intel_lp64.so => /g/software/intelXE/composer_xe_2011_sp1/mkl/lib/intel64/libmkl_intel_lp64.so (0x00002b975d76d000)
libmkl_sequential.so => /g/software/intelXE/composer_xe_2011_sp1/mkl/lib/intel64/libmkl_sequential.so (0x00002b975df53000)
libmkl_core.so => /g/software/intelXE/composer_xe_2011_sp1/mkl/lib/intel64/libmkl_core.so (0x00002b975e631000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003785600000)
libm.so.6 => /lib64/libm.so.6 (0x0000003784e00000)
libc.so.6 => /lib64/libc.so.6 (0x0000003784a00000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000378a600000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003785200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003784600000)

知道可能出了什么问题吗?

来自readelf -l ./bmdl的输出

Elf file type is EXEC (Executable file)
Entry point 0x4034b0
There are 8 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001c0 0x00000000000001c0  R E    8
  INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000e4eb4 0x00000000000e4eb4  R E    200000
  ....

更多调试

$ export LD_DEBUG=libs,files
$ ./bmdl
./bmdl: error while loading shared libraries: libmkl_intel_lp64.so: cannot open shared object file: No such file or directory
$ ldd ./bmdl
     15133: 
     15133: file=libtermcap.so.2 [0];  needed by /bin/sh [0]
     15133: find library=libtermcap.so.2 [0]; searching
     15133:  search path=/g/software/intelXE/composer_xe_2011_sp1/mkl/lib/intel64/tls/x86_64:/g/software/intelXE/composer_xe_2011_sp1/mkl/lib/intel64/tls:/g/software/intelXE/composer_xe_2011_sp1/mkl/lib/intel64/x86_64:/g/software/intelXE/composer_xe_2011_sp1/mkl/lib/intel64:/g/software/intelXE/composer_xe_2011_sp1/lib/intel64/tls/x86_64:/g/software/intelXE/composer_xe_2011_sp1/lib/intel64/tls:/g/software/intelXE/composer_xe_2011_sp1/lib/intel64/x86_64:/g/software/intelXE/composer_xe_2011_sp1/lib/intel64        (LD_LIBRARY_PATH)
     ....      

似乎LD_DEBUG 对单独运行./bmdl 没有影响。

我刚刚意识到旧的bmdl 有一个“setgid”标志,而我的新版本没有它。也许这就是原因?

-rwxr-sr-x 1 root gants 1123992 Jul 23 16:14 /scratch/helpdesk/bmdl

我从旧的bmdl 中删除了setgid 位并运行./bmdl 不会抱怨找不到库。现在的问题是为什么 setgid 会干扰动态链接库?

具有动态链接可执行文件的 setgid 可能会导致安全问题,并且受到 GNU glibc 的极大限制。例如,LD_LIBRARY_PATH 将被忽略。也许旧建筑以前从未工作过?!

【问题讨论】:

  • 您能否提供 cmd 行来显示您如何编译和链接您的 bmdl
  • 链接MKL的命令行为-L$(MKLPATH) -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread。我在这里省略了一些细节。 bmdl 是由其他人首先构建的,并且有效。几个月后,我们发现它抱怨找不到 mkl 库。所以我用它原来的makefile重建了它。新的构建工作。但是我只是觉得很奇怪为什么原来的构建不起作用,尤其是ldd可以解析所有动态链接的库。
  • 这很奇怪。您使用哪个编译器/链接器?在您的原始帖子中提供整个 complie/link cmd 行可能会有所帮助。你也可以试试静态链接。
  • 埃里克,我使用了Intel XE 12.1.5.339 compilerGNU ld version 2.17.50.0.6-12.el5 20061020。我怀疑这是编译器或链接器的问题,因为我再次构建 bmdl 并且新的工作正常。我只是对旧的bmdl 感到奇怪,我担心我们的系统可能存在一些不一致。
  • 您提到您的程序是很久以前构建的。也许在这段时间编译器/链接器已经更新,并且您没有在新构建之前清理您的项目。然后你的一些 obj 是由不同版本的编译器构建的。那么问题就出现了。

标签: linker intel-mkl ldd


【解决方案1】:

使用 MKL 需要正确设置环境变量,包括 INCLUDE、MKLROOT、LD_LIBRARY_PATH、LIBRARY_PATH、CPATH、FPATH 和 NLSPATH。

这可以通过英特尔提供的单个脚本来完成。

如果你使用intel编译器,

  $ source ${intel_dir}/bin/compilervars.sh intel64

如果你只将 MKL 与 gcc 编译器一起使用,

  $ source ${intel_dir}/mkl/bin/mklvars.sh intel64

您可以将此 cmd 行添加到您的 .bashrc,这样您就不需要每次都运行它。

【讨论】:

  • 埃里克,感谢您的回复。在我运行可执行文件之前,所有环境变量都已正确设置。
【解决方案2】:

代码是动态链接的并具有 setgid 属性。带有动态链接可执行文件的 setgid 可能会导致安全问题,并且受到 GNU glibc 的极大限制。例如,LD_LIBRARY_PATH 将被忽略。这就是为什么代码一直抱怨找不到一些共享库的原因。

【讨论】:

    【解决方案3】:

    但是当我使用 ldd 检查可执行文件中的动态链接库时,它显示找到了 mkl 库

    你不可能告诉我们整个故事,因为ldd(在 Linux 上)只是ld-linux.so 周围的一个小 shell 脚本。如果ld-linux.so 可以在ldd 调用时找到共享库,那么ld-linux.so 应该 能够在直接调用可执行文件时做到这一点(ld-linux.so实际上 /em> 在您运行 a.out 时映射共享库。

    我能想到的唯一合理的解释:

    • 您在与执行ldd 的环境不同的环境中执行bmdl,或者
    • 您的PATH 上有一个修改过的ldd,它可能会在运行“真实”ldd 之前修改环境。

    我如何知道使用了哪个链接器?

    readelf -l bmdl
    

    并寻找“请求程序解释器”。

    [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2].

    很奇怪。

    下一个调试建议:设置LD_DEBUG=libs,files 并查看ld-linux 在哪里搜索。您可以对lddbmdl 都这样做,看看差异来自哪里。

    【讨论】:

    • 当我使用/lib64/ld-linux-x86-64.so.2 启动bmdl 时,代码实际上运行完成。这让我徘徊在我们集群上的操作系统可能有问题的地方。知道如何进行调试。非常感谢。
    • 我阅读了 ld.so 的手册页,上面说动态链接器可以通过运行一些动态链接的程序或库来间接运行(在这种情况下,动态链接器的命令行选项不能传递并且,在 ELF 情况下,将执行存储在程序的 .interp 部分中的动态链接器)` 我检查了 bmdl.interp 部分,如下所示:` 0 .interp 0000001c 0000000000400200 0000000000400200 00000200 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA `我怎么知道使用了哪个链接器?
    • 我得到了“[请求程序解释器:/lib64/ld-linux-x86-64.so.2]”。这应该是对的。但是为什么单独运行'bmdl'时仍然找不到libmkl_intel_lp64.so?
    • export LD_DEBUG=libs,files 仅适用于ldd ./bmdl,不会向./bmdl 显示任何调试信息。
    • 我刚刚发现旧的 bmdl 有 setgid 标志 -rwxr-sr-x 1 root gants 1123992 Jul 23 16:14 ./bmdl 并且在我从旧的 bmdl 中删除标志后,运行 ./bmdl 不会抱怨找不到库。那么问题来了 setgid 是如何干扰共享库的呢?
    猜你喜欢
    • 2020-08-16
    • 2018-06-23
    • 2013-06-24
    • 2011-06-07
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多