LINUX内核调试相关--oops信息的定位2

Linux内核调试 | 分析Oops错误 1:'G'如果所有装载的模块都有GPL或相容的许可证,'P'如果装载了任何的专有模块。可以看到oops_test模块里的init_module的汇编情况,第24~28字节的指令用于把0赋值给x0寄存器,然后往x0寄存器写入0,wzr是一种特殊寄存器,值为0,所以这里发生写空指针错误。CPU后的数字是错误所在逻辑CPU的编号,这里是CPU0,表示CPU0发生的错误,PID:1458表示正在运行的进程ID1458,内核污染原因(G),内核版本( 5.10.66-rt53)。如果涉及到了某项原因,就会显示为。 阅读详情

Ø  实验目的与意义

1 、掌握printk 的使用、设置及实现原理,理解分级别进行打印log 信息的实现方法

2 、掌握如何分析oops 的方法

3 、掌握strace 工具的移植和使用方法

 

Ø  基本原理和方法

1 、请回顾栈的工作原理,尤其是栈帧的作用

2 、请对照printk 的源代码来进行printk 相关实验,并在实验中进一步理解源代码

 

Ø  实验内容及步骤 

一. Printk实验。

1 、在内核中编写自己的printk 代码,可利用上次系统调用实验中已有的代码,也可利用之前驱动实验中的模块。

2 、在根文件系统中增加/proc 目录,用来挂载proc 文件系统

3 、重新烧录uImage (如果有所改动的话)和根文件系统,进入控制台之后,输入命令挂载proc 文件系统:mount – t proc none /proc 。

如果挂载成功, /proc 目录应该可以看到文件,比如下面的结果:

# ls proc

1              74             devices        kpagecount     slabinfo

100            765             diskstats      kpageflags     stat

101            773            driver         loadavg        swaps

102            783            execdomains    locks          sys

103            784            fb             meminfo        sysrq-trigger

2               786            filesystems    misc           sysvipc

3              790            fs             modules        timer_list

4              804            ide            mounts         tty

5              806            interrupts     mtd            uptime

6              buddyinfo      iomem          net            version

60             bus            ioports        pagetypeinfo   vmstat

65             cmdline        irq            partitions     yaffs

71             cpu            kallsyms       sched_debug    zoneinfo

737            cpuinfo        kmsg           self

4 、检查并修改printk 的log 级别,比如下面的命令:

# cat /proc/sys/kernel/printk
7       4       1       7
# echo 1 >/proc/sys/kernel/printk
# cat /proc/sys/kernel/printk
1       4       1       7

修改之后,默认的printk 打印(级别为4 )不会显示到串口终端,但仍可以通过“ cat /proc/kmsg ”看到打印结果。

5 、通过代码和 /proc/sys/kernel/printk 分别修改log 级别,并对应printk 的源代码来分析结果。

 

二.C 语言可变参数实验

1 、在内核代码kernel/printk.c 中的printk 函数用到了C 语言中的可变参数的用法。请参考下面的代码来学习如何使用可变参数。以下代码可直接在x86 环境测试:

 

#include <stdio.h>

 

typedef char *va_list;

 

/*

  *  * Storage alignment properties

  *   */

#define  _AUPBND                 (sizeof (signed int) - 1)

#define  _ADNBND                (sizeof (signed int) - 1)

 

/*

  *  * Variable argument list macro definitions

  *   */

#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))

#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))

#define va_end(ap)              (void) 0

#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

 

 

int max ( int num, ... )

{

    int m = -0x7FFFFFFF;

    int i;

     va_list ap;

    va_start ( ap, num );

    for ( i= 0; i< num; i++ )

    {

        int t = va_arg (ap, int);

        if ( t > m )

        {

            m = t;

        }

    }

    va_end (ap);

    return m;

}

 

int main ( int argc, char* argv[] )

{   

    int n = max ( 5, 2, 6 ,3 ,8 ,1);

    printf("n=%d./n", n);

    return 0;

}

 

2 、自己动手 分析上面代码可变参数的用法及实现方式。提示:va_start ( ap, num ) 是为了取得可变参数在栈中的位置,该宏展开执行后,ap 将指向第一个可变参数。可利用GDB 和汇编代码协助分析。

  

3 、ARM 架构中通常使用寄存器而不是栈来传递参数,那么,上述可变参数的方式能够用于ARM 架构中吗?请想办法找到证据来支持你的猜测。

 

三. Oops实验。

