@@ -110,13 +110,22 @@ static void* dasm_labels[zend_lb_MAX];
110110
111111#if ZTS
112112static size_t tsrm_ls_cache_tcb_offset = 0;
113+ static size_t tsrm_tls_index = 0;
114+ static size_t tsrm_tls_offset = 0;
113115# ifdef __APPLE__
114116struct TLVDescriptor {
115117 void* (*thunk)(struct TLVDescriptor*);
116118 uint64_t key;
117119 uint64_t offset;
118120};
119121typedef struct TLVDescriptor TLVDescriptor;
122+ # elif defined(__FreeBSD__)
123+ /* https://github.com/freebsd/freebsd-src/blob/c52ca7dd09066648b1cc40f758289404d68ab886/libexec/rtld-elf/aarch64/reloc.c#L180-L184 */
124+ typedef struct TLSDescriptor {
125+ void* thunk;
126+ int index;
127+ size_t offset;
128+ } TLSDescriptor;
120129# endif
121130#endif
122131
@@ -494,8 +503,14 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
494503| MEM_ACCESS_64_WITH_UOFFSET_64 ldr, reg, TMP3, (((TLVDescriptor*)tsrm_ls_cache_tcb_offset)->offset), TMP1
495504||#else
496505| .long 0xd53bd051 // TODO: hard-coded: mrs TMP3, tpidr_el0
497- || ZEND_ASSERT(tsrm_ls_cache_tcb_offset <= LDR_STR_PIMM64);
498- | ldr reg, [TMP3, #tsrm_ls_cache_tcb_offset]
506+ || if (tsrm_ls_cache_tcb_offset == 0) {
507+ | ldr TMP3, [TMP3, #0]
508+ | MEM_ACCESS_64_WITH_UOFFSET_64 ldr, TMP3, TMP3, tsrm_tls_index, TMP1
509+ | MEM_ACCESS_64_WITH_UOFFSET_64 ldr, reg, TMP3, tsrm_tls_offset, TMP1
510+ || } else {
511+ || ZEND_ASSERT(tsrm_ls_cache_tcb_offset <= LDR_STR_PIMM64);
512+ | ldr reg, [TMP3, #tsrm_ls_cache_tcb_offset]
513+ || }
499514||#endif
500515|.endmacro
501516
@@ -2754,7 +2769,27 @@ static int zend_jit_setup(void)
27542769
27552770#if ZTS
27562771 tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset();
2772+ # if defined(__FreeBSD__)
2773+ if (tsrm_ls_cache_tcb_offset == 0) {
2774+ TLSDescriptor **where;
2775+
2776+ __asm__(
2777+ "adrp %0, :tlsdesc:_tsrm_ls_cache\n"
2778+ "add %0, %0, :tlsdesc_lo12:_tsrm_ls_cache\n"
2779+ : "=r" (where));
2780+ /* See https://github.com/ARM-software/abi-aa/blob/2a70c42d62e9c3eb5887fa50b71257f20daca6f9/aaelf64/aaelf64.rst
2781+ * section "Relocations for thread-local storage".
2782+ * The first entry holds a pointer to the variable's TLS descriptor resolver function and the second entry holds
2783+ * a platform-specific offset or pointer. */
2784+ TLSDescriptor *tlsdesc = where[1];
2785+
2786+ tsrm_tls_offset = tlsdesc->offset;
2787+ /* Index is offset by 1 on FreeBSD (https://github.com/freebsd/freebsd-src/blob/22ca6db50f4e6bd75a141f57cf953d8de6531a06/lib/libc/gen/tls.c#L88) */
2788+ tsrm_tls_index = (tlsdesc->index + 1) * 8;
2789+ }
2790+ # else
27572791 ZEND_ASSERT(tsrm_ls_cache_tcb_offset != 0);
2792+ # endif
27582793#endif
27592794
27602795 memset(sp_adj, 0, sizeof(sp_adj));
0 commit comments