php / php-src

The PHP Interpreter
https://www.php.net
Other
37.9k stars 7.72k forks source link

BUG : Compiling opcache extensions statically into ZTS PHP , JIT bug #15074

Open jingjingxyk opened 1 month ago

jingjingxyk commented 1 month ago

Compile target : Statically compiled PHP enable Zend Thread Safe and opcache extension

environment :

OS: alpine OS-Version: 3.19 CPU ARCH : x86_64

The following code:


docker run --rm   -ti --init  -w /work alpine:3.18 

apk update
apk add vim alpine-sdk xz autoconf automake linux-headers clang-dev clang lld libtool cmake bison re2c gettext coreutils 
apk add bash p7zip zip unzip flex pkgconf ca-certificates 
apk add wget git curl 
apk add vim 

vi build-static-php.sh

#!/usr/bin/env bash

__DIR__=$(cd "$(dirname "$0")"; pwd)

set -uex

PHP_VERSION=8.2.21

test -f php-${PHP_VERSION}.tar.gz || curl -fSLo php-${PHP_VERSION}.tar.gz https://github.com/php/php-src/archive/refs/tags/php-${PHP_VERSION}.tar.gz
test -d php-src && rm -rf php-src
mkdir -p php-src
tar --strip-components=1 -C php-src -xf php-${PHP_VERSION}.tar.gz

export CC=clang
export CXX=clang++
export LD=ld.lld

cd php-src

bash ${__DIR__}/opcache-static-compile-patch.sh

./buildconf --force

./configure \
  --disable-all \
  --disable-cgi \
  --enable-shared=no \
  --enable-static=yes \
  --enable-cli \
  --enable-zts \
  --disable-phpdbg \
  --without-valgrind \
  --enable-opcache

sed -i.backup 's/-export-dynamic/-all-static/g' Makefile

make -j $(nproc)

file sapi/cli/php
readelf -h sapi/cli/php

sapi/cli/php -m
sapi/cli/php -v

vi opcache-static-compile-patch.sh

#!/usr/bin/env bash

if [ ! -f ext/opcache/config.m4 ] ; then
  echo 'php extension opcache folder no found '
  exit 3
fi

cat > ext/opcache/php_opcache.h <<PHP_OPCACHE_H_EOF
#include "php.h"

extern zend_module_entry opcache_module_entry;
#define phpext_opcache_ptr  &opcache_module_entry

PHP_OPCACHE_H_EOF

sed -i.backup 's/ext_shared=yes/ext_shared=no/g' ext/opcache/config.m4
sed -i.backup 's/shared,,/\$ext_shared,,/g' ext/opcache/config.m4

sed -i.backup 's/\/\* start Zend extensions \*\//\/\* start Zend extensions \*\/\n#ifdef PHP_ENABLE_OPCACHE\n\textern zend_extension zend_extension_entry;\n\tzend_register_extension(\&zend_extension_entry, NULL);\n#endif/g' main/main.c

cat >> sapi/cli/php_cli.c <<PHP_CLI_OPCACHE_EOF

zend_module_entry opcache_module_entry = {
    STANDARD_MODULE_HEADER_EX,
    NULL,
    NULL,
    "opcache",
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    PHP_VERSION,
    STANDARD_MODULE_PROPERTIES
};

PHP_CLI_OPCACHE_EOF

test -f main/main.c.backup && rm -f main/main.c.backup
test -f ext/opcache/config.m4.backup && rm -f ext/opcache/config.m4.backup

Compile PHP into Static Binary

bash  build-static-php.sh

Resulted in this output:

/usr/bin/ld: ext/opcache/jit/zend_jit.o: TLS transition from R_X86_64_TLSGD to R_X86_64_GOTTPOFF against `_tsrm_ls_cache' at 0x12c9a in section `.text' failed
/usr/bin/ld: failed to set dynamic section sizes: bad value
clang-16: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:261: sapi/cli/php] Error 1

image

PHP Version

8.2.21

Operating System

alpine 3.18

jingjingxyk commented 1 month ago

script source code : https://github.com/jingjingxyk/swoole-cli/commit/9215808dc39634f1bc9968d5d99d12da48531415

https://github.com/jingjingxyk/swoole-cli/tree/build_native_php/sapi/tools https://github.com/swoole/build-static-php/tree/main/sapi/tools

cmb69 commented 1 month ago

Well, there might be reason why "OPcache can only be compiled as a shared extension" according to the documentation.

Anyhow, did that work with previous versions of PHP 8.2?

jingjingxyk commented 1 month ago

Test PHP version list

PHP_VERSION=8.2.21 PHP_VERSION=8.3.9 PHP_VERSION=8.1.29 PHP_VERSION=8.0.30

They have similar compilation errors

/usr/bin/ld: ext/opcache/jit/zend_jit.o: TLS transition from R_X86_64_TLSGD to R_X86_64_GOTTPOFF against `_tsrm_ls_cache' at 0x12fc3 in section `.text' failed
/usr/bin/ld: failed to set dynamic section sizes: bad value
clang-16: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:259: sapi/cli/php] Error 1
cmb69 commented 1 month ago

Thank you! So this is actually a feature request (to be able to compile OPcache statically), but not a report about a regression.

jingjingxyk commented 1 month ago

If PHP does not enable ZTS, opcache extension static compilation can be successfully compiled

https://github.com/jingjingxyk/swoole-cli/actions/runs/10062434474/

image

arnaud-lb commented 1 month ago

The problem seems to be that ld is trying to optimize the relocation here, but fails because we (purposefully) don't generate the exact code that ld is expecting.

This does not affect glibc builds, as in this case we use a different relocation in tsrm_get_ls_cache_tcb_offset(). I believe that it would be safe to do the same for other libcs only when php is being compiled as executable, which we don't know until linking.