找不到動(dòng)態(tài)鏈接庫(kù)?

前言

對(duì)于經(jīng)常在服務(wù)器上跑程序或安裝程序的朋友,不可避免的會(huì)遇到一些問(wèn)題。

其中最常見的問(wèn)題就是,像下面這樣

version `GLIBC_2.23' not found
version `GLIBC_2.15' not found

glibc 庫(kù)找不到的問(wèn)題,當(dāng)然也可能會(huì)有其他庫(kù)找不到的問(wèn)題。

那出現(xiàn)這種問(wèn)題該怎么辦呢?

常用解決方案

針對(duì)這一問(wèn)題,網(wǎng)上搜索的答案大部分都是分為以下幾步

安裝高版本的 glibc

顯然,沒(méi)有這個(gè)庫(kù),當(dāng)然先要在環(huán)境中安裝這個(gè)庫(kù)才行,比如我要安裝 glibc-2.23

  1. 下載
http://ftp.gnu.org/gnu/libc/

選擇對(duì)應(yīng)的版本并下載,如 libc-2.23.tar.gz

  1. 解壓
$ tar -zxf glibc-2.23.tar.gz
  1. 生成配置文件
$ cd glibc-2.23
$ mkdir build && cd build
$ ../configure --prefix=LIB_DIR

可以用 --prefix=LIB_DIRLIB_DIR 為你要將 glib 安裝到的路徑

通常非 root 用戶權(quán)限無(wú)法安裝到默認(rèn)的 /usr/local 目錄下,需要自己手動(dòng)指定

  1. 安裝
$ make
$ make install

等會(huì)吧,這個(gè)安裝還蠻久的。來(lái)杯咖啡,靜等安裝成功就行。

問(wèn)題

如果在 ../configure 這一步出現(xiàn)了問(wèn)題,比如我出現(xiàn) ld 版本太低的錯(cuò)誤

*** These critical programs are missing or too old: as ld

也不用著急,再安裝個(gè)較高版本的 binutils 就行。

這個(gè)怎么安裝?類似上面的 1-4 步重新來(lái)一遍就行。一般像這種 C 庫(kù)的安裝過(guò)程都是這樣的,挺簡(jiǎn)單的,只是通常拋出的異常是不簡(jiǎn)單的 (?????_?????)

  1. 配置環(huán)境

安裝完成后,大多數(shù)的答案都是將下面的命令添加到 ~/.bashrc 文件中

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:your glibc path

然后,執(zhí)行

source ~/.bashrc

但是這又會(huì)引入另一個(gè)問(wèn)題更嚴(yán)重的問(wèn)題。

glibcLinux 系統(tǒng)中最底層的 API,幾乎其他所有的庫(kù)都會(huì)依賴它。

因此當(dāng)你更新了較高版本的 glibc 時(shí),底層的庫(kù)依賴的還是低版本的 glibc 庫(kù),因此可能會(huì)導(dǎo)致系統(tǒng)的嚴(yán)重故障。

我當(dāng)初就是信了這些鬼話,添加到了環(huán)境變量中,導(dǎo)致幾乎所有的命令都無(wú)法使用。運(yùn)行命令或腳本也會(huì)出現(xiàn)

Segmentation fault

最后的解決辦法就是將 ~/.bashrc 文件中的

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:your glibc path

刪除之后,才恢復(fù)原狀。

那如何解決呢,一種方法就是每次運(yùn)行之前,在終端臨時(shí)將 glibc 的路徑添加到 LD_LIBRARY_PATH 變量中,但是這非常麻煩。

下面,我們介紹一款神器

PatchELF

PatchELF 是一個(gè)用于修改現(xiàn)有 ELF 可執(zhí)行文件和庫(kù)的簡(jiǎn)單實(shí)用程序

ELF: 可執(zhí)行與可鏈接格式(Executable and Linkable Format),常被稱為 ELF 格式。

既然它能夠更改可執(zhí)行文件,那么我們就可以直接將可執(zhí)行文件需要加載的 glibc 庫(kù)的路徑修改為我們剛才安裝的路徑。

這樣就可以在既不需要添加環(huán)境變量,也不需要手動(dòng)加載臨時(shí)變量的情況下使用。

下面,我們先安裝這個(gè)工具

