📦

Raspberry PiのパッケージをGDBでデバッグできる状態にする

2022/12/09に公開

この記事は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ファイルはそれぞれ以下です。

これらをインストールします。

$ 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