7

私は Mach-o ファイルがどのように機能するかを理解しようとしており、利用可能なオンライン リソースでかなりの進歩を遂げています (特に、ここの Apple ページ: http://developer.apple.com/library/mac/#documentation ) /developertools/conceptual/MachORuntime/Reference/reference.html ) ですが、シンボル スタブがどのように機能するかを理解する上で障害にぶつかりました。

「otool -l」を使用すると、次のセクションが表示されます。

Section
  sectname __symbolstub1
   segname __TEXT
      addr 0x00005fc0
      size 0x00000040
    offset 20416
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x80000408

しかし、16 進エディタでバイナリ ファイルのデータを見ると、次の 4 バイトが何度も繰り返されていることがわかります。

00005FC0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88
00005FD0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88
00005FE0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88  
00005FF0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88

これは、PC を一定量だけ増加させる LDR のように見えますが、シンボル テーブルの各エントリの量が同じである理由がわかりません。

誰かがなぜそうなのかを明らかにしたり、この低レベルになるリソースを提供したりできる場合は、私に知らせてください.

ありがとう!

4

1 に答える 1

16

現在の iOS での状況を説明しますが、古いバージョンでは多少異なります。

シンボル スタブは実際に関数ポインタを PC にロードします。標準の「レイジー」(オンデマンド) インポートの場合、ポインターはセクション内__lazy_symbolにあり、最初はセクション内のヘルパー ルーチンを指します__stub_helper。たとえば、次のようになります。

__symbolstub1 _AudioServicesAddSystemSoundCompletion
__symbolstub1 LDR  PC, _AudioServicesAddSystemSoundCompletion$lazy_ptr
__symbolstub1 ; End of function _AudioServicesAddSystemSoundCompletion

__lazy_symbol _AudioServicesAddSystemSoundCompletion$lazy_ptr DCD _AudioServicesAddSystemSoundCompletion$stubHelper

__stub_helper _AudioServicesAddSystemSoundCompletion$stubHelper
__stub_helper LDR R12, =nnn ; symbol info offset in the lazy bind table
__stub_helper B   dyld_stub_binding_helper

この関数dyld_stub_binding_helper__stub_helperセクションの最初の関数であり、基本的には dyld の関数への単なるトランポリンであり、dyld_stub_binder私が「シンボル情報オフセット」値と呼ぶものを渡します。その値は、遅延バインディング情報ストリーム (LC_DYLD_INFO または LC_DYLD_INFO_ONLY ロード コマンドによってポイントされる) 内のオフセットであり、dyld のコマンドを含む一種のバイトコード ストリームです。遅延インポートの一般的なシーケンスは次のようになります。

72: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(M, 0xYYYYY)
19: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(NNNN)
40: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x00, '_AudioServicesAddSystemSoundCompletion')
90: BIND_OPCODE_DO_BIND()

ここで、dyld は次のことを行います。

  1. ロード コマンドにリストされている dylib のリストで、dylib 番号 NNNN から「_AudioServicesAddSystemSoundCompletion」という名前の関数を検索します。
  2. 実行可能ファイルのセグメント番号 M を調べます (おそらく __DATA)
  3. 関数ポインタをオフセット YYYYY に書き込みます。
  4. 実際の関数がその仕事をするように、検索されたアドレスにジャンプします

書き込まれたアドレスはたまたま_AudioServicesAddSystemSoundCompletion$lazy_ptrスロットです。そのため、次に_AudioServicesAddSystemSoundCompletionが呼び出されると、dyld を経由せずに、インポートされた関数に直接ジャンプします。

注意: ファイル内のオフセット 05fc0 をすぐに確認しないでください。フィールドは仮想アドレスです。addr含まれているセグメント コマンドを検索し、開始する VA とそのファイル オフセットを確認してから、計算を行う必要があります。通常、__TEXT セグメントは 1000 から始まります。

ただし、実際のシンボル スタブは貼り付けたように見えます。おそらく最初の 1000 バイトを使用するファット ヘッダーを持つファット マッチョがあるため、オフセットが整列します。

于 2012-01-12T14:20:51.227 に答える