Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 7910

QEMUに似たRenodeでSTM32をGDBを使ってデバッグする - daisukeの技術ブログ

$
0
0

前回から、Renode という QEMU に似たオープンソースのエミュレータを試してます。

前回は、インストールとSTM32のサンプルソースの実行までをやりました。

今回は、GDB で接続して、デバッグしてみます。

それでは、やっていきます。

参考文献

GDBハンドブック

GDBハンドブック

Amazon

はじめに

「QEMUを動かす」の記事一覧です。良かったら参考にしてください。

QEMUを動かすの記事一覧

まず、Renode の公式サイトは以下です。

https://renode.io/

Renode の公式のドキュメントは以下です。

https://renode.readthedocs.io/en/latest/

また、GitHub は以下です。

https://github.com/renode/renode

今回は、Renode を GDB を使って動かしていきます。

STM32のサンプルソースをデバッグする

それでは、早速、前回の続きで、STM32F4 の Discovery を対象として Renode を起動します。

前回とは異なり、Renode モニターで start はしません。Renode のドキュメントの GDB でデバッグを見ると、Renode は、3種類のエミュレーションの開始方法が用意されていると書かれています。

1つ目は Renode から start で開始する方法で、2つ目は GDB から monitor start で開始する方法で、3つ目は GDB から接続されると自動的に開始する方法です。

今回は、2つ目の GDB から monitor start と入力して開始する方法でやってみたいと思います。

$ ./renode renode-config.resc

別のコンソールを立ち上げて、GDB を起動していきます。