1. 安裝

  1. 下載
https://github.com/dxsbiocc/patchelf

先從 GitHub 上下載源碼

  1. 配置環(huán)境
./bootstrap.sh
./configure
  1. 安裝
make
make check
make install

2. 使用

  1. 查看參數(shù)
$ patchelf 
syntax: patchelf
  [--set-interpreter FILENAME]
  [--page-size SIZE]
  [--print-interpreter]
  [--print-soname]              Prints 'DT_SONAME' entry of .dynamic section. Raises an error if DT_SONAME doesn't exist
  [--set-soname SONAME]         Sets 'DT_SONAME' entry to SONAME.
  [--set-rpath RPATH]
  [--remove-rpath]
  [--shrink-rpath]
  [--allowed-rpath-prefixes PREFIXES]           With '--shrink-rpath', reject rpath entries not starting with the allowed prefix
  [--print-rpath]
  [--force-rpath]
  [--add-needed LIBRARY]
  [--remove-needed LIBRARY]
  [--replace-needed LIBRARY NEW_LIBRARY]
  [--print-needed]
  [--no-default-lib]
  [--output FILE]
  [--debug]
  [--version]
  FILENAME...
  1. 參數(shù)描述
參數(shù) 描述
--set-interpreter FILENAME 設(shè)置動(dòng)態(tài)庫(kù)解析器
--page-size SIZE 設(shè)置頁(yè)大小
--print-interpreter 打印解析器
--print-soname 打印 DT_SONAME
--set-soname SONAME 設(shè)置 DT_SONAME
--set-rpath RPATH 設(shè)置 RPATH
--remove-rpath 刪除 RPATH
--shrink-rpath 收縮 RPATH
--allowed-rpath-prefixes PREFIXES 添加允許的 RPATH 前綴
--print-rpath 打印 RPATH
--force-rpath 強(qiáng)制使用 RPATH
--add-needed LIBRARY 添加需要的動(dòng)態(tài)庫(kù)
--remove-needed LIBRARY 刪除需要的動(dòng)態(tài)庫(kù)
--replace-needed LIBRARY NEW_LIBRARY 替換動(dòng)態(tài)庫(kù)
--print-needed 打印需要的動(dòng)態(tài)庫(kù)
--no-default-lib 不鏈接默認(rèn)的動(dòng)態(tài)庫(kù)
--output FILE 輸出文件
--debug 輸出調(diào)試信息
--version 打印版本信息

patchelf 的主要功能與動(dòng)態(tài)庫(kù)解析器、RPATH 以及動(dòng)態(tài)庫(kù)有關(guān)。

  1. 使用方式
  • 更改可執(zhí)行文件的動(dòng)態(tài)庫(kù)解析器
$ patchelf --set-interpreter /lib/my-ld-linux.so.2 my-program
  • 更改可執(zhí)行文件和庫(kù)的RPATH
$ patchelf --set-rpath /opt/my-libs/lib:/other-libs my-program
  • 收縮可執(zhí)行文件和庫(kù)的RPATH
$ patchelf --shrink-rpath my-program

該命令會(huì)刪除可執(zhí)行文件中所有不包含 DT_NEEDED 字段指定的庫(kù)的路徑。

例如:

一個(gè)可執(zhí)行文件引用一個(gè)庫(kù) libfoo.so,它的 RPATH/lib:/usr/lib:/foo/lib,而 libfoo.so 只能在 /foo/lib 中找到,那么新的 RPATH 將是 /foo/lib

其中 RPATH 指定的是可執(zhí)行文件的動(dòng)態(tài)鏈接庫(kù)的搜索路徑

  • 刪除動(dòng)態(tài)庫(kù)上聲明的依賴項(xiàng)(DT_NEEDED),可多次使用
$ patchelf --remove-needed libfoo.so.1 my-program
  • 添加動(dòng)態(tài)庫(kù)上聲明的依賴項(xiàng)(DT_NEEDED),可多次使用
$ patchelf --add-needed libfoo.so.1 my-program
  • 替換動(dòng)態(tài)庫(kù)聲明的依賴項(xiàng)(DT_NEEDED),可多次使用
$ patchelf --replace-needed liboriginal.so.1 libreplacement.so.1 my-program
  • 更改動(dòng)態(tài)庫(kù)的 SONAME
