🍢

RISC-Vのコードをqemuで実行しgdbで観察する

2023/01/31に公開

RISC-VのCPUの実機を持っていなくても、qemuを使えば実行することができるし、gdbでステップ実行することもできます。

RISC-V用のクロスgdbの準備

こちらの記事を見てください。
https://zenn.dev/tetsu_koba/articles/dfff7c29d36b25

サンプルのCのソースコード

この記事のものを使用しました。
https://zenn.dev/tetsu_koba/articles/72f8a5e9e7a156

pi.c
#include <stdio.h>

double AandW(int n)
{
	double pi = 0.0;
	if (n < 32) {
		for (; n >= 0; --n) {
			double n4 = n * 4.0;
			double tmp =
				(2 / (n4 + 1) + 2 / (n4 + 2) +
				 1 / (n4 + 3)) / (1LL << 2 * n);
			pi += n & 1 ? -tmp : tmp;
		}
	}
	return pi;
}

int main()
{
	printf("PI=%.15f\n", AandW(31));
}

コンパイル

$ zig cc -o pi_riscv64 -target riscv64-linux-musl pi.c
$ file pi_riscv64 
pi_riscv64: ELF 64-bit LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), statically linked, with debug_info, not stripped

zig ccでビルドするとデバッグ情報がついてきます。(gcc-gがデフォルトで有効になっている)

qemuで実行しgdbで観察する

qemu-riscv64またはqemu-riscv64-staticで実行。gdb用のポートは1234にした。

$ qemu-riscv64-static -g 1234 ./pi_riscv64 

別の端末からgdbを起動。

$ riscv64-linux-musl-gdb ./pi_riscv64 
GNU gdb (GDB) 12.1
Copyright (C) 2022 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=aarch64-unknown-linux-gnu --target=riscv64-linux-musl".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
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 ./pi_riscv64...

リモートデバッグのセットアップ。

(gdb) target remote :1234
Remote debugging using :1234
0x0000000000011d7c in _start ()
(gdb) b main
Breakpoint 1 at 0x11f70: file pi.c, line 22.
(gdb) c
Continuing.

Breakpoint 1, main () at pi.c:22
22		printf("PI=%.15f\n", AandW(31));

毎回逆アセンブル表示をするように指定。

(gdb) display/i $pc
1: x/i $pc
=> 0x11f70 <main+10>:	auipc	ra,0x0

RISC-Vの命令単位でステップ実行する。

