錯(cuò)誤:/lib64/libc.so.6: version `GLIBC_2.14’ not found解決辦法

不管你是用annoy還是用tensorflow,用pip安裝后,然后import的時(shí)候會(huì)產(chǎn)生類似以下的異常:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/users/kinva/tools/lib/python2.7/site-packages/annoy/__init__.py", line 15, in <module>
    from .annoylib import *
ImportError: /lib64/tls/libc.so.6: version `GLIBC_2.14' not found (required by /home/users/kinva/tools/lib/python2.7/site-packages/annoy/annoylib.so)
# 如果是TF就是lib/python2.7/site-packages/tensorflow/python/_pywrap_tensorflow.so

優(yōu)先嘗試這種方法:
python錯(cuò)誤:/lib64/libc.so.6: version `GLIBC_2.14’ not found解決辦法

我在這個(gè)問題上卡了很久,也查找了很多資料,都不能圓滿解決glibc依賴的問題,連重新編譯libc-2.14都試過了。
后來(lái)偶然發(fā)現(xiàn)了這篇文文章:Running new applications on old glibc 參考這篇文章的思路,這個(gè)問題才得以圓滿解決(感謝文章的作者,同時(shí)感謝公司內(nèi)部資料),下面根據(jù)這篇文章的思路來(lái)闡述如何逐步解決annoy或者tf依賴glibc的問題。

解決方案

解決方法主要包括兩部分內(nèi)容:

  • 減弱版本依賴以便在程序在啟動(dòng)的時(shí)候不被動(dòng)態(tài)連接器終止
  • 提供缺失的依賴函數(shù)(由最新的glibc版本提供)

下面以annoy為例,TF類似的,自己替換文件路徑即可

查看依賴

錯(cuò)誤是由/home/users/kinva/tools/lib/python2.7/site-packages/annoy/annoylib.so這個(gè)動(dòng)態(tài)連接庫(kù)引起的,那看一看這個(gè)so里到底哪部分依賴了glibc2.14。

# readelf -s 文件路徑|grep GLIBC_2.14
readelf -s /home/users/kinva/tools/lib/python2.7/site-packages/annoy/annoylib.so | grep GLIBC_2.14

輸出如下:

108: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND memcpy@GLIBC_2.14 (7)
180: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND memcpy@@GLIBC_2.14

我們看到依賴了2.14的memcpy函數(shù)。

再來(lái)看一看annoylib.so中依賴的glibc版本信息,執(zhí)行:

# readelf -V 文件路徑
readelf -V /home/users/kinva/tools/lib/python2.7/site-packages/annoy/annoylib.so

輸出:


readelf1.png

可以看出在地址偏移量0x0050處,是glibc_2.14的標(biāo)記地址,問題的關(guān)鍵是如何減弱這個(gè)版本依賴。
其思路就是想辦法讓這個(gè)glibc_2.14這個(gè)版本依賴變成可選而非強(qiáng)制性的。

更改glic_2.14依賴

  • 圖中.gpu.version_r 的地址起始位置在文件偏移量0x002288處
  • glibc_2.14版本標(biāo)記地址偏移量是0x0050,在文件地址偏移量的(0x002288+0x0050)
  • 指向0x0090偏移量的位置存放的是結(jié)構(gòu)體Elfxx_Vernaux


    glibc1.png
  • vna_flags 是依賴信息,在結(jié)構(gòu)體的第二個(gè)位置,ELFxx_Word是32bit,也就是4B,因此vna_flag的起始地址偏移量是0x04

通常Flags:none在二進(jìn)制位置的值是0x0000,根據(jù)上述分析,為了能減弱glibc_2.14的版本依賴,需要在(0x002288+0x0050+0x04)處填充0x02(對(duì)應(yīng)VER_FLG_WEAK)

因此執(zhí)行:

# 要養(yǎng)成習(xí)慣,更改文件的時(shí)候,一定要備份
cp /home/users/kinva/tools/lib/python2.7/site-packages/annoy/annoylib.so annoylib.so
# 更改為弱依賴
# 其中0x22dc需要自己計(jì)算0x002288+0x0050+0x04
# 這里替換2個(gè)地方,一個(gè)是地址,一個(gè)是文件路徑,其他保持不變。
for addr in 0x22dc; do printf '\x02' | dd conv=notrunc of=/home/users/kinva/tools/lib/python2.7/site-packages/annoy/annoylib.so  bs=1 seek=$((addr)) ; done

執(zhí)行完了,我們驗(yàn)證效果:

# readelf -V 文件路徑
readelf -V /home/users/kinva/tools/lib/python2.7/site-packages/annoy/annoylib.so
readelf2.png

看到2.14版本依賴已經(jīng)變成weak了。成功了一半。

實(shí)現(xiàn)缺失的函數(shù)

接下來(lái)需要解決缺失的memcpy函數(shù),最簡(jiǎn)單的方式是生成一個(gè)本地的動(dòng)態(tài)庫(kù)來(lái)實(shí)現(xiàn)缺失的函數(shù),并在執(zhí)行程序之前使用LD_PRELOAD去load這個(gè)動(dòng)態(tài)庫(kù)。
針對(duì)上文中指出的缺失的memcpy函數(shù),如果查看實(shí)際的glibc_2.14實(shí)現(xiàn)的memcpy函數(shù)就會(huì)發(fā)現(xiàn),其實(shí)際上和memmove相同,這樣我們可以自己實(shí)現(xiàn)這個(gè)函數(shù)(mylibc.so):

#include <string.h>
void* memcpy(void *dest, const void *src, size_t n) {
    return memmove(dest, src, n);
}

執(zhí)行以下命令編譯成so

gcc -s -shared -o mylibc.so -fPIC -fno-builtin mylibc.c

得到mylibc.so共享庫(kù)
接下來(lái)就是鏈接動(dòng)態(tài)庫(kù)就好了。

  • 可以拷貝so到已經(jīng)在引入的路徑,如我的/home/users/kinva/tools/lib
  • 或者 export LD_LIBRARY_PATH=/home/users/kinva/tools/mylib:$LD_LIBRARY_PATH

再次執(zhí)行:

[kinva@MacBook-Pro ~]$ python
Python 2.7.3 (default, Jan 24 2017, 17:03:37) 
[GCC 3.4.5 20051201 (Red Hat 3.4.5-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import annoy
>>> 

其他問題

如果還是繼續(xù)報(bào)錯(cuò),請(qǐng)注意報(bào)的so已經(jīng)不一樣了,把每一個(gè)so的問題都解決。
如果你依賴的gcc是4.8+,請(qǐng)用4.6版本,否則你要擁有root權(quán)限。

TF需要更改的文件:
_pywrap_tensorflow.so
libstdc++.so.6(root權(quán)限)
librt.so.1
_sparse_feature_cross_op.so
_bucketization_op.so
_set_ops.so
_lstm_ops.so
_sdca_ops.so
需要實(shí)現(xiàn)的so有:mylibc.so和mygettime.so
memcpy和gettime相關(guān),可以查查別的資料這個(gè)實(shí)現(xiàn)很簡(jiǎn)單的,我就不寫了。

建議

這個(gè)東西根本原因就是系統(tǒng)版本庫(kù)太老,如果更新glibc將會(huì)引起系統(tǒng)不穩(wěn)定,所以建議還是升級(jí)系統(tǒng)吧。如果是centos,建議用6u3及以上版本。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 動(dòng)態(tài)鏈接,在可執(zhí)行文件裝載時(shí)或運(yùn)行時(shí),由操作系統(tǒng)的裝載程序加載庫(kù)。大多數(shù)操作系統(tǒng)將解析外部引用(比如庫(kù))作為加載過...
    小5筒閱讀 5,764評(píng)論 0 3
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,733評(píng)論 25 709
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 8,107評(píng)論 0 27
  • 在使用 MongDB,GLIBC_2.18 缺失,尷尬。最簡(jiǎn)單的的方法,途中不要推出.
    梁同桌閱讀 33,778評(píng)論 8 7
  • 那一夜我又遇見了你 你的笑容依舊如昔 我的內(nèi)心 抑制不住的激動(dòng)和狂喜 以至于忘了 這是在我的夢(mèng)里
    紅光滿面的三皮閱讀 221評(píng)論 1 0

友情鏈接更多精彩內(nèi)容