1 、在上次系统调用实验的代码中,人为的制造产生oops 的条件,比如下面的改动:

 

asmlinkage long sys_mytest()

{

printk("pid: %d:/tThis is my call./n",current->pid);

*(int *)0 = 0;

    return 0;

}

 

2 、从串口终端得到所产生的oops 消息,并进行初步分析

3 、在内核代码中,利用arm-linux-objdump 得到kernel/sys.o 的汇编代码,对照汇编代码进行分析

4 、arm-linux-addr2line 工具可用来寻找代码地址所对应的c 代码(),可尝试:

arm-linux-addr2line –e sys.o 0xnnnn(你出错的代码地址)

 

(1) 在kernel/sys.c 文件里

#arm-linux-gcc –c sys.o sys.c(生成汇编文件)

#vim sys.o

寻找:sys_mytest

找到地址是:000000b0

而通过下面Oops 信息知道:PC is at sys_mytest+0x28/0x34

则0xnnnn( 代码出错的地址)=000000b0+0x28=0xd8

(2) # arm-linux-addr2line –e sys.o 0xd8

结果输出是137 行

则查出出错的地方在sys.c 中的137 行。

 

5 、下面是我实验中遇到的oops ,请尝试做一些初步分析:

Unable to handle kernel NULL pointer dereference at virtual address 00000000

pgd = c3eb0000

[00000000] *pgd=33ddd031, *pte=00000000, *ppte=00000000

