Kernel panic 信息分析方法

                                                Kernel panic 信息分析方法                                                                                     

 Oops: 0000 [#1] PREEMPT SMP

               Modules linked in: capidrv kernelcapi isdn slhc ipv6
loop dm_multipath snd_ens1371 gameport snd_rawmidi snd_ac97_codec
ac97_bus snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq
snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd
parport_pc floppy parport pcnet32 soundcore mii pcspkr snd_page_alloc
ac i2c_piix4 i2c_core button power_supply sr_mod sg cdrom ata_piix
libata dm_snapshot dm_zero dm_mirror dm_mod BusLogic sd_mod scsi_mod
ext3 jbd mbcache uhci_hcd ohci_hcd ehci_hcd

               Pid: 1726, comm: kstopmachine Not tainted (2.6.24-rc3-module #2)
               EIP: 0060:[<c04e53d6>] EFLAGS: 00010092 CPU: 0
               EIP is at list_del+0xa/0x61
               EAX: e0c3cc04 EBX: 00000020 ECX: 0000000e EDX: dec62000
               ESI: df6e8f08 EDI: 000006bf EBP: dec62fb4 ESP: dec62fa4
                DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
               Process kstopmachine (pid: 1726, ti=dec62000
task=df8d2d40 task.ti=dec62000)
               Stack: 000006bf dec62fb4 c04276c7 00000020 dec62fbc
c044ab4c dec62fd0 c045336c
                      df6e8f08 c04532b4 00000000 dec62fe0 c043deb0
c043de75 00000000 00000000
                      c0405cdf df6e8eb4 00000000 00000000 00000000
00000000 00000000
               Call Trace:
                [<c0406081>] show_trace_log_lvl+0x1a/0x2f
                [<c0406131>] show_stack_log_lvl+0x9b/0xa3
                [<c04061dc>] show_registers+0xa3/0x1df
                [<c0406437>] die+0x11f/0x200
                [<c0613cba>] do_page_fault+0x533/0x61a
                [<c06123ea>] error_code+0x72/0x78
                [<c044ab4c>] __unlink_module+0xb/0xf
                [<c045336c>] do_stop+0xb8/0x108
                [<c043deb0>] kthread+0x3b/0x63
                [<c0405cdf>] kernel_thread_helper+0x7/0x10
                =======================
               Code: 6b c0 e8 2e 7e f6 ff e8 d1 16 f2 ff b8 01 00 00
00 e8 aa 1c f4 ff 89 d8 83 c4 10 5b 5d c3 90 90 90 55 89 e5 53 83 ec
0c 8b 48 04 <8b> 11 39 c2 74 18 89 54 24 08 89 44 24 04 c7 04 24 be 32
6b c0
               EIP: [<c04e53d6>] list_del+0xa/0x61 SS:ESP 0068:dec62fa4
               note: kstopmachine[1726] exited with preempt_count 1

       1, 有自己编译的vmlinux: 使用gdb

          编译时打开complie with debug info选项。

          注意这行:

               EIP is at list_del+0xa/0x61

          这告诉我们,list_del函数有0x61这么大,而Oops发生在0xa处。 那么我们先看一下list_del从哪里开始:

               # grep list_del /boot/System.map-2.6.24-rc3-module
               c10e5234 T plist_del
               c10e53cc T list_del
               c120feb6 T klist_del
               c12d6d34 r __ksymtab_list_del
               c12dadfc r __ksymtab_klist_del
               c12e1abd r __kstrtab_list_del
               c12e9d03 r __kstrtab_klist_del

          于是我们知道,发生Oops时的EIP值是:

               c10e53cc + 0xa  == c10e53d6

          然后用gdb查看:

               # gdb /home/arc/build/linux-2.6/vmlinux
               (gdb) b *0xc10e53d6
               Breakpoint 1 at 0xc10e53d6: file
/usr/src/linux-2.6.24-rc3/lib/list_debug.c, line 64.

          看,gdb直接就告诉你在哪个文件、哪一行了。

          gdb中还可以这样:

               # gdb Sources/linux-2.6.24/vmlinux
               (gdb) l *do_fork+0x1f
               0xc102b7ac is in do_fork (kernel/fork.c:1385).
               1380
               1381    static int fork_traceflag(unsigned clone_flags)
               1382    {
               1383            if (clone_flags & CLONE_UNTRACED)
               1384                    return 0;
               1385            else if (clone_flags & CLONE_VFORK) {
               1386                    if (current->ptrace & PT_TRACE_VFORK)
               1387                            return PTRACE_EVENT_VFORK;
               1388            } else if ((clone_flags & CSIGNAL) != SIGCHLD) {
               1389                    if (current->ptrace & PT_TRACE_CLONE)
               (gdb)

           也可以直接知道line number。

           或者:

               (gdb) l *(0xffffffff8023eaf0 + 0xff)  /* 出错函数的地址加上偏移 */



       2, 没有自己编译的vmlinux: TIPS

          如果在lkml或bugzilla上看到一个Oops,而自己不能重现,那就只能反汇编以"Code:"开始的行。 这样可以尝试定位到
          源代码中。

          注意,Oops中的Code:行,会把导致Oops的第一条指令,也就是EIP的值的第一个字节, 用尖括号<>括起来。 但是,有些
          体系结构(例如常见的x86)指令是不等长的(不一样的指令可能有不一样的长度),所以要不断的尝试(trial-and-error)。

          Linus通常使用一个小程序,类似这样:

               const char array[] = "/xnn/xnn/xnn...";
               int main(int argc, char *argv[])
               {
                       printf("%p/n", array);
                       *(int *)0 = 0;
               }

e.g. /*{{{*/ /* 注意, array一共有从array[0]到array[64]这65个元素, 其中出错的那个操作码<8b>
== arry[43] */
#include <stdio.h>
#include <stdlib.h>


const char array[]
="/x6b/xc0/xe8/x2e/x7e/xf6/xff/xe8/xd1/x16/xf2/xff/xb8/x01/x00/x00/x00/xe8/xaa/x1c/xf4/xff/x89/xd8/x83/xc4/x10/x5b/x5d/xc3/x90/x90/x90/x55/x89/xe5/x53/x83/xec/x0c/x8b/x48/x04/x8b/x11/x39/xc2/x74/x18/x89/x54/x24/x08/x89/x44/x24/x04/xc7/x04/x24/xbe/x32/x6b/xc0";
int main(int argc, char *argv[])
{
       printf("%p/n", array);
       *(int *)0 = 0;
}
/*}}}*/



          用gcc -g编译,在gdb里运行它:

               [arc@dhcp-cbjs05-218-251 ~]$ gdb hello
               GNU gdb Fedora (6.8-1.fc9)
               Copyright (C) 2008 Free Software Foundation, Inc.
               License GPLv3+: GNU GPL version 3 or later
<[url] http://gnu.org/licenses/gpl.html[/url]>
               This is free software: you are free to change and
redistribute it.
               There is NO WARRANTY, to the extent permitted by law.
Type "show copying"
               and "show warranty" for details.
               This GDB was configured as "x86_64-redhat-linux-gnu"...
               (no debugging symbols found)
               (gdb) r
               Starting program: /home/arc/hello
               0x80484e0

               Program received signal SIGSEGV, Segmentation fault.

          注意,这时候就可以反汇编0x80484e0这个地址:

               (gdb) disassemble 0x80484e0
               Dump of assembler code for function array:
               0x080484e0 <array+0>:   imul   $0xffffffe8,%eax,%eax
               0x080484e3 <array+3>:   jle,pn 0x80484dc <__dso_handle+20>
               0x080484e6 <array+6>:   ljmp   *<internal disassembler error>
               0x080484e8 <array+8>:   rcll   (%esi)
               0x080484ea <array+10>:  repnz (bad)
               0x080484ec <array+12>:  mov    $0x1,%eax
               0x080484f1 <array+17>:  call   0x7f8a1a0
               0x080484f6 <array+22>:  mov    %ebx,%eax
               0x080484f8 <array+24>:  add    $0x10,%esp
               0x080484fb <array+27>:  pop    %ebx
               0x080484fc <array+28>:  pop    %ebp
               0x080484fd <array+29>:  ret
               0x080484fe <array+30>:  nop
               0x080484ff <array+31>:  nop
               0x08048500 <array+32>:  nop
               0x08048501 <array+33>:  push   %ebp
               0x08048502 <array+34>:  mov    %esp,%ebp
               0x08048504 <array+36>:  push   %ebx
               0x08048505 <array+37>:  sub    $0xc,%esp
               0x08048508 <array+40>:  mov    0x4(%eax),%ecx
               0x0804850b <array+43>:  mov    (%ecx),%edx
               0x0804850d <array+45>:  cmp    %eax,%edx
               0x0804850f <array+47>:  je     0x8048529
               0x08048511 <array+49>:  mov    %edx,0x8(%esp)
               0x08048515 <array+53>:  mov    %eax,0x4(%esp)
               0x08048519 <array+57>:  movl   $0xc06b32be,(%esp)
               0x08048520 <array+64>:  add    %ah,0xa70
               End of assembler dump.
               (gdb)

         OK, 现在你知道出错的那条指令是array[43],也就是mov
(%ecx),%edx,也就是说,(%ecx)指向了一个错误内存地址。

补充:

为了使汇编代码和C代码更好的对应起来, Linux内核的Kbuild子系统提供了这样一个功能: 任何一个C文件都可以单独编译成汇编文件,例如:

make path/to/the/sourcefile.s

例如我想把kernel/sched.c编译成汇编,那么:

make kernel/sched.s V=1

或者:

make kernel/sched.lst V=1


另外, 内核源代码目录的./scripts/decodecode文件是用来解码Oops的:

./scripts/decodecode < Oops.txt
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: end kernel panic not syncing attempted to kill init 是一种 Linux 系统的错误提示信息,意思是内核恐慌,无法同步,尝试终止 init 进程。这种错误通常会导致系统无法进入正常运行状态,需要进行相应的故障排查和修复。 造成这种错误的原因可能有很多,例如硬件问题、驱动程序错误、文件系统损坏等等。为了解决这种错误,需要对系统进行全面诊断和分析,找出产生问题的根本原因,然后进行具体的修复措施。 可能的解决方法包括备份数据、重新安装系统、尝试修复文件系统、检查硬件设备等等。需要根据具体的情况进行针对性的操作,保证系统能够正常运行。 综上所述,end kernel panic not syncing attempted to kill init 是一种比较严重的系统错误,需要进行及时处理,否则会影响系统的正常运行。针对这种错误需要对系统进行全面诊断和分析,找出问题根源并采取相应的解决措施。 ### 回答2: 当出现“end kernel panic not syncing attempted to kill init”错误消息时,表示Linux内核已经遇到了致命错误,无法继续正常运行。其中,“kernel panic”表明内核遇到了无法处理的错误,而“not syncing”提示内核无法同步数据。最后的“attempted to kill init”表示内核试图释放init进程以关闭系统。这个问题可能由多种原因引起,包括硬件问题、驱动程序冲突、文件系统损坏等等。解决这个问题的方法包括使用备份恢复文件系统、修复硬件问题、更新驱动程序和内核等。若未能解决问题,可能需要重新安装操作系统。总之,这个错误消息提示的是一个严重问题,需要及时对其进行诊断和解决,以确保系统能够正常运行。 ### 回答3: 这是一个由于系统内核出现了错误而导致的系统崩溃的错误消息。在Linux系统中,当系统内核检测到一个无法处理的错误时,会发出这样的信息。这个错误消息是内核级别的错误,而不是应用程序或服务级别的错误。因此,它不能通过简单地重启或重新安装应用程序或服务来解决。 "end kernel panic not syncing attempted to kill init"这条错误信息发生的原因可能很多。它可能是由于内核模块的配置错误、硬件故障、内存问题或文件系统损坏等问题所导致。在处理这个错误时,我们需要深入了解这个错误的原因并且采取恰当的措施来解决它。一些常见的解决方法包括检查硬件是否工作正常、运行诊断和修复软件、更新系统内核或回滚之前的系统状态等。 总之,这个错误消息需要被认真处理并且采取应对措施以避免进一步的损害。它可能对系统的稳定性和安全性产生不良影响,因此我们需要谨慎对待它并采取必要的步骤来解决它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值