2011-06-07 90 views
5

我想调试我的内核模块。对于我试图把一个断点do_one_initcallkernel/module.c只是我init_module之前被调用,但它显示通过KGDB调试模块

在地址无法访问内存 0x802010a0

下面是我的Makefile使用:

obj-m := hello.o 

KDIR=/lib/modules/$(shell uname -r)/build 
PWD=$(shell pwd) 

EXTRA_CFLAGS += -g 

all: 
     make -C $(KDIR) M=$(PWD) modules 

clean: 
     make -C $(KDIR) M=$(PWD) clean 

请建议我可能是什么问题。

回答

9

可加载的内核模块在内存中的位置仅在插入模块后才会设置。 在模块函数上设置断点时,gdb会查询模块文件(.ko)的地址,这是错误的。你需要通知gdb模块的实际位置。

有关更多信息,请参阅this book(第4章,调试器和相关工具部分),但下面是我设计的一个简短步骤。

  • machine1是被调试的机器。
  • machine2是运行调试器的机器。

  1. machine1上,运行modpbrobe your_module_name
  2. machine1上,运行以下shell命令:
    MODULE_NAME=your_module_name 
    MODULE_FILE=$(modinfo $MODULE_NAME| awk '/filename/{print $2}') 
    DIR="/sys/module/${MODULE_NAME}/sections/" 
    echo add-symbol-file $MODULE_FILE $(cat "$DIR/.text") -s .bss $(cat "$DIR/.bss") -s .data $(cat "$DIR/.data")
    你应该得到类似以下的输出:
    add-symbol-file /lib/modules/.../your_module_name.ko 0xffffffffa0110000 -s .bss 0xffffffffa011b948 -s .data 0xffffffffa011b6a0
  3. machine2上,运行gdb vmlinux
  4. machine2上,gdb的控制台上,在阶段2
  5. machine2上运行最后的命令的输出,gdb的控制台上,连接通过运行target remote /dev/ttyS0到MACHINE1(假设串行端口是在ttyS0来)
  6. 在machine1上运行echo g > /proc/sysrq-trigger。机器将冻结
  7. 在machine2上的gdb控制台上,根据需要设置断点。
  8. 继续调试。当需要时应该触发断点。
可能有其他问题阻止您设置断点,但这是跨越的主要障碍。
+0

我的'insmod'成功了,我看到我的'module_init' kprints int他'dmesg'。但我的'modprobe'失败。因此'modinfo'也会失败。你能否提供一些见解? – 2012-10-05 01:25:39

+1

可能有几个原因。最重要的是modprobe不知道你的模块,因为它咨询了一个数据库,所以你不能'modprobe my_module_file.ko'。相反,您需要在使用'depmod -a'将其插入数据库后执行'modprobe my_module_name'。但为了这个目的,这并不重要。你知道你的名字和文件名,所以你可以简单地使用它们,而不是回答的建议。例如'MODULE_NAME = my_module_name; MODULE_FILE = my_module_file.ko' – Nir 2012-10-09 17:30:25

+0

一个快速提示:你需要root获得 cat/sys/module/module-name-here/sections /。* 东西工作..(否则它只显示值0x0)。 – kaiwan 2015-04-03 02:42:57