(gdb) si
0x0000000000011dc6	4	{
1: x/i $pc
=> 0x11dc6 <AandW+2>:	sd	ra,104(sp)
(gdb) si
0x0000000000011dc8	4	{
1: x/i $pc
=> 0x11dc8 <AandW+4>:	sd	s0,96(sp)
(gdb) si
0x0000000000011dca	4	{
1: x/i $pc
=> 0x11dca <AandW+6>:	addi	s0,sp,112
(gdb) si
0x0000000000011dcc	4	{
1: x/i $pc
=> 0x11dcc <AandW+8>:	sw	a0,-20(s0)
(gdb) si
0x0000000000011dd0	4	{
1: x/i $pc
=> 0x11dd0 <AandW+12>:	li	a0,0
(gdb) si
5		double pi = 0.0;
1: x/i $pc
=> 0x11dd2 <AandW+14>:	sd	a0,-32(s0)
(gdb) si
6		if (n < 32) {
1: x/i $pc
=> 0x11dd6 <AandW+18>:	lw	a1,-20(s0)
(gdb) si
0x0000000000011dda	6		if (n < 32) {
1: x/i $pc
=> 0x11dda <AandW+22>:	li	a0,31
(gdb) 

レジスタのダンプ。

(gdb) info all-reg
zero           0x0	0
ra             0x11f78	0x11f78 <main+18>
sp             0x4000800440	0x4000800440
gp             0x18010	0x18010
tp             0x18c70	0x18c70 <builtin_tls+200>
t0             0x0	0
t1             0x7	7
t2             0x6474e551	1685382481
fp             0x40008004b0	0x40008004b0
s1             0x1	1
a0             0x0	0
a1             0x1f	31
a2             0x4000800508	274886296840
a3             0x0	0
a4             0xfffffffffffe7390	-101488
a5             0x12174	74100
a6             0x18cf8	101624
a7             0x60	96
s2             0x11f66	73574
s3             0x4000800508	274886296840
s4             0x0	0
s5             0x0	0
s6             0x0	0
s7             0x0	0
s8             0x0	0
s9             0x0	0
s10            0x0	0
s11            0x0	0
t3             0x18a40	100928
t4             0x6	6
t5             0x1	1
t6             0x0	0
pc             0x11dda	0x11dda <AandW+22>
ft0            {float = 0, double = 0}	(raw 0x0000000000000000)
ft1            {float = 0, double = 0}	(raw 0x0000000000000000)
ft2            {float = 0, double = 0}	(raw 0x0000000000000000)
ft3            {float = 0, double = 0}	(raw 0x0000000000000000)
ft4            {float = 0, double = 0}	(raw 0x0000000000000000)
ft5            {float = 0, double = 0}	(raw 0x0000000000000000)
ft6            {float = 0, double = 0}	(raw 0x0000000000000000)
ft7            {float = 0, double = 0}	(raw 0x0000000000000000)
fs0            {float = 0, double = 0}	(raw 0x0000000000000000)
fs1            {float = 0, double = 0}	(raw 0x0000000000000000)
--Type <RET> for more, q to quit, c to continue without paging--c
fa0            {float = 0, double = 0}	(raw 0x0000000000000000)
fa1            {float = 0, double = 0}	(raw 0x0000000000000000)
fa2            {float = 0, double = 0}	(raw 0x0000000000000000)
fa3            {float = 0, double = 0}	(raw 0x0000000000000000)
fa4            {float = 0, double = 0}	(raw 0x0000000000000000)
fa5            {float = 0, double = 0}	(raw 0x0000000000000000)
fa6            {float = 0, double = 0}	(raw 0x0000000000000000)
fa7            {float = 0, double = 0}	(raw 0x0000000000000000)
fs2            {float = 0, double = 0}	(raw 0x0000000000000000)
fs3            {float = 0, double = 0}	(raw 0x0000000000000000)
fs4            {float = 0, double = 0}	(raw 0x0000000000000000)
fs5            {float = 0, double = 0}	(raw 0x0000000000000000)
fs6            {float = 0, double = 0}	(raw 0x0000000000000000)
fs7            {float = 0, double = 0}	(raw 0x0000000000000000)
fs8            {float = 0, double = 0}	(raw 0x0000000000000000)
fs9            {float = 0, double = 0}	(raw 0x0000000000000000)
fs10           {float = 0, double = 0}	(raw 0x0000000000000000)
fs11           {float = 0, double = 0}	(raw 0x0000000000000000)
ft8            {float = 0, double = 0}	(raw 0x0000000000000000)
ft9            {float = 0, double = 0}	(raw 0x0000000000000000)
ft10           {float = 0, double = 0}	(raw 0x0000000000000000)
ft11           {float = 0, double = 0}	(raw 0x0000000000000000)
fflags         0x0	RD:0 NV:0 DZ:0 OF:0 UF:0 NX:0
frm            0x0	FRM:0 [RNE (round to nearest; ties to even)]
fcsr           0x0	RD:0 NV:0 DZ:0 OF:0 UF:0 NX:0 FRM:0 [RNE (round to nearest; ties to even)]
cycle          0x5378ecd49022f	1468461352550959
time           0x5378ecd4cf226	1468461352808998
instret        0x5378ecd4ed135	1468461352931637
priv           0x0	prv:0 [User/Application]
(gdb) 

gdbのドキュメント
https://www.sourceware.org/gdb/documentation/

関連

https://zenn.dev/tetsu_koba/articles/dfff7c29d36b25
https://zenn.dev/tetsu_koba/articles/72f8a5e9e7a156
https://zenn.dev/tetsu_koba/articles/b54e954809a86c
https://zenn.dev/tetsu_koba/articles/6725d8b22cd997
https://zenn.dev/tetsu_koba/articles/0f65daab36d40a

Discussion