seriruの技術屋ブログ

競技プログラミングやゲーム開発など技術に関することを発信します

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 した結果を出してくれる優れものです。

tarukosu.hatenablog.com

ということで Hexdump for VSCode で実行ファイルを表示した結果がこちら。

f:id:ryo_seriru:20190528231105p:plain

先頭4byteは... CF FA ED FE ということで、マジックナンバーが確認出来ました。

まとめ

  • 実行ファイルのファイルフォーマットには ELFやa.out, Mach-Oなどがある。
  • 実行ファイルの先頭には様々な情報が詰まったヘッダがあり、ファイルフォーマットを区別するマジックナンバーが付いている。
  • Mach-OのマジックナンバーCF FA ED FE
  • バイナリを読むには hexdump for VSCode が非常に便利。

セグメントとかリンカとか知らないことが多すぎる