1. ホーム
  2. assembly

[解決済み] ここでいう「@plt」とは、どういう意味でしょうか?

2023-03-28 06:15:55

質問

0x00000000004004b6 <main+30>:   callq  0x400398 <printf@plt>

どなたかご存知ですか?

アップデイト

なぜ2つの disas printf は異なる結果をもたらすのでしょうか?

(gdb) disas printf
Dump of assembler code for function printf@plt:
0x0000000000400398 <printf@plt+0>:  jmpq   *0x2004c2(%rip)        # 0x600860 <_GLOBAL_OFFSET_TABLE_+24>
0x000000000040039e <printf@plt+6>:  pushq  $0x0
0x00000000004003a3 <printf@plt+11>: jmpq   0x400388

(gdb) disas printf
Dump of assembler code for function printf:
0x00000037aa44d360 <printf+0>:  sub    $0xd8,%rsp
0x00000037aa44d367 <printf+7>:  mov    %rdx,0x30(%rsp)
0x00000037aa44d36c <printf+12>: movzbl %al,%edx
0x00000037aa44d36f <printf+15>: mov    %rsi,0x28(%rsp)
0x00000037aa44d374 <printf+20>: lea    0x0(,%rdx,4),%rax
0x00000037aa44d37c <printf+28>: lea    0x3f(%rip),%rdx        # 0x37aa44d3c2 <printf+98>

どのように解決するのですか?

これは、各プロセスのコードの個別のコピーを維持することなく、コードの修正(異なるプロセス間で異なる可能性がある、コードが仮想メモリに位置する場所に基づいてアドレスを調整する)を取得する方法です。PLTは プロシージャリンケージテーブル であり、動的ロードとリンクを使いやすくするための構造の 1 つです。

printf@plt は実際には小さなスタブで、(最終的には) 本当の printf 関数を呼び出す小さなスタブで、その後の呼び出しがより速くなるように途中で修正します。

リアル printf 関数は 任意の の場所にマッピングされるかもしれません。

したがって、呼び出し側のコード (以下、左側) と被呼び出し側のコード (以下、右側) の適切なコード共有を可能にするために、呼び出し側のコードに直接修正を適用することは望ましくありません。 その他の プロセスで配置できる場所が制限されるからです。

そのため PLT は、より小さな プロセス固有の の領域で、実行時に確実に計算されるアドレスにあります。 そのため、任意のプロセスは、悪影響を及ぼすことなく、自由にそれを変更することができます。


次の図は、あなたのコードとライブラリのコードの両方が、2 つの異なるプロセスで異なる仮想アドレスにマッピングされていることを表しています。 ProcAProcB :

Address: 0x1234          0x9000      0x8888
        +-------------+ +---------+ +---------+
        |             | | Private | |         |
ProcA   |             | | PLT/GOT | |         |
        | Shared      | +---------+ | Shared  |
========| application |=============| library |==
        | code        | +---------+ | code    |
        |             | | Private | |         |
ProcB   |             | | PLT/GOT | |         |
        +-------------+ +---------+ +---------+
Address: 0x2020          0x9000      0x6666

この特定の例は、PLTが固定された場所にマッピングされる単純なケースを示しています。この例では あなたの シナリオでは、プログラム カウンター相対検索で証明されるように、それは現在のプログラム カウンターに対して相対的に配置されます。

<printf@plt+0>: jmpq  *0x2004c2(%rip)  ; 0x600860 <_GOT_+24>

例をよりシンプルにするために、固定アドレスにしただけです。

オリジナル でロードする必要がありました。 同じ メモリ位置にロードする必要がありました。そのため、コードを共有することができませんでした。 シングル を修正する行為は、それが別の場所にマッピングされた他のプロセスを完全に混乱させるからです。

PLT とグローバル オフセット テーブル (GOT) とともに、位置に依存しないコードを使用することで 最初の を呼び出すことができます。 printf@plt (PLT内)は多段階の操作であり、その中で以下の動作が行われます。

  • を呼び出します。 printf@plt をPLTで呼び出す。
  • これは、GOT 版を(ポインタを介して)呼び出すものです。 最初は は PLT 内のいくつかのセットアップ コードを指します。
  • このセットアップコードは、まだ実行されていない場合は、関連する共有ライブラリをロードし、次に を変更します。 を変更し、それ以降の呼び出しが実際の printf PLTセットアップコードではなく、実際のprintf
  • printf@plt
printf