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を動かします。自分が入力しているのは次の情報です。
(ここで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を扱ったときは出なかった。なんでだろ。うーん。