作者

彭东林
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 at 0x809009b0: file ../init/main.c, line . (gdb) br __irq_svc
Breakpoint at 0x806e8e60: file ../arch/arm/kernel/entry-armv.S, line . (gdb) br gic_handle_irq
Breakpoint at 0x801014f4: file ../drivers/irqchip/irq-gic.c, line . (gdb) info br
Num Type Disp Enb Address What
breakpoint keep y 0x809009b0 in start_kernel at ../init/main.c:
breakpoint keep y 0x806e8e60 ../arch/arm/kernel/entry-armv.S:
breakpoint keep y 0x801014f4 in gic_handle_irq at ../drivers/irqchip/irq-gic.c: (gdb) delete br
(gdb) info br
Num Type Disp Enb Address What
breakpoint keep y 0x809009b0 in start_kernel at ../init/main.c:
breakpoint keep y 0x806e8e60 ../arch/arm/kernel/entry-armv.S: (gdb) delete br // 删除所有断点
Delete all breakpoints? (y or n) y
(gdb) info br
No breakpoints or watchpoints.
(gdb)
 
3、查看调用栈

(gdb) bt
# ftrace_traceoff (ip=, parent_ip=, data=0x80a01f48 <init_thread_union+>) at ../kernel/trace/trace_functions.c:
# 0x80109a18 in arch_cpu_idle () at ../arch/arm/kernel/process.c:
# 0x806dbd54 in p9_write_work (work=0x80a043b0 <tracer_enabled>) at ../net/9p/trans_fd.c:
# 0x8016575c in __list_del (next=<optimized out>, prev=<optimized out>) at ../include/linux/list.h:
# __list_del_entry (entry=<optimized out>) at ../include/linux/list.h:
# list_del_init (entry=<optimized out>) at ../include/linux/list.h:
# __finish_swait (q=<optimized out>, wait=0x0) at ../kernel/sched/swait.c:
# 0x80165abc in current_thread_info () at ../arch/arm/include/asm/thread_info.h:
# need_resched () at ../include/linux/sched.h:
# do_idle () at ../kernel/sched/idle.c:
# 0x806d56f8 in svc_seq_show (seq=0x80a01f94 <init_thread_union+>, statp=<optimized out>) at ../net/sunrpc/stats.c:
# 0x80900d64 in start_kernel () at ../init/main.c:
# 0x6000807c in ?? ()
Backtrace stopped: frame did not save the PC
 
4、查看寄存器的值
  • info registers (除了浮点寄存器)

(gdb) info registers
r0 0x80a043b0 -
r1 0x0
r2 0x80a01f48 -
r3 0x8011b8c0 -
r4 0x0
r5 0x80a03cd0 -
r6 0x80a03c6c -
r7 0x8097f5d8 -
r8 0x80a03cd8 -
r9 0x80a1cace -
r10 0x0
r11 0x80a01f44 -
r12 0x80a01f38 -
sp 0x80a01f38 0x80a01f38 <init_thread_union+>
lr 0x80109a18 -
pc 0x801d0ae4 0x801d0ae4 <ftrace_traceoff>
cpsr 0x60000093
  • info registers 寄存器名称   (查看指定的寄存器的值)

(gdb) info registers cpsr
cpsr 0x60000093
(gdb) info registers pc
pc 0x801d0ae4 0x801d0ae4 <ftrace_traceoff>
(gdb) info registers r0
r0 0x80a043b0 -
(gdb) info registers r0 r1
r0 0x80a043b0 -
r1 0x0
  • print/x $寄存器名   (查看指定的寄存器)
