解决找不到RUNPATH下的库的问题

阅读量: searchstar 2023-12-25 01:18:00
Categories: Tags:

这个问题困扰了我很久,受GPT4的指点才解决的,这里记录一下解决问题的过程。

症状

$ ldd rocksdb-kvexe
        libfolly.so.0.58.0-dev => /home/admin/opt/cachelib/lib/libfolly.so.0.58.0-dev (0x00007ff382e00000)
        libthrift-core.so.1.0.0 => not found

$ ./rocksdb-kvexe 
./rocksdb-kvexe: error while loading shared libraries: libthrift-core.so.1.0.0: cannot open shared object file: No such file or directory

找不到这个库:libthrift-core.so.1.0.0。它在这里:

$ stat /home/admin/opt/cachelib/lib/libthrift-core.so.1.0.0
  File: /home/admin/opt/cachelib/lib/libthrift-core.so.1.0.0
  Size: 187504          Blocks: 368        IO Block: 4096   regular file
Device: 259,2   Inode: 950220      Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/   admin)   Gid: ( 1000/   admin)
Access: 2023-12-24 16:23:10.233856940 +0000
Modify: 2023-12-23 12:44:00.000000000 +0000
Change: 2023-12-23 12:49:50.050831528 +0000
 Birth: 2023-12-23 12:49:50.050831528 +0000

我们检查一下RUNPATH

readelf -d rocksdb-kvexe | grep PATH
 0x000000000000001d (RUNPATH)            Library runpath: [/home/admin/rocksdb/build:/home/admin/opt/cachelib/lib]

它已经包含了libthrift-core.so.1.0.0所在的目录/home/admin/opt/cachelib/lib。说明RUNPATH没有问题。而且跟它同目录的libfolly.so.0.58.0-dev也找到了,说明问题不是出在binary的RUNPATH上。

排查问题

GPT4建议我用LD_DEBUG=libs来debug链接的过程:

LD_DEBUG=libs ./rocksdb-kvexe

其中有这样一段:

   1654057:     find library=libthrift-core.so.1.0.0 [0]; searching
   1654057:      search path=/home/admin/CacheLib/opt/cachelib/lib/glibc-hwcaps/x86-64-v4:/home/admin/CacheLib/opt/cachelib/lib/glibc-hwcaps/x86-64-v3:/home/admin/CacheLib/opt/cachelib/lib/glibc-hwcaps/x86-64-v2:/home/admin/CacheLib/opt/cachelib/lib/tls/haswell/avx512_1/x86_64:/home/admin/CacheLib/opt/cachelib/lib/tls/haswell/avx512_1:/home/admin/CacheLib/opt/cachelib/lib/tls/haswell/x86_64:/home/admin/CacheLib/opt/cachelib/lib/tls/haswell:/home/admin/CacheLib/opt/cachelib/lib/tls/avx512_1/x86_64:/home/admin/CacheLib/opt/cachelib/lib/tls/avx512_1:/home/admin/CacheLib/opt/cachelib/lib/tls/x86_64:/home/admin/CacheLib/opt/cachelib/lib/tls:/home/admin/CacheLib/opt/cachelib/lib/haswell/avx512_1/x86_64:/home/admin/CacheLib/opt/cachelib/lib/haswell/avx512_1:/home/admin/CacheLib/opt/cachelib/lib/haswell/x86_64:/home/admin/CacheLib/opt/cachelib/lib/haswell:/home/admin/CacheLib/opt/cachelib/lib/avx512_1/x86_64:/home/admin/CacheLib/opt/cachelib/lib/avx512_1:/home/admin/CacheLib/opt/cachelib/lib/x86_64:/home/admin/CacheLib/opt/cachelib/lib(RUNPATH from file /home/admin/opt/cachelib/lib/libthriftprotocol.so.1.0.0)

可以看到,libthrift-core.so.1.0.0libthriftprotocol.so.1.0.0的dependency,所以查找libthrift-core.so.1.0.0的时候会在libthriftprotocol.so.1.0.0的RUNPATH而不是rocksdb-kvexe的RUNPATH里找,而libthriftprotocol.so.1.0.0的RUNPATH是错误的,导致了libthrift-core.so.1.0.0找不到。

解决方案

GPT4说可以直接用patchelf --set-rpath来更正library的RUNPATH:

cd ~/opt/cachelib/lib
patchelf --set-rpath $(pwd) libthriftprotocol.so.1.0.0

问题解决。

注意不能把RUNPATH设置成相对路径,因为链接器在RUNPATH里找的时候是在当前工作目录解析RUNPATH的,而不会相对于库的路径去解析RUNPATH里的相对路径。