2012-04-16 57 views
18

如果你很幸运当你的内核模块崩溃时,你会得到一个带有很多信息的日志,比如寄存器中的值等。一个这样的信息是堆栈跟踪(对于核心转储也是如此,但我最初问这个内核模块)。就拿这个例子:如何充分利用堆栈跟踪(从内核或核心转储)?

[<f97ade02>] ? skink_free_devices+0x32/0xb0 [skin_kernel] 
[<f97aba45>] ? cleanup_module+0x1e5/0x550 [skin_kernel] 
[<c017d0e7>] ? __stop_machine+0x57/0x70 
[<c016dec0>] ? __try_stop_module+0x0/0x30 
[<c016f069>] ? sys_delete_module+0x149/0x210 
[<c0102f24>] ? sysenter_do_call+0x12/0x16 

我的猜测是,+<number1>/<number2>有事情做与已经发生了误差函数的偏移量。也就是说,通过检查这个数字,或许看看程序集输出,我应该能够找出发生该错误的那一行(更好的是,指令)。那是对的吗?

我的问题是,这两个数字究竟是什么?你如何利用它们?

回答

19
skink_free_devices+0x32/0xb0 

这意味着违例指令是从功能skink_free_devices()0xB0字节长在总的开始0x32字节。

如果用-g编译内核启用,那么你可以在函数内部的行号使用工具addr2line或我们的好老gdb

像这样的事情

$ addr2line -e ./vmlinux 0xc01cf0d1 
/mnt/linux-2.5.26/include/asm/bitops.h:244 
or 
$ gdb ./vmlinux 
... 
(gdb) l *0xc01cf0d1 
0xc01cf0d1 is in read_chan (include/asm/bitops.h:244). 
(...) 
244  return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; 
(...) 

所以控制跳下哪里只需将您要检查的地址提供给addr2linegdb,他们会告诉您源文件中存在违规功能的行号 请参阅this article for全部细节

编辑:vmlinux是用于调试内核的无压缩版本,通常发现@/lib/modules/$(uname -r)/build/vmlinux提供你已经建立从来源内核。 vmlinuz你找到/boot是压缩的内核,也有可能在调试

+0

我不知道你可以gdb linux本身!这太棒了! – Shahbaz 2012-04-16 12:13:10

+0

虽然'vmlinux'在哪里?我认为这将是Linux内核本身(在/ boot中),但是'vmlinuz ...'和addr2line说“文件格式不被识别”虽然没有什么大不了,因为我对自己的模块更感兴趣。 – Shahbaz 2012-04-16 12:15:14

+0

@Shahbaz vmlinuz只是'vmlinux'的压缩和/或剥离版本。 BOth通常会放在'/ boot'文件夹中。我现在没有和我一起检查我的linux系统。谷歌周围的两个:)这里有一些首发。 [One](http://superuser.com/questions/62575/where-is-vmlinux-on-my-ubuntu-installation)和[Two](http://superuser.com/questions/298826/how-do -i-uncompress-vmlinuz-to-vmlinux) – 2012-04-16 12:23:37

1

对于Emacs用户有用,here的是一个主要的模式,轻松堆栈跟踪中跳来跳去(使用addr2line内部)。

免责声明:我写了:)

+0

现在只需为ViM创建一个... – Shahbaz 2012-11-01 14:55:49

+0

有一些vim(对于necro抱歉):https://github.com/rzwisler/oops_trace.vim/blob/master/plugin/oops_trace.vim – stellarhopper 2015-02-10 01:13:08