はじめに
Linuxのユーザー空間のアプリをデバッグする際に、関数が実際にどのように呼び出されているのかを見たいことがある。 valgrindにはcallgrindというツールがあり、これを使うとコールグラフを生成することができる。
ターゲットにRPi3 Model Bを使用して、warrior(2.7)環境を構築する。 ホスト環境はUbuntu 18.04を使用する。
吐き出したコールグラフのデータはkcachegrindというツールで可視化することができる。 実機環境はヘッドレスで運用することとして、kcachegrindはホストPC側で使用する。
kcachegrindのインストール
Ubuntu環境にkcachegrindをインストールする。
$ sudo apt install valgrind kcachegrind
余談だが、kcachegrindの"k"はkernelではなくてKDEの”k”らしい。
環境構築
Yoctoの環境を構築する。
ソース取得
$ mkdir -p rpi-warrior/layers $ cd rpi-warrior/layers $ git clone git://git.yoctoproject.org/poky.git -b warrior $ git clone git://git.yoctoproject.org/meta-raspberrypi -b warrior $ git clone git://git.openembedded.org/meta-openembedded -b warrior $ 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
RPi3向けの基本的な設定。
MACHINE = "raspberrypi3" DL_DIR ?= "${TOPDIR}/../downloads" # enable uart ENABLE_UART = "1" # systemd DISTRO_FEATURES_append = " systemd pam" VIRTUAL-RUNTIME_init_manager = "systemd" DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" VIRTUAL-RUNTIME_initscripts = "" # network IMAGE_INSTALL_append = " connman-client" EXTRA_IMAGE_FEATURES += "ssh-server-openssh"
valgrindのための設定
local.conf
に次の設定を追加する。
# valgrind IMAGE_INSTALL_append = " valgrind" EXTRA_IMAGE_FEATURES += "dbg-pkgs"
実行環境にデバッグシンボルをインストールするためにIMAGE_FEATURESにdbg-pkgs
を追加する。
これをしないと、コールグラフ中の関数名が16進数の文字列になってしまう。
ちなみにvalgrindは次のようにしても追加できる。
# "tools-profile" - add profiling tools (oprofile, lttng, valgrind) EXTRA_IMAGE_FEATURES += "tools-profile"
ビルド
とりあえず最小構成をビルドする。
$ bitbake core-image-base
出来上がったイメージをddなどでSDカードに書き込む。
sudo dd if=tmp/deploy/images/raspberrypi3/core-image-base-raspberrypi3.rpi-sdimg of=/dev/sdX bs=100M
sdXは環境によりsdbやsdcなどになる。
lsのコールグラフ
lsコマンドのコールグラフを作ってみる。
$ valgrind --tool=callgrind ls
callgrind.out.xxx
というファイルが生成される。xxxはプロセスIDが入る。
これをホストPCにコピーして次のようにする。
$ kcachegrind callgrind.out.xxx
まとめ
Yoctoの環境でもvalgrindを使うことができる。
その時にIMAGE_FEATURESにdbg-pkgs
を入れておくと、デバッグ時のシンボルを解決できる。
また、src-pkgs
も一緒に入れておくと、gdbなどでのソースレベルデバッグも可能になる。
Yocto環境ではIMAGE_FEATURESにフラグを指定することで、デバッグシンボルの追加をすべてのパッケージに対し行うことができたりするので便利。
straceやgdbをターゲット上で使用したい場合は、IMAGE_FEATURESにtools-debug
を追加できる。
このあたりは、local.confのExtra image configuration defaults
にコメントとして記載されているので参考にすると良い。
多くの場合ターゲットはヘッドレスで運用することが想定されるので、valgrindの解析結果のファイルはホストPC側で可視化するとよい。