[小技巧] dump_stack()

本文转载至: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.c
int 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

[3] ARM Register introduction 

[5] unwind.c in kernel 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值