$ arm-none-eabi-gdb renode-example.elf 
(gdb) target remote :3333
reset_handler () at ../../cm3/vector.c:67
67for(src =&_data_loadaddr, dest =&_data;(gdb) c

GDB で接続すると、エントリポイントで停止した状態になりました。c(continue)で実行を開始すると、「hello world!」が出力されました。

GDBから操作できました
GDBから操作できました

ですが、このエミュレーションの開始は、ドキュメントに書かれている、3つ目の方法のような挙動です。

renode-config.resc ファイルには、以下のようになっています。

machine StartGdbServer 3333

Renode のドキュメントには、3つ目の方法にするには、以下のようにするとあります。

machine StartGdbServer 3333true

もしかすると、以前は、デフォルトが false だったけど、今は、デフォルトが true になったとかかもしれません。

とにかく、GDB で接続ができました。

以前作ったELFファイルでデバッグする

以前、Interface 2022年 7月号のルーレットゲームのサンプルソースを使って、QEMU で動かしました。

この ELFファイルを使って、Renode で動かしていきたいと思います。

まずは、Renode のディレクトリに、以前に作った ELFファイルのシンボリックリンクを作ります。1つ目が普通の ELFファイルで、2つ目は、一度バイナリファイルに変換して、シンボル情報などのデバッグ情報を削除して、ELFファイルに再構築したファイルです。

$ ln -s ~/eclipse-workspace/stm32f4discovery_sample/Debug/stm32f4discovery_sample.elf
$ ln -s ~/eclipse-workspace/stm32f4discovery_sample/Debug/stm32f4discovery_sample_bin2elf_entry.elf

普通のELFファイルを動かしてみる

では、まずは、普通のELFファイルの方を、手動で Renode を起動していきます。

$ renode
Gtk-Message: 21:29:43.731: Failed to load module "canberra-gtk-module"
21:29:44.6876[INFO] Loaded monitor commands from: /home/daisuke/svn_/renode/renode_1.15.0_portable/scripts/monitor.py
(monitor) mach create
21:30:27.2465[INFO] System bus created.
(machine-0) machine LoadPlatformDescription @platforms/boards/stm32f4_discovery-kit.repl
21:30:49.7163[INFO] Reading cache
21:30:50.1987[INFO] sysbus: Loaded SVD: /tmp/renode-10320/b9a14342-eb23-457c-9175-699febb364f2.tmp. Name: STM32F40x. Description: STM32F40x.
(machine-0) sysbus LoadELF @stm32f4discovery_sample.elf
21:31:19.4952[INFO] sysbus: Loading segment of 11000 bytes length at 0x8000000.
21:31:19.5196[INFO] sysbus: Loading segment of 360 bytes length at 0x8002AF8.
21:31:19.5199[INFO] sysbus: Loading segment of 256 bytes length at 0x2001F700.
(machine-0) machine StartGdbServer 3333
21:31:38.0812[INFO] machine-0: GDB server with all CPUs started on port :3333

問題なく起動できていそうです。続いて、GDB で接続します。

$ arm-none-eabi-gdb stm32f4discovery_sample.elf
(gdb) target remote :3333
Remote debugging using :3333
Reset_Handler () at ../startup.S:119
119            mrs     r0,  control
(gdb) c
Continuing.
^C
Program received signal SIGTRAP, Trace/breakpoint trap.
main () at ../main.c:107
107break;

普通のELFファイルをRenodeで動かしてみた
普通のELFファイルをRenodeで動かしてみた

GDB で接続すると、エントリポイントで停止した状態になりました。その後、c(continue)で実行開始しました。LED が見えないですが、Ctrl+C で、いったん停止すると main関数のどこかで止まったので、動いてそうです。

デバッグ情報の無いELFファイルを動かしてみる

普通の ELFファイルと同じように、手動で Renode で起動していきます。

$ renode
Gtk-Message: 21:31:59.406: Failed to load module "canberra-gtk-module"
21:32:00.3045[INFO] Loaded monitor commands from: /home/daisuke/svn_/renode/renode_1.15.0_portable/scripts/monitor.py
(monitor) mach create
21:32:20.0797[INFO] System bus created.
(machine-0) machine LoadPlatformDescription @platforms/boards/stm32f4_discovery-kit.repl
21:32:33.8938[INFO] Reading cache
21:32:34.3756[INFO] sysbus: Loaded SVD: /tmp/renode-10368/5f7902f5-f5f6-40d8-bda6-cc71e8ab32c4.tmp. Name: STM32F40x. Description: STM32F40x.
(machine-0) sysbus LoadELF @stm32f4discovery_sample.elf
21:33:04.9895[INFO] sysbus: Loading segment of 11116 bytes length at 0x8000000.
(machine-0) machine StartGdbServer 3333
21:33:18.2970[INFO] machine-0: GDB server with all CPUs started on port :3333

ELFファイルをロードしたときのログが普通の ELFファイルの場合と異なります。GDB を接続します。

$ arm-none-eabi-gdb stm32f4discovery_sample.elf
(gdb) target remote :3333
Remote debugging using :3333
0x00000000 in ?? ()

エントリポイントまでいかず、0番地で起動しました。

Renode 側のログは以下のようになっていました。

21:35:26.6557[WARNING] sysbus: [cpu: 0x0] ReadDoubleWord from non existing peripheral at 0x4.
21:35:26.6559[WARNING] sysbus: [cpu: 0x0] ReadDoubleWord from non existing peripheral at 0x0.
21:35:26.6588[ERROR] cpu: PC does not lay in memory or PC and SP are equal to zero. CPU was halted.
21:35:26.6656[INFO] cpu: Setting initial values: PC = 0x0, SP = 0x0.
21:35:26.6664[WARNING] cpu: Patching PC 0x0 for Thumb mode.
21:35:26.6678[INFO] machine-0: Machine started.

STM32 の場合、4番地はリセットハンドラのアドレスが格納されていて、0番地はスタックポインタの初期値が格納されています。そこから読み出せなかった、という警告が出ています。

このデバッグ情報の無い ELFファイルは、最低限のリンカスクリプトで ELFファイルを作っています。それが原因かもしれません。

デバッグ情報の無い raw binary のバイナリファイルで動かしてみる

Renode のドキュメントの CPU環境の構築のところを見ると、Renode は、ELFファイルだけでなく、バイナリファイルのロードにも対応しているようです。やってみます。

まずは、バイナリファイルを同じように、シンボリックリンクを作ります。

$ ln -s ~/eclipse-workspace/stm32f4discovery_sample/Debug/stm32f4discovery_sample_objcopy.bin

では、このバイナリファイルを Renode で起動していきます。

$ renode
Gtk-Message: 21:46:48.764: Failed to load module "canberra-gtk-module"
21:46:49.6671[INFO] Loaded monitor commands from: /home/daisuke/svn_/renode/renode_1.15.0_portable/scripts/monitor.py
(monitor) mach create
21:46:59.5845[INFO] System bus created.
(machine-0) machine LoadPlatformDescription @platforms/boards/stm32f4_discovery-kit.repl 
21:48:45.2759[INFO] Reading cache
21:48:45.7662[INFO] sysbus: Loaded SVD: /tmp/renode-10451/b58a73de-2638-46a1-9d68-515741ec08ce.tmp. Name: STM32F40x. Description: STM32F40x.
(machine-0) sysbus LoadBinary @stm32f4discovery_sample_objcopy.bin
The following methods are available:
 - Void LoadBinary (ReadFilePath fileName, UInt64 loadPoint, ICPU cpu = null)
Usage:
 sysbus MethodName param1 param2 ...
There was an error executing command'sysbus LoadBinary @/home/daisuke/svn_/renode/renode_1.15.0_portable/stm32f4discovery_sample_objcopy.bin'
Parameters did not match the signature

単純にバイナリファイルを指定しただけではエラーになりました。ロードするアドレスを指定する必要があるようです。その後ろの ICPU?は分からないので、とりあえずアドレスだけ指定してみます。

(machine-0) sysbus LoadBinary @stm32f4discovery_sample_objcopy.bin 0x08000000
(machine-0) machine StartGdbServer 3333 
21:57:01.2632[INFO] machine-0: GDB server with all CPUs started on port :3333

エラーは出なくなりましたが、正常な場合は、ロードされたというログが出ていたので、うまくいってないかもしれません。とりあえず GDB を接続してみます。

$ arm-none-eabi-gdb stm32f4discovery_sample_objcopy.bin 
"/home/daisuke/svn_/renode/renode_1.15.0_portable/stm32f4discovery_sample_objcopy.bin": not in executable format: file format not recognized
(gdb) target remote :3333
Remote debugging using :3333
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file"command.
0x00000000 in ?? ()

Renode 側のログです。

21:58:16.4682[WARNING] sysbus: [cpu: 0x0] ReadDoubleWord from non existing peripheral at 0x4.
21:58:16.4686[WARNING] sysbus: [cpu: 0x0] ReadDoubleWord from non existing peripheral at 0x0.
21:58:16.4712[ERROR] cpu: PC does not lay in memory or PC and SP are equal to zero. CPU was halted.
21:58:16.4781[INFO] cpu: Setting initial values: PC = 0x0, SP = 0x0.
21:58:16.4786[WARNING] cpu: Patching PC 0x0 for Thumb mode.
21:58:16.4798[INFO] machine-0: Machine started.

先ほどと同じですね。

ELFファイルの場合は、情報が不足しているので、失敗しても仕方ないですが、バイナリファイルの場合は、情報が無いファイルなので、この結果は変だと思います。

おわりに

今回は、Renode で、GDB を使って動かしてみました。

GDB 自体は問題なく動きましたが、バイナリファイルについては Renode の動作が怪しい気がします。

次回は、バイナリファイルで動作しない原因を見ていこうと思います。

この記事が誰かの役に立てば嬉しいです。

最後になりましたが、エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

今回は以上です!

最後までお読みいただき、ありがとうございました。


Viewing all articles
Browse latest Browse all 7910

Trending Articles