メインコンテンツへスキップ

自分でビルドしたLinuxカーネルをQEMUでエミュレートしてGDBでデバッグするための環境構築メモ

··2165 文字·5 分·
プログラミング Linux Linux Linuxカーネル QEMU GDB デバッグ
著者
Admin
目次
自分用のメモを作るついでに公開しています。
初心者なので間違いがあるかもしれません。
参考程度にとどめておいてください。

Linuxカーネルをビルドする
#

開発時にコンパイルが通るかどうかを確認したり、自分の変更を適用したイメージを作成したりと、頻繁にビルドすることになるので覚えておきましょう。

  1. git clone (バージョン指定する場合はgit checkout xxx)
  2. make menuconfigで.configを生成する デバッグする場合はデバッグ情報を追加、設定するなど目的に応じて設定を変更
  3. make or make -j $(nproc) でビルド (場合によってはmake cleanを先に実行する) ビルドは意外とすぐ終わる。
  4. エラーが出ていないこと&生成物が存在することを確認。
    ビルドが完了すると、
    ソースのルートディレクトリにデバッグ情報ありのカーネルイメージ、vmlinuxが生成される。
    arch/xxxx/boot/に圧縮されたカーネルイメージ、bzImageが生成される。(デバッグ情報は無し?) (xxxxはターゲットアーキテクチャ名)

ファイルシステムを作成する(Buildrootの設定&ビルド)
#

Buildrootというツールを利用します。

上のレポジトリのスクリプトのコメントに参考になる情報があるので気になる方は読んでみると良いです。

🔗Buildroot 公式

initramfsを作成してくれます。
それだけでなく設定によってはカーネルもビルドしてイメージ作成してくれたりするツールです。
組み込み向けのLinuxカーネルイメージの作成を自動化&単純化する目的で作られたツールのようです。

🔗Buildroot ドキュメントのドキュメントに従って設定&ビルドします。

vagrantうんぬんは無視して良いです。

make時に

You seem to have the current working directory in your
LD_LIBRARY_PATH environment variable. This doesn't work.

というエラーが出たら

unset LD_LIBRARY_PATH && make

してください。

設定について補足ですが、各アーキテクチャ向けのデフォルトの設定ファイルが生成できるようになっているのでそちらを利用しても良いです。

一覧は

make list-defconfigs

で表示されます。

x86_64 qemuの場合の設定は、

make qemu_x86_64_defconfig

でqemu_x86_64向けの.configが生成されるのでその後に

 make menuconfig

などでカーネルのビルドを除外したりしてください。

makeするとoutputディレクトリ内にinitramfsのイメージ等の生成物が配置されます。

QEMUでLinuxカーネルを起動
#

QEMUの導入
#

まだ、QEMUをインストールしていない方は導入してください。
環境のパッケージマネージャでおそらく見つかるはずです。

ソースからビルドして入れることもできます。

🔗https://www.qemu.org/download/ (パッケージの情報もこちらに記載されています。)

起動
#

qemu-system-x86_64 -M pc -kernel ./linux/arch/x86_64/boot/bzImage -drive file=rootfs.ext2,if=virtio,format=raw -append "rootwait root=/dev/vda console=tty1 console=ttyS0"

-kernelに利用したいカーネルイメージを指定。 -driveにBuildrootで作成したファイルシステムイメージを指定。

のようなコマンドで起動できます。

マルチプロセッサ、コア環境などをエミュレートしたい場合は

qemu-system-x86_64 --help | grep smp

を参照。

🔗https://www.qemu.org/docs/master/system/introduction.html

ログイン&バージョン確認
#

起動後、パスワードの入力を求められますが、変更していなければrootでログインできます。

uname -aでカーネルのバージョンをチェックします。 結果

gcはカーネルビルド時の最終コミットの値です。

GDBの導入
#

gdb --version

で既にインストールされているかどうか確認しましょう。

パッケージマネージャで入れるのが楽です。

バージョンが低かったりする場合はソースからビルドしましょう。
🔗https://sourceware.org/gdb/download/

QEMU&GDBでデバッグ
#

🔗https://www.qemu.org/docs/master/system/gdb.html#gdb-usage
の内容を補足したものです。

GDBを有効にしてQEMUを起動
#

qemu-system-x86_64 -M pc -kernel ./linux/arch/x86_64/boot/bzImage -drive file=rootfs.ext2,if=virtio,format=raw -append "rootwait root=/dev/vda console=tty1 console=ttyS0 nokaslr"  -s -S

-append nokaslrでデフォルトで有効な🔗Kernel Address Space Layout Randomization (KASLR)を無効にすることができます。

GDBで接続
#

ビルド時に生成されたデバッグ情報を含むカーネルイメージを指定して起動。

gdb ./linux/vmlinux

以降、gdbシェル内での操作。
リモートでQEMUのGDBサーバーに接続する。

target remote localhost:1234

1234はGDBのデフォルトのポート。

その他
#

initramfsのイメージを作成する
#

必要になったときの用のメモ。

initramfsとは?
#

大まかに説明すると、initramfsの役割はLinuxカーネルがブートするために利用する作業領域用のファイルシステム。
メモリ上にファイルシステムが構築される。
initramfs = initial RAM file system

🔗https://github.com/ntegan/basic_initramfs を参考に作成することができます。

Related

[Linux] mmvで複数ファイルをパターンで一括でリネーム、コピー、移動する方法
··455 文字·1 分
Linux ソフトウェア mmv Linux
まったく、mmvは最高だぜ!!
bashでランダムなファイルをサイズ指定して生成する方法
··221 文字·1 分
Linux bash Linux dd
ddコマンドの使い方を解説。
Rust言語でVec<Vec<T>>のT型の各要素からVec<T>を構築する方法
··304 文字·1 分
プログラミング Rust
Vec<&T>も簡単に構築できる。