suztomoの日記

2008-06-05

[]PHPの実行をPHPのソースコード(C言語)のレベルで見る方法

PHPはソースコードを読めばわかるとおりC言語で書いてあります。

そのC言語の中でPHPがどんな処理をしているのかをデバッガであるgdbを用いて見ることができるのでそれを紹介します。まぁ普通のgdbの使い方なんですが:p

ソースをダウンロードしてコンパイル

PHP-5.2.6のソースをダウンロードします。

まず./configureするとのMakefileができます。

このMakefileの中で-gオプションがついていることを確認しましょう。*1

これがデバッガ(gdb)用のオプションで、コンパイルされたバイナリファイルにソースコードとの対応付けができます。

次にmakeします。時間がかかります。

サンプルファイル

makeしている間に次のようなPHPファイルを作成しましょう。

<?php
$i = "12";
$k = intval($i);
?>

これは文字列の"12"をintval関数によってintに換えるというものです。

今回はこの文字列を表す変数がPHPのソース内でどんなデータになっているかを見てみましょう。

ちなみに、このソースを用意した理由はデバッガで途中で止めるときのbreakpointにintval関数を使うことができるからです。

別にintval関数でなくてもかまいません。(PHPはとても大きなプログラムなので1行1行実行していったら時間がいくらあっても足りません。)

intval関数のソース

さて、得に理由もなくbreakpointとしてintval関数を選びました。

そのintval関数のソースを探しましょう。grepコマンドが便利です。

カレントディレクトリからintvalという文字列が入っているファイルの一覧を表示します。

あやしいのはgmp.c、basic_functions.c、type.cあたりです。

実際にファイルを開いていってtype.cにintval関数があることがわかりました。

実行する

gdbを使って実行します。たぶん実行するファイルはsapi/cli/phpっぽいです。makeしたときにこのファイルが目に入ったので:)

上の画像のとおり、type.cというソースファイルの中の、(intval関数の中)161行目でプログラムの実行を止められれば引数であるnumの正体がわかりそうです。

というわけで下の画像のようにgdbを動かします。自分が入力しているのは次の情報です。

  • b type.c:161 type.cの161行目(intval関数の中)にきたら実行を止める
  • hoge.phpを引数としてphpを実行する

(ここでtype.cの161行目で止まる)

  • 止まったときのnumというポインタが指す値を見てみる(zvalという構造体へのポインタのようだ)
  • さらにその先を見てみる(value, refcount, typeなどの値を持つ構造体のようだ)

中に"12"の文字が見えますね。単なる文字列でも、C言語のソースの中ではいりくんだ構造をしているのがわかりますね。

このnumがどんな構造体なのかはzend.hに書いてあります(via hogelog).


ちなみにgdbはemacsから使うと便利です。はやみずさんが動画を上げてくれています。

gdbをEmacsから使う動画 - 日記を書く [・w・] はやみずさん

僕はMacのCarbonEmacsが大好きです。

うーん、いつもはgdbの左側にあるソースのバッファにbreakpointのマークと実行している行のマークが出るのだが、今回PHPを扱ったときは出なかった。なんでだろ。うーん。

と、いうわけでphpをgdbで動かして内部の構造を知るというエントリでした。まる。*2

*1:デフォルトで-gがついているんですね。不思議ですね.

*2:もしLL futureとかでこういう話をしたら興味がある人はいるんだろうか

MagicantMagicant 2008/06/06 10:09 s/grep関数/grepコマンド/

大概のアプリでは普通に configure すると -g が付いてくると思うよ。

suztomosuztomo 2008/06/08 12:15 コメントありがとー。
-gがつくのが普通なのね。実行が遅くなるわけじゃないからいいのかな。

DQNEODQNEO 2013/04/21 05:02 いまさらですが、
break zif_intval
のようにすれば、ソースコード検索しなくてもブレークポイント設定できて便利ですよ〜。
(むしろ逆に該当ソースコードの場所を教えてくれます)

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。