場景如下,需要以.o形式(靜態庫形式),發布乙個庫,給其他**整合。生成庫mylib.o之後,使用nm檢視,可以檢視到很多函式符號。但其實這個庫跟外界,應該是只通過一組指定的函式介面進行互動,其他的函式不應該暴露給外界,更不應該供外界直接呼叫。
為此,可以進行一些處理。
一種可行的方式是,將內部使用的函式,原始碼中標記為static。
但這麼修改之後,庫本身的其他原始檔,也無法使用該函式了,因為c語言中的static是將函式的作用域限定在了函式所在的原始檔。
生成庫之後,可使用工具鏈中的 objcopy 工具,修改符號表,將內部函式都修改為本地函式,這樣外部**無法直接鏈結到這些函式,只能使用指定的函式。
檢視幫助可知,objcopy 支援將除 -g 引數指定的符號外,其他符號全部修改成本地符號。
objcopy --help
-g --keep-global-symbol localize all symbols except
於是使用如下命令,
mv mylib.o mylib_origin.o
objcopy -g api_1 -g api_2 mylib_origin.o mylib.o
生成庫之後,可使用工具鏈中的 strip 工具,裁剪符號表,將不打算給外界使用的函式,直接從符號表中刪除。
檢視幫助可知,strip可用 -s 引數刪除所有符號,使用 -k 引數指定要保留的符號,使用 -n 指定要strip掉的符號。
strip --help
-s --strip-all remove all symbol and relocation information
-n --strip-symbol=do not copy symbol -k --keep-symbol=do not strip symbol --keep-file-symbols do not strip file symbol(s)
於是使用如下命令,可刪除所有符號,只保留api_1和api_2
cp mylib.o mylib_origin.o
strip -s -k api_1 -k api_2 mylib.o
使用如下命令,則是只刪除inner_fun1和inner_fun2
cp mylib.o mylib_origin.o
strip -n inner_fun1 -n inner_fun2 mylib.o
假設庫mylib.c 中有四個函式,inner_fun1,inner_fun2是內部使用的函式,api_1,api_2時給外部使用的介面。
#include void inner_fun1()
void inner_fun2()
void api_1()
void api_2() ;
編譯生產目標檔案
gcc -o mylib.o -c mylib.c
檢視符號表
nm mylib.o
0000000000000026 t api_1
0000000000000039 t api_2
u _global_offset_table_
0000000000000000 t inner_fun1
0000000000000013 t inner_fun2
u puts
四個函式都可以看到,且都是 t ,即可被外部鏈結。
注:對於每乙個符號來說,其型別如果是小寫的,則表明該符號是 local 的;大寫則表明該符號是 global(external) 的。
寫個main.c鏈結下試試
int main()
編譯鏈結
gcc main.c mylib.o -o main
執行main,可以看到成功呼叫了api,也成功呼叫了inner的函式。
./main
api 1
api 2
inner 1
inner 2
那麼先試試 static 定義,將mylib.c中的inner函式加上static
#include static void inner_fun1()
static void inner_fun2()
void api_1()
void api_2() ;
重新生成庫,再檢視符號表
nm mylib.o
0000000000000026 t api_1
0000000000000039 t api_2
u _global_offset_table_
0000000000000000 t inner_fun1
0000000000000013 t inner_fun2
u puts
可以看到,inner_fun1和inner_fun2的標記,已經不是 t,而是 t 了。
此時,外部函式嘗試鏈結使用,會報錯
gcc main.c mylib.o -o main
/tmp/cccun3al.o:在函式『main』中:
main.c:(.text+0x1e):對『inner_fun1』未定義的引用
main.c:(.text+0x28):對『inner_fun2』未定義的引用
collect2: error: ld returned 1 exit status
不修改原始檔,直接使用objcopy修改mylib.o
mv mylib.o mylib_origin.o
objcopy -g api_1 -g api_2 mylib_origin.o mylib.o
修改前後
nm mylib_origin.o mylib.o
mylib_origin.o:
0000000000000026 t api_1
0000000000000039 t api_2
u _global_offset_table_
0000000000000000 t inner_fun1
0000000000000013 t inner_fun2
u puts
mylib.o:
0000000000000026 t api_1
0000000000000039 t api_2
u _global_offset_table_
0000000000000000 t inner_fun1
0000000000000013 t inner_fun2
u puts
此時,main.c 就只能使用api_1, api_2,無法使用inner_fun1, inner_fun2了。因為inner_fun1, inner_fun2是內部符號了。
不修改原始檔,直接使用strip修改mylib.o
cp mylib.o mylib_origin.o
strip -n inner_fun1 -n inner_fun2 mylib.o
修改前後
nm mylib_origin.o mylib.o
mylib_origin.o:
0000000000000026 t api_1
0000000000000039 t api_2
u _global_offset_table_
0000000000000000 t inner_fun1
0000000000000013 t inner_fun2
u puts
mylib.o:
0000000000000026 t api_1
0000000000000039 t api_2
u _global_offset_table_
u puts
此時,main.c 就只能使用api_1, api_2,無法使用inner_fun1, inner_fun2了。因為inner_fun1, inner_fun2不存在符號表中了。
本文主要介紹了,static標記函式,objcopy和strip三種方式,避免庫內部函式被外部程式使用。但即使strip刪除了符號表,也還是可以從二進位制檔案中分析到內外部函式名稱的。所以如果想隱藏內部函式名稱,以避免暴露內部邏輯,那就還需要使用一些其他的手段。
初探python官網,展望學成目標
在初學者指引中可以找到python標準庫的相關網頁,從中可以完整地了解到這門語言的基本內容,在學習一門語言中這是十分重要的。在稍微找一下還能發現各種網路文件的鏈結,在需要查閱時,從官方給出文件中找是最好不過的了。除此之外,python的應用這一塊也是很引人注目,官網上列出了一些常見的使用場景如網頁開...
AfxBeginThread函式初探
在進行多執行緒程式設計的時候,我們經常用到afxbeginthread函式來啟動一條執行緒 該函式使用起來非常的簡單方便,其定義如下 cwinthread afxbeginthread afx threadproc pfnthreadproc,執行緒函式位址 lpvoid pparam,執行緒引數 ...
python函式初探
任何一門程式語言都會有函式,函式通常也被稱作方法,初學者聽到函式或方法可能根本不知道是什麼意思,我打個簡單的比方,電熱水壺可以把冷水燒開,那麼在這裡電熱水壺就可以被理解成乙個函式,它的主要功能是負責把冷水燒成熱水。在 python 中函式也就是指能完成乙個固定的功能的方法,並且是可重複使用的,函式最...