はじめに (対象読者・この記事でわかること)
この記事は、LinuxカーネルのeBPF技術に興味があり、特にラズベリーパイ環境でlibbpfを利用したい方を対象としています。プログラミングの初学者ではなく、LinuxシステムやC言語の基本的な知識があることを前提としています。
本記事を読むことで、ラズベリーパイでlibbpfを利用する際に発生する「libbpf: failed to find valid kernel BTF」というエラーの原因を理解し、具体的な解決方法を実践できるようになります。また、eBPFとlibbpfの基本的な概念についても理解を深めることができます。
この記事を書いた背景として、私自身がラズベリーパイでeBPFプログラミングを試みた際にこのエラーに遭遇し、解決に時間を要した経験があります。同じ問題で悩んでいる方の助けになれば幸いです。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- Linuxカーネルの基本的な知識
- C言語の基本的なプログラミング能力
- ラズベリーパイの基本的な操作知識
- コマンドラインの基本的な操作
- Makefileの基本的な理解
libbpfとkernel BTFの概要
libbpfは、LinuxカーネルのeBPF (Extended Berkeley Packet Filter) 技術を利用するためのライブラリ群です。eBPFは、Linuxカーネル内で安全に実行可能な仮想マシンであり、ネットワークパケット処理、システムトレース、セキュリティ監視などに広く利用されています。
BTF (BPF Type Format) は、eBPFプログラムがカーネル内のデータ構造にアクセスするための型情報を提供するフォーマットです。libbpfは、このBTF情報を利用してカーネルオブジェクトを正しく解釈します。
ラズパイでlibbpfを利用しようとすると、「libbpf: failed to find valid kernel BTF」というエラーが発生することがあります。これは、ラズベリーパイのカーネルにBTF情報が含まれていないか、libbpfが正しくBTF情報にアクセスできない場合に発生します。特に、Raspberry Pi OSの標準カーネルでは、BTFサポートがデフォルトで有効になっていないことが原因です。
kernel BTFエラーの解決方法
ここでは、ラズベリーパイでlibbpfを利用する際に発生するkernel BTFエラーを解決する具体的な手順を説明します。
ステップ1: ラズパイのカーネルバージョンの確認
まず、現在のラズベリーパイで使用しているカーネルバージョンを確認します。ターミナルで以下のコマンドを実行します。
Bashuname -r
出力されるカーネルバージョンをメモしておきます。一般的に、カーネルバージョンが5.4以上であればBTFサポートが利用可能ですが、ラズベリーパイの場合は追加の設定が必要です。
ステップ2: 必要なパッケージのインストール
BTF情報を生成するために、いくつかのパッケージをインストールする必要があります。以下のコマンドを実行します。
Bashsudo apt update sudo apt install -y build-essential libelf-dev llvm clang
これにより、カーネルのビルドに必要なツールと、BPFコンパイラであるclangがインストールされます。
ステップ3: カーネルのBTF情報の生成
ラズベリーパイのカーネルにBTF情報を追加するには、カーネルを再ビルドするか、BTF情報を別途生成する必要があります。ここでは、既存のカーネルにBTF情報を追加する方法を説明します。
まず、カーネルのソースコードをダウンロードします。使用しているカーネルバージョンと一致するソースコードをダウンロードします。
BashKERNEL_VERSION=$(uname -r | cut -d'-' -f1) wget https://github.com/raspberrypi/linux/archive/raspberrypi-kernel_${KERNEL_VERSION}.tar.gz tar -xvf raspberrypi-kernel_${KERNEL_VERSION}.tar.gz cd linux-raspberrypi-kernel_${KERNEL_VERSION}
次に、カーネルの.configファイルを現在のカーネル設定からコピーします。
Bashcp /boot/config-$(uname -r) .config
カーネル設定を編集し、BTFサポートを有効にします。
Bashmake ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- olddefconfig
BTFサポートを有効にするために、以下の設定を変更します。
Bashecho "CONFIG_DEBUG_INFO_BTF=y" >> .config echo "CONFIG_DEBUG_INFO_BTF_MODULES=y" >> .config
カーネルをビルドします。このプロセには数時間かかることがあります。
Bashmake ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
ビルドが完了したら、BTF情報を生成します。
Bashpahole -J vmlinux | gzip -c > /boot/vmlinux-${KERNEL_VERSION}.btf.gz
生成したBTF情報をシステムにコピーします。
Bashsudo cp /boot/vmlinux-${KERNEL_VERSION}.btf.gz /boot/
ステップ4: libbpfのビルドとインストール
libbpfをビルドしてインストールします。まず、libbpfのソースコードをダウンロードします。
Bashgit clone https://github.com/libbpf/libbpf.git cd libbpf git checkout $(git describe --tags --abbrev=0)
libbpfをビルドしてインストールします。
Bashmake sudo make install sudo ldconfig
ハマった点やエラー解決
実装中に遭遇する問題や、エラーの解決方法について記載します。
エラー1: paholeコマンドが見つからない
BTF情報を生成するためにpaholeコマンドを使用しますが、このコマンドがインストールされていない場合があります。
Bashpahole: command not found
解決策:
dwarvesパッケージをインストールします。
Bashsudo apt install dwarves
エラー2: カーネルビルド中にエラーが発生する
カーネルのビルド中に、以下のようなエラーが発生することがあります。
Basherror: unknown type name 'struct bpf_map'
解決策:
カーネルのソースコードが正しくダウンロードされていない可能性があります。カーネルバージョンを確認し、正しいソースコードをダウンロードしてください。
エラー3: libbpfのビルド中にエラーが発生する
libbpfのビルド中に、以下のようなエラーが発生することがあります。
Basherror: BPF skeleton generation failed
解決策:
BTF情報が正しく生成されていない可能性があります。ステップ3でBTF情報を生成し、正しい場所に配置されているか確認してください。
解決策
上記の手順を実行することで、「libbpf: failed to find valid kernel BTF」というエラーを解決できます。特に重要なのは、カーネルにBTF情報を追加するステップです。
また、ラズベリーパイのカーネルをカスタマイズする代わりに、BTF情報を含む事前ビルドされたカーネルを使用する方法もあります。この方法は、より簡単ですが、カーネルのアップデート時に再度設定が必要になる可能性があります。
動作確認として、以下のような簡単なeBPFプログラムを実行してみてください。
C#include <linux/bpf.h> #include <bpf/bpf_helpers.h> SEC("tracepoint/syscalls/sys_enter_openat") int trace_openat(void *ctx) { return 0; } char _license[] SEC("license") = "GPL";
このプログラムをコンパイルして実行し、エラーが発生しなければ成功です。
まとめ
本記事では、ラズベリーパイでlibbpfを利用する際に発生する「libbpf: failed to find valid kernel BTF」というエラーの原因と解決方法について解説しました。
- 要点1: ラズベリーパイのカーネルにはBTF情報がデフォルトで含まれていない
- 要点2: カーネルの再ビルドとBTF情報の生成が必要
- 要点3: libbpfのビルドとインストールを正しく実行することでエラーを解決できる
この記事を通して、ラズベリーパイ環境でeBPFプログラミングを行うための基礎知識を得られたと思います。今後は、より高度なeBPFプログラムの作成方法や、ラズベリーパイでの応用例についても記事にする予定です。
参考資料
