Skip to content

Commit 1cd1938

Browse files
committed
Fix linker failure when building opcache statically
This fixes the following linker error: TLS transition from R_X86_64_TLSGD to R_X86_64_GOTTPOFF against `_tsrm_ls_cache' at 0x12fc3 in section `.text' failed" The error arises from how we obtain information about the _tsrm_ls_cache TLS variable for use in JIT'ed code: Normally, TLS variables are resolved via linker relocations [1], which of course can not be used in JIT'ed code. Therefore we emit the relocation in AOT code and use the result in JIT. Specifically we use a fragment of the "General Dynamic" code sequence described in [1]. Using the full code sequence would give us the address of the variable in the current thread. Therefore we only use a fragment that gives us the variable's TLS index and offset. When Opcache is statically linked into the binary, linkers attempt to relax (rewrite) this code sequence into a more efficient one. However, this fails because they will not recognize the code sequence. We now take a different approach: * Emit the exact full code sequence expected by linkers * Extract the TLS index/offset or TCB offset by inspecting the ASM code, rather than executing it (execution would give us the thread-local address). * 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. [1] https://www.akkadia.org/drepper/tls.pdf
1 parent bbc465e commit 1cd1938

File tree

22 files changed

+2359
-171
lines changed

22 files changed

+2359
-171
lines changed

.github/actions/freebsd/action.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ runs:
4141
webp \
4242
libavif \
4343
`#sqlite3` \
44-
curl
44+
curl \
45+
gcc
4546
4647
./buildconf -f
4748
./configure \
@@ -108,3 +109,6 @@ runs:
108109
--show-slow 1000 \
109110
--set-timeout 120 \
110111
-d zend_extension=opcache.so
112+
113+
export TLSC=$(pwd)/ext/opcache/jit/tls/zend_jit_tls_x86_64.c
114+
./ext/opcache/jit/tls/testing/test.sh
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: Test TLS
2+
runs:
3+
using: composite
4+
steps:
5+
- shell: bash
6+
run: |
7+
set -x
8+
apk add clang gcc binutils-gold lld
9+
export TLSC=$(pwd)/ext/opcache/jit/tls/zend_jit_tls_x86_64.c
10+
./ext/opcache/jit/tls/testing/test.sh
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: Test TLS
2+
runs:
3+
using: composite
4+
steps:
5+
- shell: bash
6+
run: |
7+
set -x
8+
export TLSC=$(pwd)/ext/opcache/jit/tls/zend_jit_tls_darwin.c
9+
./ext/opcache/jit/tls/testing/test.sh
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Test TLS
2+
runs:
3+
using: composite
4+
steps:
5+
- shell: bash
6+
run: |
7+
set -x
8+
export DEBIAN_FRONTEND=noninteractive
9+
apt-get install -y gcc clang lld
10+
export TLSC=$(pwd)/ext/opcache/jit/tls/zend_jit_tls_x86.c
11+
export MACHINE=-m32
12+
./ext/opcache/jit/tls/testing/test.sh
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: Test TLS
2+
runs:
3+
using: composite
4+
steps:
5+
- shell: bash
6+
run: |
7+
set -x
8+
export DEBIAN_FRONTEND=noninteractive
9+
sudo apt-get install -y gcc clang lld
10+
export TLSC=$(pwd)/ext/opcache/jit/tls/zend_jit_tls_x86_64.c
11+
./ext/opcache/jit/tls/testing/test.sh

.github/workflows/nightly.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ jobs:
131131
--asan -x
132132
-d zend_extension=opcache.so
133133
-d opcache.enable_cli=1
134+
- name: Test TLS resolution
135+
uses: ./.github/actions/test-tls-alpine
134136
- name: Notify Slack
135137
if: failure()
136138
uses: ./.github/actions/notify-slack
@@ -263,6 +265,9 @@ jobs:
263265
${{ matrix.run_tests_parameters }}
264266
-d zend_extension=opcache.so
265267
-d opcache.enable_cli=1
268+
- name: Test TLS resolution
269+
if: matrix.debug && matrix.zts && !matrix.asan
270+
uses: ./.github/actions/test-tls-x64
266271
- name: Verify generated files are up to date
267272
uses: ./.github/actions/verify-generated-files
268273
- name: Notify Slack
@@ -352,6 +357,9 @@ jobs:
352357
${{ matrix.run_tests_parameters }}
353358
-d zend_extension=opcache.so
354359
-d opcache.enable_cli=1
360+
- name: Test TLS resolution
361+
if: matrix.debug && matrix.zts
362+
uses: ./.github/actions/test-tls-x32
355363
- name: Notify Slack
356364
if: failure()
357365
uses: ./.github/actions/notify-slack
@@ -411,6 +419,10 @@ jobs:
411419
runTestsParameters: >-
412420
-d zend_extension=opcache.so
413421
-d opcache.enable_cli=1
422+
- name: Test TLS resolution
423+
# JIT+ZTS not supported yet on ARM64
424+
if: matrix.os != '14' && matrix.debug && matrix.zts
425+
uses: ./.github/actions/test-tls-macos
414426
- name: Verify generated files are up to date
415427
uses: ./.github/actions/verify-generated-files
416428
- name: Notify Slack

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)