linux内核调试2

http://blog.chinaunix.net/uid-29401328-id-4932947.html


下面再来测试一次:

# insmod syst.ko
s_init success!
# ./test             // 卡死了,等10s会打印如下信息
asm_do_IRQ -> s3c2410_timer_irq : pid = 635 , task_name = test , pc = bf0d700c
asm_do_IRQ -> s3c2410_timer_irq : pid = 635 , task_name = test , pc =bf0d700c

我们一眼就看出来了,问题出现在test这个程序上,但具体出在哪不清楚,就要根据PC值去分析了,分析方法和之前博文讲的一样。
下面再唠叨一遍:

1. bf0d700c所在的函数。
现在的系统僵死了,我们没办法继续下去,只有重启系统。这里注意一个问题,重启系统使用的内核要和僵死时使用的内核是同一个。
因为如果内核变了,我们就很难还原僵死前的状态了,新内核pc = bf0d700c可能代表不同的代码。


用tftp启动刚才的内核,插入模块 sy.ko。
先去查看内核源码下的 System.map 文件,看PC地址是否属于其中,这里不属于(那里面是内核函数,地址都是以C开头

然后查看开发板的模块地址:cat cat /proc/kallsyms >kall.txt  或者  cat /proc/kallsyms   | grep bf0d700c 管道过滤


打开 kall.txt,在里面查找PC值相近的地址(有可能直接查到,也有可能PC位于某段地址之间),这里查到:

00000000 a system_dead.c        [sydead]
bf0d7000 t $a   [system_dead]
bf0d7000 t sysdead_test_open   [sydead]
bf0d7010 t sysdead_drv_exit     [sydead]

可知 pc =   bf0d70 0c位于 sy_open函数中。接下来去分析这个函数

2. 分析发生错误的函数
因为我们这里的代码很短,所以可以很快的定位出问题,但当代码很长时,可能就需要看汇编了。这里给出方法

反汇编 sy_open函数 位于的模块 sy.ko
arm-none-linux-gnueabi-objdump sy.ko -D > sy.dis

打开 sy.dis:(贴出对我们有用的那段
00000000 :
   0:   e1a0c00d        mov     ip, sp
   4:   e92dd800        push    {fp, ip, lr, pc}
   8:   e24cb004        sub     fp, ip, #4      ; 0x4
   c:   eafffffe        b       c

到这里就需要用汇编去分析了,我们这里的错误比较明显,就是一直跳转到自己这个函数里,调不出去了。

注:有可能两次发生僵死时PC值不一样,就算僵死在同一段代码,PC值也可能不一样。因为 果死循环是一段代码,

那么僵死时,程序可能正在执行这段代码当中的任意一句。

2 OOPS

Oops 中包含的重要信息对于所有体系结构都是完全相同的 : 寄存器上下文和回溯线索 . 回溯线索显示了导致错误发生的函数调用链 . 寄存器上下文信息可能同样有用 , 尽管使用起来不那么方便 . 如果你有函数的汇编代码 , 这些寄存器数据可以帮助你重建引发问题的现场 . 在寄存器中一个本不应该出现的数值可能会在黑暗中给你带来第一丝光明 .

[1] ksymoops

   提供编译内核是产生的 System.map 和模块信息 ( 如何你使用的是模块 ) 把 OOPS 信息解码 .

   $ ksymoops saved_oops.txt

[2] kallsysms

   开发版的 2.5 内核引入了 kallsysms 特性 , 它可以通过定义 CONFIG_KALLSYMS 配置选项启用 . 该选项可以载入内核镜像对应的内存地址的符号名称 , 所以内核可以打印解码好的跟踪线索 . 相应地 , 解码 oops 也不再需要 system.map 或者 ksysmoops 工具了 .

3 内核调试配置选

    这些选项都在内核配置编辑器的内核开发 (Kernel Hacking) 菜单中 , 他们都依赖于 CONFIG_DEBUG_KERNEL. 当你开发内核的时候 , 作为一种练习 , 不妨都打开这些选项 .

[1] 调试原子操作

    把内核配置成一旦在原子操作过程中进程进入休眠或者做了一些可能引起休眠的操作 , 就打印警告信息并提供追踪线索 .

    CONFIG_PREEMPT = y

    CONFIG_DEBUG_KERNEL = y

    CONFIG_KALLSYMS = y

    CONFIG_SPINLOCK_SLEEP = y

4 引发 bug 并打印信息

BUG() BUG_NO() 被调用时引发 oops, 导致栈的回溯和错误信息的打印

panic() 不但会打印错误信息 , 而且会挂起整个系统

dump_stack() 在终端上打印寄存器上下文和函数跟踪线索 .

5 神奇的 SysRq

    神奇系统请求键是另外一根救命稻草 , 该功能可以通过定义 CONFIG_MAGIC_SYSRQ 配置选项开启用 . 当该功能被启用的时候 , 无论内核处于什么状态 , 你都可以通过特殊的组合键跟内核进行通信 .

6 内核调试器的传奇

[1] gdb

    $ gdb vmlinux /proc/kcore

    > p global_variable

    > disassemble function

[2] kgdb

[3] kdb

http://blog.chinaunix.net/uid-26923078-id-3327126.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值