[小技巧] dump_stack()

来源:互联网 发布:狸窝视频编辑软件 编辑:程序博客网 时间:2024/06/05 15:24

本文转载至:http://jason-work-note.blogspot.jp/2012/03/dumpstack.html

How can it works for you

當你想知道在kernel裡面某個function是如何一層一層的被呼叫到的,你只要在該funciton裡加上一行 "dump_stack()",
當程式跑到那一行,就會把整個code stack印出來

How to use 

以下為使用的範例,例如我想知道wifi driver裡面的wifi_set_cardetect是怎樣被呼叫的,就可以在該funciton內加一行dump_stack()。
----------------------------------------------------------kernel/drivers/net/wireless/bcm4329/dhd_linux.cint wifi_set_carddetect(int on){        printk("%s = %d\n", __FUNCTION__, on);<span style="color:#ff0000;"><span style="white-space:pre"></span>dump_stack();</span>#ifdef CONFIG_WIFI_CONTROL_FUNC        if (wifi_control_data && wifi_control_data->set_carddetect) {                wifi_control_data->set_carddetect(on);        }#endif        return 0;}----------------------------------------------------------



執行結果如下:
------------------------------------------------------------------------------------<4>[  861.317167] wifi_set_carddetect = 1<4>[  861.320835] [<c0047a04>] (unwind_backtrace+0x0/0xf0) from [<bf003b68>] (wifi_set_carddetect+0x1c/0x54 [bcm4329])<4>[  861.331281] [<bf003b68>] (wifi_set_carddetect+0x1c/0x54 [bcm4329]) from [<bf003c10>] (wifi_probe+0x34/0x50 [bcm4329])<4>[  861.342126] [<bf003c10>] (wifi_probe+0x34/0x50 [bcm4329]) from [<c027ac68>] (platform_drv_probe+0x18/0x1c)<4>[  861.351949] [<c027ac68>] (platform_drv_probe+0x18/0x1c) from [<c0279ac8>] (driver_probe_device+0xc8/0x184)<4>[  861.361767] [<c0279ac8>] (driver_probe_device+0xc8/0x184) from [<c0279be4>] (__driver_attach+0x60/0x84)<4>[  861.371318] [<c0279be4>] (__driver_attach+0x60/0x84) from [<c02792fc>] (bus_for_each_dev+0x48/0x84)<4>[  861.380523] [<c02792fc>] (bus_for_each_dev+0x48/0x84) from [<c0278c50>] (bus_add_driver+0x9c/0x20c)<4>[  861.389655] [<c0278c50>] (bus_add_driver+0x9c/0x20c) from [<c027a1dc>] (driver_register+0xa8/0x138)<4>[  861.398851] [<c027a1dc>] (driver_register+0xa8/0x138) from [<bf03408c>] (dhd_module_init+0x8c/0x1cc [bcm4329])<4>[  861.409092] [<bf03408c>] (dhd_module_init+0x8c/0x1cc [bcm4329]) from [<c003c588>] (do_one_initcall+0x94/0x164)<4>[  861.419271] [<c003c588>] (do_one_initcall+0x94/0x164) from [<c00ac7d4>] (sys_init_module+0x90/0x1ac)<4>[  861.428567] [<c00ac7d4>] (sys_init_module+0x90/0x1ac) from [<c0041ca0>] (ret_fast_syscall+0x0/0x30)-------------------------------------------------------------------------------------

How dump_stack works

dump_stack定義在kernel/arch/arm/kernel/traps.c,程式流程為

dump_stack()  --> dump_backtrace() -->unwind_backtrace() --> dump_backtrace_entry() 

其中在 unwind_backtrace() 中會有一個 while loop,裡面透過 unwind_frame() 靠著當下的 program counter (r15) 和 link register (r14) 一層一層的往上找,每往上找一層就呼叫
dump_backtrace_entry() 把目前的位置印出來,打印出來的 message 就像這樣: 
 [<c0047a04>] (unwind_backtrace+0x0/0xf0) from [<bf003b68>] (wifi_set_carddetect+0x1c/0x54 [bcm4329])

PS: 
1. link register : 當function A的某一行呼叫funciton B時,ARM會利用這個register紀錄funciton A下一行的位址,當funciton B跑完時,CPU就知道接下來要跳回哪裡繼續執行下去。
    reference [3] [4]有ARM register的簡介。
2. unwind_frame() 裡面具體的作法可以參考[5][6] ,Stack unwinding 似乎是ARM support的一種功能,詳細請參考[6]中的pdf

Reference 

[1] 簡單實現 dump_stack

[2] Enabling Stack Dumping in Linux Kernel

[3] ARM Register introduction 

[4] armregister.jpg

[5] unwind.c in kernel 

[6] Exception Handling ABI for the ARM Architecture

0 0
原创粉丝点击