(gdb) print/x $r0
$ = 0x80a043b0
(gdb) print/x $pc
$ = 0x801d0ae4
(gdb) print/x $cpsr
$ = 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 -
r1 0x0
r2 0x80a01f48 -
r3 0x8011b8c0 -
r4 0x0
r5 0x80a03cd0 -
r6 0x80a03c6c -
r7 0x8097f5d8 -
r8 0x80a03cd8 -
r9 0x80a1cace -
r10 0x0
r11 0x80a01f44 -
r12 0x80a01f38 -
sp 0x80a01f38 0x80a01f38 <init_thread_union+>
lr 0x80109a18 -
pc 0x801d0ae4 0x801d0ae4 <ftrace_traceoff>
cpsr 0x60000093
(gdb) x/16xw 0x801d0ae4
0x801d0ae4 <ftrace_traceoff>: 0xe92dd8f0 0xe24cb004 0xe24dd008 0xe30403b0
0x801d0af4 <ftrace_traceoff+>: 0xe34800a0 0xe1a0400e 0xe590305c 0xe3130002
0x801d0b04 <update_traceon_count>: 0x0a000011 0xe10f3000 0xe3130080 0x0a00000e
0x801d0b14 <update_traceon_count+>: 0xe1a0200d 0xe3c23d7f 0xe3c3303f 0xe304572c
(gdb) x/16xw 0x80a01f38
0x80a01f38 <init_thread_union+>: 0x80a01f54 0x80a01f48 0x806dbd54 0x801099f4
0x80a01f48 <init_thread_union+>: 0x80a01f84 0x80a01f58 0x8016575c 0x806dbd2c
0x80a01f58 <init_thread_union+>: 0x80702db8 0x000000bb 0x80a74000 0xffffffff
0x80a01f68 <init_thread_union+>: 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   - ::)