Internal error: Oops: 817 [#1]

Modules linked in:

CPU: 0    Not tainted  (2.6.25.8 #7)

PC is at sys_mytest+0x28/0x34 (表示在sys_mytest+0x28 至sys_mytest+0x34 之间,以4 个字节为一个单位)

LR is at 0xc031781c

pc : [<c00561ec>]    lr : [<c031781c>]    psr: 60000013

sp : c3ec3f98  ip : c031781c  fp : c3ec3fa4

r10: 00008528  r9 : c3ec2000  r8 : c002cb84

r7 : 00000161  r6 : beeced1c  r5 : 00000000  r4 : 0000000a

r3 : 80000013  r2 : 00000001  r1 : 00000001  r0 : 00000000

Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user

Control: 0000717f  Table: 33eb0000  DAC: 00000015

Process syscall_test (pid: 777, stack limit = 0xc3ec2260)

Stack: (0xc3ec3f98 to 0xc3ec4000)

3f80:                                                       00000000 c3ec3fa8

3fa0: c002c9e0 c00561d4 00000000 beeced1c 00000161 beecef14 beecef1c 0000000a

3fc0: 0000000a 00000000 beeced1c 00000001 beecef14 000081c4 00008528 beeced18

3fe0: beeced08 beececfc 000081e8 0000f8e0 60000010 00000161 7bf2fafd eff7fbbd

Backtrace:

[<c00561c4>] (sys_mytest+0x0/0x34) from [<c002c9e0>] (ret_fast_syscall+0x0/0x2c)

Code: e59f0010 e59310d8 ebffcf47 e3a00000 (e5800000)

---[ end trace e5388d99d2481600 ]---

 

 

四. Strace实验。

1 、从www.sourceforge.net 上下载strace 的源代码

2 、配置并编译strace :

./configure --host=arm-linux

make

3 .将strace 工具加入到你的根文件系统中,并测试使用它

 

第一篇 : 定位Oops的具体代码行 作者: albcamus (百無一用書生)
(
来自Linus Torvalds的讨论:
[url]https://groups.google.com/group/linux.kernel/browse_thread/thread/b70bffe9015a8c41/ed9c0a0cfcd31111[/url]
又,[url]http://kerneltrap.org/Linux/Further_Oops_Insights[/url]
)
     
        例如这样的一个Oops:
                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

         编译出*.s文件
          
           有时侯需要对*.s文件进行分析,以确定BUG所在的位置。 对任何一个内核build目录下的*.c文件,都可以
           直接编译出*.s文件。

                   # make drivers/net/e100.s V=1
          
           而对于自己写的module,就需要在Makefile中有一个灵活的target写法:
                  
                # cat Makefile
                obj-m := usb-skel.o
                KDIR := /lib/modules/`uname -r`/build
                traget := modules

                default:
                        make -C $(KDIR) M=$(shell pwd) $(target)
                clean:
                        rm -f *.o *.ko .*.cmd *.symvers *.mod.c
                        rm -rf .tmp_versions


                # make target=usb-skel.s V=1
          
           这样,kbuild系统才知道你要make的目标不是modules,而是usb-skel.s。




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

./scripts/decodecode < Oops.txt
 
第二篇: 定位可动态加载的内核模块的OOPS代码行作者: Godbach (To be 千里马!)
最近又仔细学习了albcamus版主提供的《定位Oops的具体代码行》(链接:http://linux.chinaunix.net/bbs/viewthread.php?tid=1008573),并且进行了实践。因此这里简单总结一下,并且以实例的方式给出定位可动态加载模块Oops信息的方法。

本文欢迎自由转载,但请标明出处,并保证本文的完整性。
Godbach
Apr 19, 2009

1. 从vmlinux获取具体的代码行

文章中albcamus版主也提到了,需要有自己编译的vmlinux,而且编译时打开compile with debug info. 这个选项打开之后会使vmlinux文件比不加调试信息大一些。我这里代调试信息的是49M。建议如果学习的时候,想使用gdb的方式获取出错代码行的话,就加上这个编译条件。
然后就可以按照具体的方法去操作,可以定位到具体的C 代码行。

2. 从自己编译的内核模块出错信息中获取代码行
以ldd3中提供的misc-modules/faulty.c为例。主要以faulty_write函数作分析。
(1)由于作者提供的函数代码就一样,过于简单,我这里简单加上一些代码(也就是判断和赋值),如下:

ssize_t faulty_write ( struct file* filp,const char __user* buf, size_tcount ,
                loff_t * pos)
{
        /* make a simple fault by dereferencing a NULL pointer */
        if (count> 0x100)
                count = 0x100;
        * (int* ) 0 = 0;
        return count;
}

(2)编译该模块,并且mknod /dev/faulty
(3)向该模块写入数据:echo 1 > /dev/faulty, 内核OOPS,信息如下:

 

< 1> BUG: unable to handle kernelNULL pointer dereference atvirtual address 00000000
printing eip:
f8e8000e
* pde = 00000000
Oops: 0002 [# 3]
SMP
Modules linked in: faulty autofs4 hidp rfcomm l2cap.. . . ..//此处省略若干字符

CPU: 1
EIP: 0060: [ < f8e8000e>]Not tainted VLI
EFLAGS: 00010283 ( 2. 6. 18. 3# 2)
EIP is at faulty_write+ 0xe/ 0x19[ faulty]
eax: 00000001 ebx: f4f6ca40 ecx: 00000001 edx: b7c2d000
esi: f8e80000 edi: b7c2d000 ebp: 00000001 esp: f4dc5f84
ds: 007b es: 007b ss: 0068
Process bash ( pid: 6084, ti= f4dc5000 task= f7c8d4d0 task. ti= f4dc5000)
Stack : c1065914 f4dc5fa4 f4f6ca40 fffffff7 b7c2d000 f4dc5000 c1065f06 f4dc5fa4
       00000000 00000000 00000000 00000001 00000001 c1003d0b 00000001 b7c2d000
       00000001 00000001 b7c2d000 bfd40aa8 ffffffda 0000007b c100007b 00000004
Call Trace:
[ < c1065914>] vfs_write+ 0xa1/ 0x143
[ < c1065f06>] sys_write+ 0x3c/ 0x63
[ < c1003d0b>] syscall_call+ 0x7/ 0xb
Code: Bad EIP value.
EIP: [ < f8e8000e> ] faulty_write+ 0xe/ 0x19[ faulty] SS: ESP 0068: f4dc5f84

其中,我们应该关注的信息是第一行红色标出部分:告诉我们操作了NULL指针。其次,就是第二行红色部分:EIP is at faulty_write+0xe/0x19。这个出错信息告诉我们EIP指针出现问题的地方时faulty_write函数,而且指出了是faulty 模块。
同时,faulty_write+0xe/0x19的后半部分0xe/0x19,说明该函数的大小时0x019,出错位置是在0x0e。这两个值应该值得都是汇编代码的值。
(4)将faulty模块反汇编出汇编代码:
          objdump -d faulty.ko > faulty.s
        或
          objdump -d faulty.o > faulty.s
然后,我们打开faulty.s文件。由于我们需要关注的部分正好在文件的前面,因此我这里只贴出文件的前面一部分内容:

faulty. o:file format elf32- i386

Disassembly of section . text:

00000000 < faulty_write>:
   0: 81 f9 00 01 00 00 cmp $0x100,% ecx
   6: b8 00 01 00 00 mov $0x100,% eax
   b: 0f 46 c1 cmovbe % ecx, % eax
   e: c7 05 00 00 00 00 00 movl $0x0, 0x0
  15: 00 00 00
  18: c3 ret

00000019 < cleanup_module>:
  19: a1 00 00 00 00 mov 0x0,% eax
  1e: ba 00 00 00 00 mov $0x0,% edx
  23: e9 fc ff ff ff jmp 24 < cleanup_module+ 0xb>

00000028 < faulty_init>:
  28: a1 00 00 00 00 mov 0x0,% eax
  2d: b9 00 00 00 00 mov $0x0,% ecx
  32: ba 00 00 00 00 mov $0x0,% edx
  37: e8 fc ff ff ff call 38 < faulty_init+ 0x10>
  3c: 85 c0 test% eax,% eax
  3e: 78 13 js 53 < faulty_init+ 0x2b>
  40: 83 3d 00 00 00 00 00 cmpl $0x0, 0x0
  47: 74 03 je 4c < faulty_init+ 0x24>
  49: 31 c0 xor% eax,% eax
  4b: c3 ret
  4c: a3 00 00 00 00 mov % eax, 0x0
  51: 31 c0 xor% eax,% eax
  53: c3 ret

由以上汇编代码可以看出,faulty_write函数的大小确实是0x18 -0x00 +1 = 0x19. 那么EIP指针出问题的地方是0x0e处,代码为:

e: c7 05 00 00 00 00 00 movl $0x0, 0x0

这行汇编代码就是将0值保存到0地址的位置。那么很显然是非法的。这一行对应的C 代码应该就是:
*(int *)0 = 0;

(5)以上是对模块出错信息的分析。不过也有一定的局限。
   首先就是EIP出错的位置正好在本模块内部,这样可以在本模块定位问题;
   其次,要求一定的汇编基础,特别是当一个函数的代码比较多时,对应的汇编代码也比较大,如何准确定位到C代码行需要一定的经验和时间。

    实际运用中,可以将内核代码行的定位和可动态加载的内核模块代码行的定位结合起来使用,应该可以较快的定位问题。

    分析中有纰漏或者不妥的地方希望大家指出,也希望有网友分享更有效的方法。
出自: http://linux.chinaunix.net/bbs/thread-1097586-1-1.html
LINUX内核调试相关--oops信息的… LINUX内核调试相关--oops信息的定位2 收藏 Ø  实验目的与意义 1 、掌握printk 的使用、设置及实现原理,理解分级别进行打印log 信息的实现方法 2 、掌握如何分析oops 的方法 3 、掌握strace 工具的移植和使用方法   Ø  基本原理和方法 1 、请回顾栈的工作原理,尤其是栈帧的作用 2 、请对照printk 的源代码来进行printk 相关实验,并在实验 阅读详情

相关推荐

制造、调试OOPS

Linux Kernel OOPS调试及解决。

阿xin*的嵌入式AI 842

LINUX内核调试相关--oops信息的定位

Ø  实验目的与意义 1 、掌握printk 的使用、设置及实现原理,理解分级别进行打印log 信息的实现方法 2 、掌握如何分析oops 的方法 3 、掌握strace 工具的移植和使用方法   Ø  基本原理和方法 1 、请回顾栈的工作原理,尤其是栈帧的作用 2 、请对照pr

嵌入式成长的专栏 2080

Linux内核Oops - 实战

本文介绍了 Linux 内核 Oops 的基本概念和工作原理,通过一个包含 Workqueue 机制的内核模块实战演示了 Oops 的触发过程,并分析了错误原因及修复方法。理解 Oops 的产生机制和输出信息是内核调试的基础,下一篇我们将详细解读 Oops 输出的每一部分内容,帮助开发者更精准地定位内核错误。

u010826758的专栏 288

[转] 定位Oops的具体代码行

来自Linus Torvalds的讨论: [url]https://groups.google.com/group/linux.kernel/browse_thread/thread/b70bffe9015a8c41/ed9c0a0cfcd31111[/url] 又,[url]http://kerneltrap.org/Linux/Further_Oops_Insights[/url] ...

weixin_30687051的博客 165

24、定位内核 Oops 位置的工具与技巧

本文详细介绍了在Linux内核开发和调试过程中定位内核Oops的多种工具和技巧。内容涵盖了强制暂停以读取诊断信息、获取带有调试符号的未剥离vmlinux映像、使用objdump、GDB和addr2line等工具定位问题代码位置,以及利用内核自带脚本如checkstack.pl、decode_stacktrace.sh、faddr2line等进行深入分析的方法。文章还提供了在非原生架构(如ARM64)下的调试注意事项,以及KASLR系统中的地址转换技巧。通过实际案例和流程图梳理,帮助开发者高效定位Oops问题

e1f2g的博客 110

单相PWM整流器搭建训练——(一)拓扑原理介绍

单相整流器是一种将交流电转换为直流电的设备,主要由变压器、整流元件和滤波电路组成。变压器将输入的交流电压转换为适合整流的较低电压,整流元件(如二极管)利用其单向导电性将交流电转换为脉动直流电,最后滤波电路去除脉动直流电中的纹波,输出较为平滑的直流电,从而实现交流到直流的转换,广泛应用于各类电源设备中。

DikouNass的博客 1587

Oops分析方法详解

<br />Oops是内核编程中比较容易遇到的问题,为了跟多的了解Oops来便于调试,我对Oops提供的信息进行一个总结,以及如何调试Oops。<br /> <br /> <br />一个完整的Oops:<br /> <br />BUG: unable to handle kernel paging request at 00316b01<br />IP: [<c05dd045>] netif_receive_skb+0x335/0x377<br />*pde = 00000000<br />Thread 

dfafdasdfdasfd的专栏 2410

改进爬山算法之六:随机重启爬山算法(Random-Restart Hill Climbing,RRHC)

随机重启爬山算法(Random-Restart Hill Climbing,RRHC)是爬山算法的一种改进策略,是一种启发式搜索算法,旨在通过随机重启来克服传统爬山算法容易陷入局部最优解的局限性,并增加找到全局最优解的概率。随机重启爬山算法通过在多次运行中不断尝试不同的初始解,并在每次运行中执行标准的爬山算法,最终选择所有运行中找到的最佳解作为最终结果。(1)计算复杂度:由于需要多次运行爬山算法,因此算法的计算复杂度可能较高,特别是在解空间较大或每次迭代需要较长时间的情况下。

搏博的专栏 2204

Oops分析方法摘抄

方法详解     Oops是内核编程中比较容易遇到的问题,为了跟多的了解Oops来便于调试,我对Oops提供的信息进行一个总结,以及如何调试Oops。     一个完整的Oops:   BUG: unable to handle kernel paging request at 00316b01 IP: [] netif_receive_skb+0x335/0x377 *pd

心空漫游 1351

IGS精密星历高效获取与解析指南

本文详细介绍了IGS精密星历在高精度定位中的核心作用,对比了IGS Final、IGR和IGU等不同产品的精度与时效性差异。指南提供了从武汉大学、NASA CDDIS等数据中心高效下载数据的实战方法,并深入解析了SP3文件格式,帮助用户掌握精密星历的获取、解析与自动化处理技巧,以支持厘米级定位应用。

garlic的博客 837

手把手教你解锁TI MSPM0G3507开发板(2025新版,附XDS110接线图)

本文详细解析了2025版TI MSPM0G3507开发板的解锁方法,针对新版硬件中BSL引脚的电路设计变化提供了精准接线方案和UniFlash软件配置步骤。通过实测数据和专业指导,帮助开发者解决芯片锁定问题,确保调试接口正常响应。

weixin_42696271的博客 807

linux module crash分析

# insmod khttp.ko [ 47.885272] blk_dequeue_request: 2 callbacks suppressed [ 47.961228] khttp sysfs init begin v4 [ 47.974411] khttp:khttp installed success [ 48.012894] khttp:Connecting to .. [ 48.094931] khttp:connect success [ 48.183118] up

geshifei的博客 1684

Sublime Text4代码配色自定义方案

关于Sublime Text对于我的使用体验,只能说内置的代码主题真的都太low了,一点都不好看。所以接下来我分享一下我自定义代码配色。当然,大家也可以通过我给的中文翻译注释来自定义自己喜欢的颜色。废话不多说,直接上代码直接将代码复制粘贴到:Preferences > Customize Color Scheme 即可。},"globals":"foreground": "var(white)", // 前景色。

追求细节,成就完美 6026

linux内核oops调试跟踪

当内核出现类似用户空间的 Segmentation fault 时,oops会被打印到控制台和写入内核log缓冲区。 下面来制造一个oops,程序如下: #include <linux/init.h> #include <linux/module.h> static int __init test_init(void) { char *tmp = NULL...

chengwei_peng 2569

1999年-2022年 上市公司-企业劳动生产率数据(原始数据、代码、最终结果、参考文献)

上市公司企业劳动生产率数据集为企业和市场参与者提供了一个深入分析企业生产效率和劳动效益的工具。通过这些数据,企业可以不断探索创新的发展模式和管理方式,努力提高生产效率,为提升市场竞争力和盈利能力做出贡献。数据名称:上市公司-企业劳动生产率数据数据年份:1999-2022年数据来源:国泰安数据库1999年-2022年 上市公司-企业劳动生产率数据(原始数据、代码、最终结果、参考文献)

2401_84585615的博客 881

Couldn‘t agree a key exchange algorithm(available:curve25519-sha256,curve25519-sha256@libssh.org解决方案

本文主要介绍了Couldn’t agree a key exchange algorithm(available:curve25519-sha256,curve25519-sha256@libssh.org解决方案,希望能对使用winscp的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案 2.1 方案一 2.2 方案二

weixin_43178406的博客 4万+

利用addr2line与objdump协同分析Linux内核Oops错误源码定位

本文详细介绍了如何利用addr2line与objdump工具协同定位Linux内核Oops错误。通过解析Oops日志中的程序计数器地址,结合带调试信息的内核镜像或模块文件,可以精准地将崩溃点映射到源代码的具体行号,是Linux内核开发与驱动调试中排查崩溃问题的核心方法。

blue42的博客 619

人工智能技术基础系列之:迁移学习

作者:禅与计算机程序设计艺术 1.背景介绍 随着深度学习和神经网络的快速发展,越来越多的应用场景需要处理大量的数据和复杂的任务。然而,由于计算资源、存储空间等条件的限制,传统的人工智能方法往往不能满足实际需求。因此,为了提高效率和降低成本,研究人员提出了迁移学习的概念。本篇文章将详细介绍迁移学习的基

AI天才研究院 694

解锁Linux内核Oops调试:从错误到解决方案

常在河边走,哪能不湿鞋。用Linux,总有死机的时候,如果运气好,会看到一些所谓”Oops”信息(在屏幕上或系统日志中),Oops这个英文单词的意思是“哎呀”,当内核出错时(比如访问非法地址),输出的信息就成为Oops信息,Oops可以看成是内核级的Segmentation Fault。内核开发比用户空间开发更难的一个因素就是内核调试艰难。内核错误往往会导致系统宕机,很难保留出错时的现场,调试内核的关键在于你的对内核的深刻理解。

深度Linux 1566

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Linux 内核调试篇6

Linux 内核调试篇6(基于Linux6.6)---Oops分析

ListQ的博客 1376

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

如何调试嵌入式Linux内核崩溃:Mastering Embedded Linux Programming中的Oops分析

嵌入式Linux开发中,内核崩溃(Oops)是令人头疼的问题。本文将通过《Mastering Embedded Linux Programming》第三版中的实例,带你掌握Oops分析的完整流程,从复现问题到精确定位bug,让内核调试不再困难。 ## 什么是内核Oops? 内核Oops是Linux内核在运行时检测到错误时产生的一种异常状态。与应用程序崩溃不同,Oops通常会导致内核模块卸载或系

gitblog_00633的博客 347

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Linux内核的Oops

什么是Oops?从语言学的角度说,Oops应该是一个拟声词。当出了点小事故,或者做了比较尴尬的事之后,你可以说"Oops",翻译成中国话就叫做“哎呦”。“哎呦,对不起,对不起,我真不是故意打碎您的杯子的”。看,Oops就是这个意思。 在Linux内核开发中的Oops是什么呢?其实,它和上面的解释也没什么本质的差别,只不过说话的主角变成了Linux。当某些比较致命的问题出现时,我们的Linux

bugouyonggan的专栏 879

LINUX内核调试相关--oops信息的定位1

<br />一个简单的linux crackme的逆向<br /><br />前言<br /><br />     最不喜欢的就是写破解教程,酒后一时冲动,老夫卿发少年狂,许下将写一篇linux平台逆向的文章的诺言,作此文实非颇不得已。<br />     在此申明:本文在技术上非常初级,并没有用到什么高深的技术,本人水平亦有限,如有差错,还请见谅!<br />     <br />开始之前的准备<br /><br />     正如C语言教程从 hello world 开始,我们也由一个 crac

pulpdog的专栏 1632
上一篇: Linux 系统内核的调试
下一篇: printk
Alan0521
博客等级 码龄19年 77粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值