
x.cpp為共享庫libx.so的實作,b.cpp為可執行b的實作。
x.cpp檔案内容:
#include
// 使用C++作為編譯器
void woo()
{
printf("woo\n");
}
// foo作為共享庫的入口,必須為C函數
extern "C" foo()
printf("foo\n");
exit(0); // 請注意這裡必須調用,否則輸出foo後會有段錯誤
b.cpp檔案内容:
int main()
extern void woo();
extern "C" void foo();
woo();
foo();
return 0;
編譯x.cpp為可執行的共享庫:
g++ -g -o libx.so -fPIE -pie -nostartfiles -Wl,-e,foo -rdynamic x.cpp
-fPIE -pie是保證共享庫可以執行,其中-fPIE編譯參數,表示生成與位置無關的可執行代碼(-fPIC隻是生成與位置無關的非可執行代碼),-pid是連結參數;-Wl,-e,foo指定共享庫的入口函數,相當于可執行程式的main函數;如果沒有-nostartfiles,則連結時會報main函數未定義;-rdynamic也是必須的,否則編譯b.cpp時會報找不到foo定義;如需檢視詳細的編譯連結過程,加上-v參數。請注意不能包含<b>-shared</b>參數,否則運作共享庫時直接段錯誤。
編譯b.cpp為可執行檔案:
g++ -g -o b -L. -lx b.cpp
成功之後,libx.so和b都是可執行的了,其中libx.so的入口是foo,而b的入口是main函數。
當使用選項-fpie或-fPIE時,生成的共享庫不會為靜态成員變量或全局變量在GOT中建立對應的條目(通過objdump -x -R或readelf指令可以檢視)。選項-fpie/-fPIE與-fpic/ -fPIC的用法很相似,差別在于前者總是将生成的位置無關代碼看作是屬于程式本身,并直接連結進該可執行程式,而非存入全局偏移表GOT中。
GCC MAN描述:
-fpie
-fPIE
These options are similar to -fpic and -fPIC, but generated position independent code can be only linked into executables. Usually these options are
used when -pie GCC option will be used during linking.
-fpic
-fPIC
Generate position-independent code (PIC) suitable for use in a shared library.
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.
-pie
Produce a position independent executable on targets which support it. For predictable results, you must also specify the same set of options that were
used to generate code (-fpie, -fPIE, or model suboptions) when you specify this option.
-rdynamic
Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the
dynamic symbol table. This option is needed for some uses of "dlopen" or to allow obtaining backtraces from within a program.
-Wl的使用
-Wl表示後面的參數傳遞給連結器,其中l是linker的意思。
連結時指定共享庫的搜尋路徑(類似于設定LD_LIBRARY_PATH):
-Wl,-rpath=/usr/local/abc:/data/abc
以上也可以分開寫:
-Wl,-rpath=/usr/local/abc -Wl,-rpath=/data/abc
部分庫連結它的靜态庫,部分庫連結它的共享庫:
-Wl,-static -lb -Wl,-call_shared -la -lz
指定連結器:
-Wl,-dynamic-linker /lib/ld-linux.so.2 -e _so_start
指定導出的符号:
-Wl,--export-dynamic,--version-script,exports.lds
exports.lds的格式可以為:
global:
foo;
};
指定共享庫的soname:
-Wl,--export-dynamic,--version-script,exports.lds,-soname=libqhttpd.so
-rpath 增加共享庫搜尋路徑
--retain-symbols-file表示不丢棄未定義的符号和需要重定位的符号
--export-dynamic 建立一個動态連接配接的可執行程式時, 把所有的符号加到動态符号表中