CPUID:
FCLK: MHz
HCLK: MHz
PCLK: MHz
I2C: ready
DRAM: MiB
WARNING: Caches not enabled
Flash: Bytes
NAND: MiB
In: serial
Out: serial
Err: serial
Net: dm9000
Hit any key to stop autoboot:
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 bit mode
MAC: :0c::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 = ( hex)
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in bit mode
MAC: :0c::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 #
Bytes/s
done
Bytes transferred = (20f5 hex)
## Booting kernel from Legacy Image at ...
Image Name: Linux-4.10.+
Created: -- :: UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: Bytes = 3.3 MiB
Load Address:
Entry Point:
Verifying Checksum ... OK
## Flattened Device Tree blob at
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.+ (pengdonglin@pengdonglin-dell) (gcc version 4.8. (prerelease) (Sourcery CodeBench Lite 2014.05-) ) # Sun Aug :: CST
[ 0.000000] CPU: ARM920T [] revision (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[:], fall back to default cpu_logical_map
[ 0.000000] Built zonelists in Zone order, mobility grouping on. Total pages:
[ 0.000000] Kernel command line: noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0, kgdbwait
[ 0.000000] PID hash table entries: (order: -, bytes)
[ 0.000000] Dentry cache hash table entries: (order: , bytes)
[ 0.000000] Inode-cache hash table entries: (order: , 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 ( kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 ( kB)
[ 0.000000] vmalloc : 0xc4800000 - 0xff800000 ( MB)
[ 0.000000] lowmem : 0xc0000000 - 0xc4000000 ( MB)
[ 0.000000] modules : 0xbf000000 - 0xc0000000 ( MB)
[ 0.000000] .text : 0xc0008000 - 0xc04d7138 ( kB)
[ 0.000000] .init : 0xc066e000 - 0xc06a2000 ( kB)
[ 0.000000] .data : 0xc06a2000 - 0xc06df520 ( kB)
[ 0.000000] .bss : 0xc06df520 - 0xc0725060 ( kB)
[ 0.000000] SLUB: HWalign=, Order=-, MinObjects=, CPUs=, Nodes=
[ 0.000000] NR_IRQS:
[ 0.000000] irq: clearing pending status
[ 0.000000] irq: clearing pending status
... ...
[ 1.306659] .serial: ttySAC0 at MMIO 0x50000000 (irq = , base_baud = ) 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-) 7.7.50.20140217-cvs
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 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 // 设置串口的波特率
(gdb) target remote /dev/ttyUSB0 // 连接板子
Remote debugging using /dev/ttyUSB0
arch_kgdb_breakpoint () at kernel/debug/debug_core.c:
wmb(); /* Sync point before breakpoint */
(gdb) l
* the debugger.
*/
noinline void kgdb_breakpoint(void)
{
atomic_inc(&kgdb_setting_breakpoint);
wmb(); /* Sync point before breakpoint */
arch_kgdb_breakpoint();
wmb(); /* Sync point after breakpoint */
atomic_dec(&kgdb_setting_breakpoint);
}
(gdb) b __irq_svc // 在__irq_svc处设置断点
Breakpoint at 0xc000e8ac: file arch/arm/kernel/entry-armv.S, line .
(gdb) c //继续运行, 此时系统会在__irq_svc断点处停止
Continuing. Breakpoint , __irq_svc () at arch/arm/kernel/entry-armv.S:
irq_handler
(gdb) l //列出代码上下文 .align
__irq_svc:
svc_entry
bt_demo:
irq_handler #ifdef CONFIG_PREEMPT
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
ldr r0, [tsk, #TI_FLAGS] @ get flags
(gdb) info all-registers //打印当前的寄存器信息
r0 0x51
r1 0xbf000000
r2 0xc3433ee8
r3 0xc006967c
r4 0xc00687f8
r5 0x60000013
r6 0xffffffff
r7 0xc3433ecc
r8 0xc06df520
r9 0xc3432000
r10 0xc0695830
r11 0xb0
r12 0x60000013
sp 0xc3433e98 0xc3433e98
lr 0xc006967c
pc 0xc000e8ac 0xc000e8ac <__irq_svc+>
f0 (raw 0x000000000000000000000000)
f1 (raw 0x000000000000000000000000)
f2 (raw 0x000000000000000000000000)
f3 (raw 0x0807463a08f2689800000000)
f4 (raw 0x000000000000000000000000)
f5 (raw 0x000000000000000000000000)
f6 (raw 0x000000000000000000000000)
f7 (raw 0x000000000000000000000000)
fps 0x0
cpsr 0x60000093
(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   - ::)

CPUID:
FCLK: MHz
HCLK: MHz
PCLK: MHz
I2C: ready
DRAM: MiB
WARNING: Caches not enabled
Flash: Bytes
NAND: MiB
In: serial
Out: serial
Err: serial
Net: dm9000
Hit any key to stop autoboot:
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 bit mode
MAC: :0c::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 = ( hex)
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in bit mode
MAC: :0c::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 #
Bytes/s
done
Bytes transferred = (20f5 hex)
## Booting kernel from Legacy Image at ...
Image Name: Linux-4.10.+
Created: -- :: UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: Bytes = 3.3 MiB
Load Address:
Entry Point:
Verifying Checksum ... OK
## Flattened Device Tree blob at
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.+ (pengdonglin@pengdonglin-dell) (gcc version 4.8. (prerelease) (Sourcery CodeBench Lite 2014.05-) ) # Sun Aug :: CST
[ 0.000000] CPU: ARM920T [] revision (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[:], fall back to default cpu_logical_map
[ 0.000000] Built zonelists in Zone order, mobility grouping on. Total pages:
[ 0.000000] Kernel command line: noinitrd root=/dev/mtdblock5 rw rootfstype=jffs2 console=ttySAC0,115200n8 kgdboc=ttySAC0, kgdbcon
[ 0.000000] PID hash table entries: (order: -, bytes)
[ 0.000000] Dentry cache hash table entries: (order: , bytes)
[ 0.000000] Inode-cache hash table entries: (order: , 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 ( kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 ( kB)
[ 0.000000] vmalloc : 0xc4800000 - 0xff800000 ( MB)
[ 0.000000] lowmem : 0xc0000000 - 0xc4000000 ( MB)
[ 0.000000] modules : 0xbf000000 - 0xc0000000 ( MB)
[ 0.000000] .text : 0xc0008000 - 0xc04d7138 ( kB)
[ 0.000000] .init : 0xc066e000 - 0xc06a2000 ( kB)
[ 0.000000] .data : 0xc06a2000 - 0xc06df520 ( kB)
[ 0.000000] .bss : 0xc06df520 - 0xc0725060 ( kB)
[ 0.000000] SLUB: HWalign=, Order=-, MinObjects=, CPUs=, Nodes=
[ 0.000000] NR_IRQS:
[ 0.000000] irq: clearing pending status
... ...
[ 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
[ 2.942137] Key type dns_resolver registered
[ 2.968854] s3c-rtc .rtc: setting system clock to -- :: UTC ()
[ 2.973149] ALSA device list:
[ 2.974745] #: 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 :.
[ 17.602919] Freeing unused kernel memory: 208K
[ 17.605387] This architecture does not have kernel memory protection.
[ 22.112164] dm9000 .ethernet eth0: link down Please press Enter to activate this console. [ 24.340189] dm9000 .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-) 7.7.50.20140217-cvs
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 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
(gdb) target remote /dev/ttyUSB0
Remote debugging using /dev/ttyUSB0
arch_kgdb_breakpoint () at kernel/debug/debug_core.c:
wmb(); /* Sync point before breakpoint */
(gdb) b __irq_svc
Breakpoint at 0xc000e8ac: file arch/arm/kernel/entry-armv.S, line .
(gdb) c
Continuing. Breakpoint , __irq_svc () at arch/arm/kernel/entry-armv.S:
irq_handler
(gdb) l .align
__irq_svc:
svc_entry
bt_demo:
irq_handler #ifdef CONFIG_PREEMPT
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
ldr r0, [tsk, #TI_FLAGS] @ get flags
(gdb) info all-registers
r0 0x51
r1 0xbf000000
r2 0xc2dd3eb8
r3 0xc0068894
r4 0xc00687f8
r5 0x60000013
r6 0xffffffff
r7 0xc2dd3e9c
r8 0x2
r9 0xc2dd2000
r10 0x0
r11 0x1166284
r12 0x60000013
sp 0xc2dd3e68 0xc2dd3e68
lr 0xc0068894
pc 0xc000e8ac 0xc000e8ac <__irq_svc+>
f0 (raw 0x000000000000000000000000)
f1 (raw 0x000000000000000000000000)
f2 (raw 0x000000000000000000000000)
f3 (raw 0x0807463a099d92c000000000)
f4 (raw 0x000000000000000000000000)
f5 (raw 0x000000000000000000000000)
f6 (raw 0x000000000000000000000000)
f7 (raw 0x000000000000000000000000)
fps 0x0
cpsr 0x60000093
(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 \
-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= -net tap,vlan=,ifname=tap3 \
-nographic \
-S -s

然后Qemu会等待远程gdb连接,此时我们在另一个窗口中执行下面的命令:


$arm-none-linux-gnueabi-gdb ./out_aarch32/vmlinux
GNU gdb (Sourcery CodeBench Lite 2014.05-) 7.7.50.20140217-cvs
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 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:
Remote debugging using localhost:
0x60000000 in ?? ()
(gdb) b start_kernel
Breakpoint at 0x809009b0: file ../init/main.c, line .
(gdb) c
Continuing. Breakpoint , start_kernel () at ../init/main.c:
{
(gdb) l
vmalloc_init();
ioremap_huge_init();
} asmlinkage __visible void __init start_kernel(void)
{
char *command_line;
char *after_dashes; set_task_stack_end_magic(&init_task);

完。

 
 
 
 

最新文章

  1. 「标准」的 JS风格
  2. Module Zero之用户管理
  3. Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析
  4. 32、shiro 框架入门三
  5. C#委托Action、Action&lt;T&gt;、Func&lt;T&gt;、Predicate&lt;T&gt;
  6. 将定时任务cron 解析成中文
  7. 数组有没有length()这个方法? String有没有length()这个方法?
  8. ubuntu 折腾之路
  9. w​i​n​d​o​w​s​7​旗​舰​版​I​I​S​6​配​置​-​保​证​能​发​布
  10. tmux environment keep
  11. &lt;Win32_12&gt;程序员求爱的创意程序——升级版^_^
  12. hdu 2594 Simpsons’ Hidden Talents 【KMP】
  13. .net SoapHeader验证
  14. Yii2自带的验证码背景颜色怎么调?
  15. JavaScript(第三十一天)【JSON】
  16. Android中GridView的一些特殊属性
  17. /var/log各种日志
  18. git 入门教程之版本管理
  19. Transform Model
  20. 使用Jersey上传文件

热门文章

  1. CEO、COO、CFO、CTO、CXO
  2. 在windows上实现多个java jdk的共存解决办法
  3. php递归函数细节
  4. 盒子模型与flex模型
  5. Java ListIterator(迭代器)
  6. ModelAndView学习笔记
  7. linux install weblogic
  8. mysql的完整卸载
  9. JS实现音乐播放器
  10. 005.基于docker部署etcd集群部署