Skip to content

Commit f649720

Browse files
committed
Fix GH-11188: Error when building TSRM in ARM64
Although the issue mentioned FreeBSD, this is a broader problem: the current ARM64 code to load the TLS offset assumes a setup with the non-default TLS model. This problem can also apply on some configurations on other platforms.
1 parent ce7ed6e commit f649720

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

TSRM/TSRM.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,11 +777,20 @@ TSRM_API size_t tsrm_get_ls_cache_tcb_offset(void)
777777
asm("adrp %0, #__tsrm_ls_cache@TLVPPAGE\n\t"
778778
"ldr %0, [%0, #__tsrm_ls_cache@TLVPPAGEOFF]"
779779
: "=r" (ret));
780-
# else
780+
# elif defined(TSRM_TLS_MODEL_DEFAULT)
781+
/* Surplus Static TLS space isn't guaranteed. */
782+
ret = 0;
783+
# elif defined(TSRM_TLS_MODEL_INITIAL_EXEC)
784+
asm("adrp %0, :gottprel:_tsrm_ls_cache\n\t"
785+
"ldr %0, [%0, #:gottprel_lo12:_tsrm_ls_cache]"
786+
: "=r" (ret));
787+
# elif defined(TSRM_TLS_MODEL_LOCAL_EXEC)
781788
asm("mov %0, xzr\n\t"
782789
"add %0, %0, #:tprel_hi12:_tsrm_ls_cache, lsl #12\n\t"
783790
"add %0, %0, #:tprel_lo12_nc:_tsrm_ls_cache"
784791
: "=r" (ret));
792+
# else
793+
# error "TSRM TLS model not set"
785794
# endif
786795
return ret;
787796
#else

TSRM/TSRM.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,13 @@ TSRM_API const char *tsrm_api_name(void);
150150

151151
#if !__has_attribute(tls_model) || defined(__FreeBSD__) || defined(__MUSL__) || defined(__HAIKU__)
152152
# define TSRM_TLS_MODEL_ATTR
153+
# define TSRM_TLS_MODEL_DEFAULT
153154
#elif __PIC__
154155
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("initial-exec")))
156+
# define TSRM_TLS_MODEL_INITIAL_EXEC
155157
#else
156158
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("local-exec")))
159+
# define TSRM_TLS_MODEL_LOCAL_EXEC
157160
#endif
158161

159162
#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,22 @@ static void* dasm_labels[zend_lb_MAX];
110110

111111
#if ZTS
112112
static 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__
114116
struct TLVDescriptor {
115117
void* (*thunk)(struct TLVDescriptor*);
116118
uint64_t key;
117119
uint64_t offset;
118120
};
119121
typedef 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,24 @@ 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+
/* https://github.com/freebsd/freebsd-src/blob/c52ca7dd09066648b1cc40f758289404d68ab886/libexec/rtld-elf/aarch64/reloc.c#L225-L233 */
2781+
TLSDescriptor *tlsdesc = where[1];
2782+
2783+
tsrm_tls_offset = tlsdesc->offset;
2784+
/* Index is offset by 1 on FreeBSD (https://github.com/freebsd/freebsd-src/blob/22ca6db50f4e6bd75a141f57cf953d8de6531a06/lib/libc/gen/tls.c#L88) */
2785+
tsrm_tls_index = (tlsdesc->index + 1) * 8;
2786+
}
2787+
# else
27572788
ZEND_ASSERT(tsrm_ls_cache_tcb_offset != 0);
2789+
# endif
27582790
#endif
27592791

27602792
memset(sp_adj, 0, sizeof(sp_adj));

0 commit comments

Comments
 (0)