👻

[php-src を読む] 環境構築編

2022/12/14に公開

この記事は PHP Advent Calendar 2022 14 日目の記事です。

はじめに

PHP の理解を深めるために php-src を読んでいたのですが、ソースコードを読むだけで理解するのは難しい!
ということで、実際に動かしながら挙動を確認できる環境を作りました。

今回作成した Docker 環境のソースコードはリポジトリにあります。
ご自由にお使いください。

作成する環境

OS: Debian 12 Bookworm
PHP: 8.3.2-dev

構築手順

  1. リポジトリをクローン
  2. php-src と vld を取得
  3. PHP のインストール準備
  4. イメージを作成

1. リポジトリをクローン

git clone https://github.com/sayuprc/reading-php-src.git

cd reading-php-src

以降の手順はすべて reading-php-src 配下で行います。

2. php-src と vld を取得

php-src と vld のリポジトリを取得します。

make clone

php-src はブランチを指定して取得します。(デフォルトは PHP-8.3)

3. PHP のインストール準備

PHP のインストールや Docker コンテナで利用する環境変数を定義しておくファイルを作成します。

make copy

コマンドの実行により、下記のファイルが作成されます。
必要に応じて修正してください。

  • .env
  • ./docker/config.nice
  • ./docker/installer
  • ./docker/php.ini

.env

Docker イメージのタグを設定します。

.env
TAG=8.3

./docker/config.nice

PHP のビルドオプションを記載します。

./docker/config.nice
#! /bin/sh
#
# Created by configure

'./configure' \
'--disable-all' \
'--enable-debug' \
'--with-pear' \
'--enable-xml' \
'--with-libxml' \
'--with-openssl' \
'--enable-opcache' \
"$@"

./docker/installer

必要なライブラリ等をインストールするコマンドです。

./docker/installer
apt install -y \
  autoconf \
  bison \
  curl \
  gcc \
  gdb \
  git \
  libsqlite3-dev \
  libssl-dev \
  libxml2-dev \
  make \
  openssl \
  pkg-config \
  re2c \
  sqlite3 \
  wget

./docker/php.ini

PHP の設定ファイルです。

4. イメージを作成

Docker イメージを作成します。
イメージのタグは .env に設定している値になります。

make build

デバッグする

今回は、phpinfo() の内部的な挙動を追ってみます。

src/sample.php
<?php

phpinfo();

オペコードを見る

$ php -d vld.active=1 -d vld.execute=0 src/sample.php
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /usr/local/src/php-src/src/sample.php
function name:  (null)
number of ops:  3
compiled vars:  none
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
    3     0  E >   INIT_FCALL                                               'phpinfo'
          1        DO_ICALL
    4     2      > RETURN                                                   1

branch: #  0; line:     3-    4; sop:     0; eop:     2; out0:  -2
path #1: 0,

ブレークポイントを設定し、コードを実行する

PHP の標準関数の場合、zif_ をプレフィックスとしてつけるとブレークポイントを設定できるようです。

ファイル名と行数を指定してもブレークポイントの設定は可能です。

$ gdb sapi/cli/php

# ブレークポイントを設定
>>> b zif_phpinfo

# PHP のコードを実行
>>> r src/sample.php

r src/sample.php を実行するとキャプチャのような画面になります。

この画面になったら、ns コマンドを実行して、処理を続行します。

n はステップアウト実行、s はステップイン実行になります。

変数の中身は p <変数名>printzv <変数名>[1] などで見ることができます。

gdb の使い方は参考にある記事が分かりやすいので、そちらをご参照ください。

最後に

これで PHP をより理解するための準備ができました。

参考

GDBデバッギング覚え書き - しばそんノート

脚注
  1. printzv は php-src の .gdbinit に定義してあります。
    php-src の .gdbinit には他にも便利なコマンドが定義してあります。 ↩︎

GitHubで編集を提案

Discussion