Position Independent Code (PIC)

Linux 系統在做 static linking 的時候,linker 需要解析所有引用到外部 object file 的 symbol,然後將位址填回檔案中參考到這些 symbol 的地方。那 dynamic linking 呢?由於 linking 完後 executable 中,.text (程式碼) 部份是放到唯讀的 section,那 program loader 怎麼修改指令呢?其實 dynamic linking 採用跟 static linking 不一樣的作法,稱作 position independent code (PIC)。


由於 executable 中的指令在 loading 時不能修改,因此使用了一個放在 data section 中的 global offset table (GOT)。GOT 中記錄了外部函式或變數的位址。假如我們程式中呼叫了一個外部的函式 ext(),那在 GOT 中就會放這個函式的絕對位址。程式中只要透過 GOT,一樣可以呼叫到 外部的 ext()。這有點像間接定址的概念。


換句話說,在 linking 時,executable 指令的部份已經參考到 GOT 中的某項位址。在 loading 時,loader 不用改變 executable 中的指令 (也不能改變),只需將外部模組中 ext() 的位址填入位在 data section 中的 GOT 就可以了。


基本上 GOT 只用在呼叫外部函式或使用外部變數的時候。針對內部函式及內部變數,程式使用相對定址的方式就直接可以參考到,無需 GOT。


注意的是,一個 so 檔內部的資料區段,在每一個連結它的 process 中都有一個副本。所有參照到資料區段中變數的位址,都會在載入時被 relocate。這稱載入時重定 (load time relocation)。


如果我們在 compile so 檔時不使用 -fPIC 選項,那麼就是不使用 PIC 的方式,而是使用載入時重定的方式。這樣子指令的部份也會在 process 中有副本 --- 等於就沒用到 dynamic linking 節省記憶體的好處了。


留言

  1. 請問一下, linux的share library, 程式區段都是多process共用的, 資料區段都是每個process有一份,  如果是使用-fPIC的時候, 是這個意思嗎? 謝謝

    [版主回覆12/22/2011 09:15:46]是的~

    回覆刪除

張貼留言

熱門文章