検索
連載

第12回 Universal Binary【前編】Undocumented Mac OS X(3/5 ページ)

NeXTのMulti Architecture Binaryそのものと言える技術「Universal Binary」。今回から、Universal Binaryの詳細を解説していこう。

PC用表示 関連情報
Share
Tweet
LINE
Hatena

Mach-OとUniversal Binaryの詳細

 では、Universal Binaryがどういった実装なのかを見てみよう。

 まず、Mac OS XのバイナリフォーマットはほかのUNIXで一般的なELFやCOFFではなく、Mach-Oという形式である。Mach-Oの構造を簡単に説明すると図2のようになる。先頭にMachヘッダがあり、続いて可変長のLoad Commandsがあり、最後に実際のコードやデータをつなぎ合わせたデータ領域がある。Machヘッダには、Machヘッダであることを示す32ビットのmagicナンバー*「0xfeedface」と、対応するCPUのアーキテクチャを示す数値が記載されている(図3)

図2
図2 Mach-Oバイナリの構造
図3
図3 Machヘッダはこのような構造体で表現されている(/usr/include/mach-o/loader.h参照)。構造体の先頭のmagicには、それぞれMH_MAGICで表現される定数が書き込まれている。MH_CIGAMはエンディアンの異なる環境での比較用に定義されている。あらかじめ逆の値を用意しておくことで、エンディアンの変換を1回省略できるからだ

 Load Commandsはダイナミックローダー(dyld)によって実行されるコマンドの集まりで、コードを格納するTEXTセグメントやDATAセグメント、スタックといったメモリ領域を確保、確保したメモリ領域に対して実行ファイルの一部をマップしたり、レジスタの値を設定したり、スレッドを呼び起こしTEXTセグメントにマップされたコードを実行するといった処理が記載されている(図4)。実行ファイルのデータ領域は特に構造を持たないが、このLoad Commandsを読み解いていくことで複数のバイナリデータをつなぎ合わせたものであると分かる。

図4
図4 Load commadsの構造。Load commandsはMachヘッダの後ろに配置され、共通のload_command構造体とそれぞれのコマンドに特有の構造体の組み合わせで構成されている
図5

 Universal Binaryでは、このMachヘッダの前にFATヘッダとfat_archという構造体が置かれる(図5)。FATヘッダにはそれを表すmagicナンバー「0xcafebabe」が記載され、続けてその後に幾つfat_arch構造体が続いているかが示されている。fat_arch構造体にはCPUのアーキテクチャを示す数値とそのアーキテクチャに対応するMachヘッダへのオフセットが記録されている(図6、コラム3

図5 Universal Binaryの構造。Universal Binaryでは、MachヘッダではなくFATヘッダがファイルの先頭に存在する。FATヘッダの後にはfat_arch構造体があり、それぞれの後ろに続くMachヘッダのオフセットを記録している(編集部注:図5はデザイン上の都合でアイコンとして用意しました。上記アイコンをクリックいただくことでご覧いただけます)
図6
図6 FATヘッダとfat_arch構造体。Universal Binaryでは、MachヘッダではなくFATヘッダが先頭に配置される。FATヘッダには定数FAT_MAGICと、続くfat_archの数が記録されている。fat_arch構造体はFATヘッダの後にnfat_archで指定された数だけ配置される。それぞれ、Universal Binaryに含まれるコードに対応し、どのアーキテクチャに対応するか、そのファイル内でのオフセットはどこかなどが記録される

 Darwinカーネルのexecシステムコールは、実行するファイルの先頭が「0xfeedface」だったらそのままdyldに制御を移すが、「0xcafebabe」の場合はこのfat_arch構造体を順番に読み、自身のアーキテクチャに最も適合するものを選択、Machヘッダを読み込みdyldに制御を移す(実行例1、2)

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

実行例1 非Universal Binaryのダンプ。ファイルの先頭にMach-Oのmagicナンバーである0xfeedfaceがあるのが分かる

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

実行例2 Universal Binaryのダンプ。ファイルの先頭にFATヘッダのmagicナンバーである0xcafebabeがあるのが分かる

 なお、先頭16バイトが「0x2321」(ASCIIで「#!」)だった場合、一般のUNIXと同様に実行ファイルはスクリプトだと見なされる。「#!」に続けて指定されたインタープリタに制御が移り、スクリプトが実行される。

Intel CPU搭載Macの場合

 Intel CPUを搭載したMacのカーネルでは、若干処理が異なる。実行ファイルにx86のコードが含まれていない場合、今度はPowerPCのコードを探し、/usr/libexec/oahにあるtransitというバイナリを経由してこれを「実行」する。残念ながらこの部分に関してはまだソースが公開されてないため詳細は不明だが、このtransitというコマンドと、transitからMach-IPCを使って起動されるtransitedというサーバプロセスが、PowerPCコードをIntelのコードに変換するトランスレータ、Rosettaの実体であろう。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

このページで出てきた専門用語

magicナンバー

プログラム中に表れる、明確な意味や役割を持つ具体的な値。


関連キーワード

Mac | Mac OS X | x86 | Apple | WWDC


Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る