mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix JIT TLS on MacOS
The dynamic loader, starting around version 1284, patches the thunk emitted for
thread local variables by the compiler, so that its format changes from
struct Thunk {
void *func;
size_t module;
size_t offset;
}
to
struct Thunk_v2 {
void *func;
uint32_t module;
uint32_t offset;
// other fields
}
which has the same size, but not the same layout.
This is mentionned in
9307719dd8/libdyld/ThreadLocalVariables.h (L90)
As a result, access to thread specific variables in JIT is broken.
Fix by using the new layout when the new dynamic loader is in use.
Closes GH-20121
This commit is contained in:
2
NEWS
2
NEWS
@@ -18,6 +18,8 @@ PHP NEWS
|
||||
- Opcache:
|
||||
. Fixed bug GH-20081 (access to uninitialized vars in preload_load()).
|
||||
(Arnaud)
|
||||
. Fixed bug GH-20121 (JIT broken in ZTS builds on MacOS 15).
|
||||
(Arnaud, Shivam Mathur)
|
||||
|
||||
- Phar:
|
||||
. Fix memory leak of argument in webPhar. (nielsdos)
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__x86_64__)
|
||||
# include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
int jit_globals_id;
|
||||
#else
|
||||
|
||||
@@ -2826,6 +2826,25 @@ static zend_never_inline void zend_jit_set_sp_adj_vm(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__x86_64__)
|
||||
/* Thunk format used since dydl 1284 (approx. MacOS 15)
|
||||
* https://github.com/apple-oss-distributions/dyld/blob/9307719dd8dc9b385daa412b03cfceb897b2b398/libdyld/ThreadLocalVariables.h#L146 */
|
||||
struct TLV_Thunkv2
|
||||
{
|
||||
void* func;
|
||||
uint32_t key;
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
/* Thunk format used in earlier versions */
|
||||
struct TLV_Thunkv1
|
||||
{
|
||||
void* func;
|
||||
size_t key;
|
||||
size_t offset;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int zend_jit_setup(void)
|
||||
{
|
||||
if (!zend_cpu_supports_sse2()) {
|
||||
@@ -2889,12 +2908,25 @@ static int zend_jit_setup(void)
|
||||
# elif defined(__APPLE__) && defined(__x86_64__)
|
||||
tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset();
|
||||
if (tsrm_ls_cache_tcb_offset == 0) {
|
||||
size_t *ti;
|
||||
struct TLV_Thunkv2 *thunk;
|
||||
__asm__(
|
||||
"leaq __tsrm_ls_cache(%%rip),%0"
|
||||
: "=r" (ti));
|
||||
tsrm_tls_offset = ti[2];
|
||||
tsrm_tls_index = ti[1] * 8;
|
||||
: "=r" (thunk));
|
||||
|
||||
/* Detect dyld 1284: With dyld 1284, thunk->func will be _tlv_get_addr.
|
||||
* Unfortunately this symbol is private, but we can find it
|
||||
* as _tlv_bootstrap+8: https://github.com/apple-oss-distributions/dyld/blob/9307719dd8dc9b385daa412b03cfceb897b2b398/libdyld/threadLocalHelpers.s#L54
|
||||
* In earlier versions, thunk->func will be tlv_get_addr, which is not
|
||||
* _tlv_bootstrap+8.
|
||||
*/
|
||||
if (thunk->func == (void*)((char*)_tlv_bootstrap + 8)) {
|
||||
tsrm_tls_offset = thunk->offset;
|
||||
tsrm_tls_index = (size_t)thunk->key * 8;
|
||||
} else {
|
||||
struct TLV_Thunkv1 *thunkv1 = (struct TLV_Thunkv1*) thunk;
|
||||
tsrm_tls_offset = thunkv1->offset;
|
||||
tsrm_tls_index = thunkv1->key * 8;
|
||||
}
|
||||
}
|
||||
# elif defined(__GNUC__) && defined(__x86_64__)
|
||||
tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset();
|
||||
|
||||
Reference in New Issue
Block a user