http://blog.chinaunix.net/u/548/showart.php?id=1005650

定位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]
)
   
       例如这样的一个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

(我没用过,就只提一下。)

转载于:https://blog.51cto.com/axlrose/1288976

定位Oops的具体代码行[zt]相关推荐

  1. 【转】定位oops的具体代码行

    最近在学写linux驱动,按照宋宝华的<linux设备驱动开发详解>上的例子一步步来写.编译运行以后出现oops,不知道怎么调试,上网搜了一下,看到这篇文章,感觉不错转载到这里. 来自Li ...

  2. 正确定位混淆后Crash代码行数

    Android--定位混淆后Crash代码行数 一.需求背景 二.前期准备 三.对混淆日志进行还原 四.示例 一.需求背景 打包时需要对代码进行混淆,目的是增加安全性,防⽌反编译.但这会导致App崩溃 ...

  3. linux addr2line,定位so文件崩溃代码行数

    当我们使用别人的ndk时,可能别人的so文件会崩溃,这个时候需要定位该so文件崩溃的代码的行数,即哪一行.方法如下: 1.找到ndk下面的该目录:D:\IT\AndroidStudio\SDK\ndk ...

  4. 用 addr2line 定位 OOPS 死机代码位置

    1. 一般 OOPS 死机时内核的 LOG kmsg 中会出现些函数地址等信息. 2. 执行 android代码包中的addr2line bin文件,比如文件 ./prebuilts/gcc/linu ...

  5. 使用MAP文件快速定位程序崩溃代码行

    作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统 造成巨大的损失.但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事.其实测试中出现 ...

  6. 使用MAP文件快速定位程序崩溃代码行(转)

    作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失.但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事.其实测试中出现程 ...

  7. Oops快速定位代码行方法

     原址 Oops 是内核调式中常见的错误之一,尽管Oops出错的时候会打印出堆栈和函数调用关系,但是要定位到哪一行代码,如果仅仅从打印来看,需要不断的增加打印信息来调式,往往事倍功半,这里以举一个例子 ...

  8. VS2010下使用dmp文件和pdb文件定位程序异常代码行号的注意事项

    2018-01-12 创建人:Ruo_Xiao 2018-01-15 修改人:Ruo_Xiao 添加为dump.exe和pdb版本保持一致的原因. 一.minidump文件 崩溃转储是创建一个应用程序 ...

  9. php找出函数定义位置,WordPress如何快速定位PHP函数所在文件位置及代码行号?

    有时候我们需要修改别人源码里的代码,却找不到对应的函数放在了哪儿,就可以用使用本文介绍的办法,帮你快速定位函数位置.特别是某些写法不规范的WordPress主题,各种模块,函数到处放,找半天的那种.那 ...

  10. git定位追踪一行或若干行代码修改历史记录

                                                             git定位追踪一行或若干行代码修改历史记录 先使用git blame追踪溯源这些行代码 ...

最新文章

  1. PHP cURL可以在单个请求中检索响应标头和正文吗?
  2. HDU1584 蜘蛛牌 DFS回溯
  3. 在 IntelliJ IDEA 中创建基本的 Maven 多模块项目
  4. oracle := 和=,oracle a:=100 和 b=:c 区别
  5. C/C++:读写文件
  6. 上海科技大学计算机研究生调剂,2021年上海科技大学考研招生调剂信息
  7. Java 程序设计基础知识
  8. WebGame服务端架构分析(一)
  9. maya python 弹出窗口_Open Project Folder (python in maya)
  10. NOIP 2018模拟赛 by zwz T3 磨懒虫主义
  11. ssrs报表服务器数据库配置文件,ReportingServicesService 配置文件
  12. BIGEMAP下载等高线(高程)使用教程
  13. Promise学习:基础入门
  14. JAVA 映射HashMap和HashTable的区别和实用
  15. coreseek错误WARNING: failed to open pid_file '/usr/local/coreseek/var/log/searchd_mysql.pid'
  16. 读书笔记 -- 推荐系统实践(1)
  17. `Algorithm-Solution` `AcWing` 378. 骑士放置
  18. 很好的微信小程序小结
  19. E. Tyler and Strings(组合计数 + 树状数组/线段树)(带重复元素的全排列)
  20. VRTK4.0 学习Day4

热门文章

  1. 使用iMazing为iPad添加PDF文档
  2. Git下修改提交的author和email信息
  3. ASP.NET MVC 解析模板生成静态页一(RazorEngine)
  4. 《C Primer Plus》读书笔记
  5. SaaS行业乘风杨帆,中小企业市场潜力分析
  6. 2799 高校排名 加强版
  7. 学习U-Boot之--mkconfig
  8. 架构之路(二):性能
  9. [置顶]       jQuery旋转插件—rotate
  10. 考研复习(8)-图的基本操作