はじめに
Yocto ProjectでビルドしたZephyrのアプリケーション(elf)をqemuとgdbでデバッグしてみる。
環境
下記で作成した環境をベースに作業する
gdb-multiarch
使用するgdbはUbuntu 20.04でaptで導入可能なgdb-multiarch
。
$ sudo apt install gdb-multiarch
runqemuについて
bitbakeでZephyrアプリケーションをビルドすると、下記のコマンドでqemuを使用してアプリケーションを実行することができる。
$ runqemu
bitbake同様に下記を実行して環境変数を設定しておく必要がある。
$ source poky/oe-init-build-env build
runqemu
はqemuを実行するためのラッパスクリプトで、実行するelfのパスや環境変数、必要なオプションなどを自動的にqemuに渡してくれるようになっている。
下記のようにすると追加で任意にパラメータをqemuに渡すことができる。
$ runqemu qemuparams='-serial mon:stdio'
runqemuの詳しい使い方は下記のように調べることができる。
$ runqemu --help Usage: you can run this script with any valid combination of the following environment variables (in any order): KERNEL - the kernel image file to use BIOS - the bios image file to use ROOTFS - the rootfs image file or nfsroot directory to use DEVICE_TREE - the device tree blob to use MACHINE - the machine name (optional, autodetected from KERNEL filename if unspecified) Simplified QEMU command-line options can be passed with: nographic - disable video console novga - Disable VGA emulation completely sdl - choose the SDL UI frontend gtk - choose the Gtk UI frontend gl - enable virgl-based GL acceleration (also needs gtk or sdl options) gl-es - enable virgl-based GL acceleration, using OpenGL ES (also needs gtk or sdl options) egl-headless - enable headless EGL output; use vnc (via publicvnc option) or spice to see it serial - enable a serial console on /dev/ttyS0 serialstdio - enable a serial console on the console (regardless of graphics mode) slirp - enable user networking, no root privileges is required snapshot - don't write changes to back to images kvm - enable KVM when running x86/x86_64 (VT-capable CPU required) kvm-vhost - enable KVM with vhost when running x86/x86_64 (VT-capable CPU required) publicvnc - enable a VNC server open to all hosts audio - enable audio [*/]ovmf* - OVMF firmware file or base name for booting with UEFI tcpserial=<port> - specify tcp serial port number qemuparams=<xyz> - specify custom parameters to QEMU bootparams=<xyz> - specify custom kernel parameters during boot help, -h, --help: print this text -d, --debug: Enable debug output -q, --quiet: Hide most output except error messages Examples: runqemu runqemu qemuarm runqemu tmp/deploy/images/qemuarm runqemu tmp/deploy/images/qemux86/<qemuboot.conf> runqemu qemux86-64 core-image-sato ext4 runqemu qemux86-64 wic-image-minimal wic runqemu path/to/bzImage-qemux86.bin path/to/nfsrootdir/ serial runqemu qemux86 iso/hddimg/wic.vmdk/wic.vhd/wic.vhdx/wic.qcow2/wic.vdi/ramfs/cpio.gz... runqemu qemux86 qemuparams="-m 256" runqemu qemux86 bootparams="psplash=false" runqemu path/to/<image>-<machine>.wic runqemu path/to/<image>-<machine>.wic.vmdk runqemu path/to/<image>-<machine>.wic.vhdx runqemu path/to/<image>-<machine>.wic.vhd
qemuをgdb serverとして実行する
qemuはqemu上で実行中のelfをデバッグするために、gdb serverのプロトコル喋れるようになっている。 (厳密には多分いろいろ違うと思うけど、とりあえず。)
runqemuに下記のオプションをつけて実行すると、elfの先頭でブレーク状態に、localhostの1234ポートで接続できるようになる。
$ runqemu qemuparams="-S -s" runqemu - INFO - Running bitbake -e ... runqemu - INFO - Continuing with the following parameters: KERNEL: [/home/mickey/work/yocto/x86-hardknott/mb-hardknott/build/tmp/deploy/images/microbit-v1/my-app.elf] MACHINE: [microbit-v1] FSTYPE: [elf] ROOTFS: [/home/mickey/work/yocto/x86-hardknott/mb-hardknott/build/tmp/deploy/images/microbit-v1/my-app-image-microbit-v1.elf] CONFFILE: [/home/mickey/work/yocto/x86-hardknott/mb-hardknott/build/tmp/deploy/images/microbit-v1/my-app-image-microbit-v1.qemuboot.conf] runqemu - INFO - Running /home/mickey/work/yocto/x86-hardknott/mb-hardknott/build/tmp/work/x86_64-linux/qemu-helper-native/1.0-r1/recipe-sysroot-native/usr/bin/qemu-system-arm -nographic -vga none -machine microbit -cpu cortex-m0 -m 256 -s -S -serial mon:vc -serial null -kernel /home/mickey/work/yocto/x86-hardknott/mb-hardknott/build/tmp/deploy/images/microbit-v1/my-app.elf -append ' mem=256M '
この状態で、別の端末を開き下記のように実行する
$ cd tmp/deploy/images/microbit-v1/ $ gdb-multiarch my-app.elf
するとgdbのプロンプトが表示されるので下記のように入力する。
(gdb) target remote :1234
これでqemuに接続される。
下記のようにしてmain関数にブレークを貼る。
(gdb) b main
実行してみる。
(gdb) c Continuing. Breakpoint 1, main () at /home/mickey/work/yocto/x86-hardknott/mb-hardknott/build/tmp/work/cortexm0-poky-eabi/my-app/2.5.0+gitAUTOINC+fe7c2efca8_c3bd2094f9-r0/my-app/src/main.c:10 10 printk("Hello My Application World! %s\n", CONFIG_BOARD);
きちんとmain関数でブレークすることが確認できた。
まとめ
YoctoでビルドしたZephyrアプリケーションのelfをqemu + gdbでデバッグできることを確認した。
meta-armでmicrobit-v1のマシン定義をした人が丁寧にqemu対応のための設定も作り込んでくれているため、 micro:bit向けのelfをqemu向けにリビルドすることなくqemu + gdbでデバッグができるようになっている。
BSP次第だが、Yoctoではこういうこともできるのがおもしろい。
(おまけ) micro:bitのrunqemuのための設定
meta-arm/conf/machine/microbit-v1.conf
の下記の部分。
runqemuで呼び出されるqemu-systemや、それに渡されるオプションを定義している。
# For runqemu QB_SYSTEM_NAME = "qemu-system-arm" QB_MACHINE = "-machine microbit" QB_CPU = "-cpu cortex-m0" QB_OPT_APPEND = "-nographic -vga none" QB_RNG = ""