前言
提示:linux调试的方法有很多种,简单的是直接打printk但是有时候想看调用链,就没有那么直观:
这里介绍使用 dump_stack() 内核中内置的方法,来查看调用链。
一、dump_stack() 机制
从字面的意思就可以看出,这个是一个 调用回溯call trace;
打印的格式是 [<ffffffff816a3d91>] dump_stack+0x19/0x1b
即:[调用地址] symbol+offset/size
offset偏移量
size是函数的长度
二、使用方法
1.直接将函数放入需要的地方
代码如下(示例):
#include <linux/init.h>
#include <linux/module.h>
MODULE_AUTHOR("andy");
MODULE_DESCRIPTION("test");
MODULE_LICENSE("GPL");
MODULE_VERSION("v1.1.0");
void func3(int n)
{
printk("-----%d\n", n);
dump_stack();
return;
}
void func2(int n)
{
printk("func2 %d\n", n);
dump_stack();
func3(n*2);
return;
}
void func1(int n)
{
printk("func1 %d\n", n);
dump_stack();
func2(++n);
return;
}
static int patch_init(void)
{
func1(1);
dump_stack();
return 0;
}
static void patch_exit(void){
printk("[testkern]exit\n");
return ;
}
module_init(patch_init);
module_exit(patch_exit);
编译请参考:Makefile
2.执行结果
结果截取一段:
[ 1122.093231] 0000000000000002 0000000029ed49d3 ffff880034397d20 ffffffff816a3d91
[ 1122.093232] ffff880034397d38 ffffffffc06b4071 0000000000000001 ffff880034397d50
[ 1122.093233] ffffffffc06b40b9 ffffffff819f9020 ffff880034397d60 ffffffffc06b40d3
[ 1122.093234] Call Trace:
[ 1122.093236] [<ffffffff816a3d91>] dump_stack+0x19/0x1b
[ 1122.093237] [<ffffffffc06b4071>] func2+0x21/0x40 [testkern]
[ 1122.093238] [<ffffffffc06b40b9>] func1+0x29/0x30 [testkern]
[ 1122.093240] [<ffffffffc06b40d3>] patch_init+0x13/0x20 [testkern]
[ 1122.093241] [<ffffffff810020e8>] do_one_initcall+0xb8/0x230
[ 1122.093242] [<ffffffff81100734>] load_module+0x1f64/0x29e0
[ 1122.093244] [<ffffffff8134bbf0>] ? ddebug_proc_write+0xf0/0xf0
[ 1122.093245] [<ffffffff810fcdd3>] ? copy_module_from_fd.isra.42+0x53/0x150
[ 1122.093246] [<ffffffff81101366>] SyS_finit_module+0xa6/0xd0
[ 1122.093248] [<ffffffff816b4fc9>] system_call_fastpath+0x16/0x1b
可以比较清楚的看清调用的链路
system_call_fastpath->SyS_finit_module->…func1->func2
3.分析地址
通过/proc/kallsyms查看对比
[root@localhost ~]# cat /proc/kallsyms | grep func1 | grep test
ffffffffc06b4090 t func1 [testkern]
[root@localhost ~]# cat /proc/kallsyms | grep func2 | grep test
ffffffffc06b4050 t func2 [testkern]
func1的地址是ffffffffc06b4090,与上面的 ffffffffc06b40b9 - 0x29 相等
func2的地址是ffffffffc06b4050,与上面的ffffffffc06b4071 - 0x21 相等