1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00
Files
archived-php-src/ext/opcache/config.w32
Arnaud Le Blanc 73b1ebfa20 Fix linker failure when building Opcache statically
We use linker relocations to fetch the TLS index and offset of _tsrm_ls_cache.
When building Opcache statically, linkers may attempt to optimize that into a
more efficient code sequence (relaxing from "General Dynamic" to "Local Exec"
model [1]). Unfortunately, linkers will fail, rather than ignore our
relocations, when they don't recognize the exact code sequence they are
expecting.

This results in errors as reported by GH-15074:

    TLS transition from R_X86_64_TLSGD to R_X86_64_GOTTPOFF against
    `_tsrm_ls_cache' at 0x12fc3 in section `.text' failed"

Here I take a different approach:

 * Emit the exact full code sequence expected by linkers
 * Extract the TLS index/offset by inspecting the linked ASM code, rather than
   executing it (execution would give us the thread-local address).
 * We detect when the code was relaxed, in which case we can extract the TCB
   offset instead.
 * This is done in a conservative way so that if the linker did something we
   didn't expect, we fallback to a safer (but slower) mechanism.

One additional benefit of that is we are now able to use the Local Exec model in
more cases, in JIT'ed code. This makes non-glibc builds faster in these cases.

Closes GH-18939.

Related RFC: https://wiki.php.net/rfc/make_opcache_required.

[1] https://www.akkadia.org/drepper/tls.pdf
2025-07-26 16:43:41 +02:00

76 lines
2.6 KiB
Plaintext

ARG_ENABLE("opcache", "whether to enable Zend OPcache support", "yes");
ARG_ENABLE("opcache-jit", "whether to enable JIT (not supported for ARM64)", "yes");
if (PHP_OPCACHE != "no") {
ZEND_EXTENSION('opcache', "\
ZendAccelerator.c \
zend_accelerator_blacklist.c \
zend_accelerator_debug.c \
zend_accelerator_hash.c \
zend_accelerator_module.c \
zend_accelerator_util_funcs.c \
zend_persist.c \
zend_persist_calc.c \
zend_file_cache.c \
zend_shared_alloc.c \
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
ADD_EXTENSION_DEP('opcache', 'date');
ADD_EXTENSION_DEP('opcache', 'hash');
ADD_EXTENSION_DEP('opcache', 'pcre');
if (PHP_OPCACHE_JIT == "yes") {
if (TARGET_ARCH == 'arm64') {
WARNING("JIT not enabled; not yet supported for ARM64");
} else if (CHECK_HEADER_ADD_INCLUDE("ir/ir.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) {
var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1";
var ir_target = (X64 ? "IR_TARGET_X64" : "IR_TARGET_X86");
var ir_src = "ir_strtab.c ir_cfg.c ir_sccp.c ir_gcm.c ir_ra.c ir_save.c \
ir_dump.c ir_check.c ir_patch.c";
DEFINE("IR_TARGET", ir_target);
DEFINE("DASM_FLAGS", dasm_flags);
DEFINE("DASM_ARCH", "x86");
DEFINE("TLS_TARGET", "win");
AC_DEFINE('HAVE_JIT', 1, 'Define to 1 to enable JIT.');
ADD_FLAG("CFLAGS_OPCACHE", "/I \"ext\\opcache\\jit\\ir\" /D "+ir_target+" /D IR_PHP");
if (PHP_DEBUG == "yes") {
ADD_FLAG("CFLAGS_OPCACHE", "/D IR_DEBUG");
}
if (CHECK_HEADER_ADD_INCLUDE("capstone\\capstone.h", "CFLAGS_OPCACHE", PHP_OPCACHE+ ";" + PHP_PHP_BUILD + "\\include") &&
CHECK_LIB("capstone.lib", "opcache", PHP_OPCACHE)) {
AC_DEFINE('HAVE_CAPSTONE', 1, 'Define to 1 if Capstone is available.');
ir_src += " ir_disasm.c";
}
ADD_MAKEFILE_FRAGMENT(configure_module_dirname + "\\jit\\Makefile.frag.w32");
ADD_SOURCES(configure_module_dirname + "\\jit",
"zend_jit.c zend_jit_vm_helpers.c",
"opcache", "ext\\opcache\\jit");
if (PHP_ZTS == "yes") {
ADD_SOURCES(configure_module_dirname + "\\jit\\tls",
"zend_jit_tls_win.c",
"opcache", "ext\\opcache\\jit\\tls");
}
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
"ir.c", "opcache", "ext\\opcache\\jit\\ir");
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
"ir_emit.c", "opcache", "ext\\opcache\\jit\\ir");
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
ir_src, "opcache", "ext\\opcache\\jit\\ir");
} else {
WARNING("JIT not enabled, headers not found");
}
}
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
}