Linux原始碼分析工具鏈
前言
看原始碼是一個程式設計師必須經歷的事情,也是可以提升能力的一個捷徑。個人認為: 要完全掌握一個軟體的方法只有閱讀原始碼。
在Windows下有sourceinsight這個原始碼閱讀軟體(雖然我沒用過,但是網上評價還不錯),由於我是個Linuxer,並不喜歡用Windows,所以自然是選擇在Linux下閱讀原始碼的工具了。
下面我將逐一介紹在Linux下閱讀原始碼的工具。
vim+ctags+cscope
原始碼閱讀三劍客:vim配合ctags和cscope,足以在原始碼裡面自由翱翔,在函式和變數間自由跳轉。
安裝
sudo apt-get install vim ctags cscope
vim
vim的使用就略過了,網上資料很多,不是一篇文章能說完的,未來我可能會寫一篇vim的使用心得。推薦一篇簡明 Vim 練級攻略,看完就差不多會用了。
ctags
ctags的使用很簡單,vim已經內建了對ctags的支援。
首先在原始碼根目錄執行ctags -R,遞迴的為原始碼建立tags,在根目錄會生成一個Tags的檔案,存放各種函式和變數的tag,便於跳轉:
- 使游標在函式或變數上,Ctrl + ]即可跳轉到其定義處
- Ctrl + t可以回到你跳轉之前的位置
對於簡單的程式碼,ctags就夠用了,但是對於比較複雜的程式碼來說,ctags顯得有點力不從心,於是,下一位劍客就登場了。
cscope
vim同樣內建了對cscope的支援。
首先在原始碼根目錄執行cscope -Rbq,就會生成cscope.out檔案(索引資料庫)
- -R: 在生成索引檔案時,搜尋子目錄樹中的程式碼
- -b: 只生成索引檔案,不進入cscope的介面
- -q: 生成cscope.in.out和cscope.po.out檔案,加快cscope的索引速度
然後在vim中執行:cs add cscope.out,新增資料庫。
接下來就可以使用:cs find x var進行查詢。(x代表查詢選項,var表示要查詢的函式或變數名)
cscope支援8種查詢方式
- s: 查詢C語言符號,即查詢函式名、巨集、列舉值等出現的地方
- g: 查詢函式、巨集、列舉等定義的位置,類似ctags所提供的功能
- d: 查詢本函式呼叫的函式
- c: 查詢呼叫本函式的函式
- t: 查詢指定的字串
- e: 查詢egrep模式,相當於egrep功能,但查詢速度快多了
- f: 查詢並開啟檔案,類似vim的find功能
- i: 查詢包含本檔案的檔案
例如,我們想在vim 7.0的原始碼中查詢呼叫do_cscope()函式的函式,我們可以輸入:”:cs find c do_cscope“,回車後發現沒有找到匹配的功能,可能並沒有函式呼叫do_cscope()。我們再輸入”:cs find s do_cscope“,查詢這個C符號出現的位置,現在vim列出了這個符號出現的所有位置。
每次都有輸入cs find來查詢資料是不是有點麻煩,有沒有更方便的方法呢。當然有,vim的神奇之處在其可定製性。提供一份cscope的配置,將其放在.vimrc中即可。
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " cscope setting """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" if has("cscope") set csprg=/usr/bin/cscope set csto=1 set cst set nocsverb " add any database in current directory if filereadable("cscope.out") cs add cscope.out endif set csverb endif nmap <C-@>s :cs find s <C-R>=expand("<cword>")<CR><CR> nmap <C-@>g :cs find g <C-R>=expand("<cword>")<CR><CR> nmap <C-@>c :cs find c <C-R>=expand("<cword>")<CR><CR> nmap <C-@>t :cs find t <C-R>=expand("<cword>")<CR><CR> nmap <C-@>e :cs find e <C-R>=expand("<cword>")<CR><CR> nmap <C-@>f :cs find f <C-R>=expand("<cfile>")<CR><CR> nmap <C-@>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR> nmap <C-@>d :cs find d <C-R>=expand("<cword>")<CR><CR>
上面的配置即把Ctrl + @作為:cs find的快捷鍵,也就是說要查詢某個函式名,只需要把游標放在函式名上,按下Ctrl + @ + s即可,簡直不能更方便。而且你可以自己修改配置,對映到自己覺得舒服的快捷鍵上。
本著不重複造輪子的原則,我就簡單的寫了cscope的基本用法,其實基本上就夠用了,進階的用法參考這篇文章vi/vim使用進階: 程式設計師的利器 – cscope。
doxygen
上面我們講的是用vim來檢視原始碼,但是面對幾十萬程式碼的時候,想要看清楚各個結構體之間的關係就不是vim能夠做到的了。這時候我們就需要doxygen來幫手了。
Doxygen is the de facto standard tool for generating documentation from annotated C++ sources, but it also supports other popular programming languages such as C, Objective-C, C#, PHP, Java, Python, IDL (Corba, Microsoft, and UNO/OpenOffice flavors), Fortran, VHDL, Tcl, and to some extent D.
doxygen是一個根據原始碼生成文件的工具,這貨雖然主要是給C++用的,但是它也對其他語言有支援。
安裝直接去官網,按照其指導安裝即可。
下面介紹一下doxygen的使用方法。
首先,在原始碼根目錄執行doxygen -g,然後在根目錄就會突然冒出一個名為Doxyfile的檔案,這個檔案就是doxygen生成文件的配置檔案了。
那麼,重點來了,怎麼配置這個檔案,預設的配置是根據程式碼生成各個結構體的成員資料,然後生成html和latex兩個資料夾,分別是網頁和latex文件。
說實話,預設生成的文件並沒有什麼卵用,除了讓你更方便的看到各個結構體的組成成員。我們關心的是各個結構體之間的關係,這是針對C而言的。對與C++和java而言,關心的是類之間的關係。所以,預設的配置肯定是要修改的。至於怎麼改,看官方文件。
當然了,如果這篇文章唯一給出的建議就是看文件,那這篇文章有什麼意義呢。大家都知道看文件可以解決問題,但是時間成本太高,而且是英文的。寫這篇文章的目的是分享自己學習得到的經驗,讓大家少走彎路,如果不能解決你的問題,只能去看文件了。
接下來我根據我自己看文件用到的配置跟大家解釋一下。
首先,Doxygen裡面的配置可謂又臭又長,你絕對不會有讀完它的慾望。所以我給出幾個關鍵的配置項,到時候搜尋它修改即可
- 這是針對各種語言優化輸出的選項,預設都是NO,因為它不清楚你用的是什麼語言(話說看一下字尾不就知道了嗎…)
OPTIMIZE_OUTPUT_FOR_C OPTIMIZE_OUTPUT_JAVA OPTIMIZE_FOR_FORTRAN OPTIMIZE_OUTPUT_VHDL
- 這個是生成文件的型別的選項,預設生成html和latex,共支援六種型別的文件,每種型別的生成配置也是很多,具體根據需要配置
GENERATE_HTML GENERATE_LATEX GENERATE_RTF GENERATE_XML GENERATE_DOCBOOK GENERATE_MAN
- 關於生成影像的選項。doxygen使用dot這個工具來繪圖,所以要先執行sudo apt-get install graphviz安裝dot。在設定好這個繪圖選項之後,doxygen就會生成各個結構體的關係,對於類會生成函式呼叫關係(我沒試過,因為只試過C的)。
HAVE_DOT (一定要置為YES,後面的選項都依賴這個) DOT_NUM_THREADS (使用dot繪圖的執行緒數量,越多越快,我一般是設定跟cpu的核數一樣)
給一個結構體關係圖,就是doxygen生成的。
[machine_class]
最後一步,在原始碼根目錄執行doxygen,它會自動找到Doxygen配置,根據配置生成文件。
gdb
最後一個工具,大名鼎鼎的gdb。分析原始碼執行流程的最好方式的是執行它,然後一步步執行。用來觀察它最好的工具當然是gdb了(針對C/C++)。
gdb的使用我也不打算造輪子,直接參考用GDB除錯程式,這篇寫的很好,通俗易懂。
後記
以上就是我在閱讀原始碼的時候使用的Linux工具,三劍客vim+ctags+cscope,兩板斧doxygen gdb,足以馳騁原始碼的江湖。
以上工具,vim和gdb是最難學的,學習曲線很陡峭。但是學好之後,就能守得雲開見月明。
相關文章
- linux原始碼分析Linux原始碼
- Fabric 1.0原始碼分析(3)Chaincode(鏈碼)原始碼AI
- Linux下init程式原始碼分析Linux原始碼
- Fabric 1.0原始碼分析(4)Chaincode(鏈碼)#platforms(鏈碼語言平臺)原始碼AIPlatform
- Fabric 1.0原始碼分析(42)scc(系統鏈碼)原始碼
- Riffa學習——Linux Driver原始碼分析Linux原始碼
- Fabric 1.0原始碼分析(5)Chaincode(鏈碼)體系總結原始碼AI
- Retrofit原始碼分析三 原始碼分析原始碼
- Dubbo原始碼分析(五)Dubbo呼叫鏈-服務端原始碼服務端
- Linux程式排程邏輯與原始碼分析Linux原始碼
- [轉帖]Linux核心原始碼分析分享專題Linux原始碼
- Linux核心原始碼分析之set_arch (一)Linux原始碼
- Linux核心原始碼分析之setup_arch (四)Linux原始碼
- Linux核心原始碼分析之setup_arch (三)Linux原始碼
- Linux核心原始碼分析之setup_arch (二)Linux原始碼
- 集合原始碼分析[2]-AbstractList 原始碼分析原始碼
- 集合原始碼分析[3]-ArrayList 原始碼分析原始碼
- Guava 原始碼分析之 EventBus 原始碼分析Guava原始碼
- 【JDK原始碼分析系列】ArrayBlockingQueue原始碼分析JDK原始碼BloC
- 集合原始碼分析[1]-Collection 原始碼分析原始碼
- Android 原始碼分析之 AsyncTask 原始碼分析Android原始碼
- Fabric 1.0原始碼分析(29) Orderer #multichain(多鏈支援包)原始碼AI
- 高德APP全鏈路原始碼依賴分析工程APP原始碼
- Flink 運算元鏈可以合併的原始碼分析原始碼
- 以太坊原始碼分析(36)ethdb原始碼分析原始碼
- 以太坊原始碼分析(38)event原始碼分析原始碼
- 以太坊原始碼分析(41)hashimoto原始碼分析原始碼
- 以太坊原始碼分析(43)node原始碼分析原始碼
- 以太坊原始碼分析(51)rpc原始碼分析原始碼RPC
- 以太坊原始碼分析(52)trie原始碼分析原始碼
- Rockchip RK3588 - Rockchip Linux Recovery recovery原始碼分析Linux原始碼
- Linux 核心排程器原始碼分析 - 初始化Linux原始碼
- 【linux】i2c使用分析&原始碼實戰Linux原始碼
- Fabric 1.0原始碼分析(42)scc(系統鏈碼) #cscc(通道相關)原始碼
- 《吊打分析師》實戰—深圳鏈家租房資料分析 | 附原始碼原始碼
- 深度 Mybatis 3 原始碼分析(一)SqlSessionFactoryBuilder原始碼分析MyBatis原始碼SQLSessionUI
- 鏈路追蹤 SkyWalking 原始碼分析 —— 除錯環境搭建原始碼除錯
- 以太坊原始碼分析(21)chain_indexer 區塊鏈索引原始碼AIIndex區塊鏈索引
- k8s client-go原始碼分析 informer原始碼分析(6)-Indexer原始碼分析K8SclientGo原始碼ORMIndex