php-srcのコードリーディングした内容をコツコツ残すテスト。その16
今日からopcache
の前にmacOSでsoのgdbデバッグがうまくいかなかったので備忘録。
発生していた事象
–enable-debugでビルドしても opcache.so
がうまく解釈されずこんな感じに ??
となってしまってブレークポイントも効かない状態に。
(gdb) b compile_file
Breakpoint 2 at 0x100458c32: file Zend/zend_language_scanner.l, line 642.
(gdb) r
Starting program: sapi/cli/php -dopcache.enable_cli=1 -dopcache.opt_debug_level=0x10000 -dopcache.jit=disable -dzend_extension=/path/to/modules/opcache.so 1.php
[New Thread 0x260b of process 93229]
[New Thread 0x2303 of process 93229]
warning: unhandled dyld version (17)
Thread 2 hit Breakpoint 2, compile_file (file_handle=0x7ff7bfefe228, type=8) at Zend/zend_language_scanner.l:642
642 zend_op_array *op_array = NULL;
(gdb) bt
#0 compile_file (file_handle=0x7ff7bfefe228, type=8) at Zend/zend_language_scanner.l:642
#1 0x0000000100217e69 in phar_compile_file (file_handle=0x7ff7bfefe228, type=8) at ext/phar/phar.c:3351
#2 0x0000000102da18e4 in ?? ()
#3 0x0000000264e8ae9a in ?? ()
#4 0x0100000102a5b5a0 in ?? ()
#5 0x0000000100ecd508 in ?? ()
#6 0x0000000000000000 in ?? ()
本当はこうなってほしい
(gdb) bt
#0 compile_file (file_handle=0x7fffffffd2f0, type=8) at Zend/zend_language_scanner.l:641
#1 0x00005555557f8f04 in phar_compile_file (file_handle=0x7fffffffd2f0, type=8) at /root/php-src-php-8.1.4/ext/phar/phar.c:3351
#2 0x00007ffff56935c5 in opcache_compile_file (file_handle=0x7fffffffd2f0, type=8, op_array_p=0x7fffffffaca8) at /root/php-src-php-8.1.4/ext/opcache/ZendAccelerator.c:1789
#3 0x00007ffff5694a2a in persistent_compile_file (file_handle=0x7fffffffd2f0, type=8) at /root/php-src-php-8.1.4/ext/opcache/ZendAccelerator.c:2160
#4 0x0000555555a4c0bc in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /root/php-src-php-8.1.4/Zend/zend.c:1754
#5 0x00005555559a90c4 in php_execute_script (primary_file=0x7fffffffd2f0) at /root/php-src-php-8.1.4/main/main.c:2538
#6 0x0000555555bc1f6d in do_cli (argc=5, argv=0x5555568366c0) at /root/php-src-php-8.1.4/sapi/cli/php_cli.c:965
#7 0x0000555555bc3075 in main (argc=5, argv=0x5555568366c0) at /root/php-src-php-8.1.4/sapi/cli/php_cli.c:1367
set solib-search-path /path/to/modules/
など色々試みましたがうまくいかず…orz
gdbserver + Docker(Ubuntu)を使ったデバッグ
Docker上のUbuntuでPHPを同じようにビルド・デバッグしたところ問題なく動いたのでUbuntu上でgdbでデバッグしました。
こんな感じでDockerfileを用意
FROM ubuntu
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENV PHP_VERSION 8.1.4
RUN apt update
RUN apt install -y wget unzip gdb autoconf gcc bison re2c pkg-config libxml2-dev libsqlite3-dev make vim
WORKDIR /root
RUN wget https://github.com/php/php-src/archive/refs/tags/php-${PHP_VERSION}.zip && unzip php-${PHP_VERSION}.zip
WORKDIR /root/php-src-php-${PHP_VERSION}
RUN ./buildconf --force
RUN ./configure --enable-debug
RUN make -j4
CMD /bin/bash
でビルドして立ち上げ
$ docker build . -t php-gdb
$ docker run -it \
-v $(pwd)/tmp:/tmp \
-p 8001:8001 \
--cap-add=SYS_PTRACE --security-opt="seccomp=unconfined" \
php-gdb
> cp /usr/local/bin/php /tmp/php # Docker上のPHPのバイナリを使うのでvolumesで共有する用にコピー
このDocker上のgdbのTUIモードでデバッグしても良かったが、どうせならVSCodeでデバッグしてみたかったので以下のようにしてgdbserverを使ってみました。
Docker上で以下のコマンドでgdbserverを立ち上げ
gdbserver localhost:8001 \
/usr/local/bin/php \
-dopcache.enable_cli=1 \
-dopcache.opt_debug_level=0x10000 \
-dzend_extension=$(pwd)/modules/opcache.so 1.php
ホストのVSCodeのlaunch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/tmp/php",
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "/usr/local/bin/gdb",
"miDebuggerServerAddress": "localhost:8001",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Relace absolute path of source code",
"ignoreFailures": false,
"text": "set substitute-path /root/php-src-php-8.1.4 ${workspaceFolder}"
}
]
}
]
}
programでホストOS用のビルドしたPHPだとダメでゲストOS=Docker用のビルドしたPHPを指定する必要があり、 ${workspaceFolder}/tmp/php
に設置している。
set substitute-path /root/php-src-php-8.1.4 ${workspaceFolder}
によってリモートのパスとローカルのパスのマッピングを行っている。
あとはこの状態でVSCodeでデバッグすればOK。
VSCodeを使わない場合はこんな感じでデバッグできる。
$ gdb
> target remote localhost:8001
> set substitute-path /root/php-src-php-8.1.4 ${workspaceFolder}
> b main
> continue