$ patchelf --set-soname libnewname.so.3.4.5 path/to/libmylibrary.so.1.2.3
  1. 示例

我有一個(gè) msi 分析的可執(zhí)行文件 msisensor-blood

在終端執(zhí)行時(shí),出現(xiàn)錯(cuò)誤

$ ./msisensor-blood
./msisensor-blood: /lib64/libm.so.6: version `GLIBC_2.23' not found (required by ./msisensor-blood)
./msisensor-blood: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ./msisensor-blood)
./msisensor-blood: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./msisensor-blood)

從輸出信息可以看出,需要兩個(gè)庫(kù)

  • glibc-2.15libc.so.6 庫(kù)
  • glibc-2.23libm.so.6 庫(kù)

首先, 我們用 ldd 命令列出其動(dòng)態(tài)庫(kù)依賴關(guān)系

./msisensor-blood: /lib64/libm.so.6: version `GLIBC_2.23' not found (required by ./msisensor-blood)
./msisensor-blood: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ./msisensor-blood)
./msisensor-blood: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./msisensor-blood)
        linux-vdso.so.1 =>  (0x00007ffc75beb000)
        libz.so.1 => /home/dengxs/software/zlib-1.2.11/lib/libz.so.1 (0x00007f7594351000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00000033dee00000)
        libstdc++.so.6 => /home/dengxs/software/anaconda3/lib/libstdc++.so.6 (0x00007f75941c4000)
        libm.so.6 => /lib64/libm.so.6 (0x00000033de600000)
        libgomp.so.1 => /home/dengxs/software/anaconda3/lib/libgomp.so.1 (0x00007f7594196000)
        libgcc_s.so.1 => /home/dengxs/software/anaconda3/lib/libgcc_s.so.1 (0x00007f7594182000)
        libc.so.6 => /lib64/libc.so.6 (0x00000033de200000)
        /lib64/ld-linux-x86-64.so.2 (0x00000033dde00000)
        librt.so.1 => /lib64/librt.so.1 (0x00000033df200000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00000033dea00000)

OK!就是把下面兩個(gè)動(dòng)態(tài)庫(kù)替換掉

libm.so.6 => /lib64/libm.so.6
...
libc.so.6 => /lib64/libc.so.6

更換 libm.so.6 的路徑

patchelf --replace-needed libm.so.6 /home/dengxs/software/glibc-2.23/lib/libm.so.6 msisensor-blood 

更換 libc.so.6 的路徑

patchelf --replace-needed libc.so.6 /share/software/glibc/2.15/lib/libc.so.6 msisensor-blood

再看下動(dòng)態(tài)庫(kù)列表

$ ldd msisensor-blood
        linux-vdso.so.1 =>  (0x00007ffde0199000)
        libz.so.1 => /home/dengxs/software/zlib-1.2.11/lib/libz.so.1 (0x00007f6a786df000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00000033dee00000)
        libstdc++.so.6 => /home/dengxs/software/anaconda3/lib/libstdc++.so.6 (0x00007f6a78552000)
        /home/dengxs/software/glibc-2.23/lib/libm.so.6 (0x00007f6a7844b000)
        libgomp.so.1 => /home/dengxs/software/anaconda3/lib/libgomp.so.1 (0x00007f6a7841d000)
        libgcc_s.so.1 => /home/dengxs/software/anaconda3/lib/libgcc_s.so.1 (0x00007f6a78409000)
        /share/software/glibc/2.15/lib/libc.so.6 (0x00007f6a78062000)
        /lib64/ld-linux-x86-64.so.2 (0x00000033dde00000)
        librt.so.1 => /lib64/librt.so.1 (0x00000033df200000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00000033dea00000)

OK,已經(jīng)替換成功了

接下去看看能不能直接運(yùn)行

$ ./msisensor-blood 


Program: msisensor-blood (homopolymer and miscrosatelite analysis using cfDNA bam files)
Version: v0.1
Author: Beifang Niu && Kai Ye

Usage:   msisensor-blood <command> [options]

Key commands:

 scan            scan homopolymers and miscrosatelites
 msi             msi scoring

沒(méi)問(wèn)題,一切順利。(^?^)??

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評(píng)論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,727評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,411評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,777評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,978評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,216評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,657評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,960評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容