はじめに
gdbserverによるリモートデバッグ環境を今まで真面目に作ったことがなかったので調べてみた。
詳細な手順はここで紹介されている。
ターゲットはラズベリーパイ3。
この方法は、ターゲットにインストールされている既存のアプリケーションのデバッグに役立つ。
環境構築
いつものやつ。
INITはsystemdで。
ソース取得
$ mkdir -p rpi-thud/layers $ cd rpi-thud/layers $ git clone git://git.yoctoproject.org/poky.git -b thud $ git clone git://git.yoctoproject.org/meta-raspberrypi -b thud $ git clone git://git.openembedded.org/meta-openembedded -b thud $ cd ../
環境変数設定
$ source layers/poky/oe-init-build-env build
自動的にビルドディレクトリに移動される。 これで、bitbake関連のツールが使用可能になる。
レイヤ追加
$ bitbake-layers add-layer ../layers/meta-openembedded/meta-oe $ bitbake-layers add-layer ../layers/meta-openembedded/meta-python $ bitbake-layers add-layer ../layers/meta-openembedded/meta-networking $ bitbake-layers add-layer ../layers/meta-raspberrypi/
local.confの修正
local.confを次のように修正する。
MACHINE = "raspberrypi3" DL_DIR ?= "${TOPDIR}/../downloads" # enable uart(optional) ENABLE_UART = "1" # systemd DISTRO_FEATURES_append = " systemd pam" VIRTUAL-RUNTIME_init_manager = "systemd" DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" VIRTUAL-RUNTIME_initscripts = "" # debugfs IMAGE_GEN_DEBUGFS = "1" IMAGE_FSTYPES_DEBUGFS = "tar.bz2" # gdbserver IMAGE_INSTALL_append = " gdbserver" # debug build DEBUG_BUILD = "1" # network IMAGE_INSTALL_append = " connman connman-client" EXTRA_IMAGE_FEATURES += "ssh-server-openssh"
ビルド
$ bitbake core-image-base $ bitbake core-image-base -c populate_sdk
SDKのインストール
できあがったpoky-glibc-x86_64-core-image-base-cortexa7t2hf-neon-vfpv4-toolchain-2.6.2.sh
を実行しSDKをインストールする。
$ tmp/deploy/sdk/poky-glibc-x86_64-core-image-base-cortexa7t2hf-neon-vfpv4-toolchain-2.6.2.sh
ターゲットを起動する
できあがったcore-image-base-raspberrypi3.rpi-sdimg
をマイクロSDカードに書き込み、ラズベリーパイ3を起動する。
$ sudo dd if=tmp/deploy/images/raspberrypi3/core-image-base-raspberrypi3.rpi-sdimg of=/dev/sdX bs=100M
/dev/sdX
は環境に応じてsdb
やsdc
に変更する。
debugfsの設定
デバッグに必要なシンボルファイルなどを完全に含んだsysrootを作成するには、debugfs
を使用する必要がある。
ここでいうdebugfs
はカーネル機能のdebugfsとは異なり、デバッグ情報を含んだファイルシステムイメージのことを指す。
debugfsを生成するにはlocal.conf
に次の行を追記する。
IMAGE_GEN_DEBUGFS = "1" IMAGE_FSTYPES_DEBUGFS = "tar.bz2"
debugfsはデバッグ情報のみを含んだいわばフラグメントなので、単体で使用しても意味がない。 使用するには次のようにする。
$ mkdir debugfs $ cd debugfs $ tar xvf ../build/tmp/deploy/images/raspberrypi3/core-image-base-raspberrypi3.tar.bz2 $ tar xvf ../build/tmp/deploy/images/raspberrypi3/core-image-base-raspberrypi3-dbg.tar.bz2
populate_sdkで作成したツールチェインをインストールした場所にもデバッグ情報を含んだsysrootが存在するが、 ターゲット上のすべてのファイルが含まれているわけではない。 SDKを使用して新規に開発したアプリケーションをデバッグするのには十分だが、それ以外のターゲット上のアプリケーションをデバッグするときには debugfsを含んだ完全なファイルシステムのイメージが必要となる。
デバッグ手順
次のような手順になる。
- ターゲットでgdbserverを起動
- ホストPCでgdbを起動
試しにlsコマンドをデバッグしてみる。
ターゲット側
$ gdbserver localhost:1234 /bin/ls
ホストPC側
$ source /opt/poky/2.6.2/environment-setup-cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi $ cd debugfs/../ #debugfsの1つ上の階層 $ arm-poky-linux-gnueabi-gdb (gdb) set sysroot debugfs (gdb) set substitute-path /usr/src/debug debugfs/usr/src/debug (gdb) target remote ターゲットのIPアドレス:1234
この時点からデバッグ可能となる。
次のようにデバッグする。
(gdb) b ls_main (gdb) c
これで(busyboxでの)lsコマンドのエントリポイントでブレークする。
gdbgui
gdbguiを使用する場合は次のようにする。
$ gdbgui -g arm-poky-linux-gnueabi-gdb
デバッグビルドについて
強い最適化がかかっている場合だと、シンボルデバッグ時におかしな挙動に見えることがある。
DEBUG_BUILD
を有効化すると、bitbake実行時の最適化を抑えることができる。
local.conf
に次の行を追加する。
DEBUG_BUILD = "1"
これがない場合はTARGET_CFLAGSは次のようになる。
export TARGET_CFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types -fdebug-prefix-map=/home/mickey/work/yocto/rpi-thud/build/tmp/work/raspberrypi3-poky-linux-gnueabi/core-image-base/1.0-r0=/usr/src/debug/core-image-base/1.0-r0 -fdebug-prefix-map=/home/mickey/work/yocto/rpi-thud/build/tmp/work/raspberrypi3-poky-linux-gnueabi/core-image-base/1.0-r0/recipe-sysroot= -fdebug-prefix-map=/home/mickey/work/yocto/rpi-thud/build/tmp/work/raspberrypi3-poky-linux-gnueabi/core-image-base/1.0-r0/recipe-sysroot-native= "
DEBUG_BUILD= "1"
の場合のTARGET_CFLAGSは次のようになる。
export TARGET_CFLAGS=" -O -fno-omit-frame-pointer -g -feliminate-unused-debug-types -fdebug-prefix-map=/home/mickey/work/yocto/rpi-thud/build/tmp/work/raspberrypi3-poky-linux-gnueabi/core-image-base/1.0-r0=/usr/src/debug/core-image-base/1.0-r0 -fdebug-prefix-map=/home/mickey/work/yocto/rpi-thud/build/tmp/work/raspberrypi3-poky-linux-gnueabi/core-image-base/1.0-r0/recipe-sysroot= -fdebug-prefix-map=/home/mickey/work/yocto/rpi-thud/build/tmp/work/raspberrypi3-poky-linux-gnueabi/core-image-base/1.0-r0/recipe-sysroot-native= -pipe"
-O2
が-O
になり、-fno-omit-frame-pointer
がついている。これによってデバッグ情報が失われないようになっている。
まとめ
SDKを使用して新規に開発したアプリケーションをデバッグするにはSDKに含まれるsysrootのターゲット側のディレクトリで間に合うが、 既存のアプリケーションや、実機環境に近い状態でインテグレートした後のアプリケーションをデバッグする際には、 debugfsを使用する必要があることがわかった。