gdb-helper

介绍GDB的使用。

Base command

在看GDB之前,先看下openocd是如何运行的,以及GDB是如何连上openocd的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$ cat cpu.cfg
adapter speed 29000

source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg]

set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME -rtos hwthread

init

halt
echo "Ready for Remote Connections"

$ openocd -f cpu.cfg
Open On-Chip Debugger 0.11.0-rc2+dev-01540-gca49f403e (2021-03-23-22:17)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : Hardware thread awareness created
Info : ftdi: if you experience problems at higher adapter clocks, try the command "ftdi_tdo_sample_edge falling"
Info : clock speed 29000 kHz
Info : JTAG tap: riscv.cpu tap/device found: 0x00000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x0)
Info : datacount=4 progbufsize=16
Info : Disabling abstract command reads from CSRs.
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=64, misa=0x80000000001431af
Info : starting gdb server for riscv.cpu on 3333
Info : Listening on port 3333 for gdb connections
Ready for Remote Connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

$ riscv64-unknown-elf-gdb
GNU gdb (SiFive GDB 8.3.0-2020.04.0) 8.3
......
(gdb) target extended-remote localhost:3333
(gdb) file elf
(gdb) load
(gdb) compare-sections

remote connection

1
2
# 使用local socket连接target
(gdb) target extended-remote localhost:3333

file

1
2
# 导入可执行文件
(gdb) file /home/francis/xx.elf

load

1
2
# 下载文件
(gdb) load

run

默认情况下,run 指令会一直执行程序,直到执行结束。如果程序中手动设置有断点,则 run 指令会执行程序至第一个断点处。

1
2
3
4
# 开始运行
(gdb) run
# 也可以缩写
(gdb) r

start

start 指令会执行程序至 main() 主函数的起始位置,即在 main() 函数的第一行语句处停止执行(该行代码尚未执行)。

1
(gdb) start

starti

starti是在main函数的第一条指令处设置断点,再执行run。也就是停在main函数的第一条指令处停止执行。

1
(gdb) starti

continue

1
2
3
(gdb) continue
# 也可以用缩写
(gdb) c

step

1
2
# 执行一步
(gdb) step

stepi

1
2
3
4
# 执行一条指令
(gdb) stepi
# 缩写
(gdb) si

next

1
(gdb) next

nexti

1
(gdb) nexti

上面这几个有什么区别?

Breakpoint/Watchpoint

break

1
2
3
4
5
6
# 软件断点
(gdb) break main
# 或者使用缩写
(gdb) b main
# 在某个程序地址上打断点
(gdb) b *0x400522

hbreak

1
2
3
4
5
6
# 硬件断点
(gdb) hbreak main
# 或者使用缩写
(gdb) hb main
# 在程序某个地址上打断点
(gdb) hbreak *0xffffffe0006037e2

info break

1
2
# 打印breakpoint信息
(gdb) info break

delete breakpoint

1
(gdb) delete breakpoints 1

disable breakpoint

1
(gdb)

watchpoint

1
(gdb) watch *(unsigned int*)0x816c9c00

display

display pc

1
2
# 打印当前pc
(gdb) display/i $pc

print

1
2
# 以十六进制打印
(gdb) p/x $pc

打印某个地址的值

1
(gdb) p/x (*(unsigned int *)0x80000000)

修改某个地址的值

1
(gdb) set (*(unsigned int *)0x80000000) = 55

backtrace

1
2
3
(gdb) backtrace
# 缩写
(gdb) bt

Altering Execution

修改变量

1
2
3
4
5
6
7
8
(gdb) print x=4
(gdb) whatis width
type = double
(gdb) p width
$4 = 13
(gdb) set width=47
Invalid syntax in expression
(gdb) set var width = 4

从指定位置开始执行

1
2
(gdb) j location
(gdb) set $pc = 0x80000000

Multiple thread

info thread

1
2
3
4
# 显示thread信息
(gdb) info threads
Id Target Id Frame
* 1 Thread 1 (Name: riscv.cpu, state: debug-request) 0x00000000810000b8 in ?? ()

切换线程

1
(gdb) thread 2

RISCV command

复位

1
(gdb) monitor reset halt

修改一片内存

1
(gdb) monitor mwd 0x80000000 0 0x10000

mwd: write doubleword (64bits)

mww: write word (32bits)

mwh: write half word (16bits)

mwb: write byte (8bits)

1
mwd [phys] addr doubleword [count]

debug single core image

1
2
3
4
5
6
7
$ openocd -f ebc.cfg
$ riscv64-unknown-elf-gdb dhrystone.elf
(gdb) target extended-remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) info threads
(gdb) j _enter

debug multi-core image

1
2
3
4
5
6
7
8
9
$ openocd -f ebc-2-hwthread.cfg
$ riscv64-unknown-elf-gdb dhrystone.elf
(gdb) target extended-remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) info threads
(gdb) thread 2
(gdb) set $pc=0x80000000
(gdb) j _enter