Mach-O入門
Mach-O(Mach object)
Mach-OとはMach objectの略で、Mac OS Xでプログラムやライブラリをディスクに格納する際に使用されるファイルフォーマットです。Mach-Oのファイルは、先頭にヘッダがあり、load commandおよびsegmentがその後にあります。segmentは複数のsectionを含んでいて、1から連番が振られています。
これらのヘッダの構造は、mach-o/loader.hに記述されています。
Mach-Oヘッダ
Mach-Oファイルは1つのアーキテクチャ向けのコードとデータを格納しています。どのアーキテクチャ向けのファイルかは、Mach-Oヘッダに格納されています。複数のアーキテクチャ向けのMach-Oファイルをまとめたものが、いわゆるユニバーサルバイナリと呼ばれるものです。
Mach-OヘッダはすべてのMach-Oファイルの先頭に必ず存在し、そのファイルがMach-Oファイルであることを表します。Mach-Oヘッダの内容は、otool(1)の-hオプションで見ることができます。
> otool -h /sw/bin/zsh /sw/bin/zsh: Mach header magic cputype cpusubtype filetype ncmds sizeofcmds flags 0xfeedface 7 3 2 15 1588 0x00002085
-vオプションを使用すると、多少親切な表示になります。
> otool -h -v /sw/bin/zsh /sw/bin/zsh: Mach header magic cputype cpusubtype filetype ncmds sizeofcmds flags MH_MAGIC I386 ALL EXECUTE 15 1588 NOUNDEFS DYLDLINK TWOLEVEL SUBSECTIONS_VIA_SYMBOLS
Mach-Oヘッダは次のような構造をしています。
struct mach_header { uint32_t magic; /* マジックナンバー */ cpu_type_t cputype; /* CPUタイプ */ cpu_subtype_t cpusubtype; /* CPUサブタイプ */ uint32_t filetype; /* ファイル形式 */ uint32_t ncmds; /* load commandの数 */ uint32_t sizeofcmds; /* load commandのサイズ */ uint32_t flags; /* フラグ */ };
magicはマジックナンバーです。32bitのMach-Oファイルでは0xfeedface、64ビットのMach-Oファイルでは0xfeedfacfです。
cputypeおよびcpusubtypeはmach/machine.hで記述されているCPU種別です。
filetypeは以下のどれかを表しています。
型名 | 値 | 説明 |
---|---|---|
MH_OBJECT | 0x1 | 再配置可能なオブジェクトファイル |
MH_EXECUTE | 0x2 | 実行可能ファイル |
MH_CORE | 0x4 | コアファイル |
MH_DYLIB | 0x6 | 共有ライブラリ |
MH_DYLINKER | 0x7 | ダイナミックリンカ共有ライブラリ |
MH_BUNDLE | 0x8 | バンドルファイル |
ncmdsはload commandの数を表します。
sizeofcmdsはload commandの合計サイズを表します。
flagsはフラグです。以下のフラグがあります。
フラグ名 | 説明 |
---|---|
MH_NOUNDEFS | ビルド時に未解決の参照がないことを表します |
MH_INCRLINK | インクリメンタルリンクされていることを表します |
MH_DYLDLINK | ダイナミックリンクされていることを表します |
MH_TWOLEVEL | 2レベルの名前空間を使用していることを表します |
MH_BINDATLOAD | ロード時に未解決の参照を解決すべきことを表します |
MH_PREBOUND | 未解決の参照がprebindされていることを表します |
MH_PREBINDABLE | prebind可能であることを表します |
MH_NOFIXPREBINDING | prebind agentに通知しないことを表します |
MH_ALLMODSBOUND | 依存しているライブラリに対して2レベルの名前空間を使用してprebindされていることを表します |
MH_CANONICAL | prebindが解除されていることを表します |
MH_SPLIT_SEGS | 読み込み専用と読み書き可能なsegmentに分割されていることを表します |
MH_FORCE_FLAT | フラットな名前空間を使用していることを表します |
MH_SUBSECTIONS_VIA_SYMBOLS | sectionが分割可能であることを表します |