| ファイル名拡張子 |
なし .o、、、.dylib[ .kext1] |
|---|---|
| 統一型識別子 (UTI) | com.apple.mach-o-binary |
| 開発者 | カーネギーメロン大学、Apple Inc. |
| フォーマットの種類 | バイナリ、実行可能、オブジェクト、共有ライブラリ、コアダンプ |
| コンテナ用 | ARM、SPARC、PA-RISC、PowerPC、x86 実行可能コード、メモリイメージダンプ |
Mach-O は、 Mach オブジェクトファイル形式の略で、実行可能ファイル、オブジェクト コード、共有ライブラリ、動的にロードされるコード、コア ダンプのファイル形式です。a.out 形式を置き換えるために開発されました。
Mach-O は、 Mach カーネルに基づく一部のシステムで使用されます。NeXTSTEP 、macOS、iOS は、ネイティブ実行可能ファイル、ライブラリ、オブジェクト コードにこの形式を使用するシステムの例です。
Mach-O ファイルレイアウト
各 Mach-O ファイルは、1 つの Mach-O ヘッダー、それに続く一連のロード コマンド、それに続く 1 つ以上のセグメントで構成され、各セグメントには 0 ~ 255 のセクションが含まれます。Mach-O は、シンボルへの参照を処理するために REL再配置形式を使用します。シンボルを検索するとき、Mach-O は 2 レベルの名前空間を使用し、各シンボルを「オブジェクト/シンボル名」のペアにエンコードします。その後、最初にオブジェクト、次にシンボル名で線形検索されます。[2]
基本構造は、ファイル内の他の場所にあるデータページを参照する可変長の「ロードコマンド」のリスト[3]であり、 Accentの実行可能ファイル形式でも使用されていました。[引用が必要] Accent ファイル形式は、 Spice Lisp のアイデアに基づいています。[引用が必要]
すべてのデータ構造内のすべてのマルチバイト値は、コードが生成されたホストのバイト順序で書き込まれます。[4]
Mach-O ヘッダー
32 ビット コードのマジック ナンバーは です0xfeedfaceが、64 ビット アーキテクチャのマジック ナンバーは です0xfeedfacf。
予約値は 64 ビット Mach-O ファイルにのみ存在します。これは、将来の使用または 64 ビット ヘッダーの拡張のために予約されています。
CPU タイプは、コードの命令セット アーキテクチャを示します。ファイルが 64 ビット バージョンの命令セット アーキテクチャ用の場合、CPU タイプ値には0x01000000ビットが設定されます。
CPUタイプの値は次のとおりです。[6]
各 CPU タイプには、コードが対象とする CPU タイプの特定のモデルを示す CPU サブタイプ値のセットがあります。CPU タイプの新しいモデルは、古い CPU モデルでサポートされていない命令やその他の機能をサポートしている場合があります。そのため、新しいモデル用にコンパイルまたは作成されたコードには、古いモデルでは不正な命令が含まれる可能性があり、そのコードが古いモデルで実行されるとトラップしたり、正しく動作しなくなったりすることがあります。古いモデル用のコードは、新しいモデルでも問題なく実行されます。
CPUタイプがARMの場合、サブタイプは次のようになります。[6]
CPUタイプがx86の場合、サブタイプは次のようになります。[6]
サブタイプ値の後にはファイル タイプ値が続きます。
ファイル タイプ値の後には、ロード コマンドの数と、Mach-O ヘッダーの後のロード コマンドの合計バイト数が続き、その後に次の設定が可能な 32 ビット フラグが続きます。
フラグ内で複数のバイナリ桁を 1 つに設定して、バイナリに適用される情報や設定を識別できます。
Mach-O ヘッダーの末尾に到達したため、ロード コマンドが読み取られます。
マルチアーキテクチャバイナリ
複数のMach-Oファイルをマルチアーキテクチャバイナリに組み合わせることができます。これにより、単一のバイナリファイルに、 ARM64やx86-64などの異なるプロセッサアーキテクチャ[7]を含む、さまざまな世代や種類のAppleデバイスなどの複数の命令セットアーキテクチャをサポートするコードを含めることができます。[8]
ユニバーサルヘッダー内のすべてのフィールドはビッグエンディアンです。[4]
ユニバーサルヘッダーは次の形式です: [9]
マルチアーキテクチャバイナリのマジックナンバーは0xcafebabeビッグエンディアンのバイト順なので、ヘッダーの最初の 4 バイトは常に0xca 0xfe 0xba 0xbeその順序になります。
バイナリの数は、ヘッダーに続くエントリの数です。
ヘッダーの後に、次の形式のエントリのシーケンスが続きます。[10]
エントリのシーケンスの後に、Mach-O イメージのシーケンスが続きます。各エントリは Mach-O イメージを参照します。
エントリの CPU タイプとサブタイプは、エントリが参照する Mach-O イメージの CPU タイプとサブタイプと同じである必要があります。
ファイル オフセットとサイズは、エントリが参照する Mach-O イメージの先頭のファイル内のオフセットと Mach-O イメージのサイズです。
セクション アラインメントは、エントリが参照する Mach-O イメージに必要なファイル内のバイト アラインメントの 2 を底とする対数です。たとえば、値が 14 の場合、イメージは 2 14バイト境界、つまり 16384 バイト境界にアラインメントされている必要があります。これは、マルチアーキテクチャ バイナリを変更するツールによって、イメージを適切にアラインメントするために必要となります。
ロードコマンド
ロード コマンドは Mach-O ヘッダーの直後に読み取られます。
Mach-O ヘッダーは、Mach-O ヘッダーの後に存在するロード コマンドの数と、ロード コマンドが終了するバイト単位のサイズを示します。ロード コマンドのサイズは冗長性チェックとして使用されます。
最後のロード コマンドが読み取られ、ロード コマンドのバイト数が一致しない場合、または最後のロード コマンドに到達する前にロード コマンドのバイト数を超えると、ファイルが破損する可能性があります。
各ロードコマンドは、次の形式のエントリのシーケンスです。[11]
ロード コマンド タイプは、ロード コマンド内のパラメータを識別します。ロード コマンドが0x80000000ビット セットで始まる場合、バイナリをロードまたは実行するためにロード コマンドが必要であることを意味します。これにより、古い Mach-O ローダーは、アプリケーションのロードに必須ではない、ローダーが理解できないコマンドをスキップできます。
セグメントロードコマンド
ロードコマンドタイプを使用するMach-Oバイナリは0x00000001、セグメントロードコマンドの32ビットバージョンを使用します。[12]は0x00000019、セグメントロードコマンドの64ビットバージョンを指定するために使用されます。[13]
セグメント ロード コマンドは、Mach-O ヘッダーが 32 ビットか 64 ビットかによって異なります。これは、64 ビット プロセッサ アーキテクチャでは 64 ビット アドレスが使用され、32 ビット アーキテクチャでは 32 ビット アドレスが使用されるためです。
すべての仮想 RAM アドレスは、アプリケーションの間隔を保つためにベース アドレスに追加されます。セグメント ロード コマンドの各セクションには、アプリケーションのベース アドレスに基づいて調整する必要があるセクション内のオフセットを指定する再配置リスト オフセットがあります。アプリケーションを、ベース アドレス 0 などの定義済みの RAM アドレス位置に配置できる場合は、再配置は不要です。
セグメント名は、バイト単位で 16 文字を超えることはできません。未使用の文字は0x00値に含まれます。
セグメント コマンドには、仮想アドレス空間にセクションを書き込むアドレスとアプリケーションのベース アドレスが含まれます。アドレス位置に書き込むバイト数 (アドレス サイズ)。
アドレス情報の後には、Mach-O バイナリ内のセグメント データが配置されているファイル オフセットと、ファイルから読み取るバイト数が続きます。
アドレス サイズがファイルから読み取るバイト数より大きい場合、RAM 空間の残りのバイトが設定されます0x00。
__PAGEZERO と呼ばれるセグメントがあり、ファイル オフセットが 0 で、ファイル内のサイズが 0 です。このセグメントには、定義された RAM アドレスとサイズがあります。ファイルから 0 バイトを読み取るため、バイナリが RAM に配置されるアドレス位置が 0 で埋められます。このセグメントは、以前のアプリケーションからのデータをすべてセクションから取り除くために必要です。
セグメントが最初に仮想アドレス空間に配置されると、初期仮想メモリ保護値によって指定された CPU アクセス許可が付与されます。仮想アドレス空間の領域に対するアクセス許可は、 などのルーチンを呼び出すアプリケーションまたはライブラリ コードによって変更される場合がありますmprotect()。最大仮想メモリ保護によって、セグメントへのアクセスに付与できるアクセス許可が制限されます。
次に、CPU アドレス保護設定の後に、セグメント フラグ設定の後に読み取られるこのセグメント内のセクションの数があります。
セグメントフラグの設定は次のとおりです。
セグメント内のセクションの数は、次のように読み取られるエントリのセットです。
セクションのセグメント名は、セグメントのロード コマンド名と一致する必要があります。セクション エントリは、セグメント内のデータに位置付けられます。アプリケーション ベース アドレスがゼロ以外の値に追加された場合は、各セクションは、セクション内のアドレスを調整するための再配置エントリに位置付けられます。
セクション サイズは、セクションのアドレス位置のサイズと、ファイル内のオフセット位置のサイズの両方に適用されます。
セクションのフラグ/タイプの値は次のように読み取られます。
セクションに適用される設定には、バイナリ桁が 1 に設定されています。最後の 8 つのバイナリ桁は、セクション タイプ値です。
Mach-O ローダーは、シンボル ポインター セクションとシンボル スタブ セクションを記録します。これらは、間接シンボル テーブルによって順番に使用され、メソッド呼び出しにロードされます。
各シンボル スタブのサイズは、reserved2 値に格納されます。各ポインターは、32 ビット Mach-O では 32 ビットのアドレス位置、64 ビット Mach-O では 64 ビットのアドレス位置です。セクションの終わりに達すると、間接シンボル テーブルを読み取りながら次のセクションに移動します。
セグメント番号とセクション番号
セグメントとセクションは、圧縮および非圧縮のリンク編集情報セクション内のセグメント番号とセクション番号によって配置されます。
セグメント値 3 は、Mach-O ファイル内の 0 から始まる 4 番目のセグメント ロード コマンドのデータへのオフセットを意味します (0、1、2、3 = 4 番目のセグメント)。
セクションもセクション 1 から番号が付けられます。セクション値 0 は、どのセクションでも定義されていないシンボル (未定義) のシンボル テーブルで使用されます。たとえば、メソッドや、別のバイナリ シンボル テーブル セクション内に存在するデータなどです。
7 つのセクションがあるセグメントの場合、最後のセクションは 8 になります。次のセグメント ロード コマンドに 3 つのセクションがある場合、セクション 9、10、11 というラベルが付けられます。セクション番号 10 は、2 番目のセグメント、セクション 2 を意味します。
セクションの読み取り順序とアドレス/ファイル オフセット位置を保存しないと、シンボル テーブルとリンク情報を適切に読み取ることができません。
RAM アドレスや再配置を使用せずにファイル オフセットを簡単に使用して、シンボル リーダーを構築し、リンク編集セクションを読み取ったり、メソッド呼び出しをマップしたり、逆アセンブラーを設計したりすることができます。
Mach-O ローダーを構築する場合は、アプリケーションが互いに上書きされないように、アプリケーション間の間隔を保つために、セクションを定義された RAM アドレスとベース アドレスにダンプする必要があります。
セグメント名とセクション名は好きな名前に変更でき、セグメント コマンドの順序を変更しない限り、セクション番号またはセグメント番号で適切なセクションを見つけるのに問題はありません。
リンクライブラリ
リンク ライブラリは他の Mach-O バイナリと同じですが、プログラムが開始されるメイン エントリ ポイントを指定するコマンドはありません。
リンク ライブラリ ファイルをロードするためのロード コマンドは 3 つあります。
ロード コマンド タイプは、0x0000000C動的にリンクされた共有ライブラリへの完全なファイル パス用です。
ロード コマンド タイプは、0x0000000Dアプリケーションの現在のパスから動的にリンクされた共有場所用です。
ロード コマンド タイプは0x00000018、欠落が許可されている動的にリンクされた共有ライブラリ用です。シンボル名は他のリンク ライブラリに存在し、ライブラリが欠落している場合に使用されます。つまり、すべてのシンボルが弱くインポートされます。
リンク ライブラリ コマンドは次のように読み取られます。
ファイル パス名は、常に 24 である文字列オフセットから始まります。テキスト文字あたりのバイト数は、コマンド サイズの残りのバイト数です。ライブラリ ファイル パスの末尾は、 という文字で識別されます0x00。残りの0x00値は、パディングとして使用されます (存在する場合)。
リンクライブラリ序数
ライブラリは、圧縮および非圧縮のリンク編集情報セクション内の序数によって配置されます。
リンク ライブラリには、序数 1 から番号が付けられます。序数値 0 は、シンボル テーブルで、シンボルが別の Mach-O バイナリに外部シンボルとして存在しないことを指定するために使用されます。
リンク ライブラリ コマンドの順序を変更しない限り、リンク編集情報では、順序番号によって読み取る適切なライブラリを問題なく見つけることができます。
パフォーマンス上の理由から、リンク ライブラリ コマンドは0x00000018使用しないでください。ライブラリが見つからない場合、ロードされているすべてのリンク ライブラリを検索する必要があります。
__LINKEDIT シンボルテーブル
Mach-O アプリケーション ファイルとリンク ライブラリの両方にシンボル テーブル コマンドがあります。
コマンドは次のように読みます。
シンボル ファイル オフセットは、Mach-O ヘッダーの開始からファイル内のシンボル エントリの開始位置までの相対的なオフセットです。シンボル エントリの数は、シンボル テーブルの終わりを示します。
シンボルには、文字列テーブルのサイズを超えない名前オフセットがあります。各シンボル名オフセットは、文字列テーブル ファイルのオフセットに追加されます。このオフセットは、Mach-O ヘッダーの開始に相対的です。各シンボル名は、0x00バイト値で終わります。
シンボル アドレスは、32 ビット Mach-O ファイルの場合は 32 ビット アドレスを使用し、64 ビット Mach-O ファイルの場合は 64 ビット アドレスを使用します。
各シンボルエントリは次のように読み取られます。
シンボル名オフセットが文字列テーブル オフセットに追加されます。最後のテキスト文字バイトは として読み取られます0x00。
シンボル タイプ値には、バイナリで調整可能な複数のセクションがあります。シンボル タイプは次のように読み取られます。
マークされた数字は?指定された目的に使用され、マークされた数字はx他の目的に使用されます。
最初の 3 つの 2 進数字は、コンパイルされたマシン コード命令を基準とした関数名と、アドレス位置による行番号を特定するシンボルです。この情報により、コードがクラッシュした場所の行番号を生成できます。ローカル デバッグ シンボルは、アプリケーションを設計するときにのみ役立ちますが、アプリケーションを実行するためには必要ありません。
次のフラグ設定:
外部シンボルは、リンク ライブラリ内に定義されたアドレスを持ち、Mach-O アプリケーション内の未定義シンボルにコピーできるシンボルです。アドレスの場所は、リンク ライブラリのベース アドレスに追加されます。
プライベート シンボルは、未定義のシンボルの名前と一致していてもスキップされます。プライベート シンボルと外部シンボルは、同じファイル内にある場合にのみ、未定義のシンボルに設定できます。
シンボル タイプの後には、シンボルが存在するセクション番号が続きます。セクション番号はバイト値 (0 ~ 255) です。セグメント ロード コマンドを使用して 255 を超えるセクションを追加できますが、その場合、セクション番号はシンボル エントリで使用されるバイト値の範囲外になります。
セクション番号が 0 の場合、シンボルはアプリケーションのどのセクションにも存在せず、シンボルのアドレス位置は 0 であり、未定義として設定されます。一致する外部シンボル名は、シンボル アドレスを持つリンク ライブラリで見つかる必要があります。
データ情報フィールドには、一致するシンボル名を持つ外部シンボルが見つかるリンク ライブラリの序数が含まれます。データ情報ビット フィールドは次のように分類されます。
シンボルが外部シンボルであるか、現在のファイル内に存在する場合、ライブラリ序数は 0 に設定されます。未定義のシンボルのみが、データ情報セクションを使用してライブラリ序数とリンカー オプションを指定します。
ダイナミック ローダー フラグのオプションは次のとおりです。
適用される 4 つのオプションのいずれかを設定できます。
アドレス タイプ オプションの値は次のとおりです。
値によって設定できるのは、アドレス タイプの 1 つの値だけです。ポインターは、プログラム マシン コードによって読み取られ、別のバイナリ ファイルからメソッドを呼び出す値です。プライベートとは、他のプログラムがバイナリ自体以外の関数/メソッドを読み取ったり呼び出したりできないようにすることを意味します。レイジーとは、ポインターが dyld_stub_binder に移動し、シンボルを検索してメソッドを呼び出し、dyld_stub_binder の場所をシンボルの場所に置き換えることを意味します。バイナリ内のマシン コードから実行されるそれ以上の呼び出しは、シンボルのアドレスに移動し、dyld_stub_binder は呼び出されません。
シンボルテーブルの構成
シンボル テーブル エントリはすべて、タイプ順に保存されます。最初に読み取られるシンボルは、ローカル デバッグ シンボル (存在する場合)、次にプライベート シンボル、次に外部シンボル、最後に別の Mach-O バイナリの外部シンボル アドレスを含む別のバイナリ シンボル テーブルにリンクする未定義シンボルです。
シンボル テーブル情報ロード コマンドは、0x0000000BMach-O バイナリにシンボル テーブル セクションがある場合に常に存在します。このコマンドは、ローカル シンボルの数、プライベート シンボルの数、外部シンボルの数、および未定義シンボルの数をリンカーに通知します。また、シンボルの開始番号も識別します。シンボル テーブル情報は、動的リンカーがシンボル エントリを読み取る前に使用されます。これは、未定義シンボルをロードするシンボルの読み取りを開始する場所と、すべてのシンボル エントリを読み取ることなく一致する外部シンボルを探す読み取りを開始する場所を動的リンカーに通知するためです。
各シンボルは 0 から順に番号が付けられるため、シンボル セクション内のシンボルの順序は変更しないでください。シンボル テーブル情報コマンドは、未定義のシンボルをスタブおよびポインター セクションにロードする順序としてシンボル番号を使用します。順序を変更すると、マシン コード実行中に間違ったメソッドが呼び出されることになります。
__LINKEDIT シンボルテーブル情報
0x00000002シンボル テーブル情報コマンドは、リンク中に未定義のシンボルと外部シンボルを高速に検索するために、
ダイナミック リンカーがシンボル テーブル コマンドの下にあるシンボル テーブル エントリをどこで読み取るかを知るために使用されます。
コマンドは次のように読みます。
シンボル インデックスは、Mach-O 32 ビットの場合は 12 倍、Mach-O 64 ビットの場合は 16 倍に、シンボル テーブル エントリのオフセットを加算して、シンボル番号インデックスによってシンボル エントリを読み取るためのオフセットを見つけます。
ローカル シンボル インデックスは、シンボル エントリの先頭にあるため 0 です。ローカル シンボルはデバッグ情報に使用されます。
ローカル シンボルの数は、シンボル インデックスの後に存在するシンボルの数です。
シンボル テーブル エントリを高速に読み取るために、外部シンボルと未定義シンボルに対して同じ 2 つのプロパティが繰り返されます。
プライベート シンボルがある場合、ローカル シンボルと外部シンボルの間には小さなインデックス/サイズのギャップがあります。
ゼロのファイル オフセットは未使用です。
間接テーブル
Mach-O ローダーは、セグメント ロード コマンド中にシンボル ポインター セクションとシンボル スタブ セクションを記録します。これらは間接シンボル テーブルによって順番に使用され、メソッド呼び出しでロードされます。セクションの終わりに達すると、次のセクションに移動します。
間接シンボル テーブル オフセットは、シンボル番号インデックスとして使用される 32 ビット (4 バイト) 値のセットを特定します。
シンボル インデックス番号の順序は、ポインター セクションとスタブ セクションに各シンボル アドレスを次々に書き込む順序です。
シンボル スタブ セクションには、別の Mach-O バイナリからメソッド/関数を呼び出すための間接シンボル アドレスへの JUMP 命令を含むマシン コード命令が含まれます。各 JUMP 命令のサイズはプロセッサ タイプに基づいており、セグメント ロード コマンドの section32/64 の下の reserved2 値に格納されます。
ポインター セクションは、32 ビット Mach-O バイナリの場合は 32 ビット (4 バイト) のアドレス値、64 ビット Mach-O バイナリの場合は 64 ビット (8 バイト) のアドレス値です。ポインターはマシン コードによって読み取られ、読み取られた値は、マシン コード命令を格納するのではなく、メソッド/関数を呼び出す場所として使用されます。
シンボル インデックス番号0x40000000ビット セットは絶対メソッドであり、ポインターがメソッドの正確なアドレスに配置されることを意味します。
シンボル インデックス番号0x80000000ビット セットはローカル メソッドであり、ポインター自体がメソッドに配置され、メソッド名がないことを意味します (ローカル メソッド)。
逆アセンブラを設計している場合は、シンボル名だけを各スタブとポインタのオフセット アドレスに簡単にマップして、他の Mach-O ファイルで未定義のシンボル アドレスの場所を探すことなく、実行されているメソッドまたは関数の呼び出しを表示できます。
__LINKEDIT 圧縮テーブル
圧縮リンク編集テーブル コマンドが存在する場合、シンボル テーブル内の未定義/外部シンボルは不要になります。間接シンボル テーブルとスタブおよびポインター セクションの場所は不要になります。
新しい OS バージョンと古い OS バージョンでロードされる下位互換性のある Mach-O ファイルを構築する場合、間接シンボル テーブルは依然として存在します。
ファイル オフセットがゼロの場合は、未使用のセクションになります。
バインディング情報
バインド、弱いバインド、および遅延バインド セクションは、同じ操作コード形式を使用して読み取られます。
元々、シンボル テーブルは、シンボル テーブルのデータ情報フィールドのアドレス タイプを、遅延、弱、または非遅延として定義します。
弱い結合とは、ライブラリ序数で検索するライブラリが設定されており、設定されたシンボル名が存在しないが、以前にロードされた別の Mach-O ファイルに存在する場合、シンボルの場所は他の Mach-O ファイルから使用されることを意味します。
遅延とは、書き込まれたアドレスが dyld_stub_binder に配置され、シンボルを検索してメソッドを呼び出し、dyld_stub_binder の場所をシンボルの場所に置き換えることを意味します。バイナリ内のマシン コードから実行されるそれ以上の呼び出しは、シンボルのアドレスに配置され、dyld_stub_binder は呼び出されません。
単純な古いバインド セクションでは、複雑な読み込みやアドレス指定のトリックは実行されません。シンボルは、設定されたライブラリ序数内に存在する必要があります。
リンク ライブラリの序数を設定するバイト値0x1X。16 進数 X は、0 から 15 までのライブラリ序数です。
リンク ライブラリの序数を、操作コードの後に読み取られる値に設定する
0x20バイト値。0x2F
バイトシーケンス0x20 0x84 0x01セットの序数 132。
演算コードの後の数値は、LEB128数値としてエンコードされます。最後の 7 つの 2 進数字が加算されて、最後の 2 進数字が値に 1 に設定されている限り、より大きな数値が形成されます。これにより、可変長の数値をエンコードできます。
シンボル名を設定するバイト値0x4X。X でマークされた 16 進数はフラグ設定を設定します。
フラグ設定 8 は、メソッドが弱インポートされていることを意味します。フラグ設定 1 は、メソッドが非弱インポートされていることを意味します。
バイト シーケンスは0x48 0x45 0x78 0x61 0x6D 0x70 0x6C 0x65 0x00、シンボル名の例を設定します。最後のテキスト文字バイトは です0x00。これは弱いインポートでもあり、同じ名前の別のエクスポート可能なシンボルが見つかった場合に置き換えられることを意味します。
バイト値によって0x7X現在の位置が設定されます。X でマークされた 16 進数は、選択されたセグメント 0 ~ 15 です。操作コードの後には、セグメント オフセットに
LEB128番号として追加されたオフセットが続きます。
バイト シーケンスは、0x72 0x8C 0x01位置を 3 番目のセグメント ロード コマンド アドレスに設定し、アドレスに 140 を追加します。
0x90現在のセット位置をセット シンボル名とライブラリ序数にバインドする操作コード0x9F。32 ビット Mach-O バイナリの場合は現在のセット位置を 4 バイト増分し、64 ビット Mach-O バイナリの場合はセット アドレスを 8 増分します。
バイトシーケンス0x11 0x72 0x8C 0x01 0x48 0x45 0x78 0x61 0x6D 0x70 0x6C 0x65 0x00 0x90 0x48 0x45 0x78 0x61 0x6D 0x70 0x6C 0x65 0x32 0x00 0x90
リンク ライブラリの序数を 1 に設定します。位置をセグメント番号 2 に設定し、現在の位置に 140 を追加します。選択したライブラリ序数で Example という名前のシンボルを検索します。操作コードは0x90シンボル アドレスを書き込み、現在の設定アドレスを増分します。その後の操作コードは、次のシンボル名を設定して、Example2 という名前のシンボルを検索します。操作コードは0x90シンボル アドレスを書き込み、現在の設定アドレスを増分します。
新しい形式では、シンボル テーブル内の繰り返しフィールドが削除され、間接シンボル テーブルは廃止されます。
アプリケーションのメインエントリポイント
type で始まるロード コマンドは、0x00000028アプリケーションが開始するアドレス位置を指定するために使用されます。
プログラムのセグメント/セクションを実行するために再配置する必要がない場合、メイン エントリ ポイントは正確なアドレス位置になります。これは、アプリケーション セグメント アドレスがアプリケーション ベース アドレス 0 に追加され、セクションの再配置が不要であった場合にのみ当てはまります。
Mach-O ローダーの主なエントリ ポイントは、プログラムのベース アドレスとアドレス位置です。これは、CPU がマシン コード命令の実行を開始するように設定されているアドレスです。
0x00000005これは、プログラムの開始前にすべてのレジスタが持つべき状態を保存するため、CPU タイプによって異なっていた
古いロード コマンドに代わるものです。
アプリケーションUUID番号
type で始まるロード コマンドは、アプリケーションの
ユニバーサル一意識別子0x0000001B(UUID)を指定するために使用されます。
UUID には、アプリケーションがコンパイルされたときに生成される 128 ビットの一意のランダム番号[引用が必要]が含まれており、インターネット上またはアプリ ストアでアプリケーション ファイルを識別するために使用できます。
最小OSバージョン
type で始まるロード コマンドは、0x00000032最小 OS バージョン情報を指定するために使用されます。
バイナリの実行対象となるプラットフォームの種類は次のとおりです。
32 ビット バージョン値は、16 ビット値と 2 つの 8 ビット値として読み取られます。 の 32 ビット バージョン値は、値が 13 である 、次の 8 ビットは値が 2 である 、最後の 8 ビットは値が 0 である と0x000D0200分解され、バージョン番号は 13.2.0v になります。 SDK バージョン値も同様に読み取られます。
0x000D0x020x00
バイナリを作成するツールの数は、次のように読み取られるエントリのセットです。
ツールタイプの値は次のとおりです。
バージョン番号は、OS バージョンや SDK バージョンと同じように読み取られます。
Mac OS X 10.6プラットフォームの導入により、Mach-O ファイルは大幅に変更され、10.6 以降で実行されているコンピュータでコンパイルされたバイナリは、(デフォルトでは) Mac OS X 10.6 以降で実行されているコンピュータでのみ実行可能になりました。この違いは、以前の Mac OS X バージョンのダイナミック リンカーが理解できないロード コマンドに起因しています。Mach-O 形式のもう 1 つの重要な変更は、リンク編集テーブル (__LINKEDIT セクションにあります) の機能の変更です。10.6 では、これらの新しいリンク編集テーブルは、使用されていない不要な情報を削除することによって圧縮されますが、Mac OS X 10.5 以前では、この新しいリンク編集テーブル形式を読み取ることができません。下位互換性のある実行ファイルを作成するには、リンカー フラグ "-mmacosx-version-min=" を使用できます。
その他の実装
Mach-O アプリケーションは、コンピュータのコア タイプと一致する Mach-O バイナリ イメージが存在する限り、異なるオペレーティング システムまたは OS で実行できます。ほとんどのデスクトップは x86 であるため、セクションをメモリにロードすれば、x86 バイナリの Mach-O は問題なく実行されます。Mach-O が ARM コアを持つ iPhone 用に設計されている場合、それを実行するには ARM コア (Apple Silicon ARM である必要はありません) を搭載した PC が必要になります。そうでない場合は、ARM でエンコードされた命令を同等の x86 でエンコードされた命令に変更する必要があります。Mach-O をロードして直接実行すると、別のオペレーティング システムに存在しない他の Mach-O バイナリから関数/メソッドを呼び出す未定義のシンボルが発生するという問題があります。一部のシンボルは、異なるオペレーティング システムで同等の他の関数を呼び出すことも、アダプタ関数を呼び出して他のバイナリ関数呼び出しを macOS の同等の機能のように動作させることさえできます。デバイスに保存される Mach-O ファイルは、iPhone (iOS)、macOS、watchOS、tvOS 間で異なる場合があります。未定義のシンボルからの関数呼び出しに違いが発生します。
NetBSDのいくつかのバージョンでは、バイナリ互換性の実装の一環としてMach-Oサポートが追加され、一部のMac OS 10.3バイナリを実行できるようになりました。[14] [15]
Linuxでは、浜地真一郎氏[16]が10.6バイナリをロードできるMach-Oローダーを作成しました。このローダーをベースにしたより拡張性の高いソリューションとして、DarlingプロジェクトはmacOSアプリケーションをLinux上で実行できる完全な環境を提供することを目指しています。
Rubyプログラミング言語の場合、ruby-macho [17]ライブラリはMach-Oバイナリパーサーとエディターの実装を提供します。
参照
参考文献
- ^ Mach-O プログラミングトピック(PDF) . Apple. 2006 年 11 月 28 日。
- ^ 「OS X ABI Mach-O ファイル形式リファレンス」。Apple Inc. 2009年2月4日。2014年9月4日時点のオリジナルよりアーカイブ。
- ^ Avadis Tevanian, Jr.、Richard F. Rashid、Michael W. Young、David B. Golub、Mary R. Thompson、William Bolosky、Richard Sanzi (1987 年 6 月)。「Mach での共有メモリとメモリ マップ ファイル用の Unix インターフェイス」。USENIXサマー カンファレンスの議事録。米国アリゾナ州フェニックス: USENIX 協会}。pp. 53–67。
- ^ ab 「データ型」。OS X ABI Mach-O ファイル形式リファレンス。Apple Inc. 2009年2月4日 [2003]。2014年9月4日時点のオリジナルよりアーカイブ。
- ^ GitHubの loader.h
- ^ GitHubのabc machine.h
- ^ 「ユニバーサルバイナリと32ビット/64ビットPowerPCバイナリ」。OS X ABI Mach-Oファイルフォーマットリファレンス。Apple Inc. 2009年2月4日[2003]。2014年9月4日時点のオリジナルよりアーカイブ。
- ^ 「ユニバーサルmacOSバイナリの構築」。Apple Developer。
- ^ "fat_header". OS X ABI Mach-O ファイル形式リファレンス。Apple Inc. 2009年2月4日 [2003]。2014年9月4日時点のオリジナルよりアーカイブ。
- ^ "fat_arch". OS X ABI Mach-O ファイル形式リファレンス。Apple Inc. 2009年2月4日 [2003]。2014年9月4日時点のオリジナルよりアーカイブ。
- ^ 「Load Command Data Structures」。OS X ABI Mach-O ファイル形式リファレンス。Apple Inc. 2009 年 2 月 4 日 [2003]。2014 年 9 月 4 日時点のオリジナルよりアーカイブ。
- ^ "segment_command". OS X ABI Mach-O ファイル形式リファレンス。Apple Inc. 2009年2月4日 [2003]。2014年9月4日時点のオリジナルよりアーカイブ。
- ^ "segment_command_64". OS X ABI Mach-O ファイル形式リファレンス。Apple Inc. 2009年2月4日 [2003]。2014年9月4日時点のオリジナルよりアーカイブ。
- ^ Emmanuel Dreyfus (2006 年 6 月 20 日). 「NetBSD/powerpc および NetBSD/i386 の Mach および Darwin バイナリ互換性」 。2013年10 月 18 日閲覧。
- ^ Emmanuel Dreyfus (2004 年 9 月)、NetBSD における Mac OS X バイナリ互換性: 課題と実装(PDF)
- ^ Shinichiro Hamaji、Linux 用 Mach-O ローダー - 私が書いた...
- ^ William Woodruff (2021 年 11 月 15 日)、Mach-O ファイルを解析するための純粋な Ruby ライブラリ。
文献
- レビン、ジョナサン(2019年9月25日)。*OS内部、第1巻:ユーザーモード(v1.3.3.7版)。ノースキャッスル、ニューヨーク:Technologeeks。ISBN 978-0-9910555-6-2。
- Singh, Amit (2006 年 6 月 19 日)。Mac OS X 内部: システムアプローチ。Addison -Wesley Professional。ISBN 978-0-13-270226-3。
外部リンク
- Wayback Machineの OS X ABI Mach-O ファイル形式リファレンス(2014 年 9 月 4 日アーカイブ) (Apple Inc.)
- – DarwinとmacOSファイル形式マニュアル
- Mach オブジェクト ファイル (NEXTSTEP ドキュメント)
- Mach-O ダイナミック ライブラリ リファレンス
- Mach-O のリンクとロードのトリック
- マックオビュー
- JDasm (macOS、iOS、Windows PE、ELF 用のクロスプラットフォーム逆アセンブラー、およびファイル形式分析ツール)
