KGDB调试汇总

KGDB调试汇总

通过KGDB,可以在内核代码中设置断点,单步调试和观察变量;为了使用KGDB,需要有两个系统,一个称为开发机,一个称为目标机,被调试的内核运行于目标机上,同时开发机与目标机不要求有相关的体系结构,两者通过串口连接。

目的:在某嵌入式设备中使用kgdb对内核的调试

gdb+gdbserver用来调试用户程序

gdb+kgdb用来调试内核

如何共用串口

1)在PC机安装Cgwin,通过读写/dev/ttyS0即可与某嵌入式设备共用同一个串口,此时需要将secureCRT的连接断开;

2)在PC机上安装虚拟机,如virtual box上将串口设置成host device,即可与主机共享串口,连接的时候亦需要将secureCRT的连接断开。

在一端输入cat /dev/ttyS0,在另一端echo “字符串”>/dev/ttyS0,如何cat中显示此字符串,表明串口通信成功。

内核选项

-->打开-g选项

-->打开kgdb选项

在cgwin中编译gdb

$ tar -zxvf gdb-7.6.tar.gz

$./configure--target=mips-linux--prefix=/home/lym/bin

$make

$make install

编译成功后如下:

在目标机上动态启动KGDB

1)通过输入echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc注册通过ttyS0进行数据传输;

2)输入echo g > /proc/sysrq-trigger动态启动KGDB。

在开发机上远程连接目标机

1)输入set remotebaud 115200设置对端波特率为115200;

2)输入target remote /dev/ttyS0通过串口连接到对端。

通过设置set debug remote 1,可以查看发送和接收的报文。

问题1

Bogus trace status replay from target:E22

 

解释:由于kgdb不支持qTStatus命令而返回E22错误信息,修改kgdb代码,此时返回空包即可,修改如下:(/kernel-2.6.32-longterm/kernel/kgdb.c)

 

 

 

 

 

问题2

Remote 'g' packet reply is too long

 

解释:修改gdb接收报文处理方式,如下:(gdb-7.6/gdb/remote.c)

 

 

 

 

 

 

 

 

 

 

 

附录一

GDB与远程目标之间通过串行协议来进行通信,其为基于ASCII,以gdb发送命令,目标端返回执行结果的方式来进行,命令和回复在传输过程中封装在一个packet中,每个packet以$开始,接着是实际数据,数据以#结束,后面再接用于校验的数据。

GDB通过set remotelogfile [filepath]指定log路径,此文件需要再开始记录前手工创建。

 

KGDB实现的基本命令:

‘g’

格式:$g#67

描述:gdb向目标端发送这个命令来获取目标机当前寄存器的值

回复:+ $123456789abcdef0...#xx

'+'用来应答'g'这个命令,表明目标端正确地收到这个命令,然后就是目标端的回复包,gdb规定用8十六进制个数字来表示一个寄存器的值,所以第一个寄存器的值为12345678,第二个为9abcdef0,依此类推,而具体每个寄存器的含义和寄存器个数又体系结构决定,定义在gdb的代码中. 当然这里8个数字是对32位系统来说的,为什么是8位?限于我们这个协议是基于ASCII的,一个十六进制数只能标记4位,那32位自然是8个十六进制数了。

 

‘G’

格式:$GXXXXXXXXXXX...#xx

描述:和g相反,这个命令用来设置目标机当前寄存器的值

回复:+ $OK#9a (OK表示成功)

 

‘m’

格式:$m6a1bbb,2#b9

描述:读取一段内存的值,这里是读取以6a1bbb位起始地址的两个字节

回复:+ $f488#0a 目标端把值返回.

 

‘M’

格式:$Mccc5cc,2:a340#01

描述:设置一段内存的值,这里是把以ccc5cc位开始地址的两个字节设成a340

回复:+ $OK#9a

 

‘s’

格式:$sADDR#xx

描述:用户进行单步调试时用到,ADDR指明了程序将从那个地址恢复运行,如果忽略ADDR,程序就从断点处继续运行

回复:+ 目标端会马上返回数据正确或错误接收,但不会马上返回信息,具体信息要到下一次断点被触发时才会返回

 

‘c’

格式:$cADDR#xx

描述:让程序恢复正常运行

回复:和‘s’一样

 

‘Z’

格式:$ZTADDR,LENGTH#xx

描述:'Z'命令用来设置断点或watch点,用过gdb的同志应该不会陌生了 
'T'字段定义了这个命令的对象,0:软件断点,1:硬件断点,2:写watch点,3:读watch点,4:访问watch点. 
'ADDR'就是我们所关心的内存地址,'LENGTH',对于软件中断它指明被断点指令覆盖的内存长度,kgdb对于软件断点忽略掉它,因为触发 kgdb的指令与体系结构相关,已经定义在kgdb这边,就如x86的int3在内存里面的二进制指令为"0xcc";对于硬件断点和watch 点,'LENGTH'指明gdb关注的内存长度. 

 

