gcc -fpic 和 -fPIC 參數問題

gcc -fpic 和 -fPIC 參數問題

目的:生成位置無關的代碼。

位置無關代碼(Position-Independent Code),則產生的代碼中,沒有絕對地址,全部使用相對地址,故而代碼可以被加載器加載到內存的任意位置,都可以正確的執行。這正是共享庫所要求的,共享庫被加載時,在內存的位置不是固定的。

如果不加-fPIC,則加載.so文件的代碼段時,代碼段引用的數據對象需要重定位, 重定位會修改代碼段的內容,這就造成每個使用這個.so文件代碼段的進程在內核裏都會生成這個.so文件代碼段的copy.每個copy都不一樣,取決於 這個.so文件代碼段和數據段內存映射的位置.
也就是
不加fPIC編譯出來的so,是要再加載時根據加載到的位置再次重定位的.(因爲它裏面的代碼並不是位置無關代碼)
如果被多個應用程序共同使用,那麼它們必須每個程序維護一份.so的代碼副本了.(因爲.so被每個程序加載的位置都不同,顯然這些重定位後的代碼也不同,當然不能共享)
我們總是用fPIC來生成so,也從來不用fPIC來生成.a;fPIC與動態鏈接可以說基本沒有關係,libc.so一樣可以不用fPIC編譯,只是這樣的so必須要在加載到用戶程序的地址空間時重定向所有表目.

下面情況可以不用fPIC編譯動態庫so:

1.該庫可能需要經常更新
2.該庫需要非常高的效率(尤其是有很多全局量的使用時)
3.該庫並不很大.
4.該庫基本不需要被多個應用程序共享

如果用沒有加這個參數的編譯後的共享庫,也可以使用的話,可能是兩個原因:
1:gcc默認開啓-fPIC選項
2:loader使你的代碼位置無關

 

gcc 官網解釋:https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options

-fpic

Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts (the dynamic loader is not part of GCC; it is part of the operating system). If the GOT size for the linked executable exceeds a machine-specific maximum size, you get an error message from the linker indicating that -fpic does not work; in that case, recompile with -fPIC instead. (These maximums are 8k on the SPARC, 28k on AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit.)

Position-independent code requires special support, and therefore works only on certain machines. For the x86, GCC supports PIC for System V but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent.

When this flag is set, the macros __pic__ and __PIC__ are defined to 1.

如果目標計算機支持,則生成適合在共享庫中使用的位置無關代碼(PIC)。 這樣的代碼通過全局偏移表(GOT)訪問所有常量地址。 動態加載程序在程序啓動時解析GOT條目(動態加載程序不是GCC的一部分;它是操作系統的一部分)。 如果鏈接的可執行文件的GOT大小超過了計算機特定的最大大小,則您會從鏈接程序中收到一條錯誤消息,指示-fpic無法正常工作; 在這種情況下,請改用-fPIC重新編譯。 (這些最大值在SPARC上爲8k,在AArch64上爲28k,在m68k和RS / 6000上爲32k。x86沒有此限制。)

與位置無關的代碼需要特殊的支持,因此僅在某些機器上有效。 對於x86,GCC支持PIC for System V,但不支持Sun 386i。 爲IBM RS / 6000生成的代碼始終與位置無關。

設置此標誌後,宏__pic__和__PIC__被定義爲1。

 

-fPIC

If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset table. This option makes a difference on AArch64, m68k, PowerPC and SPARC.

Position-independent code requires special support, and therefore works only on certain machines.

When this flag is set, the macros __pic__ and __PIC__ are defined to 2.

如果目標機器支持,則發出與位置無關的代碼,該代碼適用於動態鏈接並避免對全局偏移表的大小進行任何限制。 此選項對AArch64,m68k,PowerPC和SPARC有所不同。

與位置無關的代碼需要特殊的支持,因此僅在某些機器上有效。

設置此標誌後,宏__pic__和__PIC__被定義爲2。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章