2011-06-07 94 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