linnx内核出现段错误(segment fault)的调试方法

来源:互联网 发布:百年战争 知乎 编辑:程序博客网 时间:2024/05/22 02:08

当你的程序在运行的过程中访问到空指针,那么linux系统就会出现非法访问内存错误,通常称为段错误(segmeng fault)

段错误分为用户态和内核态两种情况:

当用户态程序出现访问非法地址出现段错误时,程序退出并答应“segment fault”提示信息,这种情况下不会导致系统崩溃,修改好程序之后还可以再次运行。

但是发生在内核态的段错误,会导致系统崩溃,死机现象,要再次用就只能重启机器才可以。所以应尽量避免内核台访问非法指针出现段错误。在编写内核态代码的时候,在读写指针之前要养成先判断指针是否有效然后在赋值的习惯。

但是如果真的在内核台出现的段错误,那么如何快速有效的定位段错误出现的位置。下面介绍两种方法帮助快捷找出段错误所在位置。

1.使用xxx-xxx-objdump命令把你的运行的代码反汇编。

    

我的实验平台是ba,根据不同的平台选用不用的交叉工具链

Ba-linux-objdump -D -S exe(.o&hex……)> objdump.txt

上面的命令解释:

-D    反汇编所有节的内容

-S     尽可能显示与反汇编混合的源代码

    

下面是我对自己可运行文件的反汇编:

    static int mfvd_in_ring_release_cb(int ringpair_id, uint32_t optdata)

    {

偏移地址    机器码                        汇编指令

       0:    cd 41 3f ff                 b.sw       -0x4(r1),r10

       4:    05 41                       b.mov      r10,r1

        struct mfvd_stream_dev *dev = (struct mfvd_stream_dev *)optdata;

        dev->in_ring.id = -1;

       6:    00 ef                       b.movi     r7,-0x1

       8:    cc e4 3d 80                 b.sw       0x1bc(r4),r7

        return 0;

    }

       c:    00 60                       b.movi     r3,0x0

       e:    cd 41 7f ff                 b.lwz      r10,-0x4(r1)

      12:    47 d2 48                    b.jr       r9

00000015 <mfvd_read>:

        return 0;

    }

2.根据内核态出现段错误时打印的信息分析段错误

    a)、当前pc寄存器的值

    当你的程序出现段错误时,根据内核的段错误处理机制一边会打印错误的提示信息。这些信息通常包括,当前之前指针,堆栈指针,最后运行的机器码等。

    Oops#: 0000

CPU #: 0

   PC: d0c7f54d    SR: 00008a7f    SP: c42a9530

GPR00: 00000000 GPR01: c42a9530 GPR02: c033e000 GPR03: c42a9938

GPR04: 00097e00 GPR05: 0000032a GPR06: 00000bb8 GPR07: 00000000

GPR08: c42a9d3c GPR09: d0c7f689 GPR10: c42a9530 GPR11: 0000032a

GPR12: c434bd14 GPR13: 0000000c GPR14: 00097e00 GPR15: 00000000

GPR16: c42a9538 GPR17: 00097e00 GPR18: 00000001 GPR19: c434860c

GPR20: 00000003 GPR21: 00000001 GPR22: 00000010 GPR23: 00000000

GPR24: 0000032a GPR25: 00000040 GPR26: 00000004 GPR27: c42a9d38

GPR28: 00000004 GPR29: c42a8000 GPR30: c4348724 GPR31: 00000000

  RES: 00000000 oGPR3: c42a9938 syscallno: c42a94c0

如上面所示,PC:d0c7f54d,这个值就是你运行出错时的地址,根据这个地址,去反汇编文件objdum.txt中查找这个地址的位置,找出该位置对应的机器码源代码,那么你就可以清除知道你代码出错的位置了。

    b)、出现段错误之后打印的机器码

 =======================

Code: ff 6f 46 40 67 39 33 41 07 36 02 e0 41 18 30 cd 41 7f ff 47 d2 48 08 99 (24) c4 c0 6c c6

 a1 24 e4 40 6c e7 c0 60 c6 39 24 e4 80 34 e7 c0 6c e7 d0

上面的打印信息是内错出错之后,打印出来的最后执行的那一段机器码。同样道理,在反汇编文件objdunp.txt中查找这些机器码出现的位置,那么就可以确定源代码出错的位置。

原创粉丝点击