Raspberry PiのパッケージをGDBでデバッグできる状態にする
この記事はUMITRON Advent Calendar 2022 - Adventarの9日目の記事です。
アドベントカレンダーの2日目の記事でも言及した通り、弊社ではRaspberry Piを用いています。このRaspberry Piを用いた開発をしている中で、Raspberry Piにインストールされている(した)パッケージのソフトウェアの挙動に不明な点があり、またソースコードを読んでも読み解くのが難しい、ということがありました。
そこで、GDBを用いてデバッグしつつ挙動を確認しました。そこで調べるのに結構時間がかかってしまったので、この記事ではこの時得られた知見を共有したいと思います。
背景
通常Raspberry Piにインストールされているパッケージや、debian package repositoryからインストールするパッケージにはdebug symbolが含まれていません。このdebug symbolが含まれていない場合、gdbなどによるデバッグを行うことが出来ません。
Debianでは通例、このdebug symbolだけを切り出した専用パッケージを1つの通常パッケージごとに用意していて、これをインストールするとデバッグ出来るようになります。これらのpackageは 元パッケージ名-dbgsym
という名前になっています。また、インストールするdbgsymパッケージは元packageと同じbuild idでなければ動きません。そしてdbgsymパッケージは通常、メインのdebian package repositoryとは別のrepositoryで提供されます。
この辺りがRaspberry Piの場合違います。Raspberry Piは一部のパッケージがRaspberry Pi専用にカスタマイズされ、本家のパッケージとは別バージョンで提供されています。これらのカスタマイズされたパッケージはカスタマイズのないパッケージとは別のrepositoryで提供され、dbgsymパッケージも同じrepositoryで提供されています。
これらのdebian package repositoryは通常バージョンが /etc/apt/sources.list
に記載された http://raspbian.raspberrypi.org/raspbian/ で、カスタマイズされたバージョンが /etc/apt/sources.list.d/raspi.list
に記載された http://archive.raspberrypi.org/debian/ になります。
ここで問題になるのが、通常バージョンのpackageに対応するdbgsymパッケージが(おそらく)提供されていないということです(私は見つけられませんでした)。ググるとdbgsymのdebian package repositoryとして http://debug.mirrors.debian.org/debian-debug/ が見つかります。このrepositoryではRaspberry Piにインストールされているパッケージと厳密に同じバージョンのdbgsymパッケージも見つかりますが、build idが違うため利用できません。これを解決するためには、同じbuild idのパッケージをインストールし直す必要があります。
次はこれらを前提として、具体的にどのようにdbgsymパッケージをインストールするか解説します。
Raspberry Pi用パッケージの場合
まず対象のパッケージがRaspberry Pi用にカスタマイズされているかどうかを確認します。例えばffmpegの場合、バージョンの末尾が rpt3 となっており、これはRaspberry Pi用にカスタマイズされたバージョンであることを示しています( rpt ではなく rpi の場合もあります)。
$ dpkg -l ffmpeg
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-======================-============-================================================================
ii ffmpeg 7:4.3.4-0+deb11u1+rpt3 armhf Tools for transcoding, streaming and playing of multimedia files
この場合、dbgsymパッケージはRaspberry Piのプリインで登録されているdebian package repository( http://archive.raspberrypi.org/debian/ )で提供されているので、設定無しでaptでインストールすることができます。
$ apt-cache show ffmpeg-dbgsym
Package: ffmpeg-dbgsym
Source: ffmpeg
Version: 7:4.3.4-0+deb11u1+rpt3
Auto-Built-Package: debug-symbols
Architecture: armhf
Maintainer: Debian Multimedia Maintainers <debian-multimedia@lists.debian.org>
Installed-Size: 638
Depends: ffmpeg (= 7:4.3.4-0+deb11u1+rpt3)
Priority: optional
Section: debug
Filename: pool/main/f/ffmpeg/ffmpeg-dbgsym_4.3.4-0+deb11u1+rpt3_armhf.deb
Size: 551508
SHA256: e8afc6f4bde5560c97550dd3e93b4531c34a3776f84f62736e68b36bff2422aa
SHA1: f561e304f175b8d2a15bda1f55fb1e5501c261a4
MD5sum: 62731e60c867bd85ca436207cee6760d
Description: debug symbols for ffmpeg
Description-md5: 2801dfb26f691e1e953125f850606365
Build-Ids: 0467880a7cad52d8cc1a1e695044e7526a33a25b 3780abeca869254536cbe6dd9785457276eaeca5 cc6c5ff0212eb37c1030bf2919c09d6fcba9bf16 f1296763e94cc2e7d4d940db56c5b3eb8d1c7e4d
$ sudo apt-get install -y ffmpeg-dbgsym
これでgdbでデバッグができるようになりました。以下のログメッセージからdebug symbolが読み込まれていることがわかります。
$ gdb -q ffmpeg
Reading symbols from ffmpeg...
Reading symbols from /usr/lib/debug/.build-id/f1/296763e94cc2e7d4d940db56c5b3eb8d1c7e4d.debug...
(gdb)
gdbの使い方はこの記事では解説しません。
aptで同じversionのdbgsymパッケージが見つからない場合
aptで見つかるdbgsymパッケージのバージョンがインストール済みのパッケージと違う場合があります。以下ではdhcpcd5のインストール済みのバージョンが rpt7 , aptで見つかるdbgsymパッケージのバージョンが rpt9 となっています。
$ dpkg -l dhcpcd5
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-==============-============-====================================================
ii dhcpcd5 1:8.1.2-1+rpt7 armhf DHCPv4, IPv6RA and DHCPv6 client with IPv4LL support
$ apt-cache show dhcpcd5-dbgsym
Package: dhcpcd5-dbgsym
Source: dhcpcd5
Version: 1:8.1.2-1+rpt9
Auto-Built-Package: debug-symbols
Architecture: armhf
Maintainer: Scott Leggett <scott@sl.id.au>
Installed-Size: 402
Depends: dhcpcd5 (= 1:8.1.2-1+rpt9)
Priority: optional
Section: debug
Filename: pool/main/d/dhcpcd5/dhcpcd5-dbgsym_8.1.2-1+rpt9_armhf.deb
Size: 364356
SHA256: b38cac5ed80ff3f72b8de65bd394d802132b3c3124a6005872bc446828a0a962
SHA1: 037824710f796760046714de3242b40e7e8dae0b
MD5sum: bcf64d99029961e6722a325c479590bf
Description: debug symbols for dhcpcd5
Description-md5: 88f98e734c4e1dfc28fefbfb55d3d333
Build-Ids: 57b52a85e3f4ea11da5e4b31d8a285c5f5a2921f e513c8229aed657132dae430811d3cb3ff2691da
dbgsymパッケージは同じバージョンの元パッケージに依存しているため、上記のケースでそのままdbgsymパッケージをaptでインストールしようとすると、元パッケージも新しいバージョンがインストールされてしまいます。
元のパッケージをアップデートしたくないケースでは、aptを使わずに直接インストールする必要があります。aptからはdhcpcd5と同じ rpt7 のdbgsymが見えませんが、debian package repositoryには.debファイルがあるので、それを直接ダウンロードしaptではなくdpkgコマンドでインストールします。
$ wget -q http://archive.raspberrypi.org/debian/pool/main/d/dhcpcd5/dhcpcd5-dbgsym_8.1.2-1+rpt7_armhf.deb
$ sudo dpkg -i dhcpcd5-dbgsym_8.1.2-1+rpt7_armhf.deb
これでパッケージのアップデートを避けつつdbgsymパッケージをインストールし、gdbによるデバッグが可能になります。
$ gdb -q dhcpcd
Reading symbols from dhcpcd...
Reading symbols from /usr/lib/debug/.build-id/e5/13c8229aed657132dae430811d3cb3ff2691da.debug...
(gdb)
通常パッケージの場合
次に、Raspberry Pi用にカスタマイズされていないパッケージのケースを考えます。例えばfileパッケージはRaspberry Piのカスタマイズが行われていません。
$ dpkg -l file
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-============-============-==========================================================
ii file 1:5.39-3 armhf Recognize the type of data in a file using "magic" numbers
前述の通り、このパッケージに対応するdbgsymパッケージを見つけることができなかったので、インストールし直すことを考えます。そこでRaspberry Piではなく、Debian公式のrepositoryから同じバージョンの同じパッケージをダウンロードしてインストールします。
Debian公式のrepositoryは http://ftp.debian.org/debian , dbgsymのrepositoryは http://debug.mirrors.debian.org/debian-debug/ です。この2つのrepositoryのパッケージは同じbuild idのパッケージを提供しているようです。
sources.listに追加してaptでインストールしても良いのですが、Raspberry Piデフォルトのrepositoryとバッティングしてしまって管理が面倒なので、直接.debファイルをダウンロードしてdpkgでインストールすることにします。該当.debファイルはそれぞれ以下です。
- http://ftp.debian.org/debian/pool/main/f/file/file_5.39-3_armhf.deb
- http://debug.mirrors.debian.org/debian-debug/pool/main/f/file/file-dbgsym_5.39-3_armhf.deb
これらをインストールします。
$ wget -q http://ftp.debian.org/debian/pool/main/f/file/file_5.39-3_armhf.deb http://debug.mirrors.debian.org/debian-debug/pool/main/f/file/file-dbgsym_5.39-3_armhf.deb
$ sudo dpkg -i file_5.39-3_armhf.deb file-dbgsym_5.39-3_armhf.deb
これでgdbでデバッグができるようになりました。
$ gdb -q file
Reading symbols from file...
Reading symbols from /usr/lib/debug/.build-id/1f/b26d6111df7058791cc8da32f9875a9c642604.debug...
(gdb)
解説は以上です。
ウミトロンでは一緒に働く仲間を募集しています。持続可能な水産養殖を地球に実装するというミッションの元で、私たちと一緒に水産養殖xテクノロジーに取り組みませんか?
Discussion