基于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 按浮点数格式显示变量
 
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);

完。

posted @ 2017-08-28 17:22  dolinux  阅读(2620)  评论(0编辑  收藏  举报