Jared的學習筆記:學習系統軟體的點點滴滴
記錄著在交通大學資工科所,當宅宅研究生的學習點滴。 期望能有更多人,加入討論的行列!
2016年8月30日 星期二
Introduction to OpenVX
OpenVX 基本介紹
這份投影片包含大致上的口頭說明於註解(所以請進入slideshare,下載下來,才有註解可以看),這是一份用來meeting時報告的投影片,由淺入深,分享出來是因為有感於目前(2016/08)沒有什麼相關的中文資源,期望能幫助大家更快速的了解OpenVX是什麼!
標籤:
入門,
介紹,
教學,
Introduction,
OpenVX
GDB實用教學:自動化你的debug
這是一篇看了"Give me 15 minutes & I'll change your view of GDB"的心得以及延伸,原始投影片可以見CppCon2015。
如果不曉得什麼是GDB,建議從「Linux 除錯利器 - GDB 簡介」開始學習,此篇是給知道什麼是GDB,但總覺得GDB不是那麼好用的開發者,重新認識GDB,跟隨著影片的腳步,重現一次。
雖然GDB是在終端機中使用,輸入l可以列出目前的程式碼,但大家一定還是覺得很難用,所以就有了tui的出現:
但如果只以單純的
這邊以一個簡單的helloworld程式(hello.c)來說明:
那更進一步呢:
試著輸入以下的指令,會有神奇的事情發生!
這個功能,可以使GDB來輸出某些structure,使其格式漂漂亮亮。
更多功能可以參看這裡,20:47處有範例
在01:12:00之後,有更多的python與GDB的相關教學!
這裡的範例程式碼,可以參閱這裡(就上面那影片),約24:48處有快速瀏覽的過程。 細節的部份,請參考影片,這裡僅以文字敘述:
不斷測試,之後會出現segmentation fault(core dump)
輸入
會出現某個紀錄最後stack的檔案
透過gdb -c 可以進行post mortem debugging,
原則上就是這個檔案會存有,當時該process的address space以及registers的值(包含general registers 和fault status registers)
這與我大四時,曾進行過的某個專案有點關係,有興趣可以看看。
那麼該如何透過gdb利用這個core dump file呢?
會發現,即使輸入bt,因為stack已經被破壞了,GDB目前無法辨識。
所以只好利用自動化的GDB測試,重現問題點,並且透過reverse-gdb重現。
GDB會分別顯示對應的中斷點編號,或是透過
可以看到對應編號,然後透過command + 編號,可以指定當中斷發生時,要做的對應行為:(假設main是中斷點2),每一行就是一個指令,然後結束輸入end即可。
如果之後過程中,有要一直按enter顯示下一頁,可以透過
然後如果程式的最後一行假設是中斷點3:
如果透過:
可能會出現
如果輸入
那倒底怎麼回事了呢?
透過
那這個位置是誰導致的問題呢?
透過watch point來觀察:
watch-point就會噴出到底是哪一行code搞的鬼!
範例:
另外,GDB一樣有類似macro的機制可以使用,用來看大量structure還不錯用,可以參考我以前用過簡單的macro
GDB也有GUI
雖然GDB是在終端機中使用,輸入l可以列出目前的程式碼,但大家一定還是覺得很難用,所以就有了tui的出現:$ gdb -tui
or
$ gdbtui
都可以用指令的方式進入GDB的圖形介面。但如果只以單純的
$ gdb進入的話,只要按下ctrl + x +a 就可以了。
這邊以一個簡單的helloworld程式(hello.c)來說明:
#include <stdio.h> int main(void) { int i = 0; printf("Hello, world\n"); printf("i is %d\n",i); i++; printf("i is now %d\n",i); }
接下來在終端機輸入:
$ gcc -g -O0 -o hello hello.c $ gdb ./hello
(gdb) start
然後按下ctrl + x +a 後,就變成這樣了!
這時候,如果有遇到破圖,按下ctrl + L 就可以刷新畫面。
如要關閉tui,在按一次ctrl + x +a 即可
到這裡,大部份已知有tui可以用的人,都覺得沒什麼!
不過驚喜的就是:如果按ctrl + x + 2會出現組合語言(類似objdump出來的結果)的視窗!
再按一次相同的組合鍵,會跳出register的內容!
而且是以循環的方式呈現。
於gdbtui中,沒辦法使用 方向鍵上、方向鍵下 來使用之前使用過的指令,記得改用ctrl + p 和 ctrl +n來使用歷史指令。
或是透過ctrl + x + o 來切換active window,方向鍵上下,可能就會有你想要的功能了!
GDB也有python可以用
先來看個小示範,一樣是上面的hello.c(gdb) python > print('hello python')此時按下ctrl+D(或輸入end) 退出python,就可以看到輸出!
GDB的物件可以與python互通:
試著輸入以下的指令,會有神奇的事情發生!
(gdb) python gdb.Breakpoint('7') (gdb) python bp = gdb.Breakpoint('10') (gdb) python bp.enabled = False (gdb) python print (gdb.breakpoints()) (gdb) python print (gdb.breakpoints()[0].location) (gdb) python print (gdb.breakpoints()[0].enabled) (gdb) python python_var = gdb.parse_and_eval('code_var_name') (gdb) python gdb.execute('next') (gdb) python help('gdb')
這個功能,可以使GDB來輸出某些structure,使其格式漂漂亮亮。
更多功能可以參看這裡,20:47處有範例
在01:12:00之後,有更多的python與GDB的相關教學!
透過GDB自動化除錯
如果開發過程式的朋友都知道,有些memory/stack的問題,並非每次都會發生,但發生了又不知道問題在哪,這時候就是GDB出場救援的時刻了!這裡的範例程式碼,可以參閱這裡(就上面那影片),約24:48處有快速瀏覽的過程。 細節的部份,請參考影片,這裡僅以文字敘述:
$ while ./bug_program ; do echo OK; done
不斷測試,之後會出現segmentation fault(core dump)
輸入
$ ls -lth core*
會出現某個紀錄最後stack的檔案
透過gdb -c 可以進行post mortem debugging,
原則上就是這個檔案會存有,當時該process的address space以及registers的值(包含general registers 和fault status registers)
這與我大四時,曾進行過的某個專案有點關係,有興趣可以看看。
那麼該如何透過gdb利用這個core dump file呢?
$ gdb -c [core-dump-file]
會發現,即使輸入bt,因為stack已經被破壞了,GDB目前無法辨識。
所以只好利用自動化的GDB測試,重現問題點,並且透過reverse-gdb重現。
$ gdb ./bug_program
(gdb) b main (gdb) b [program last line] 或 (gdb) b _exit
GDB會分別顯示對應的中斷點編號,或是透過
(gdb) info b
可以看到對應編號,然後透過command + 編號,可以指定當中斷發生時,要做的對應行為:(假設main是中斷點2),每一行就是一個指令,然後結束輸入end即可。
(gdb) command 2 (gdb) record (gdb) continue (gdb) end
如果之後過程中,有要一直按enter顯示下一頁,可以透過
(gdb) set pagination off來避免這個麻煩。
然後如果程式的最後一行假設是中斷點3:
(gdb) command 3 (gdb) run (gdb) end可以透過這些指令,讓程式不斷的在GDB中重複運行,接下來就可以準備開始了!
(gdb) run就會不斷重複執行,直到問題發生!
問題發生後
(gdb) p $pc可以看到pc的位置,輸出可能是:1 = (void (*))0x5e4c5d00
如果透過:
(gdb) p/x *0x5e4c5d00
可能會出現
Cannot access memory at address 0x5e4c5d00因為一般core dump就是因為存取到不合法的address(不屬於此address space的空間)所導致的。
如果輸入
(gdb) bt應該也只會得到一堆"?"的frame,無用的資訊。
這時候reverse GDB就要出場了
輸入(gdb) reverse-stepi就能看到程式最後執行到哪一行了!
那倒底怎麼回事了呢?
透過
(gdb) disassemble可以發現,是最後的return發生問題,此時輸入:
(gdb) print $sp可能會輸出:2 = (void *) 0x7fffffffdc98
(gdb) print *(long**)0x7fffffffdc98這就是有bug的address !!(sp企圖存取的位置)
那這個位置是誰導致的問題呢?
透過watch point來觀察:
(gdb) watch *(long**)0x7fffffffdc98 (gdb) reverse-continue
watch-point就會噴出到底是哪一行code搞的鬼!
作者的"~./gdbinit"設定分享
set history save on set print pretty on set pagination on set confirm off
GDB debug "fork"
常用指令:set follow-fork-mode child|parent set detach-on-fork off info inferiors inferior [infno] set follow-exec-mode new|same add inferior [name] clone-inferior
GDB debug "threads"
thread apply 1-4 print $sp thread apply all backtrace thread apply all backtrace full
GDB catch points
manual延伸指令
投影片的最後有列出一些好用的指令,這裏特別列出,我覺得很有用的部分:(gdb) info line hello.c:6 (gdb) info line *$pc列出該行程式碼,對應的組合語言
(gdb) save breakpoints breakpoints.record將使用過的breakpoints儲存成breakpoints.record(檔案)
(gdb) dprintf location,template,expression [,expression ...]將中斷點設置在特定位置(function/line)後,並且輸出對應的expression(到指定的位置)
範例:
(gdb) set dprintf-channel mylog (gdb) set dprintf-function fprintf (gdb) set dprintf-style call (gdb) dprintf main,"main function encounterd!\n" Dprintf 1 at 0x40052e: file hello.c, line 5. (gdb) info breakpoints Num Type Disp Enb Address What 1 dprintf keep y 0x000000000040052e in main at hello.c:5 call (void) fprintf (mylog,"main function encounterd!\n")參考這裡 或 manual
(gdb) break xxx if yyy這個值得注意的是,GDB裡面可以呼叫程式內已有的function或一些標準的library function,如這個stackoverflow的例子
(gdb) call [function]類似(gdb) print [function],可是不會顯示回傳值,但經過測試,兩者行為幾乎一樣
(gdb) commands所有中斷點,發生時,要做的指令清單,輸入end結束。
(gdb) commands (gdb) [some commands] (gdb) silent (gdb) [some commands] (gdb) endsilent是特殊的中斷點指令,會使silent之後的GDB提示都不顯示,如果commands後馬上接silent,連中斷發生的提示都不會顯示!
另外,GDB一樣有類似macro的機制可以使用,用來看大量structure還不錯用,可以參考我以前用過簡單的macro
訂閱:
文章 (Atom)