gcc或g++的編譯選項 -shared -fPIC 與 -g -rdynamic 部分轉載
動態庫
Linux 下動態連結庫(shared object file,共享物件檔案)的檔案字尾為.so
,它是一種特殊的目標檔案(object file),可以在程式執行時被載入(連結)進來。使用動態連結庫的優點是:程式的可執行檔案更小,便於程式的模組化以及更新,同時,有效記憶體的使用效率更高。
建立一個動態連結庫,可使用 GCC 的-shared
選項。輸入檔案可以是原始檔、彙編檔案或者目標檔案。另外還得結合-fPIC
選項。-fPIC 選項作用於編譯階段,告訴編譯器產生與位置無關程式碼(Position-Independent Code);這樣一來,產生的程式碼中就沒有絕對地址了,全部使用相對地址,所以程式碼可以被載入器載入到記憶體的任意位置,都可以正確的執行。這正是共享庫所要求的,共享庫被載入時,在記憶體的位置不是固定的。
gcc選項-g與-rdynamic的異同
-g ,是一個除錯選項,是一個編譯選項,即在原始碼編譯的過程中起作用,讓gcc把更多除錯資訊(也就包括符號資訊)收集起來並將存放到最終的目標檔案內。
-rdynamic 卻是一個 連線選項 ,它將指示聯結器把所有符號(而不僅僅只是程式已使用到的外部符號)都新增到動態符號表(即.dynsym表)裡,以便那些通過 dlopen() 或 backtrace() (這一系列函式使用.dynsym表內符號)這樣的函式使用。
新增-rdynamic選項後,.dynsym表就包含了所有的符號,不僅是已使用到的外部動態符號,還包括本程式內定義的符號,比如bar、foo、baz等。
[root@www c]# gcc -O0 -rdynamic -o t.rd t.c
[root@www c]# readelf -s t.rd
Symbol table '.dynsym' contains 20 entries:
Symbol table '.symtab' contains 67 entries:
[root@www c]# strip t.rd [root@www c]# readelf -s t.rd
簡單總結一下-g選項與-rdynamic選項的差別:
1,-g選項新新增的是除錯資訊(一系列.debug_xxx段),被相關除錯工具,比如gdb使用,可以被strip掉。
2,-rdynamic選項新新增的是動態連線符號資訊,用於動態連線功能,比如dlopen()系列函式、backtrace()系列函式使用,不能被strip掉,即強制strip將導致程式無法執行:
[root@www c]# ./t.rd test[root@www c]# strip -R .dynsym t.rd [root@www c]# ./t.rd
3 .symtab表在程式載入時會被載入器 丟棄 ,gdb等除錯工具由於可以直接訪問到磁碟上的二進位制程式檔案:
[root@www c]# gdb t.g -q
Reading symbols from /home/work/dladdr/c/t.g...done.
因此可以使用所有的除錯資訊,這包括.symtab表;
而backtrace()系列函式作為程式執行的邏輯功能,無法去讀取磁碟上的二進位制程式檔案,因此只能使用.dynsym表。
其它幾個工具可以動態指定檢視,比如nm、objdump:
[root@www c]# nm t.rd nm: t.rd: no symbols [root@www c]# nm -D t.rd 0000000000400848 R _IO_stdin_used w _Jv_RegisterC
[root@www c]# objdump -T t.rd t.rd: file format elf64-x86-64 DYNAMIC SYMBOL TABLE: 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 printf
4,-rdynamic選項不產生任何除錯資訊,因此在一般情況下,新增的附加資訊比-g選項要少得多。除非是完全的靜態連線,否則即便是沒有加-rdynamic選項,程式使用到的外部動態符號,比如前面示例裡的printf,也會被自動加入到.dynsym表。
makefile編寫
[fdj@hs-192-168-33-206 tst]$ cat makefile
INCDIR = -I .
CC = g++
CFLAGS = -c -g
LFLAGS = -rdynamic
#so LFLAGS = -shared -fPIC
TARGET = demo
OBJS=testDst.o US_Time_Until.o
all: cleanobj $(TARGET)
testDst.o:testDst.cpp
$(CC) $(CFLAGS) testDst.cpp $(INCDIR)
US_Time_Until.o:US_Time_Until.cpp
$(CC) $(CFLAGS) US_Time_Until.cpp $(INCDIR)
$(TARGET):$(OBJS)
$(CC) $(LFLAGS) -o $(TARGET) $(OBJS)
cleanobj:
rm -f *.o
clean:cleanobj
clean all
相關文章
- 用ccache加速你的gcc/g++編譯(轉)GC編譯
- linux下gcc/g++編譯用法LinuxGC編譯
- GCC編譯選項GC編譯
- GCC 編譯選項GC編譯
- gcc與g++的區別GC
- gcc 和 g++ 的聯絡和區別,使用 gcc 編譯 c++GC編譯C++
- GCC的-g選項應該在編譯階段起作用(轉)GC編譯
- GCC/G++學習筆記 - 1 - 執行預編譯GC筆記編譯
- gcc編譯引數-fPIC的一些問題GC編譯
- gcc g++支援C++11 標準編譯及其區別GCC++編譯
- gcc 和 g++ 的區別GC
- gcc常用的編譯選項對程式碼的影響(轉)GC編譯
- g++的編譯器真強大編譯
- G++編譯連結的那些事!G++的特殊使用方法[常用]編譯
- linux下gcc/g++命令LinuxGC
- g++ 和 gcc 的相同點和區別GC
- Linux下修改gcc和g++的版本LinuxGC
- cmake中新增 -g編譯選項編譯
- gcc 編譯器與 clang 編譯器GC編譯
- gcc最佳編譯引數(轉)GC編譯
- 安裝 GCC 編譯器(轉)GC編譯
- gcc編譯GC編譯
- 編譯器GCC與Clang的異同編譯GC
- 【知識點】 gcc和g++的聯絡和區別GC
- FreeBSD中的GNU C編譯器--編譯器GCC(轉)編譯GC
- GCC 使用指南及gcc最佳編譯引數(轉)GC編譯
- 【轉】gcc中的-w -W和-Wall選項GC
- PHP編譯選項PHP編譯
- GCC編譯器的使用GC編譯
- gcc編譯器小知識FAQ(轉)GC編譯
- 核心編譯選單中相關選項的意義(轉)編譯
- ubuntu 20.04安裝GCC G++ 6.2,支援c++ 14UbuntuGCC++
- __cxa_pure_virtual報錯(g++編譯虛擬函式時)編譯函式
- linux下的gcc編譯LinuxGC編譯
- gcc編譯cpp檔案GC編譯
- vc 編譯連線選項編譯
- GNU 編譯器家族 GCC 內部探密(轉)編譯GC
- GCC編譯器背後的故事GC編譯