2013-05-07 32 views

答えて

7

間接呼び出しとジャンプは、callq *%r13jmpq *0x204d8a(%rip)のように、命令の後で、場所の前に*となります。

私は私のx86-64 Linuxマシンからの二つの実例を紹介します:動的にリンクされた実行可能ファイルの呼び出し

  • ユーザ提供の比較関数を呼び出すC標準ライブラリに

    1. のqsort()のstrcmp()

    GLIBCでのqsort()実装は実際には異なるソートAを呼び出し入力サイズに依存したアルゴリズムです。コードスニペットは、上記R13に比較関数のアドレスを移動し、最終的に間接呼び出しを行い

    0000003cbde37d70 <msort_with_tmp.part.0>: 
        <...> 
        3cbde37dd6: 4c 8b 68 10    mov 0x10(%rax),%r13 
        <...> 
        3cbde37e2f: 41 ff d5    callq *%r13 
    

    :そのような一の実装は /lib64/libc.so.6 にmsort_with_tmp()あります。 のstrcmp()を呼び出して動的にリンクされた実行可能ファイルの

    、私は、一例として/binに/真を使用します。メインの実行中のstrcmp()へのすべての呼び出しは、PLTスタブへの呼び出し、のstrcmpする@ PLTに翻訳されます:

    $ gdb /bin/true 
    (gdb) disassemble '[email protected]' 
    0x401350 <+0>: ff 25 8a 4d 20 00 jmpq *0x204d8a(%rip) # 0x6060e0 <[email protected]> 
    0x401356 <+6>: 68 19 00 00 00 pushq $0x19 
    0x40135b <+11>: e9 50 fe ff ff jmpq 0x4011b0 
    

    最初の命令では、0x204d8a(%リッピング)RIPを使用しています位置付けるための相対アドレス指定[email protected]

    我々はは、実行時に保持しているどのような値[email protected]検査しようとした場合:

    (gdb) break *0x401350 
    (gdb) run --XXX 
    Breakpoint 1, 0x0000000000401350 in [email protected]() 
    
    (gdb) p/a '[email protected]' 
    $1 = 0x3cbdf2fbe0 <__strcmp_sse42> 
    (gdb) break *0x3cbdf2fbe0 
    Breakpoint 2 at 0x3cbdf2fbe0: file ../sysdeps/x86_64/multiarch/strcmp-sse42.S, line 128. 
    (gdb) continue 
    Continuing. 
    
    Breakpoint 2, __strcmp_sse42() 
        at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:128 
    128  mov %esi, %ecx 
    

    我々はは/ usrに__strcmp_sse42()[email protected]ポイントいることがわかり/lib64/libc.so.6。したがって

    私たちが出会った最初の間接ジャンプ、jmpq * 0x204d8a(%リッピング)中のstrcmpする@ PLTは、__strcmp_sse42()にジャンプしてしまいます。これは実際にはSTT_GNU_IFUNCメカニズムです。動的リンカを使用して、実行時にCPUの能力に基づいて最も適切なstrcmp()を検索します。

  • 0

    x86-64 CPUの場合、コールおよびジャンプ命令は暗黙的に%rip相対です。

    ので、関連するモードがあります。

    jmpq $6 # Direct, relative: Jump to %rip+0x6 
    jmpq *$6 # Direct, absolute: Jump to 0x6 
    jmpq %r13 # Indirect, relative: Jump to %rip+%r13 
    jmpq *%r13 # Indirect, absolute: Jump to %r13. Aka "movq %r13, %rip" 
    

    そして二重間接モード:

    jmpq 0x20(%r13) # Jump to %rip + *(%r13 + 0x20). 
    jmpq *0x20(%r13) # Jump to *(%r13 + 0x20) 
    

    が最後のアドレッシングモードは非常に一般的に

    callq *0x20(%r13) 
    

    としてC++解体に見られます%r13にはvtableのアドレスが含まれます。したがって、オフセット0x20のvtableのエントリを検索し、そのエントリが指す関数を呼び出します。 vtableは複数の呼び出しサイトから使用されるため、%RIP相対値は意味をなさないので、常に絶対モード(%RIP相対ではありません)です。

    +0

    'switch'と関数ポインタ呼び出し。 –

    関連する問題