Vmlinux
bzImage > カーネルイメージのビルドとフォーマット

Linuxカーネルイメージは通常、Linuxカーネルソースのディレクトリ（もしくはオプションを指定し、最終生成物を出力するディレクトリ）において次のコマンドを実行することで得られる。
make
現行のバージョン2.6では、アーキテクチャによって、このとき暗黙のうちに指定されるターゲットは異なる。例えばx86（i386ならびにx86-64）アーキテクチャにおいては、暗黙のうちに
make bzImage
と指定されている。これはbzImageを生成せよとの指令を発行したことになる。
正常にビルドが進むと、端末エミュレータに以下のように表示される（以下、i386をターゲットとしたバージョン2.6.38-rc2のビルドより一部抜粋した。ビルドプロセスはリリース毎、アーキテクチャ毎に多岐に渡るため、この環境での説明に限定する）。
[... ビルドプロセス（"表示"をクリックしてください。） ...]
...
  CC      init/calibrate.o
  LD      init/built-in.o
  ...
  AR      arch/x86/lib/lib.a
  LD      vmlinux.o
  MODPOST vmlinux.o
  ...
  LD      .tmp_vmlinux1
  KSYM    .tmp_kallsyms1.S
  AS      .tmp_kallsyms1.o
  LD      .tmp_vmlinux2
  KSYM    .tmp_kallsyms2.S
  AS      .tmp_kallsyms2.o
  ...
  LD      vmlinux
  SYSMAP  System.map
  SYSMAP  .tmp_System.map
  CC      arch/x86/boot/a20.o
  ...
  CC      arch/x86/boot/edd.o
  VOFFSET arch/x86/boot/voffset.h
  LDS     arch/x86/boot/compressed/vmlinux.lds
  AS      arch/x86/boot/compressed/head_32.o
  CC      arch/x86/boot/compressed/misc.o
  CC      arch/x86/boot/compressed/string.o
  CC      arch/x86/boot/compressed/cmdline.o
  CC      arch/x86/boot/compressed/early_serial_console.o
  OBJCOPY arch/x86/boot/compressed/vmlinux.bin
  HOSTCC  arch/x86/boot/compressed/relocs
  RELOCS  arch/x86/boot/compressed/vmlinux.relocs
  GZIP    arch/x86/boot/compressed/vmlinux.bin.gz
  HOSTCC  arch/x86/boot/compressed/mkpiggy
  MKPIGGY arch/x86/boot/compressed/piggy.S
  AS      arch/x86/boot/compressed/piggy.o
  LD      arch/x86/boot/compressed/vmlinux
  ZOFFSET arch/x86/boot/zoffset.h
  AS      arch/x86/boot/header.o
  ...
  CC      arch/x86/boot/video-bios.o
  LD      arch/x86/boot/setup.elf
  OBJCOPY arch/x86/boot/setup.bin
  OBJCOPY arch/x86/boot/vmlinux.bin
  HOSTCC  arch/x86/boot/tools/build
  BUILD   arch/x86/boot/bzImage
