みつきんのメモ

組み込みエンジニアです。Interface誌で「My オリジナルLinuxの作り方」連載中

Yocto環境 callgrindでコールグラフを作成する

はじめに

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

f:id:mickey_happygolucky:20190830002744p:plain
kcachegrind

まとめ

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側で可視化するとよい。