‘z’

格式:$zTADDR,LENGTH#xx

描述:各项与'Z'相同.用来取消断点。

 

回复类型:

错误回复

格式:+ $E01#a6 

描述::如果目标端在执行gdb的命令时出错时返回错误回复,比如访问内存时出错.E后面根两位的错误码,错误码在gdb里面没有定义

 

空回复

格式:+ $#00 

描述:当目标端不认识gdb发来的命令时,返回空回复表示自己不支持这个命令

 

‘S’

格式:$SAA#b8

作用:AA表明触发这次通信的那个异常相关的信号,这个信号就是posix标准中的信号

 

 

 

 

‘T’

格式:$TAAN..:R..;N..:R..#xx

作用:AA同样是信号号, N..:R.. 这表明一个寄存器和它的值,N标记寄存器号,R是它对应的值,其中,如果N不是一个16进制数而是"thread",那么后面R的值就指明当前的进程号. 如果是其它的字符串gdb会省略

 

附录二

gdb常用指令

 

r

run

运行.程序还没有运行前使用

c            

cuntinue  

运行到下一断点处

q

quit                       

退出

tab

tab

命令补全功能

h   

help

帮助

s

step

跟入函数

n

next

执行下一行的代码。如果是函数调用,也当作一行代码,执行到此函数返回

b   

breakpoint

设置断点,用法:(1)b 函数名 (2)b 文件名:行号

info b

info breakpoints

查看断点数

del

delete

删除断点:delete 断点号

list

列出代码行。一次列10 行。 也可在 list 后面跟上 文件名:行号

watch

watch

观察一个变量的值。每次中断时都会显示这个变量的值

what

what

显示变量的类型

p

print

打印一个变量的值。print 也可改变一个值,通过指令 p b = 100,变量b

的值就变成100

start

start

从主函数 main 开始运行调试

fin

finish

运行直至当前函数返回

 

 

 

 

KGDB调试内核:

gdb调试内核类似于调试应用程序进程,kgdb支持gdb的执行控制命令、栈跟踪和线程分析等,但kgdb不支持watchpointkgdb通过gdb宏来执行watchpoint

  1. 停止内核执行

在gdb终端中按下ctrl+c,gdb将发送停止消息给kgdb stub,kgdb stub控制内核的运行,并与gdb通信;

  1. 内核继续运行

在gdb终端中发命令“continue”告诉kgdb stub让内核继续运行,直到遇到一个断点;

  1. 设置断点

设置断点命令如”(gdb)b module.c:2168”

  1. 进入函数代码

使用命令”(gdb)step”进入一个函数,使用命令”(gdb)next”执行下一行

  1. 显示堆栈信息

使用命令”(gdb)bt”

  1. 线程分析

gdb具有分析应用程序线程的特征,允许查看其中的线程,通过与kgdb可以查看内核线程,通过backtrace,info regi等命令可以显示线程上下文信息

  1. Watchpoint

执行断点 当代码在断点地址执行时,触发执行断点。由于硬件断点有限,建议通过gdb break命令使用软件断点,除非可避免修改代码。

写断点 当系统对在断点地址的内存位置进行写操作时,触发一个写断点。写断点可以放置可变长度的数据。写断点的长度指示为观察的数据类型长度,1表示为字节数据,2表示为2字节数据,3表示为4字节数据。

访问断点 当系统读或写断点地址的内存时,触发一个访问断点。访问断点也有可变长度数据类型。

因为gdb stub目前不使用gdb用于硬件断点的协议,因此,它通过gdb宏访问硬件断点。硬件断点的gdb宏说明如下:

1)hwebrk – 放置一个执行断点。

用法:hwebrk breakpointno address

2)hwwbrk – 放置一个写断点。

用法:hwwbrk breakpointno length address

3)hwabrk – 放置一个访问断点。

用法:hwabrk breakpointno length address

4)hwrmbrk – 删除一个断点

用法:hwrmbrk breakpointno

5)exinfo – 告诉是否有一个软件或硬件断点发生。如果硬件断点发生,打印硬件断点的序号。

这些命令要求的参数说明如下:

breakpointno – 0~3

length - 1~3

address - 16进制内存位置(没有0x),如:c015e9bc

 

注1:

telnet远程设置:

Config模式下:

line vty 0 4

no login

privil level 15

 

注2:

修改串口波特率:

stty ispeed 115200 ospeed 115200 -F /dev/ttyS0

 

注3:

有时候gdb会收到非法报文,提示Ignoring  packet error,continue…

修改printk级别,不再向串口输出打印信息

echo 0 > /proc/sysrq-trigger

猜你喜欢

转载自blog.csdn.net/b0207191/article/details/99678406
今日推荐