gdb 和 addr2line 调试内核模块
#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION ("Oops"); MODULE_AUTHOR("weiqifa"); static int my_oops_init(void) { int *a; a = (int *)0x00003333; *a = 3; printk(KERN_ALERT "oops %d\n",a); return 0; } static void my_oops_exit(void) { printk(KERN_ALERT "Goodbye, oops\n"); } module_init(my_oops_init); module_exit(my_oops_exit) |
ifneq ($(KERNELRELEASE),) EXTRA_CFLAGS = -Wall -g obj-m := oops.o else PWD := $(shell pwd) KVER := $(shell uname -r) KDIR := /lib/modules/$(KVER)/build all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions endif |
root@ubuntu:~/linuxBook/oopsmodules# dmesg |tail -20 [ 815.844634] RSP: 0018:ffff88003b933de8 EFLAGS: 00010246 [ 815.844635] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000001 [ 815.844637] RDX: 0000000000040770 RSI: 0000000000003333 RDI: ffffffffa0359024 [ 815.844638] RBP: ffff88003b933e68 R08: 00000000000030d4 R09: 0000000000000100 [ 815.844639] R10: 8000000000000000 R11: 0000000000000000 R12: ffffffffa0358000 [ 815.844640] R13: 0000000000000000 R14: 0000000001005010 R15: 0000000000000000 [ 815.844641] FS: 00007fb80a1f6700(0000) GS:ffff88003d600000(0000) knlGS:0000000000000000 [ 815.844643] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 815.844643] CR2: 0000000000003333 CR3: 0000000036198000 CR4: 00000000000407f0 [ 815.844687] Stack: [ 815.844689] ffff88003b933e68 ffffffff8100215a 0000000001005010 0000000000000000 [ 815.844691] ffff88003b933e38 ffffffff8105ec93 0000000000000000 0000000000000000 [ 815.844693] 0000000001005010 ffffffffa0020000 ffff88003b933e68 00000000181edb8b [ 815.844695] Call Trace: [ 815.844734] [<ffffffff8100215a>] ? do_one_initcall+0xfa/0x1b0 [ 815.844740] [<ffffffff8105ec93>] ? set_memory_nx+0x43/0x50 [ 815.844752] [<ffffffff8175a462>] do_init_module+0x80/0x1d1 [ 815.844759] [<ffffffff810ec66d>] load_module+0x4ed/0x620 [ 815.844761] [<ffffffff810e9f10>] ? show_initstate+0x50/0x50 [ 815.844763] [<ffffffff810ec854>] SyS_init_module+0xb4/0x100 [ 815.844798] [<ffffffff8177b55d>] system_call_fastpath+0x1a/0x1f [ 815.844800] Code: <c7> 04 25 33 33 00 00 03 00 00 00 48 89 e5 e8 3c 16 40 e1 31 c0 5d [ 815.844809] RIP [<ffffffffa0358014>] my_oops_init+0x14/0x30 [oops] [ 815.844812] RSP <ffff88003b933de8> [ 815.844813] CR2: 0000000000003333 [ 815.844818] ---[ end trace f8f9b64af5078acc ]--- |
[ 815.844809] RIP [<ffffffffa0358014>] my_oops_init+0x14/0x30 [oops] [ 815.844812] RSP <ffff88003b933de8> |
查看模块的加载地址
root@ubuntu:~/linuxBook/oopsmodules# cat /proc/modules |grep oops oops 13418 1 - Loading 0xffffffffa0358000 (OX+) root@ubuntu:~/linuxBook/oopsmodules# |
使用 addr2line 找到 oops 位置
root@ubuntu:~/linuxBook/oopsmodules# addr2line -e oops.o 0x14 /home/linux/linuxBook/oopsmodules/oops.c:12 root@ubuntu:~/linuxBook/oopsmodules# |
root@ubuntu:~/linuxBook/oopsmodules# objdump -dS --adjust-vma=0xffffffffa0358000 oops.ko oops.ko: file format elf64-x86-64 Disassembly of section .text: ffffffffa0358000 <init_module>: MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION ("Oops"); MODULE_AUTHOR("weiqifa"); static int my_oops_init(void) { ffffffffa0358000: e8 00 00 00 00 callq ffffffffa0358005 <init_module+0x5> ffffffffa0358005: 55 push %rbp int *a; a = (int *)0x00003333; *a = 3; printk(KERN_ALERT "oops %d\n",a); ffffffffa0358006: be 33 33 00 00 mov $0x3333,%esi ffffffffa035800b: 48 c7 c7 00 00 00 00 mov $0x0,%rdi ffffffffa0358012: 31 c0 xor %eax,%eax static int my_oops_init(void) { int *a; a = (int *)0x00003333; *a = 3; ffffffffa0358014: c7 04 25 33 33 00 00 movl $0x3,0x3333 ffffffffa035801b: 03 00 00 00 MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION ("Oops"); MODULE_AUTHOR("weiqifa"); static int my_oops_init(void) { ffffffffa035801f: 48 89 e5 mov %rsp,%rbp int *a; a = (int *)0x00003333; *a = 3; printk(KERN_ALERT "oops %d\n",a); ffffffffa0358022: e8 00 00 00 00 callq ffffffffa0358027 <init_module+0x27> return 0; } ffffffffa0358027: 31 c0 xor %eax,%eax ffffffffa0358029: 5d pop %rbp ffffffffa035802a: c3 retq ffffffffa035802b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) ffffffffa0358030 <cleanup_module>: static void my_oops_exit(void) { ffffffffa0358030: e8 00 00 00 00 callq ffffffffa0358035 <cleanup_module+0x5> ffffffffa0358035: 55 push %rbp printk(KERN_ALERT "Goodbye, oops\n"); ffffffffa0358036: 48 c7 c7 00 00 00 00 mov $0x0,%rdi ffffffffa035803d: 31 c0 xor %eax,%eax *a = 3; printk(KERN_ALERT "oops %d\n",a); return 0; } static void my_oops_exit(void) { ffffffffa035803f: 48 89 e5 mov %rsp,%rbp printk(KERN_ALERT "Goodbye, oops\n"); ffffffffa0358042: e8 00 00 00 00 callq ffffffffa0358047 <cleanup_module+0x17> } ffffffffa0358047: 5d pop %rbp ffffffffa0358048: c3 retq ffffffffa0358049: 00 00 add %al,(%rax) ... root@ubuntu:~/linuxBook/oopsmodules# |
*a = 3; ffffffffa0358014: c7 04 25 33 33 00 00 movl $0x3,0x3333 |
使用函数dump_stack()调试内核
#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { dump_stack(); printk(KERN_ALERT "Hello, world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); |
[176360.807755] [<ffffffff81765bf5>] dump_stack+0x64/0x82 [176360.807776] [<ffffffffa0275000>] ? 0xffffffffa0274fff [176360.807779] [<ffffffffa027500e>] hello_init+0xe/0x20 [hello] [176360.807931] [<ffffffff8100215a>] do_one_initcall+0xfa/0x1b0 [176360.808709] [<ffffffff8105ec93>] ? set_memory_nx+0x43/0x50 [176360.808717] [<ffffffff8175a462>] do_init_module+0x80/0x1d1 [176360.809093] [<ffffffff810ec66d>] load_module+0x4ed/0x620 [176360.809097] [<ffffffff810e9f10>] ? show_initstate+0x50/0x50 [176360.809100] [<ffffffff810ec854>] SyS_init_module+0xb4/0x100 [176360.809187] [<ffffffff8177b55d>] system_call_fastpath+0x1a/0x1f [176360.809308] Hello, world |
实现源码位置
几个比较关键的函数调用关系
dump_stack总结
使用vmlinux调试内核
./prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-addr2line -f -e kernel/vmlinux weiqifa@dev:~/rk3399_7in1$ ./prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-addr2line -f -e kernel/vmlinux ffffff8008459f3c rk_iommu_domain_free /data/weiqifa/rk3399_7in1/kernel/drivers/iommu/rockchip-iommu.c:1005 (discriminator 2) weiqifa@dev:~/rk3399_7in1$ |
linux@ubuntu:/usr/src/linux-headers-3.13.0-117/kernel$ cat /proc/interrupts CPU0 0: 26 IO-APIC-edge timer 1: 12200 IO-APIC-edge i8042 8: 1 IO-APIC-edge rtc0 9: 0 IO-APIC-fasteoi acpi 12: 110704 IO-APIC-edge i8042 14: 0 IO-APIC-edge ata_piix 15: 0 IO-APIC-edge ata_piix 16: 21165 IO-APIC-fasteoi vmwgfx, snd_ens1371 17: 76243 IO-APIC-fasteoi ehci_hcd:usb1, ioc0 18: 657 IO-APIC-fasteoi uhci_hcd:usb2 19: 197583 IO-APIC-fasteoi eth0 40: 0 PCI-MSI-edge PCIe PME, pciehp |