Macで実行ファイルのヘッダのマジックナンバーをVSCode拡張機能を使って見るまで
タイトル通り。
プログラムの実行フォーマットについてあまりに無知すぎたので備忘録です。
実行ファイルフォーマット
Wikipediaによると、
実行ファイル(じっこうファイル、Executable、Executable file)とは、コンピュータがプログラムとして解釈実行できるファイルである。実行可能ファイル、実行形式ファイル、あるいは単に実行形式とも呼ばれる。
ということらしいです。
具体的な例として、ELFフォーマットやa.outがあります。
特にELFはLinuxなどで採用されており、広く普及しているファイルフォーマットです。
実行ファイルは多くの場合、ファイルフォーマットを識別するためのマジックナンバーやCPUの種類、アーキテクチャなどを含むヘッダから始まります。
Mach-O
多くのOSで実行ファイル形式として採用されているELFですが、Macの場合はMach-Oという形式で保存されます。
Mach-Oのヘッダは, /usr/include/mach-o/loader.h
に定義されている C
の構造体が付与されます。
以下、loader.h
。
struct mach_header_64 { uint32_t magic; /* mach magic number identifier */ cpu_type_t cputype; /* cpu specifier */ cpu_subtype_t cpusubtype; /* machine specifier */ uint32_t filetype; /* type of file */ uint32_t ncmds; /* number of load commands */ uint32_t sizeofcmds; /* the size of all the load commands */ uint32_t flags; /* flags */ uint32_t reserved; /* reserved */ };
先頭 4byte
にマジックナンバー、それ以降はcpuのタイプ、fileのタイプと続きます。
また、マジックナンバーは
/* Constant for the magic field of the mach_header_64 (64-bit architectures) */ #define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
と定義されています。
すなわち、実行ファイルを生成するとリトルエンディアンで先頭から CF FA ED FE
と格納されるはずです。
実際に簡単な C
のプログラムを使って確認してみます。
#include <stdio.h> int main() { printf("Hello world\n"); }
これをコンパイルすると、実行時に Hello world
と表示される実行ファイル a.out
が生成されます。
実行ファイルは 0, 1
から成るバイナリデータです。
これからこのバイナリを読みマジックナンバーを確認するわけですが、普通のエディタではバイナリは読めません。
ということで VSCode
の拡張機能 hexdump for VSCode
を使用してみます。
詳しい説明は紹介する記事に譲りますが、 VSCode
上でバイナリを hexdump
した結果を出してくれる優れものです。
ということで Hexdump for VSCode
で実行ファイルを表示した結果がこちら。
先頭4byteは... CF FA ED FE
ということで、マジックナンバーが確認出来ました。
まとめ
- 実行ファイルのファイルフォーマットには ELFやa.out, Mach-Oなどがある。
- 実行ファイルの先頭には様々な情報が詰まったヘッダがあり、ファイルフォーマットを区別するマジックナンバーが付いている。
- Mach-Oのマジックナンバーは
CF FA ED FE
。 - バイナリを読むには
hexdump for VSCode
が非常に便利。
セグメントとかリンカとか知らないことが多すぎる