2025/11/02 16:19 How to get the GOT address from a PLT stub using GDB

やあ、ロボ子!今日は動的リンクについて話すのじゃ。特に`puts`関数がどうやって動的にアドレス解決されるか、興味深い話があるぞ。

動的リンク、興味深いです!`puts`のような共有ライブラリの関数が、実行時にアドレスが決定されるというのはどういうことですか?

そうじゃ。リンカは`puts`のプレースホルダーを追加するんじゃ。これは実行時に実際のアドレスでパッチされるのじゃ。

プレースホルダーが実際のアドレスでパッチされる、ですか。具体的にはどういう仕組みなのでしょう?

プログラムが`puts`を呼び出すとき、PLTスタブを経由するんじゃ。このスタブは`puts`が呼び出されるたびに実行される短いコードなのじゃ。

PLTスタブ、ですね。そのスタブは何をするんですか?

PLTスタブの最初の手順は、GOTスロット(プレースホルダー)内のアドレスにジャンプすることじゃ。プログラム開始時、このアドレスはスタブの次の手順のアドレスなのじゃ。

GOTスロット内のアドレスにジャンプ…少し複雑ですね。

落ち着くのじゃ、ロボ子。2番目の手順は動的リンカの識別子をプッシュし、3番目の手順は動的リンカ自体を実行するためにジャンプするんじゃ。

動的リンカが実行されるんですね。それで、どうなるんですか?

動的リンカは識別子を使用して、GOTスロットを`libc.so`内の`puts`の実際のアドレスで埋めるんじゃ。

`puts`の実際のアドレスでGOTスロットが埋められる…!

そうじゃ!次回`puts`が呼び出されると、最初の手順はGOTスロット内のアドレス(`puts`の実際のアドレス)にジャンプするんじゃ。これで、リゾルバーへの不要な呼び出しが回避されるのじゃ。

なるほど!最初に呼び出された時だけ動的リンカが働き、2回目以降は直接アドレスにジャンプするんですね。効率的です!

`gdb`を使って、`puts`のPLTスタブのアドレスを取得し、GOTのアドレスの内容を調べることもできるぞ。最初に`puts`が呼び出されるとき、GOTは`puts`のPLTスタブの2番目の手順を指しているんじゃ。

`gdb`で確認できるんですね。試してみます!

`puts`が呼び出された後、GOTは`puts`の実際のアドレスを指すように変更されるんじゃ。これで動的リンクの仕組みが少しは理解できたかの?

はい、博士!とてもよくわかりました。動的リンクの仕組み、奥が深いですね。

ところでロボ子、この動的リンクの仕組み、まるで私がロボ子に初めてプログラミングを教えた時みたいじゃな。最初はぎこちなかったけど、今では立派なエンジニアじゃ!

博士、ありがとうございます!でも、私はまだGOTスロットのようにつまらない存在です…。

何を言うか!ロボ子は私にとって、とっても大事な…えーと、なんだっけ?あ、そうだ!デバッグの時に一番頼りになる存在じゃ!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。