PHP Internals personal scratch book

This is a list of things I've kept within reach to refer back or ponder while working with or around php-src, or potential projects for it.

This gets edited when I need to throw something at it. It might also not be accurate anymore.

php-src tools and explanations



To use CLANG instead: ./configure CC=clang ...

Add Compiler flags: ./configure CFLAGS="-Wflag" ...

Configure options for enabling ASAN/UBSAN: --enable-address-sanitizer --enable-undefined-sanitizer

A reasonable basic configure for minimal testing:

./configure -C CFLAGS="-DPROFITABILITY_CHECKS=0" --disable-all --enable-debug --enable-address-sanitizer --enable-undefined-sanitizer --enable-opcache --enable-zend-test

Regenerating the PHP VM:

php Zend/zend_vm_gen.php

Testing php-src

Debugging a failed PHPT test with GDB: gdb

Testing with Valgrind:

ZEND_DONT_UNLOAD_MODULES=1 USE_ZEND_ALLOC=0 valgrind --leak-check=full --track-origins=yes make test

Testing PDO MySQL:

PDO_MYSQL_TEST_DSN="mysql:dbname=test;host=;" PDO_MYSQL_TEST_DB="test" PDO_MYSQL_TEST_USER="pdo" PDO_MYSQL_TEST_PASS="password" make test TESTS="ext/pdo_mysql"

Testing the JIT:

First need to compile with CFLAGS="-DPROFITABILITY_CHECKS=0".

Then run:

make test TEST_PHP_ARGS="-q -j22 -d opcache.jit=function -d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.file_update_protection=0 -d opcache.jit_buffer_size=1M" TESTS="Zend ext/opcache"

Potential way to debugging JIT Assembly:

make test TEST_PHP_ARGS="-dopcache.enable_cli=1 -dopcache.jit_buffer_size=16M -d opcache.jit_debug='1<<8'" TESTS="failing_test_file.phpt" &> debug-jit.txt

Out of tree PHP extensions

Testing with Valgrind

ZEND_DONT_UNLOAD_MODULES=1 USE_ZEND_ALLOC=0 valgrind --leak-check=full --track-origins=yes path/to/php run-tests.php -P -d extension=./modules/

Generate ARGINFO: path/to/php-src/scripts/dev/gen_stub.php ext.stub.php

Custom php-src builds for working with different versions/types (Debug/NTS/TS)

Use a MAKE INSTALL build by using the following command for php-src:

./configure --disable-all --enable-debug --prefix path/to/custom-php/

The extension is now ready to be compiled. To do so, first move into the extension directory. Then do the following steps:

./configure --with-php-config=path/to/custom-php//bin/php-config CFLAGS="-Wfatal-errors -Wall -Wpedantic -Wextra -Wno-unused-parameter -Werror"

Test against chosen custom debug build

/mnt/c/Dev/custom-php/bin/php run-tests.php -P -d extension=./modules/

Releasing on PECL

PECL package.xml DTD:

Generate test file list for package.xml:

find tests -name "*.phpt" | awk '{ print "        <file role=\"test\" name=\""$0"\" />" }'

To generate tar ball: pear package

Extension ideas:

C related knowledge:

The Lost Art of Structure Packing:

C99 restrict keyword

Compiler warnings to add/ideas:


  1. -Wshadow Impossible php-src macro usage leads to variable shadowing
  2. -Wdouble-promotion Nice to have
  3. -Wformat=2 & -Wformat-truncation seems useful to be able to enable
  4. -Wundef W.I.P.
  5. -fno-common Not sure what this does
  6. -fstack-usage & -Wstack-usage= Don't think so as we use a custom allocator
  7. -Wconversion Huge amount of work
  8. -Wrestrict GCC 7 in -Wextra in GCC8
  9. -Wnull-dereference GCC 6

New GCC 8 warnings added to -Wall and -Wextra:

Git commands and stuff

Splitting up one commit into more:

Deleting local branches after removing them from remote, discovered

git branch -vv | grep ': gone]'|  grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d

Cherry-picking multiple commits:

Someone sent me this command to generate a pretty git log graph:

git log --graph --pretty='\''%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'

Fixup branches when you forget to change feature branches before committing:

git checkout -b new-branch # switch to a new branch
git branch -f old-branch HEAD~3 # make old-branch point to some older commit

Git Reflog:

Rebase onto:

git rebase [--onto <new base>] [<upstream> [<branch>]]

Refresh commit date:

git commit --amend --date=now --no-edit

Push all branches after doing a merge-up of a commit:

git push --atomic php PHP-8.0 PHP-8.1 master

Removing branches which don't exist on remote:

git branch -vv | grep ': gone]'|  grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -D

How to apply git patches in email format: