基于at91rm9200的arm平台 kgdb+linux内核调试
2010年06月27日
在做这个实验之前,本人参考了bob_zhang2004的贴子,实现了在vmware下的x86平台linux的kgdb调试。现在准备建立arm平台,在这边先说说我的意图,希望大家指导,
在bob_zhang2004的帖子中,也说明了arm平台建立kgdb调试的思路,就是在打了core-lite.patch 和 arm-lite.patch的补丁后,我们需要在arch/arm/mach-XXX/目录下实现适合我们自己板子的kgdb-serial.c文件。
在 kgdb-serial.c文件中,主要是实现下面的几个函数:kgdb_serial_init() , kgdb_serial_putchar() , kgdb_serial_getchar() 。这在http://www.arm.linux.org.uk/deve ... tch.php?id=1335%2F1 上有说明。
不知道谁用这种方法实现了arm平台的kgdb调试。还请各位指导指导。本人正在实验中!!!
2007-09-11
今天一天,主要熟悉了9200在linux中的一些配置,以及 9200的Debug串口的驱动编程。在参考kgdb补丁在pxa的板子上的kgdb_serial.c文件(了解其函数意图,在9200上实现其同等功能)。代码是写出来了,但是还没有编译,这边先贴出来给大家,哪位大侠了解的也帮忙找找bug。明天开始编译实验。大家祝我好运啊!!
这边是针对2.6.13版本的kernel以及补丁2.6.13-at91.patch.gz进行编程的。我这边把我的代码帖给大家。这个代码可以编译通过,但是kgdb补丁在2.6.13版本(linux-2.6.13-kgdb-2.3.tar.bz2)似乎少了core.patch这个补丁。在最后编译的时候,会提示出错。所以本人又把kernel改成2.6.15.5版本,这样和我前面做x86平台调试的时候是一样的版本了。
2007-09-12
今天在把2.6.13版本下编写的kgdb_serial.c文件修改成适合2.6.15.5版本。2.6.15.5版本主要是 9200的补丁在头文件上作了很大的修改。对于很多结构体以及物理地址与虚拟地址之间的转换的方式都做了修改。这些修改有下面几个头文件中就可以体现出来:include\asm-arm\arch-at91rm9200目录下的
AT91RM9200_USART.h hardware.h board.h AT91RM9200_SYS.h pio.h AT91RM9200.h。
所以这边修改了kgdb_serial.c文件。如下
我们把kgdb_serial.c文件放置在目录arch/arm/mach-at91rm9200/目录下,并且修改该目录下的Makefile。在 Makefile的最后加上:
obj-$(CONFIG_KGDB) += kgdb_serial.o /* 在kgdb调试功能打开的时候,编译kgdb_serial.cw文件 */
配置完后,我们就按照正常的配置方式配置内核,对于kgdb选项我们要选上:
kernel hacking ---> KGDB: kernel debugging with remote gdb
--->KGDB: Console messages through gdb
--->Method for KGDB communication(KGDB: Use only
kernel modules for I/O)
内核配置完毕之后,我们就可以make zImage来生成zImage。然后通过uboot的mkimage来生成uImage. 这边还需要注意的是,在uboot传递给kernel的启动参数必须加上kgdbwait参数。在kgdb的官方文档中介绍的kgdbwait 8250kgdb=0,115200。因为我们不是用8250的串口控制器,所以我们只要传递kgdbwait的这个参数。(本人暂时是这样做的)。我的启动参数如下:
# ./gdbmod-2.4 vmlinux
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/tls/i686/libthread_db.so.1".
(gdb) set remotebaud 115200
(gdb) target remote /dev/ttyS0
Remote debugging using /dev/ttyS0
do_early_param (param=0xc001e195 "kgdbwait", val=0x0) at init/main.c:412
412 {
(gdb) break console_init
Breakpoint 1 at 0xc0016d0c: file drivers/char/tty_io.c, line 2928.
(gdb) c
Continuing.
[New thread 32768]
Program received signal SIGTRAP, Trace/breakpoint trap.
0x2001dc08 in ?? () at proc_fs.h:194
194 remove_proc_entry(name,proc_net);
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x2001dc08 in ?? () at proc_fs.h:194
194 remove_proc_entry(name,proc_net);
(gdb) list
189 return res;
190 }
191
192 static inline void proc_net_remove(const char *name)
193 {
194 remove_proc_entry(name,proc_net);
195 }
196
197 #else
这边我们可以判断host端的gdb已经和target上的kgdb连接上了。但是我发现内核根本无法启动,一直在0x2001dc08 in ?? () at proc_fs.h:194
194 remove_proc_entry(name,proc_net) 停下来。这边还是个问题。不知道哪位大侠能够帮忙解决一下。我也将继续努力,希望能给大家送上好消息.
2007-9-14
在前面kgdb的调试中,host的gdb已经能够和target的kgdb通讯正常了。但是还是会出现一个问题,如上红字所标示的。
后面在augustusqing网友的提醒下,是因为我host上的gdb初始化是采用x86平台的:This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/tls/i686/libthread_db.so.1".导致的。正确的应该是在host上采用初始化为arm平台的gdb来调试。
这边我们可以到相应的官方网站上去下载gdb源码。针对linux-2.6.15.5-kgdb-2.4补丁的gdb版本是6.4版本。所以我们下载 gdb-6.4.tar。gz。然后按照arm平台对gdb进行配置、编译、安装(详细步骤可以参考本人bolg上关于gdb的文章:《GDB 远程调试的实现》)。
然后我们就可以调用arm-linux-gdb来调试内核了。信息如下:
# ./arm-linux-gdb vmlinux
bash: child setpgid (20000 to 20000): 没有那个进程
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux"...
(gdb) set remotebaud 115200
(gdb) target remote /dev/ttyS0
Remote debugging using /dev/ttyS0
0xc0057fc4 in $d () at kernel/kgdb.c:1872
1872 atomic_set(&kgdb_setting_breakpoint, 1);
warning: shared library handler failed to enable breakpoint
(gdb) break console_init
Breakpoint 1 at 0xc0016d18: file drivers/char/tty_io.c, line 2932.
(gdb) c
Continuing.
[New thread 32768]
Breakpoint 1, console_init () at drivers/char/tty_io.c:2932
2932 (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
(gdb) c
Continuing.
Linux version 2.6.15.5 (root@dengdalong) (gcc version 3.4.1) #3 Sat Sep 8 10:02:56 CST 2007
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: Atmel AT91RM9200-DK
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 179 MHz, master 59 MHz, main 18.432 MHz
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists
Kernel command line: root=/dev/ram rw kgdbwait initrd=0x20a00000,4M init=/linuxrc console=ttyS0,115200,mem=16M ip=192.168.2.10
Waiting for connection from remote gdb...
AT91: 128 gpio irqs in 4 banks
PID hash table entries: 128 (order: 7, 2048 bytes)
Console: colour dummy device 80x30
Linux version 2.6.15.5 (root@dengdalong) (gcc version 3.4.1) #3 Sat Sep 8 10:02:56 CST 2007
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: Atmel AT91RM9200-DK
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 179 MHz, master 59 MHz, main 18.432 MHz
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists
Kernel command line: root=/dev/ram rw kgdbwait initrd=0x20a00000,4M init=/linuxrc console=ttyS0,115200,mem=16M ip=192.168.2.10
Waiting for connection from remote gdb...
AT91: 128 gpio irqs in 4 banks
PID hash table entries: 128 (order: 7, 2048 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 16MB = 16MB total
Memory: 9964KB available (1652K code, 368K data, 96K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
checking if image is initramfs...it isn't (no cpio magic); looks like an initrd
Freeing initrd memory: 4096K
NET: Registered protocol family 16
usbcore: registered new driver usbfs
usbcore: registered new driver hub
NetWinder Floating Point Emulator V0.97 (double precision)
io scheduler noop registered
io scheduler anticipatory registered
AT91 Real Time Clock driver.
AT91 SPI driver loaded
AT91 Watchdog Timer enabled (5 seconds)
ttyS0 at MMIO 0xfefff200 (irq = 1) is a AT91_SERIAL
ttyS1 at MMIO 0xfefc4000 (irq = 7) is a AT91_SERIAL
RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
at91_ether: Your bootloader did not configure a MAC address.
eth0: AT91 ethernet at 0xfefbc000 int=24 10-HalfDuplex (00:00:00:00:00:00)
eth0: Davicom 9196 PHY (Copper)
physmap flash device: 200000 at 10000000
phys_mapped_flash: Found 1 x16 devices at 0x0 in 16-bit bank
Support for command set 0001 not present
gen_probe: No supported Vendor Command Set found
at91_cf: irqs det #64, io #0
usbmon: debugfs is not available
at91rm9200-ohci at91rm9200-ohci: AT91RM9200 OHCI
at91rm9200-ohci at91rm9200-ohci: new USB bus registered, assigned bus number 1
at91rm9200-ohci at91rm9200-ohci: irq 23, io mem 0x00300000
usb usb1: Product: AT91RM9200 OHCI
usb usb1: Manufacturer: Linux 2.6.15.5 ohci_hcd
usb usb1: SerialNumber: at91rm9200
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
udc: at91_udc version 8 March 2005
mice: PS/2 mouse device common for all mice
i2c /dev entries driver
Found AT91 i2c
AT91RM9200 MCI initialized
NET: Registered protocol family 2
IP route cache hash table entries: 256 (order: -2, 1024 bytes)
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
usb 1-2: new low speed USB device using at91rm9200-ohci and address 2
usb 1-2: device descriptor read/64, error -110
usb 1-2: device descriptor read/64, error -110
IP-Config: Failed to open eth0
IP-Config: No network devices available.
RAMDISK: Compressed image found at block 0
usb 1-2: new low speed USB device using at91rm9200-ohci and address 3
usb 1-2: device descriptor read/64, error -110
usb 1-2: device descriptor read/64, error -110
usb 1-2: new low speed USB device using at91rm9200-ohci and address 4
usb 1-2: device not accepting address 4, error -110
usb 1-2: new low speed USB device using at91rm9200-ohci and address 5
usb 1-2: device not accepting address 5, error -110
VFS: Mounted root (ext2 filesystem).
Freeing init memory: 96K
系统启动到这边,gdb上就没有打印出来信息了。正常启动的话,应该后面是挂载文件系统。但是我没有用过kgdb,不知道这样是不是正常的。也不知道,到这边如果要调试程序,应该怎么去调试。等待继续努力!!看看kgdb的官方文档,去多了解一下。
2007-09-23
最近因为工作的原因,所以linux的学习停滞了一下,这边把这几天所做的kgdb的arm平台调试做一下说明。前面在kernel打上kgdb补丁后,通过debeg串口(同时作为console)连接host上的gdb,在挂载文件系统的时候,串口上就没有输出了。后面我把kgdb的调试串口改成 9200的uart2,debug的uart作为kernel的console。这个时候能够在console上清楚的看到kernel已经挂载上 ramdisk,shell也正常启动了。至于为什么在gdb串口中没有输出,我猜想是因为,系统这个时候没有任何断点,程序在正常运行了,那么在gdb 那边也就不能得到任何信息,所以就不显示任何的东西。所以看来kgdb调试的时候,需要两个串口。一个作为console,一个作为gdb的串口。
如果我们的驱动模块静态编译进kernel的,那么我应该可以在kernel启动的时候,在register驱动的时候设置断点,从而达到调试的目的。至于动态加载的模块程序调试。本人在随后实验后贴出。
还有前面说到2.6.13版本在打上kgdb补丁后不能正常编译问题,这个问题我另起一篇文章说明!网上也有相关的patch说明。
2007-10-03
最近工作比较多,所以linux的实验就停下来了,前面我将kgdb已经成功的安装在kernel上,kernel的启动调试已经可以正常运作了。后面需要实验的就是kgdb调试动态加载的模块。但是我的实验总是不成功,
在test machine中insmod ****.ko后,develop machine的gdb会正确的停在module.c的sys_module_init的函数中。但是准备step单步进入模块的init函数,gdb提示segmentation fault,这个错误是因为访问了错误的内存造成的。所以我这边怀疑是gdb的原因。gdb在调试模块的时候对地址的解析会出现错误。但是我编译的gdb 也是kgdb官方网上下载gdb-6.3-kgdb-2.3.tar.bz2。但是是配置成ARM模式。
后面只能将模块编译进内核,然后再进行调试了。模块编译进内核,只需要将程序拷贝到arch/arm/mach-at91rm9200目录,然后修改该目录下的Makefile。增加下面两句:
obj-y += scull.o
scull-objs = access.o main.o pipe.o
其中scull模块程序由access.c main.c pipe.c构成。