為什麼不能把so文件靜態鏈接到可執行文件中?

能不能指定把so文件靜態鏈接進可執行文件中? 如果不能, 是為什麼? so文件少了某些必要的信息, 還是別的什麼問題?

我知道動態鏈接和靜態鏈接的區別和各自的優缺點, 就想知道能不能在沒有.a文件只有.so文件的情況下編譯出一個不依賴.so的可執行文件

我認為, 如果so的信息完全包含a的信息, 那麼應該可以有辦法把so轉換成a, 也就可以完全靜態編譯了. 現在的情況是沒有人做, 還是由於某種原因不能做呢?


dynamic linking

Basically, a static library is just a collection of objects, and the
linker resolves the symbol names into fixed addresses -- this is
required for static linking. On the other hand, a shared library is much
more like an independent executable, which is loaded into memory by the
loader and has entry point addresses to which the program jumps.
However, relocation tables that static libraries have are generally not
preserved when a shared library is being linked, so it"s in general not
possible to extract linkable object code from inside a linked shared
library.


理論上說這種事兒是有可能的,so一般會保留relocation table,否則它就只能load到固定的位置了,而且rtld事實上乾的就是這個活兒。

你可能遇到障礙無非就是這幾個:

1、so本身已經link過一遍,不再是一堆obj了,你只能拿它當做一個單一的link單元

2、so是PIC,沒辦法把它變換成non-PIC,所以即便你把so link進來,也只能用PIC的方式調用裡面的函數,因為so內部的函數調用你沒法改。

3、stack randomization可能會給你挖坑,因為它會影響call stack的布局。

4、so的init/deinit流程需要手工調用

不過要想實現這個功能,你可能需要把ELF規範文本挖地三尺,而且還要做好「錯的不是我而是這個世界」的思想準備。


不管是Windows還是Linux,靜態庫可以變成動態庫,反之則不能,因為確實丟失了大量信息。

具體丟失了那些信息,你可以參考 @石守謙 的回答。


其實 在Windows讓 把DLL改成lib

exe改成DLL 還真有 ?_?


很明確的說,不行的。 你不能把雞當鴨用。 如果你改ld,就另當別論的。


推薦閱讀:

關於這段C代碼為什麼會輸出這種結果?
開發一個 C++ 編譯器的難度有多大,難點又在哪裡?
量子計算機的出現能否加快cpp的編譯時間?
為什麼給Mac編寫的軟體不能在Windows上運行?
Haskell 執行速度怎樣?

TAG:內存管理 | CC | Linux開發 | 編譯 |