vmlinuz から vmlinux を抽出する方法
普段生活していると vmlinuz を vmlinux に変換したくなることはしばしばあると思いますが、その手順はどうも忘れがち。
今回はその変換レシピをメモ。
前提知識
まず、vmlinuz の中には gzip 圧縮されたカーネルイメージが同梱されています。
同梱というより、vmlinuz は vmlinux + ちょっとしたヘッダやメタ情報といった感じで、メインはカーネルイメージです。
このカーネルイメージを取り出し、展開したものが vmlinux です。
vmlinuz イメージを用意
まず vmlinuz とはなにか。これは /boot 下にある vmlinux-* から始まるファイル。
/boot/vmlinuz-3.2.0-52-generic みたいなファイル、ありますよね?
こいつを専用のワーキングディレクトリに移動。場所は /tmp/kernel で。
$ mkdir /tmp/kernel $ sudo cp /boot/vmlinuz-3.2.0-52-generic /tmp/kernel/vmlinuz $ sudo chmod +r /tmp/kernel/vmlinuz
ついでに名前も vmlinuz に変更。さらに読めるよう chmod.
展開
さて早速展開します。
とはいえ、どこから展開すればよいのでしょう?
カーネルイメージは gzip 圧縮されているので、gzip ヘッダ('1f 8b 08 00')を探してやりましょう。
aoking:/tmp/kernel $ od -A d -t x1 vmlinuz | grep '1f 8b 08 00' 0018016 48 8d 83 f0 6f 4b 00 ff e0 1f 8b 08 00 00 00 00
発見。18016 バイトの列の 10 バイト目からです。つまり、18026 バイトからがカーネルイメージであって、それ以前のものは破棄すべきデータです。
18026 バイト以降を展開してファイルに保存するコマンドは下記の通り。
aoking:/tmp/kernel $ dd if=vmlinuz bs=1 skip=18025 | zcat > vmlinux gzip: stdin: decompression OK, trailing garbage ignored
見ての通り、dd コマンドで先頭をスキップし、それ以降を zcat に渡して展開したものを vmlinux に吐き出してます。これで vmlinux イメージの抽出は完了。
aoking:/tmp/kernel $ file vmlinux vmlinux: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=0x62a37e23540d4dd4230ebbb70970051b38d7391f, stripped
ちなみに
今回は 18025 バイト分をスキップしましたが、それを間違えると zcat に怒られるので間違った vmlinux イメージが作られる心配は無しです。
aoking:/tmp/kernel $ dd if=vmlinuz bs=1 skip=18026 | zcat > vmlinux gzip: stdin: not in gzip format