Skip to content

Commit 73b1ebf

Browse files
committed
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
1 parent 04feb45 commit 73b1ebf

17 files changed

+2402
-171
lines changed

ext/opcache/config.m4

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,23 @@ if test "$PHP_OPCACHE" != "no"; then
7373
IR_TARGET=IR_TARGET_X64
7474
DASM_FLAGS="-D X64APPLE=1 -D X64=1"
7575
DASM_ARCH="x86"
76+
TLS_TARGET="darwin"
7677
],
7778
[*x86_64*|amd64-*-freebsd*], [
7879
IR_TARGET=IR_TARGET_X64
7980
DASM_FLAGS="-D X64=1"
8081
DASM_ARCH="x86"
82+
TLS_TARGET="x86_64"
8183
],
8284
[[i[34567]86*|x86*]], [
8385
IR_TARGET=IR_TARGET_X86
8486
DASM_ARCH="x86"
87+
TLS_TARGET="x86"
8588
],
8689
[aarch64*], [
8790
IR_TARGET=IR_TARGET_AARCH64
8891
DASM_ARCH="aarch64"
92+
TLS_TARGET="aarch64"
8993
])
9094
9195
AS_VAR_IF([PHP_CAPSTONE], [yes],
@@ -102,6 +106,10 @@ if test "$PHP_OPCACHE" != "no"; then
102106
103107
JIT_CFLAGS="-I@ext_builddir@/jit/ir -D$IR_TARGET -DIR_PHP"
104108
AS_VAR_IF([ZEND_DEBUG], [yes], [JIT_CFLAGS="$JIT_CFLAGS -DIR_DEBUG"])
109+
110+
AS_VAR_IF([PHP_THREAD_SAFETY], [yes], [
111+
ZEND_JIT_SRC="$ZEND_JIT_SRC jit/tls/zend_jit_tls_$TLS_TARGET.c"
112+
])
105113
])
106114

107115
AC_CHECK_FUNCS([mprotect shm_create_largepage])

ext/opcache/config.w32

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ if (PHP_OPCACHE != "no") {
3333
DEFINE("IR_TARGET", ir_target);
3434
DEFINE("DASM_FLAGS", dasm_flags);
3535
DEFINE("DASM_ARCH", "x86");
36+
DEFINE("TLS_TARGET", "win");
3637

3738
AC_DEFINE('HAVE_JIT', 1, 'Define to 1 to enable JIT.');
3839

@@ -52,6 +53,11 @@ if (PHP_OPCACHE != "no") {
5253
ADD_SOURCES(configure_module_dirname + "\\jit",
5354
"zend_jit.c zend_jit_vm_helpers.c",
5455
"opcache", "ext\\opcache\\jit");
56+
if (PHP_ZTS == "yes") {
57+
ADD_SOURCES(configure_module_dirname + "\\jit\\tls",
58+
"zend_jit_tls_win.c",
59+
"opcache", "ext\\opcache\\jit\\tls");
60+
}
5561
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
5662
"ir.c", "opcache", "ext\\opcache\\jit\\ir");
5763
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.so
2+
*.o
3+
main
4+
main.dSYM

0 commit comments

Comments
 (0)