動態(tài)庫

1、編譯隱藏的過程
假設(shè)有一個源文件:

#include <stdio.h>
#pragma pack(2)

#define N 666
#define PR_D(x) printf(#x" = %d\n", x )
#define CONNECT(a,b) (a##b)

#ifdef N
    #define VERSION "2.0"
#else
    #define VERSION "0.1"
#endif

int ijk;

int main(void)
{
    printf("(%s,%s,%s,%d)\n", __TIME__, __FILE__, __FUNCTION__,  __LINE__); /* print __LINE__ */
    printf("%s\n", VERSION); // print version
    PR_D(ijk);
    printf("%d\n", CONNECT(i,jk) );

    return 0;
}

通常用 gcc 完整的編譯命令是 gcc hello.c -o hello
上面的完整編譯可以分解為 預(yù)處理策菜、編譯酒贬、匯編、鏈接锭吨。

預(yù)處理可以用命令 cpp hello.c > hello.i 或者 gcc -E hello.c -o hello.i零如,

$ gcc -E hello.c
...
# 2 "hello.c" 2
#pragma pack(2)
# 14 "hello.c"

# 14 "hello.c"
int ijk;

int main(void)
{
    printf("(%s,%s,%s,%d)\n", "07:03:49", "hello.c", __FUNCTION__, 18);
    printf("%s\n", "2.0");
    printf("ijk"" = %d\n", ijk );
    printf("%d\n", (ijk) );

    return 0;
}

可以看到:
#include 被展開了,頭文件內(nèi)容太多不放在這里了祸憋。
#define 被展開了夺衍,除了__FUNCTION__喜命,其他都替換了。
#if#ifdef 等條件編譯被展開了壁榕,VERSION 已經(jīng)替換成 "2.0" 了牌里。
注釋已經(jīng)被刪除了务甥。
#pragma 會保留喳篇,在后面編譯階段處理。
添加了行號麸澜、文件名等標識,以便下一個過程編譯可以產(chǎn)生調(diào)試用的行號编矾,以及如果編譯報錯時可以打印行號馁害。

如果代碼里面有太多條件編譯,不知道哪個定義了凹蜈,哪個沒定義時炉媒,可以查看 gcc -E的信息,或者直接使用#pragma message

#ifdef N
    #pragma message("N defined!")
#else
    #pragma message("N undeclared静尼!")
#endif

編譯階段的命令是 gcc -S hello.i -o hello.s
匯編段的命令是 as hello.s -o hello.o 或者 gcc -c hello.s -o hello.o

查看 .c 代碼的匯編代碼可以用 gcc -S -g -o hello.s hello.c 查看 .o文件的匯編代碼可以用 objdump -S hello.o > hello.s

2鼠渺、靜態(tài)鏈接
如果一些函數(shù)很通用,其他項目也要用拦盹,可以抽出來,單獨做成庫恬口,這樣就不用寫重復(fù)代碼了沼侣。
生成靜態(tài)庫:

gcc -c xxx.c -o xxx.o
ar -rcs libxxx.a xxx.o

鏈接:

gcc main.o -L . -lxxx -o s.out

可以查看靜態(tài)庫包文件中含了哪些文件:

$ ar -t libxxx.a
xxx.o

ar tv /usr/lib/gcc/x86_64-linux-gnu/8/libgcc.a

ar -x 可以從 *.a 解壓出 *.o文件:

ar -x libxxx.a

靜態(tài)鏈接的缺點:
一是浪費空間,每個可執(zhí)行程序中都有一份所有需要的目標文件的副本养铸;
二是更新比較麻煩,每當(dāng)庫函數(shù)的代碼修改了兔甘,不僅要重新編譯靜態(tài)庫鳞滨,還需要重新鏈接所有用到該庫的項目,以形成新的可執(zhí)行程序太援。
優(yōu)點就是執(zhí)行的時候速度快一些。

3仙蛉、動態(tài)鏈接
可執(zhí)行文件較小碱蒙,在程序運行時才將它們鏈接在一起形成一個完整的程序,不會在內(nèi)存中存在多份副本哀墓。

生成動態(tài)庫的命令:

gcc -c xxx.c -o xxx.o
gcc -fPIC -shared xxx.o -o libxxx.so

鏈接的命令和靜態(tài)是一樣的喷兼,不過動態(tài)鏈接后,運行時可能會報錯

error while loading shared libraries: libxxx.so: cannot open shared object file: No such file or directory

因為找不到該動態(tài)庫吠各,需要把庫文件所在目錄添加到環(huán)境變量:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

查詢一個可執(zhí)行文件依賴哪些動態(tài)庫:

$ ldd a.out 
    linux-vdso.so.1 (0x00007ffd04588000)
    libxxx.so => ./libxxx.so (0x00007f3989050000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3988c5f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f3989454000)

查看某個函數(shù)是否在某個庫文件中

$ nm -D /lib/x86_64-linux-gnu/libc.so.6 |grep xxx_1
$ nm -D libxxx.so |grep xxx_1
000000000000065a T xxx_1

除了 nm 命令勉抓,還可以使用 readelfobjdumpstrings 命令纵散,這些命令都屬于 GNU binutils 工具集隐圾。:

$ readelf -a libxxx.so |grep xxx_1
     8: 000000000000065a    31 FUNC    GLOBAL DEFAULT   12 xxx_1
    55: 000000000000065a    31 FUNC    GLOBAL DEFAULT   12 xxx_1
$ objdump -tT libxxx.so |grep xxx_1
000000000000065a g     F .text  000000000000001f              xxx_1
000000000000065a g    DF .text  000000000000001f  Base        xxx_1
$ strings libxxx.so |grep xxx_1
xxx_1
xxx_1
xxx_1

比如我們在嵌入式編程,改了一個函數(shù)硕盹,想看看效果叨咖,又不想完整編譯啊胶、重新升級垛贤,這時候替換板子上的 .so 文件會比較快,這時候就需要確認一下這個函數(shù)屬于哪一個庫文件某饰。

/usr/lib/ 善绎、 /usr/local/lib//lib/ 目錄有很多 *.a 和 *.so 文件,可以用這些命令來測試玩一玩炬守。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末剂跟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鳍置,更是在濱河造成了極大的恐慌送淆,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砖第,死亡現(xiàn)場離奇詭異环凿,居然都是意外死亡放吩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惕澎,“玉大人,你說我怎么就攤上這事捣卤。” “怎么了董朝?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵子姜,是天一觀的道長。 經(jīng)常有香客問我牧抽,道長遥赚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任呼巴,我火速辦了婚禮御蒲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厚满。我一直安慰自己遵馆,他們只是感情好丰榴,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著换况,像睡著了一般盗蟆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上觉吭,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天仆邓,我揣著相機與錄音伴鳖,去河邊找鬼绒北。 笑死,一個胖子當(dāng)著我的面吹牛峻汉,可吹牛的內(nèi)容都是我干的脐往。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼瘤礁,長吁一口氣:“原來是場噩夢啊……” “哼梅尤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起赡盘,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤缰揪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抛姑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艳狐,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡毫目,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浆西。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡近零,死狀恐怖抄肖,靈堂內(nèi)的尸體忽然破棺而出窖杀,到底是詐尸還是另有隱情,我是刑警寧澤入客,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布桌硫,位于F島的核電站,受9級特大地震影響铆隘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掏湾,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一肿嘲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧砚嘴,春花似錦涩拙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至怔接,卻和暖如春稀轨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奋刽。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肚吏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓党觅,卻偏偏與公主長得像坞生,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子又兵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容