简单的oops调试

15 篇文章 0 订阅
3 篇文章 0 订阅

oops

~ # insmod /mnt/oops.ko
[  117.135066] oops: loading out-of-tree module taints kernel.
[  117.142239] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[  117.142564] Mem abort info:
[  117.142679]   ESR = 0x96000046
[  117.142812]   Exception class = DABT (current EL), IL = 32 bits
[  117.142991]   SET = 0, FnV = 0
[  117.143114]   EA = 0, S1PTW = 0
[  117.143242] Data abort info:
[  117.143364]   ISV = 0, ISS = 0x00000046
[  117.143494]   CM = 0, WnR = 1
[  117.143651] user pgtable: 4k pages, 39-bit VAs, pgdp = (____ptrval____)
[  117.143853] [0000000000000000] pgd=000000005984f003, pud=000000005984f003, pmd=0000000000000000
[  117.144482] Internal error: Oops: 96000046 [#1] PREEMPT SMP
[  117.144744] Modules linked in: oops(O+)
[  117.145175] CPU: 1 PID: 1202 Comm: insmod Tainted: G           O      5.0.0-gadef409-dirty #308
[  117.145542] Hardware name: linux,dummy-virt (DT)
[  117.145825] pstate: 40000005 (nZcv daif -PAN -UAO)
[  117.146198] pc : hello_init+0x1c/0x1000 [oops]
....
Segmentation fault

查看log,定位到pc指针

pc : hello_init+0x1c/0x1000 [oops]

关于func+0x##/0x####的定位解读:形如 函数+偏移/长度
func指示了异常函数名
0x##表示出错的偏移位置
0x####表示func函数的大小

如果系统没有重启,查看驱动加载地址

~ # cat /sys/module/oops/sections/.init.text
0xffffff8008aa5000

使用gdb加载ko文件

aarch64-linux-gnu-gdb oops.ko

(gdb) file vmlinux      ----->加载内核镜像文件
Load new symbol table from "vmlinux"? (y or n) y
Reading symbols from vmlinux...done.
(gdb) add-symbol-file oops.o 0xffffff8008aa5000  -----> 手工加载文件
add symbol table from file "oops.o" at
	.text_addr = 0xffffff8008aa5000
(y or n) y
Reading symbols from oops.o...done.
(gdb) disassemble hello_init
Dump of assembler code for function hello_init:
   0x0000000000000000 <+0>:	stp	x29, x30, [sp, #-16]!
   0x0000000000000004 <+4>:	mov	x29, sp
   0x0000000000000008 <+8>:	mov	x0, x30
   0x000000000000000c <+12>:	bl	0xc <hello_init+12>
   0x0000000000000010 <+16>:	mov	x1, #0x0                   	// #0
   0x0000000000000014 <+20>:	mov	w2, #0x1                   	// #1
   0x0000000000000018 <+24>:	mov	w0, #0x0                   	// #0
   0x000000000000001c <+28>:	str	w2, [x1]
   0x0000000000000020 <+32>:	ldp	x29, x30, [sp], #16
   0x0000000000000024 <+36>:	ret
End of assembler dump.
(gdb) 

定位到0x000000000000001c <+28>:    str    w2, [x1]

本人测试时 (gdb) add-symbol-file oops.o 0x0000000000000000 加载到0x0000000000000000也可以定位到0x1c的位置

 

是不是觉得太麻烦?直接l指令定位查看出错位置。无需file vmlinux

(gdb) l *(hello_init+0x1c)
0x1c is in hello_init (/xxx/oops.c:9).
4	
5 	static int __init hello_init(void)
6	{
7	    int *p = 0;
8	
9	    *p = 1;
10	
11	    return 0;
12	}
13	

注意这个只是定位出错的地方,不代表修改点,对于复杂的问题无法一眼就可看出

 

不想用gdb?使用objdump反汇编

aarch64-linux-gnu-objdump -S oops.o
oops.o:     file format elf64-littleaarch64
Disassembly of section .init.text:
0000000000000000 <init_module>:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>

static int __init hello_init(void)
{
   0:	a9bf7bfd 	stp	x29, x30, [sp, #-16]!
   4:	910003fd 	mov	x29, sp
   8:	aa1e03e0 	mov	x0, x30
   c:	94000000 	bl	0 <_mcount>
    int *p = 0;

    *p = 1;
  10:	d2800001 	mov	x1, #0x0                   	// #0
  14:	52800022 	mov	w2, #0x1                   	// #1

    return 0;
}
  18:	52800000 	mov	w0, #0x0                   	// #0
    *p = 1;
  1c:	b9000022 	str	w2, [x1]
}
  20:	a8c17bfd 	ldp	x29, x30, [sp], #16
  24:	d65f03c0 	ret

Disassembly of section .exit.text:

0000000000000000 <cleanup_module>:
{
   0:	d65f03c0 	ret

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果在驱动调试过程中遇到了 OOPS,可以尝试以下方法来处理: 1. 首先,使用 dmesg 命令来查看系统的内核日志,以了解 OOPS 发生的具体原因。 2. 如果 OOPS 是由于内存访问越界、空指针访问等原因引起的,可以尝试使用 KASAN 或者 KMSAN 这类内核安全检测工具来帮助定位错误。 3. 如果 OOPS 是由于驱动调用了不支持的硬件操作或者系统调用,可以尝试使用 ltrace 和 strace 命令来跟踪驱动的函数调用,以找出调用的源头。 4. 如果 OOPS 是由于驱动中的 bug 引起的,可以尝试使用 kgdb 等内核调试工具来定位错误。 5. 如果以上方法都无法解决 OOPS 问题,可以尝试在内核邮件列表或者内核论坛上提问,寻求其他开发者的帮助。 ### 回答2: 驱动调试过程中遇到oops是一种操作系统发现内核发生严重错误的情况。出现oops意味着驱动程序执行过程中发生了一些不可预料的问题,需要及时处理。 首先,当出现oops时,我们需要尽早记录错误信息。oops会输出一些关键信息,如错误类型、内核堆栈跟踪和导致问题的代码行。我们应该将这些信息记录下来,以便后续分析和解决问题。 其次,我们可以使用调试工具来分析oops。例如,可以使用GDB调试工具通过设置断点、观察变量值以及执行追踪命令等方式,进一步分析问题所在。通过调试工具,我们可以准确追踪到问题发生的具体位置,有助于找到原因。 同时,我们也可以进行代码审查。通过仔细检查驱动程序的相关代码,我们可以尝试找到潜在的问题区域。可能的原因包括内存管理错误、指针操作问题或与其他模块的交互冲突等。通过排查代码逻辑,我们可以找到问题并进行修复。 另外,还可以考虑升级或更新驱动程序。有时,驱动程序中的某些错误可能是已知的问题,并且可能在最新的版本中得到修复。因此,将驱动程序升级到最新版本可能会解决oops问题。 最后,我们需要发布错误报告并与社区或供应商联系。将oops信息提交给开发者社区或驱动程序供应商,他们可能已经遇到过类似的问题,或者能够提供解决方案或补丁程序。 综上所述,正确处理驱动调试过程中的oops问题非常重要。我们应该记录问题信息、使用调试工具进行进一步分析、进行代码审查、升级驱动程序以及与相关社区或供应商联系,以解决该问题。 ### 回答3: 在驱动调试过程中,如果遇到oops(内核崩溃),首先需要收集相关的信息以便进一步分析和解决问题。处理oops的一般步骤如下: 1.收集信息:记录oops发生时的行为、错误信息和堆栈跟踪等关键信息。首先要注意保存控制台输出、截图或记录错误信息,尤其是调用栈跟踪。如果配置了oops当前行的反汇编器(disassembler),还可以保存反汇编器的输出。 2.重新构建内核:为了能够更好地跟踪和分析问题,可以重新构建内核,并开启调试符号以提供更详细的信息。 3.分析调用栈:通过调用栈跟踪信息,定位并分析造成oops的函数和行为。了解哪些函数或驱动模块可能与oops相关,会有助于排查问题。 4.查找相关的补丁或解决方案:根据分析结果,查找相关的内核补丁、参考文档、社区讨论等,以寻找可能的解决方案。 5.测试和验证:通过调整和应用解决方案,对驱动进行测试和验证,以确保修复了oops并且问题已被解决。 6.错误报告和反馈:如果问题是由驱动本身引起的,应该及时向驱动开发者或内核社区报告该问题,并提供详细的分析和重现步骤。 最后,要注意及时更新和升级驱动程序,以调试工具和技术来解决oops问题。尽可能利用内核开发工具、调试工具和相关文档资源,加强对驱动的调试和排查能力,提高驱动的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值