基于TQ2440和Qemu的GDB+串口调试(1)
作者
彭东林
pengdonglin137@163.com
平台
TQ2440 + Linux-4.10.17
Qemu(vexpress-ca9) + Linux-4.10.17
概述
下面简单介绍一下用TQ2440和Qemu来搭建KGDB调试环境,对于TQ2440采用KGDB+串口的调试,对于Qemu来说,它已经提供了调试接口,只需在启动qemu时添加相关参数即可。
正文
一、GDB基础知识
1、控制命令
n: 单步运行
c: 继续运行
q: 退出gdb
2、设置、查看和删除断点
(gdb) br start_kernel Breakpoint 6 at 0x809009b0: file ../init/main.c, line 483. (gdb) br __irq_svc Breakpoint 7 at 0x806e8e60: file ../arch/arm/kernel/entry-armv.S, line 219. (gdb) br gic_handle_irq Breakpoint 8 at 0x801014f4: file ../drivers/irqchip/irq-gic.c, line 352. (gdb) info br Num Type Disp Enb Address What 6 breakpoint keep y 0x809009b0 in start_kernel at ../init/main.c:483 7 breakpoint keep y 0x806e8e60 ../arch/arm/kernel/entry-armv.S:219 8 breakpoint keep y 0x801014f4 in gic_handle_irq at ../drivers/irqchip/irq-gic.c:352 (gdb) delete br 8 (gdb) info br Num Type Disp Enb Address What 6 breakpoint keep y 0x809009b0 in start_kernel at ../init/main.c:483 7 breakpoint keep y 0x806e8e60 ../arch/arm/kernel/entry-armv.S:219 (gdb) delete br // 删除所有断点 Delete all breakpoints? (y or n) y (gdb) info br No breakpoints or watchpoints. (gdb)
3、查看调用栈
(gdb) bt #0 ftrace_traceoff (ip=2157986736, parent_ip=0, data=0x80a01f48 <init_thread_union+8008>) at ../kernel/trace/trace_functions.c:351 #1 0x80109a18 in arch_cpu_idle () at ../arch/arm/kernel/process.c:73 #2 0x806dbd54 in p9_write_work (work=0x80a043b0 <tracer_enabled>) at ../net/9p/trans_fd.c:521 #3 0x8016575c in __list_del (next=<optimized out>, prev=<optimized out>) at ../include/linux/list.h:104 #4 __list_del_entry (entry=<optimized out>) at ../include/linux/list.h:119 #5 list_del_init (entry=<optimized out>) at ../include/linux/list.h:158 #6 __finish_swait (q=<optimized out>, wait=0x0) at ../kernel/sched/swait.c:108 #7 0x80165abc in current_thread_info () at ../arch/arm/include/asm/thread_info.h:94 #8 need_resched () at ../include/linux/sched.h:3500 #9 do_idle () at ../kernel/sched/idle.c:222 #10 0x806d56f8 in svc_seq_show (seq=0x80a01f94 <init_thread_union+8084>, statp=<optimized out>) at ../net/sunrpc/stats.c:105 #11 0x80900d64 in start_kernel () at ../init/main.c:653 #12 0x6000807c in ?? () Backtrace stopped: frame did not save the PC
4、查看寄存器的值
- info registers (除了浮点寄存器)
(gdb) info registers r0 0x80a043b0 -2136980560 r1 0x0 0 r2 0x80a01f48 -2136989880 r3 0x8011b8c0 -2146322240 r4 0x0 0 r5 0x80a03cd0 -2136982320 r6 0x80a03c6c -2136982420 r7 0x8097f5d8 -2137524776 r8 0x80a03cd8 -2136982312 r9 0x80a1cace -2136880434 r10 0x0 0 r11 0x80a01f44 -2136989884 r12 0x80a01f38 -2136989896 sp 0x80a01f38 0x80a01f38 <init_thread_union+7992> lr 0x80109a18 -2146395624 pc 0x801d0ae4 0x801d0ae4 <ftrace_traceoff> cpsr 0x60000093 1610612883
- info registers 寄存器名称 (查看指定的寄存器的值)
(gdb) info registers cpsr cpsr 0x60000093 1610612883 (gdb) info registers pc pc 0x801d0ae4 0x801d0ae4 <ftrace_traceoff> (gdb) info registers r0 r0 0x80a043b0 -2136980560 (gdb) info registers r0 r1 r0 0x80a043b0 -2136980560 r1 0x0 0
- print/x $寄存器名 (查看指定的寄存器)
(gdb) print/x $r0 $7 = 0x80a043b0 (gdb) print/x $pc $8 = 0x801d0ae4 (gdb) print/x $cpsr $9 = 0x60000093
下面的字符用于设置数据显示的格式:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量
5、查看内存的值
x/<n/f/u> <addr>
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容
f 表示显示的格式:
x 按十六进制格式显示变量
d 按十进制格式显示变量
u 按十六进制格式显示无符号整型
o 按八进制格式显示变量
t 按二进制格式显示变量
a 按十六进制格式显示变量
c 按字符格式显示变量
f 按浮点数格式显示变量
u 表示将多少个字节作为一个值取出来,如果不指定的话,GDB默认是4个bytes,如果不指定的话,默认是4个bytes。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来,可以设置如下几种:
b 表示单字节
h 表示双字节
w 表示四字 节
g 表示八字节
(gdb) info registers r0 0x80a043b0 -2136980560 r1 0x0 0 r2 0x80a01f48 -2136989880 r3 0x8011b8c0 -2146322240 r4 0x0 0 r5 0x80a03cd0 -2136982320 r6 0x80a03c6c -2136982420 r7 0x8097f5d8 -2137524776 r8 0x80a03cd8 -2136982312 r9 0x80a1cace -2136880434 r10 0x0 0 r11 0x80a01f44 -2136989884 r12 0x80a01f38 -2136989896 sp 0x80a01f38 0x80a01f38 <init_thread_union+7992> lr 0x80109a18 -2146395624 pc 0x801d0ae4 0x801d0ae4 <ftrace_traceoff> cpsr 0x60000093 1610612883 (gdb) x/16xw 0x801d0ae4 0x801d0ae4 <ftrace_traceoff>: 0xe92dd8f0 0xe24cb004 0xe24dd008 0xe30403b0 0x801d0af4 <ftrace_traceoff+16>: 0xe34800a0 0xe1a0400e 0xe590305c 0xe3130002 0x801d0b04 <update_traceon_count>: 0x0a000011 0xe10f3000 0xe3130080 0x0a00000e 0x801d0b14 <update_traceon_count+16>: 0xe1a0200d 0xe3c23d7f 0xe3c3303f 0xe304572c (gdb) x/16xw 0x80a01f38 0x80a01f38 <init_thread_union+7992>: 0x80a01f54 0x80a01f48 0x806dbd54 0x801099f4 0x80a01f48 <init_thread_union+8008>: 0x80a01f84 0x80a01f58 0x8016575c 0x806dbd2c 0x80a01f58 <init_thread_union+8024>: 0x80702db8 0x000000bb 0x80a74000 0xffffffff 0x80a01f68 <init_thread_union+8040>: 0x80a03c40 0x80952a28 0x00000001 0x80a74000
上面查看了pc和sp指向的内存地址的内容。
二、TQ2440 + KGDB + 串口
- 配置内核
Kernel hacking ----> Compile-time checks and compiler options ----> [*] Compile the kernel with debug info ----> [*] Kernel debugging ----> [*] KGDB: kernel debugger ----> <*> KGDB: use kgdb over the serial console
然后编译内核,然后我们就可以在uboot中配置bootargs,用新的kernel启动, 由于目前板子上只有一个调试串口,所以在使用gdb打开串口时,需要把其他
使用该串口的应用关闭,如ckermit以及minicom。
- 具体调试有两种方式
方式一:开机启动阶段kernel自动等待连接
设置uboot的bootargs如下:
setenv bootargs 'noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0,115200 kgdbwait'
设置完bootargs后,可以保存。上面新加的工kgdb调试的参数是'kgdboc=ttySAC0,115200 kgdbwait',表示将来kernel会在ttySAC0这个串口等待连接,并且波特率设置的是115200,kgdbwait表示开机时kernel会自动等待连接。
然后执行boot命令,这样uboot会自动去解析并执行设置在bootcmd环境变量中的命令, log如下:
U-Boot 2015.04-g5095150-dirty (May 25 2017 - 20:13:52) CPUID: 32440001 FCLK: 400 MHz HCLK: 100 MHz PCLK: 50 MHz I2C: ready DRAM: 64 MiB WARNING: Caches not enabled Flash: 0 Bytes NAND: 256 MiB In: serial Out: serial Err: serial Net: dm9000 Hit any key to stop autoboot: 0 TQ2440 # TQ2440 # setenv bootargs 'noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0,115200 kgdbwait' TQ2440 # boot dm9000 i/o: 0x20000000, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 00:0c:29:2a:5c:a5 operating at 100M full duplex mode Using dm9000 device TFTP from server 192.168.1.2; our IP address is 192.168.1.8 Filename 'uImage'. Load address: 0x30008000 Loading: T ################################################################# ################################################################# ################################################################# ####################################### 434.6 KiB/s done Bytes transferred = 3432536 (346058 hex) dm9000 i/o: 0x20000000, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 00:0c:29:2a:5c:a5 operating at 100M full duplex mode Using dm9000 device TFTP from server 192.168.1.2; our IP address is 192.168.1.8 Filename 'dtb'. Load address: 0x32000000 Loading: T # 1000 Bytes/s done Bytes transferred = 8437 (20f5 hex) ## Booting kernel from Legacy Image at 30008000 ... Image Name: Linux-4.10.17+ Created: 2017-08-27 12:49:14 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3432472 Bytes = 3.3 MiB Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 32000000 Booting using the fdt blob at 0x32000000 Loading Kernel Image ... OK Loading Device Tree to 33aa7000, end 33aac0f4 ... OK Starting kernel ... Uncompressing Linux... done, booting the kernel. [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.10.17+ (pengdonglin@pengdonglin-dell) (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29) ) #40 Sun Aug 27 20:49:04 CST 2017 [ 0.000000] CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c000717f [ 0.000000] CPU: VIVT data cache, VIVT instruction cache [ 0.000000] OF: fdt:Machine model: TQ2440 [ 0.000000] Memory policy: Data cache writeback [ 0.000000] DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256 [ 0.000000] Kernel command line: noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0,115200 kgdbwait [ 0.000000] PID hash table entries: 256 (order: -2, 1024 bytes) [ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) [ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) [ 0.000000] Memory: 57572K/65536K available (4923K kernel code, 245K rwdata, 1412K rodata, 208K init, 278K bss, 7964K reserved, 0K cma-reserved) [ 0.000000] Virtual kernel memory layout: [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB) [ 0.000000] vmalloc : 0xc4800000 - 0xff800000 ( 944 MB) [ 0.000000] lowmem : 0xc0000000 - 0xc4000000 ( 64 MB) [ 0.000000] modules : 0xbf000000 - 0xc0000000 ( 16 MB) [ 0.000000] .text : 0xc0008000 - 0xc04d7138 (4925 kB) [ 0.000000] .init : 0xc066e000 - 0xc06a2000 ( 208 kB) [ 0.000000] .data : 0xc06a2000 - 0xc06df520 ( 246 kB) [ 0.000000] .bss : 0xc06df520 - 0xc0725060 ( 279 kB) [ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [ 0.000000] NR_IRQS:103 [ 0.000000] irq: clearing pending status 00000003 [ 0.000000] irq: clearing pending status 00000002 ... ... [ 1.306659] 50000000.serial: ttySAC0 at MMIO 0x50000000 (irq = 32, base_baud = 0) is a S3C2440 [ 2.156124] console [ttySAC0] enabled [ 2.162327] KGDB: Registered I/O driver kgdboc [ 2.163879] KGDB: Waiting for connection from remote gdb...
可以看到此时kernel已经进入等待gdb连接模式, 由于我是用的是ckermit,所以此时需要先退出ckermit,否则下面的gdb将无法打开串口。
在PC上执行如下的命令:
$arm-linux-gdb vmlinux GNU gdb (Sourcery CodeBench Lite 2014.05-29) 7.7.50.20140217-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://sourcery.mentor.com/GNUToolchain/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from vmlinux...done. (gdb) set serial baud 115200 // 设置串口的波特率 (gdb) target remote /dev/ttyUSB0 // 连接板子 Remote debugging using /dev/ttyUSB0 arch_kgdb_breakpoint () at kernel/debug/debug_core.c:1070 1070 wmb(); /* Sync point before breakpoint */ (gdb) l 1065 * the debugger. 1066 */ 1067 noinline void kgdb_breakpoint(void) 1068 { 1069 atomic_inc(&kgdb_setting_breakpoint); 1070 wmb(); /* Sync point before breakpoint */ 1071 arch_kgdb_breakpoint(); 1072 wmb(); /* Sync point after breakpoint */ 1073 atomic_dec(&kgdb_setting_breakpoint); 1074 } (gdb) b __irq_svc // 在__irq_svc处设置断点 Breakpoint 1 at 0xc000e8ac: file arch/arm/kernel/entry-armv.S, line 220. (gdb) c //继续运行, 此时系统会在__irq_svc断点处停止 Continuing. Breakpoint 1, __irq_svc () at arch/arm/kernel/entry-armv.S:220 220 irq_handler (gdb) l //列出代码上下文 215 216 .align 5 217 __irq_svc: 218 svc_entry 219 bt_demo: 220 irq_handler 221 222 #ifdef CONFIG_PREEMPT 223 ldr r8, [tsk, #TI_PREEMPT] @ get preempt count 224 ldr r0, [tsk, #TI_FLAGS] @ get flags (gdb) info all-registers //打印当前的寄存器信息 r0 0x51 81 r1 0xbf000000 3204448256 r2 0xc3433ee8 3275964136 r3 0xc006967c 3221657212 r4 0xc00687f8 3221653496 r5 0x60000013 1610612755 r6 0xffffffff 4294967295 r7 0xc3433ecc 3275964108 r8 0xc06df520 3228431648 r9 0xc3432000 3275956224 r10 0xc0695830 3228129328 r11 0xb0 176 r12 0x60000013 1610612755 sp 0xc3433e98 0xc3433e98 lr 0xc006967c 3221657212 pc 0xc000e8ac 0xc000e8ac <__irq_svc+76> f0 0 (raw 0x000000000000000000000000) f1 0 (raw 0x000000000000000000000000) f2 0 (raw 0x000000000000000000000000) f3 0 (raw 0x0807463a08f2689800000000) f4 0 (raw 0x000000000000000000000000) f5 0 (raw 0x000000000000000000000000) f6 0 (raw 0x000000000000000000000000) f7 0 (raw 0x000000000000000000000000) fps 0x0 0 cpsr 0x60000093 1610612883 (gdb) x/16xw 0xc3433e98 /*将sp栈中的内容打印出来*/ 0xc3433e98: 0x0000002f 0x00000001 0x60000013 0xc0707338 0xc3433ea8: 0x00000000 0xc3679900 0xc0687e40 0x00000000 0xc3433eb8: 0xc06df520 0xc0637d40 0xc0695830 0x000000b0 0xc3433ec8: 0x60000013 0xc3433ee8 0xc006967c 0xc00687f8 (gdb) 0xc3433ed8: 0x60000013 0xffffffff 0x00000053 0x00000000 0xc3433ee8: 0xc06c24c0 0xc02aa38c 0x00000000 0x00000000 0xc3433ef8: 0x00000006 0xc06a1428 0x00000006 0xc0687e58 0xc3433f08: 0x00000000 0xc00098ac 0xc0638b00 0x000000b0 (gdb)
退出的话,执行quit。
方式二:启动起来后,手动触发,使系统进入等待kgdb连接模式
设置uboot的bootargs如下:
setenv bootargs 'noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0,115200 kgdbcon'
然后可以saveenv,最后执行boot命令启动。
此时系统会正常开机:
U-Boot 2015.04-g5095150-dirty (May 25 2017 - 20:13:52) CPUID: 32440001 FCLK: 400 MHz HCLK: 100 MHz PCLK: 50 MHz I2C: ready DRAM: 64 MiB WARNING: Caches not enabled Flash: 0 Bytes NAND: 256 MiB In: serial Out: serial Err: serial Net: dm9000 Hit any key to stop autoboot: 0 TQ2440 # TQ2440 # TQ2440 # TQ2440 # setenv bootargs 'noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0,115200 kgdbcon' TQ2440 # boot dm9000 i/o: 0x20000000, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 00:0c:29:2a:5c:a5 operating at 100M full duplex mode Using dm9000 device TFTP from server 192.168.1.2; our IP address is 192.168.1.8 Filename 'uImage'. Load address: 0x30008000 Loading: T ################################################################# ################################################################# ################################################################# ####################################### 436.5 KiB/s done Bytes transferred = 3432536 (346058 hex) dm9000 i/o: 0x20000000, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 00:0c:29:2a:5c:a5 operating at 100M full duplex mode Using dm9000 device TFTP from server 192.168.1.2; our IP address is 192.168.1.8 Filename 'dtb'. Load address: 0x32000000 Loading: T # 1000 Bytes/s done Bytes transferred = 8437 (20f5 hex) ## Booting kernel from Legacy Image at 30008000 ... Image Name: Linux-4.10.17+ Created: 2017-08-27 12:49:14 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3432472 Bytes = 3.3 MiB Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 32000000 Booting using the fdt blob at 0x32000000 Loading Kernel Image ... OK Loading Device Tree to 33aa7000, end 33aac0f4 ... OK Starting kernel ... Uncompressing Linux... done, booting the kernel. [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.10.17+ (pengdonglin@pengdonglin-dell) (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29) ) #40 Sun Aug 27 20:49:04 CST 2017 [ 0.000000] CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c000717f [ 0.000000] CPU: VIVT data cache, VIVT instruction cache [ 0.000000] OF: fdt:Machine model: TQ2440 [ 0.000000] Memory policy: Data cache writeback [ 0.000000] DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256 [ 0.000000] Kernel command line: noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0,115200 kgdbcon [ 0.000000] PID hash table entries: 256 (order: -2, 1024 bytes) [ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) [ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) [ 0.000000] Memory: 57572K/65536K available (4923K kernel code, 245K rwdata, 1412K rodata, 208K init, 278K bss, 7964K reserved, 0K cma-reserved) [ 0.000000] Virtual kernel memory layout: [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB) [ 0.000000] vmalloc : 0xc4800000 - 0xff800000 ( 944 MB) [ 0.000000] lowmem : 0xc0000000 - 0xc4000000 ( 64 MB) [ 0.000000] modules : 0xbf000000 - 0xc0000000 ( 16 MB) [ 0.000000] .text : 0xc0008000 - 0xc04d7138 (4925 kB) [ 0.000000] .init : 0xc066e000 - 0xc06a2000 ( 208 kB) [ 0.000000] .data : 0xc06a2000 - 0xc06df520 ( 246 kB) [ 0.000000] .bss : 0xc06df520 - 0xc0725060 ( 279 kB) [ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [ 0.000000] NR_IRQS:103 [ 0.000000] irq: clearing pending status 00000003 ... ... [ 2.822615] uda134x-codec uda134x-codec: uda134x_codec_probe enter. [ 2.823450] uda134x-codec uda134x-codec: uda134x_parse_dt parse successfully. [ 2.836250] s3c24xx_i2s_component_probe enter [ 2.836801] uda134x_soc_probe enter: UDA134X SoC Audio Codec [ 2.910656] s3c24xx_snd_rxctrl enter [ 2.910994] s3c24xx_i2s_set_fmt enter [ 2.922893] s3c24xx_uda134x s3c24xx_uda134x: uda134x-hifi <-> s3c2440-i2s mapping ok [ 2.941382] NET: Registered protocol family 17 [ 2.942137] Key type dns_resolver registered [ 2.968854] s3c-rtc 57000000.rtc: setting system clock to 2000-01-06 21:09:02 UTC (947192942) [ 2.973149] ALSA device list: [ 2.974745] #0: S3C24XX_UDA134X [ 3.182558] jffs2: Empty flash at 0x025024bc ends at 0x02502800 [ 3.346774] jffs2: Empty flash at 0x02a552bc ends at 0x02a55800 [ 3.411970] jffs2: Empty flash at 0x0317390c ends at 0x03174000 [ 3.592276] jffs2: Empty flash at 0x056b40f0 ends at 0x056b4800 [ 17.600541] VFS: Mounted root (jffs2 filesystem) on device 31:5. [ 17.602919] Freeing unused kernel memory: 208K [ 17.605387] This architecture does not have kernel memory protection. [ 22.112164] dm9000 20000000.ethernet eth0: link down Please press Enter to activate this console. [ 24.340189] dm9000 20000000.ethernet eth0: link up, 100Mbps, full-duplex, lpa 0x4DE1 Set Env for Tslib [root@tq2440 ]#
然后在板子上执行如下命令:
[root@tq2440 ]# echo g > /proc/sysrq-trigger [ 85.019192] sysrq: SysRq : DEBUG [ 85.019436] KGDB: Entering KGDB
可以看到此时系统进入了KGDB模式,等待远程GDB连接.
接下来关闭ckermit,并在PC上执行跟上面一样的命令:
$arm-linux-gdb vmlinux GNU gdb (Sourcery CodeBench Lite 2014.05-29) 7.7.50.20140217-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://sourcery.mentor.com/GNUToolchain/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from vmlinux...done. (gdb) set serial baud 115200 (gdb) target remote /dev/ttyUSB0 Remote debugging using /dev/ttyUSB0 arch_kgdb_breakpoint () at kernel/debug/debug_core.c:1070 1070 wmb(); /* Sync point before breakpoint */ (gdb) b __irq_svc Breakpoint 1 at 0xc000e8ac: file arch/arm/kernel/entry-armv.S, line 220. (gdb) c Continuing. Breakpoint 1, __irq_svc () at arch/arm/kernel/entry-armv.S:220 220 irq_handler (gdb) l 215 216 .align 5 217 __irq_svc: 218 svc_entry 219 bt_demo: 220 irq_handler 221 222 #ifdef CONFIG_PREEMPT 223 ldr r8, [tsk, #TI_PREEMPT] @ get preempt count 224 ldr r0, [tsk, #TI_FLAGS] @ get flags (gdb) info all-registers r0 0x51 81 r1 0xbf000000 3204448256 r2 0xc2dd3eb8 3269279416 r3 0xc0068894 3221653652 r4 0xc00687f8 3221653496 r5 0x60000013 1610612755 r6 0xffffffff 4294967295 r7 0xc2dd3e9c 3269279388 r8 0x2 2 r9 0xc2dd2000 3269271552 r10 0x0 0 r11 0x1166284 18244228 r12 0x60000013 1610612755 sp 0xc2dd3e68 0xc2dd3e68 lr 0xc0068894 3221653652 pc 0xc000e8ac 0xc000e8ac <__irq_svc+76> f0 0 (raw 0x000000000000000000000000) f1 0 (raw 0x000000000000000000000000) f2 0 (raw 0x000000000000000000000000) f3 0 (raw 0x0807463a099d92c000000000) f4 0 (raw 0x000000000000000000000000) f5 0 (raw 0x000000000000000000000000) f6 0 (raw 0x000000000000000000000000) f7 0 (raw 0x000000000000000000000000) fps 0x0 0 cpsr 0x60000093 1610612883 (gdb) x/16xw 0xc2dd3e68 0xc2dd3e68: 0x00000013 0x00000001 0x60000013 0xc0707338 0xc2dd3e78: 0xc06b6518 0x00000067 0x00000000 0x00000007 0xc2dd3e88: 0x00000002 0x01167788 0x00000000 0x01166284 0xc2dd3e98: 0x60000013 0xc2dd3eb8 0xc0068894 0xc00687f8 (gdb) 0xc2dd3ea8: 0x60000013 0xffffffff 0x00000051 0xbf000000 0xc2dd3eb8: 0xc06af650 0xc029515c 0x00000051 0x00000002 0xc2dd3ec8: 0x00000000 0xa0000013 0x00000001 0x00000002 0xc2dd3ed8: 0x01167788 0xc0295664 0xc34cca80 0xc0103a64
退出的话,在gdb里执行quit命令,再次打开ckermit还可以连上板子,并且还可以再次通过echo使kernel再次进入等待远程gdb连接模式。
三、Qemu + GDB
这部分参考的是笨叔叔的《奔跑吧 Linux内核》。
首先需要配置内核,确保编译出来的内核包含调试信息:
Kernel hacking ----> Compile-time checks and compiler options ----> [*] Compile the kernel with debug info
在启动Qemu的时候设置两个参数:
-S: 表示Qemu虚拟机会冻结CPU,知道远程的GDB输入相应的控制命令
-s: 表示在1234端口接受GDB的调试连接
下面是启动Qemu的命令:
sudo qemu-system-arm \ -M vexpress-a9 \ -m 1024M \ -smp 1 \ -kernel ./linux-4.10/out_aarch32/arch/arm/boot/zImage \ -append "root=/dev/mmcblk0p1 rw rootfstype=ext4 console=ttyAMA0 init=/linuxrc ignore_loglevel firmware_class.path=/etc/firmware" \ -sd ./rootfs/fs_vexpress_1G.img \ -dtb ./linux-4.10/out_aarch32/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \ -net nic,vlan=3 -net tap,vlan=3,ifname=tap3 \ -nographic \ -S -s
然后Qemu会等待远程gdb连接,此时我们在另一个窗口中执行下面的命令:
$arm-none-linux-gnueabi-gdb ./out_aarch32/vmlinux GNU gdb (Sourcery CodeBench Lite 2014.05-29) 7.7.50.20140217-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://sourcery.mentor.com/GNUToolchain/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ./out_aarch32/vmlinux...done. (gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x60000000 in ?? () (gdb) b start_kernel Breakpoint 1 at 0x809009b0: file ../init/main.c, line 483. (gdb) c Continuing. Breakpoint 1, start_kernel () at ../init/main.c:483 483 { (gdb) l 478 vmalloc_init(); 479 ioremap_huge_init(); 480 } 481 482 asmlinkage __visible void __init start_kernel(void) 483 { 484 char *command_line; 485 char *after_dashes; 486 487 set_task_stack_end_magic(&init_task);
完。
本文来自博客园,作者:dolinux,未经同意,禁止转载