gcc報錯 can not be used when making a shared object; recompile with -fPIC


使用google protobuf時,出現錯誤

/usr/bin/ld: /usr/local/lib/libprotobuf.a(message_lite.o): relocation R_X86_64_32S against `_ZTVN6google8protobuf11MessageLiteE' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libprotobuf.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

搜了下,幾篇文章如下:


查看整個編譯過程,編譯過程中看到沒有-fPIC選項,如何加進去
看protobuffer的README和INSTALL文檔,看到需要添加特殊編譯選項,需要在執行configure的時候引入,
於是make clean; make uninstall

./configure CXXFLAGS=-fPIC
查看編譯文件,發現已經有了編譯選項-fPIC,再次執行編譯安裝
重新編譯程序,這次沒有報錯,沒有出錯,問題解決。

另外回答;

原因:
-fPIC 是個神馬東東呢?
選項 -fPIC
PIC是Position-Independent-Code的縮寫。在計算機系統中,PIC和PIE(Position-IndependentExecutable)是可以在主存中不同位置執行的目標代碼。PIC經常被用在共享庫中,這樣就能將相同的庫代碼為每個程序映射到一個位置,不用擔心覆蓋掉其他程序或共享庫。

為so動態庫編譯的時候加上了 -fPIC,但是連接的 libprotobuf.a文件並不是 -fPIC生成的,所以就報錯了。
那就是說連接的 libprotobuf.aa 文件,也需要加上 -fPIC 選項進行編譯了。

gcc -fPIC選項

關於-fPIC:http://blog.sina.com.cn/s/blog_54f82cc201011op1.html

使用 -fPIC 選項,會生成 PIC 代碼。.so 要求為 PIC,以達到動態鏈接的目的,否則,無法實現動態鏈接。
 
non-PIC 與 PIC 代碼的區別主要在於 access global data, jump label 的不同。
比如一條 access global data 的指令,
non-PIC 的形勢是:ld r3, var1
PIC 的形式則是:ld r3, var1-offset@GOT,意思是從 GOT 表的 index 為 var1-offset 的地方處
指示的地址處裝載一個值,即 var1-offset@GOT 處的4個 byte 其實就是 var1 的地址。這個地址只有在運行的時候才知道,
是由 dynamic-loader(ld-linux.so) 填進去的。
 
再比如 jump label 指令
non-PIC 的形勢是:jump printf ,意思是調用 printf。
PIC 的形式則是:jump printf-offset@GOT,意思是跳到 GOT 表的 index 為 printf-offset 的地方處
指示的地址去執行,這個地址處的代碼擺放在 .plt section,每個外部函數對應一段這樣的代碼,其功能是呼叫
dynamic-loader(ld-linux.so) 來查找函數的地址(本例中是 printf),然后將其地址寫到 GOT 表的 index 為 printf-offset 的地方,
同時執行這個函數。這樣,第2次呼叫 printf 的時候,就會直接跳到 printf 的地址,而不必再查找了。
 
GOT 是 data section, 是一個 table, 除專用的幾個 entry,每個 entry 的內容可以再執行的時候修改;
PLT 是 text section, 是一段一段的 code,執行中不需要修改。
每個 target 實現 PIC 的機制不同,但大同小異。比如 MIPS 沒有 .plt, 而是叫 .stub,功能和 .plt 一樣。
 
可見,動態鏈接執行很復雜,比靜態鏈接執行時間長;但是,極大的節省了 size,PIC 和動態鏈接技術是計算機發展史上非常重要的一個里程碑。
 

 

/usr/bin/ld: libs/X86_64/libglog.a(libglog_la-logging.o): relocation R_X86_64_32S against `_ZTVN6google4base6LoggerE' can not be used when making a shared object; recompile with -fPIC libs/X86_64/libglog.a: could not read symbols: Bad value collect2: error: ld returned 1 exit status

只能安裝錯誤提供的方法重現編譯libglog.a了,然后,替換了libglog.

CXXFLAGS="-O3 -fPIC" ./configure --prefix=glog-0.3.3/install

參考:http://zrj.me/archives/1066


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM