日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

骚操作:利用强弱符号制作插件库

發(fā)布時(shí)間:2023/12/2 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 骚操作:利用强弱符号制作插件库 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

當(dāng)有強(qiáng)符號(hào)和弱符號(hào)時(shí),選擇使用強(qiáng)符號(hào)

那么我們正可以利用這個(gè)原則做以下事情:

  • 定義為弱符號(hào),如果是弱符號(hào),使用默認(rèn)行為

  • 如果鏈接了庫(kù),是強(qiáng)符號(hào),則使用外部定義行為

以此來實(shí)現(xiàn)一個(gè)類似插件的功能。通俗一點(diǎn)說:

  • 當(dāng)沒有插件時(shí),使用默認(rèn)行為

  • 鏈接了插件時(shí),使用插件的功能

原理和示例

其原理也非常簡(jiǎn)單:

  • 外部引用弱符號(hào)

  • 如果符號(hào)地址為0,則說明外部沒有鏈接插件庫(kù),未有強(qiáng)符號(hào),走默認(rèn)流程

  • 如果符號(hào)地址不為0,則說明鏈接了插件庫(kù),執(zhí)行插件庫(kù)的功能。

示例程序如下:

#include __attribute__((weak))?void?my_print();void?test_print() {//?如果是強(qiáng)符號(hào),說明鏈接了外部插件,使用外部定義if(my_print){my_print();}else{//?弱符號(hào),走默認(rèn)邏輯printf("this?is?weak?print\n");} } int?main(void) {test_print();return?0; }

上面的test_print函數(shù)是弱符號(hào),在沒有其他地方定義的情況下,也是能夠正常編譯運(yùn)行的:

$?gcc?-o?main?main.c $?./main this?is?weak?print

觀察可執(zhí)行文件:

$?nm?main?|grep?my_printw?my_print

通過nm命令我們也可以知道test_print是弱符號(hào),它前面的修飾字符是W,代表weak。

插件庫(kù)

前面的示例程序已經(jīng)能否工作了,如何讓它能否支持插件庫(kù)呢?或者說,如何讓它支持外部的插件功能呢?

這里以靜態(tài)庫(kù)為例:

//?print_plugin.c #include void?my_print() {printf("this?is?plugin?print\n"); }

制作靜態(tài)庫(kù):

$?gcc?-c?print_plugin.c $?ar?-rcs?libprint_plugin.a?print_plugin.o

鏈接插件庫(kù)

現(xiàn)在重新編譯main程序,并使用插件庫(kù):

$?gcc?-o?main?main.c?-L./?-lprint_plugin $?gcc??-o?main??main.c??-L.?-Wl,--whole-archive?-lprint_plugin?-Wl,--no-whole-archive $?nm?main?|grep?my_print 000000000000067a?T?my_print $?./main this?is?plugin?print

需要注意的是,這里在鏈接插件庫(kù)之前,需要加上:

-Wl,--whole-archive

該選項(xiàng)會(huì)將插件庫(kù)中所有符號(hào)都鏈接進(jìn)來,若非如此,在main.c中已經(jīng)有了my_print符號(hào),將不會(huì)鏈接進(jìn)來,而在此之后,又要將該選項(xiàng)恢復(fù)。最終我們可以通過nm命令看到my_print符號(hào)已經(jīng)不再是W了。也就看到了最后:

this?is?plugin?print

的打印了。

也就實(shí)現(xiàn)了我們所謂插件的功能,換句話說,可以對(duì)目標(biāo)程序進(jìn)行功能的裁剪或者增加。

總結(jié)

由于以下幾點(diǎn)原因,我們可以自己做一些支持插件庫(kù)的程序:

  • 1.重復(fù)強(qiáng)弱符號(hào)同存在時(shí),使用強(qiáng)符號(hào)

  • 2.弱符號(hào)鏈接不存在時(shí),不會(huì)報(bào)錯(cuò)

  • 3.未鏈接的外部符號(hào),地址為0,可通過判斷避免訪問非法地址

再結(jié)合前面的例子分別解釋一下:

1.在開始的程序中,即便沒有鏈接插件庫(kù),程序也可以正常編譯鏈接通過,而不會(huì)報(bào)錯(cuò)
2.沒有鏈接插件庫(kù)時(shí),由于其函數(shù)地址為0,因此,我們程序內(nèi)判斷,if(xxx),當(dāng)?shù)刂窞?時(shí),執(zhí)行默認(rèn)的行為語句。

聲明:

本文于網(wǎng)絡(luò)整理,版權(quán)歸原作者所有,如來源信息有誤或侵犯權(quán)益,請(qǐng)聯(lián)系我們刪除或授權(quán)事宜。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的骚操作:利用强弱符号制作插件库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。