externintregister_test_notifier(struct notifier_block *nb); staticstructtask_struct *p; staticintnotifier_test_deal_0(struct notifier_block *nb, unsignedlong action, void *val){ printk("enter %s \n", __func__); switch(action) { case FIRST_EVENT: printk("action is 0x%lu in func is %s\n", action, __func__); break; case SECOND_EVENT: printk("aciotn is 0x%lu in func is %s\n", action, __func__); break; default: printk("nothing to do\n"); break; } return0; }
staticintnotifier_test_deal_1(struct notifier_block *nb, unsignedlong action, void *val){ printk("enter %s \n", __func__); switch(action) { case FIRST_EVENT: printk("action is 0x%lu in func is %s\n", action, __func__); break; case SECOND_EVENT: printk("aciotn is 0x%lu in func is %s\n", action, __func__); break; default: printk("nothing to do\n"); break; } return0; }
➜ x86-busybox-rootfs gdb vmlinux (gdb) b start_kernel Breakpoint 1 at 0xffffffff82d23c7c: file init/main.c, line 929. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0xffffffff82d23c7c in start_kernel at init/main.c:929 (gdb) target remote:1234 Remote debugging using :1234 0x00000000034005a4 in ?? () (gdb) bt #0 0x00000000034005a4 in ?? () #1 0x00000000033ffb02 in ?? () #2 0x00000000000001ff in ?? () #3 0x000000000000003f in ?? () #4 0x0000000001000000 in ?? () #5 0x0000000000000000 in ?? () (gdb) c Continuing.
Thread 1 hit Breakpoint 1, start_kernel () at init/main.c:929 929 { (gdb)
//eg file test-A.c int test1; EXPORT_SYMBOL(test1); int test2=2; EXPORT_SYMBOL(test2); staticintcall_test_notifier(unsignedlong action, void *data){ return raw_notifier_call_chain(¬ifier_test, action, data); } EXPORT_SYMBOL(call_test_notifier);
objdump打印所有symbol
1 2 3 4 5 6 7
➜ 1-notifier git:(master) ✗ objdump -t test-A.ko ... 0000000000000000 g O .bss 0000000000000004 test1 0000000000000000 g O .data 0000000000000004 test2 >>因为test2已经初始化 0000000000000000 l F .text 0000000000000017 call_test_notifier 0000000000000020 l F .text 0000000000000014 register_test_notifier ...
nm打印
1 2 3 4 5
➜ 1-notifier git:(master) ✗ nm test-A.ko 0000000000000000 B test1 0000000000000000 D test2 0000000000000000 t call_test_notifier 0000000000000020 t register_test_notifier
➜ x86-busybox-rootfs gdb vmlinux (gdb) target remote:1234 Remote debugging using :1234 0xffffffff8fb1127b in ?? () (gdb) add-symbol-file /github/busybox/initramfs/x86-busybox-rootfs/test-A.ko -s .text 0xffffffffc0058000 add symbol table from file "/github/busybox/initramfs/x86-busybox-rootfs/test-A.ko" at .text_addr = 0xffffffffc0058000 (y or n) y Reading symbols from /github/busybox/initramfs/x86-busybox-rootfs/test-A.ko...done. (gdb) b call_test_notifier Breakpoint 1 at 0xffffffffc0058000: file /github/linux-driver/1-notifier/test-A.c, line 11. >>symbol地址 = .text + 偏移,即/proc/kallsyms打印 (gdb) b register_test_notifier Breakpoint 2 at 0xffffffffc0058020: file /github/linux-driver/1-notifier/test-A.c, line 17. (gdb) c Continuing.
此时再插入test-B和test-C即可触发模块
1 2 3 4 5 6 7 8
/lib/modules/5.17.0+ # insmod test-B.ko [ 2003.258864] enter notifier_test_B_init pid is 122 >>断点2 hit 1 /lib/modules/5.17.0+ # insmod test-C.ko [ 2010.537016] enter notifier_test_C_init pid is 123 >>断点2 hit 2 [ 2010.582501] enter notifier_test_deal_1 >>断点1 hit 1 [ 2010.586064] action is 0x1 in func is notifier_test_deal_1 [ 2010.586365] enter notifier_test_deal_0 [ 2010.586521] action is 0x1 in func is notifier_test_deal_0
Thread 1 hit Breakpoint 2, register_test_notifier (nh=0xffffffffc005f020) at /github/linux-driver/1-notifier/test-A.c:17 warning: Source file is more recent than executable. 17return raw_notifier_call_chain(¬ifier_test, action, data); >>断点2 hit 1 (gdb) c Continuing.
Thread 1 hit Breakpoint 2, register_test_notifier (nh=0xffffffffc005f000) at /github/linux-driver/1-notifier/test-A.c:17 17return raw_notifier_call_chain(¬ifier_test, action, data); >>断点2 hit 2 (gdb) c Continuing.
Thread 1 hit Breakpoint 1, call_test_notifier (action=1, data=0xffffffffc0063038) >>断点1 hit 1 at /github/linux-driver/1-notifier/test-A.c:11 11int test1; (gdb) c Continuing. ^C Thread 1 received signal SIGINT, Interrupt. 0xffffffff8fb1127b in ?? () (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0xffffffffc0058000 in call_test_notifier at /github/linux-driver/1-notifier/test-A.c:11 breakpoint already hit 1 time 2 breakpoint keep y 0xffffffffc0058020 in register_test_notifier at /github/linux-driver/1-notifier/test-A.c:17 breakpoint already hit 2 times
在使用前需要编译gdb脚本去生成constants.py,否则对应的接口调用时会提示constants.py找不到的,比如proc.py:15:from linux import constants调用
1
make scripts_gdb
配置~/.gdbinit,增加gdb插件配置
1 2
set debug auto-load on setauto-load safe-path /github/linux
之后在linux目录下开始gdb调试
使用
先检查是否生效
1 2 3 4 5 6 7 8 9 10 11 12 13
(gdb) apropos lx ... lx-dmesg -- Print Linux kernel log buffer lx-fdtdump -- Output Flattened Device Tree header and dump FDT blob to the filename lx-genpd-summary -- Print genpd summary lx-iomem -- Identify the IO memory resource locations defined by the kernel lx-ioports -- Identify the IO port resource locations defined by the kernel lx-list-check -- Verify a list consistency lx-lsmod -- List currently loaded modules lx-mounts -- Report the VFS mounts of the current process namespace lx-ps -- Dump Linux tasks lx-symbols -- (Re-)load symbols of Linux kernel and currently loaded modules ...
内核先插入test-A.ko和test-B.ko,进行notifier注册
1 2 3 4
/lib/modules/5.17.0+ # insmod test-A.ko [ 28.098009] enter notifier_test_A_init pid is 103 /lib/modules/5.17.0+ # insmod test-B.ko [ 64.108107] enter notifier_test_B_init pid is 112
gdb在attach到内核后,通过lx-symbols自动插入模块symbol到gdb
1 2 3 4 5 6 7 8 9 10 11 12
//先切换到模块目录 (gdb) cd /github/linux-driver/ Working directory /github/linux-driver. (gdb) cd 1-notifier/ Working directory /github/linux-driver/1-notifier. //自动插入模块symbols (gdb) lx-symbols loading vmlinux scanning for modules in /github/linux-driver/1-notifier loading @0xffffffffc0005000: /github/linux-driver/1-notifier/test-B.ko loading @0xffffffffc0000000: /github/linux-driver/1-notifier/test_A.ko
(gdb) b call_test_notifier Breakpoint 1 at 0xffffffffc0000000: file /github/linux-driver/1-notifier/test-A.c, line 16. (gdb) b register_test_notifier Breakpoint 2 at 0xffffffffc0000020: file /github/linux-driver/1-notifier/test-A.c, line 22. //内核插入test-C,触发断点 (gdb) c Continuing. loading @0xffffffffc000a000: /github/linux-driver/1-notifier/test-C.ko [Switching to Thread 2]
Thread 2 hit Breakpoint 1, call_test_notifier (action=1, data=0xffffffffc000b038) at /github/linux-driver/1-notifier/test-A.c:16 16staticintcall_test_notifier(unsignedlong action, void *data){ (gdb) n 17return raw_notifier_call_chain(¬ifier_test, action, data);
//开始对链表数据的调试,具体数据关系见README //事件为1, data为no use (gdb) p action $12 = 1 (gdb) x/s data 0xffffffffc000b038: "no use"