Root device is (8, 3)
Setup is 15068 bytes (padded to 15360 bytes).
System is 2828 kB
CRC 5051e6e4
Kernel: arch/x86/boot/bzImage is ready  (#1)
カーネルに静的リンクされる全てのオブジェクトコードはvmlinux.oにリンクされる。これとは別に、全てのオブジェクトファイルからシンボルのみを取り出し、単一のELFセクションヘッダとして保持するオブジェクトコード.tmp_kallsyms2.o（数字はカーネルコンフィグレーションにより異なる）が生成される。この2つのファイルをリンクしたものが本記事の対象とする実行ファイルvmlinuxである。続いてこのファイルにnmコマンドをかけ、シンボルテーブルSystem.mapファイルを生成する（.tmp_System.mapは比較検査のため生成する）。続いて圧縮ルーチンを含めたカーネルイメージのブート用ルーチンのビルドが開始される。
（以下、x86アーキテクチャにおいて$(BITS)はビット数に読み替えてほしい）
カーネルの圧縮、カーネルイメージの伸長などに関するソースコードはarch/x86/boot/compressedに存在する。
arch/x86/boot/compressed/head_$(BITS).oはカーネルイメージのメモリアドレス前方に位置し、BIOSから得た低レベルなハードウェアの情報を処理するためのコードである。詳細はソースコードのarch/x86/boot/compressed/head_$(BITS).Sやそのエントリポイントstartup_$(BITS)、リンカスクリプトなどを参照せよ。
arch/x86/boot/compressed/misc.oは後方に位置するカーネル本体を含むコードをzlibなどのアルゴリズムを用いて伸長するコードである。有名なUncompressing Linux...というコンソールの表示はこの処理において見られる（実際の処理はアーキテクチャ毎に様々で、BIOSや起動直後のシステムが認識可能なメモリアドレスの制限のため、段階的に複雑なメモリ配置を行いこれを実現している。詳しくは、arch/x86/boot/compressed/misc.cのdecompress_kernelなどのキーワードを参考に処理内容を見てほしい）。
head_$(BITS).o, misc.oその他カーネルイメージの伸長後に利用する低レベルコードをビルドし終わると、piggy.oというオブジェクトコードと一緒にリンクされ、arch/x86/boot/compressed/vmlinuxという実行ファイルを生成する（このファイルは本記事で説明の対象としているvmlinuxではないことに注意せよ）。piggy.oは次のようなプロセスをたどり生成される。ディレクトリのトップにあるvmlinuxは、GNU Binutilsにより配布されるobjcopyコマンドを利用し、.commentなど不要なELFセクションヘッダとシンボル情報を全て削除されたうえで実行ファイルarch/x86/boot/compressed/vmlinux.binに変換される。このファイルに圧縮をかけ更に専用のツールを用いて、vmlinux.bin.gz（圧縮アルゴリズムにより拡張子は異なる）をELFのセクションヘッダに埋め込んだ特殊なELFオブジェクトファイルが生成される。これがpiggy.oである（詳しくはarch/x86/boot/compressed/Makefileを参照せよ）。
この後ブート用の低レベルコードのビルドが続く。カーネルのブートに関するコードは前述の圧縮・伸長コードも含め、arch/x86/bootに存在する。
arch/x86/boot/header.oはカーネルイメージの先頭メモリアドレスに存在するコードである。エントリーポイント_startから開始されるこのコードにより前述した伸長用ルーチンを後ほど呼び出す。
このコードは以前のリリースにおける、2つのコードbootsect.o、setup.oの一部を抜きだし、再構成したものである。ちなみにbootsect.oはフロッピーディスク用のダイレクトブート用コードであったがバージョン2.6では、header.Sの一部にダイレクトブートできない旨のメッセージを表示するコードのみ残っているに過ぎない。setup.oの残部は細かく分けられ、一部は前述のhead_$(BITS).oにも含まれている。
このオブジェクトファイルも含め、ビデオBIOS用処理などの低レベルなコードがarch/x86/boot/setup.elfという実行ファイルとしてリンクされる。
ここまで正常に終了したならば、bzImageの完成は目前となる。arch/x86/boot/setup.elfとarch/x86/boot/compressed/vmlinuxはobjcopyコマンドの特殊なオプションによりそれぞれELFバイナリからrawバイナリ（「生バイナリ」とも。リロケーション情報を削除し、メモリ上に直接展開・実行可能なコード。詳細はobjcopyのマニュアルまたはInfoドキュメントを参照せよ）arch/x86/boot/setup.binとarch/x86/boot/vmlinux.binに変換される。この二つをカーネルビルド時にしか使われない専用ツールで結合すると、arch/x86/boot/bzImageが完成する。
ビルドの終了メッセージの意味は次の通りである。
"Root device is (8, 3)"、これはルートディレクトリのマウントされているファイルシステムはメジャー番号8番、マイナー番号3番（デバイスファイル参照）にあることを予めカーネルイメージに埋め込んだことを示す（ルートファイルシステムがブートローダで指定されていない場合、デフォルトで使用される）。すなわちこれはSCSIディスクの第一番目のディスク先頭第3パーティション(/dev/sda3)にルートファイルシステムがあることを示す。次の2行はカーネルイメージのデータサイズを示している。CPUがリアルモード状態のときに使用されるセットアップコード("Setup")は、セクタサイズにきれいに収めるため、512の倍数となる15360バイトにパディングされたことを通知している。"System"はカーネル本体を含むコードでこの場合1MBをゆうに越え、2828kBとなっている。続いてイメージのCRCが検出され、これが初回(#1)のビルドであることを通知し、ビルドプロセスは終了する。
以上よりbzImageファイルは特殊なバイナリフォーマットを持っている: すなわち、主に次のデータを連結し、構成されていることが分かる。
bzImage = setup.bin + vmlinux.bin
  setup.bin <---(raw binary)--- setup.elf <--- header.o + main.o + more...
  vmlinux.bin <---(raw binary)--- head_(BITS).o + misc.o + more... + piggy.o
    piggy.o <---(compressed + embedded)--- vmlinux <--- vmlinux.o + .tmp_kallsyms2.o <--- *.o *.a
                                             `|
                                          System.map