1 /*
2 +----------------------------------------------------------------------+
3 | Zend JIT |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | https://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Dmitry Stogov <dmitry@php.net> |
16 | Xinchen Hui <laruence@php.net> |
17 | Hao Sun <hao.sun@arm.com> |
18 +----------------------------------------------------------------------+
19 */
20
21
22 #ifdef HAVE_CAPSTONE
23 # define HAVE_DISASM 1
24 # include <capstone.h>
25 # define HAVE_CAPSTONE_ITER 1
26 #elif ZEND_JIT_TARGET_X86
27 # define HAVE_DISASM 1
28 # define DISASM_INTEL_SYNTAX 0
29
30 # include "jit/libudis86/itab.c"
31 # include "jit/libudis86/decode.c"
32 # include "jit/libudis86/syn.c"
33 # if DISASM_INTEL_SYNTAX
34 # include "jit/libudis86/syn-intel.c"
35 # else
36 # include "jit/libudis86/syn-att.c"
37 # endif
38 # include "jit/libudis86/udis86.c"
39 #endif /* HAVE_CAPSTONE */
40
41 #ifdef HAVE_DISASM
42
43 static void zend_jit_disasm_add_symbol(const char *name,
44 uint64_t addr,
45 uint64_t size);
46
47 #ifndef _WIN32
48 # include "jit/zend_elf.c"
49 #endif
50
51 #include "zend_sort.h"
52
53 #ifndef _GNU_SOURCE
54 # define _GNU_SOURCE
55 #endif
56
57 #ifndef _WIN32
58 #include <dlfcn.h>
59 #endif
60
61 struct _sym_node {
62 uint64_t addr;
63 uint64_t end;
64 struct _sym_node *parent;
65 struct _sym_node *child[2];
66 unsigned char info;
67 char name[1];
68 };
69
zend_syms_rotateleft(zend_sym_node * p)70 static void zend_syms_rotateleft(zend_sym_node *p) {
71 zend_sym_node *r = p->child[1];
72 p->child[1] = r->child[0];
73 if (r->child[0]) {
74 r->child[0]->parent = p;
75 }
76 r->parent = p->parent;
77 if (p->parent == NULL) {
78 JIT_G(symbols) = r;
79 } else if (p->parent->child[0] == p) {
80 p->parent->child[0] = r;
81 } else {
82 p->parent->child[1] = r;
83 }
84 r->child[0] = p;
85 p->parent = r;
86 }
87
zend_syms_rotateright(zend_sym_node * p)88 static void zend_syms_rotateright(zend_sym_node *p) {
89 zend_sym_node *l = p->child[0];
90 p->child[0] = l->child[1];
91 if (l->child[1]) {
92 l->child[1]->parent = p;
93 }
94 l->parent = p->parent;
95 if (p->parent == NULL) {
96 JIT_G(symbols) = l;
97 } else if (p->parent->child[1] == p) {
98 p->parent->child[1] = l;
99 } else {
100 p->parent->child[0] = l;
101 }
102 l->child[1] = p;
103 p->parent = l;
104 }
105
zend_jit_disasm_add_symbol(const char * name,uint64_t addr,uint64_t size)106 static void zend_jit_disasm_add_symbol(const char *name,
107 uint64_t addr,
108 uint64_t size)
109 {
110 zend_sym_node *sym;
111 size_t len = strlen(name);
112
113 sym = malloc(sizeof(zend_sym_node) + len + 1);
114 if (!sym) {
115 return;
116 }
117 sym->addr = addr;
118 sym->end = (addr + size - 1);
119 memcpy((char*)&sym->name, name, len + 1);
120 sym->parent = sym->child[0] = sym->child[1] = NULL;
121 sym->info = 1;
122 if (JIT_G(symbols)) {
123 zend_sym_node *node = JIT_G(symbols);
124
125 /* insert it into rbtree */
126 do {
127 if (sym->addr > node->addr) {
128 ZEND_ASSERT(sym->addr > (node->end));
129 if (node->child[1]) {
130 node = node->child[1];
131 } else {
132 node->child[1] = sym;
133 sym->parent = node;
134 break;
135 }
136 } else if (sym->addr < node->addr) {
137 if (node->child[0]) {
138 node = node->child[0];
139 } else {
140 node->child[0] = sym;
141 sym->parent = node;
142 break;
143 }
144 } else {
145 ZEND_ASSERT(sym->addr == node->addr);
146 if (strcmp(name, node->name) == 0 && sym->end < node->end) {
147 /* reduce size of the existing symbol */
148 node->end = sym->end;
149 }
150 free(sym);
151 return;
152 }
153 } while (1);
154
155 /* fix rbtree after instering */
156 while (sym && sym != JIT_G(symbols) && sym->parent->info == 1) {
157 if (sym->parent == sym->parent->parent->child[0]) {
158 node = sym->parent->parent->child[1];
159 if (node && node->info == 1) {
160 sym->parent->info = 0;
161 node->info = 0;
162 sym->parent->parent->info = 1;
163 sym = sym->parent->parent;
164 } else {
165 if (sym == sym->parent->child[1]) {
166 sym = sym->parent;
167 zend_syms_rotateleft(sym);
168 }
169 sym->parent->info = 0;
170 sym->parent->parent->info = 1;
171 zend_syms_rotateright(sym->parent->parent);
172 }
173 } else {
174 node = sym->parent->parent->child[0];
175 if (node && node->info == 1) {
176 sym->parent->info = 0;
177 node->info = 0;
178 sym->parent->parent->info = 1;
179 sym = sym->parent->parent;
180 } else {
181 if (sym == sym->parent->child[0]) {
182 sym = sym->parent;
183 zend_syms_rotateright(sym);
184 }
185 sym->parent->info = 0;
186 sym->parent->parent->info = 1;
187 zend_syms_rotateleft(sym->parent->parent);
188 }
189 }
190 }
191 } else {
192 JIT_G(symbols) = sym;
193 }
194 JIT_G(symbols)->info = 0;
195 }
196
zend_jit_disasm_destroy_symbols(zend_sym_node * n)197 static void zend_jit_disasm_destroy_symbols(zend_sym_node *n) {
198 if (n) {
199 if (n->child[0]) {
200 zend_jit_disasm_destroy_symbols(n->child[0]);
201 }
202 if (n->child[1]) {
203 zend_jit_disasm_destroy_symbols(n->child[1]);
204 }
205 free(n);
206 }
207 }
208
zend_jit_disasm_find_symbol(uint64_t addr,int64_t * offset)209 static const char* zend_jit_disasm_find_symbol(uint64_t addr,
210 int64_t *offset) {
211 zend_sym_node *node = JIT_G(symbols);
212 while (node) {
213 if (addr < node->addr) {
214 node = node->child[0];
215 } else if (addr > node->end) {
216 node = node->child[1];
217 } else {
218 *offset = addr - node->addr;
219 return node->name;
220 }
221 }
222 return NULL;
223 }
224
225 #ifdef HAVE_CAPSTONE
zend_jit_disasm_branch_target(csh cs,const cs_insn * insn)226 static uint64_t zend_jit_disasm_branch_target(csh cs, const cs_insn *insn)
227 {
228 unsigned int i;
229
230 #if ZEND_JIT_TARGET_X86
231 if (cs_insn_group(cs, insn, X86_GRP_JUMP)) {
232 for (i = 0; i < insn->detail->x86.op_count; i++) {
233 if (insn->detail->x86.operands[i].type == X86_OP_IMM) {
234 return insn->detail->x86.operands[i].imm;
235 }
236 }
237 }
238 #elif ZEND_JIT_TARGET_ARM64
239 if (cs_insn_group(cs, insn, ARM64_GRP_JUMP)
240 || insn->id == ARM64_INS_BL
241 || insn->id == ARM64_INS_ADR) {
242 for (i = 0; i < insn->detail->arm64.op_count; i++) {
243 if (insn->detail->arm64.operands[i].type == ARM64_OP_IMM)
244 return insn->detail->arm64.operands[i].imm;
245 }
246 }
247 #endif
248
249 return 0;
250 }
251 #endif
252
zend_jit_disasm_resolver(struct ud * ud,uint64_t addr,int64_t * offset)253 static const char* zend_jit_disasm_resolver(
254 #ifndef HAVE_CAPSTONE
255 struct ud *ud,
256 #endif
257 uint64_t addr,
258 int64_t *offset)
259 {
260 #ifndef _WIN32
261 # ifndef HAVE_CAPSTONE
262 ((void)ud);
263 # endif
264 const char *name;
265 void *a = (void*)(zend_uintptr_t)(addr);
266 Dl_info info;
267
268 name = zend_jit_disasm_find_symbol(addr, offset);
269 if (name) {
270 return name;
271 }
272
273 if (dladdr(a, &info)
274 && info.dli_sname != NULL
275 && info.dli_saddr == a) {
276 return info.dli_sname;
277 }
278 #else
279 const char *name;
280 name = zend_jit_disasm_find_symbol(addr, offset);
281 if (name) {
282 return name;
283 }
284 #endif
285
286 return NULL;
287 }
288
zend_jit_cmp_labels(Bucket * b1,Bucket * b2)289 static int zend_jit_cmp_labels(Bucket *b1, Bucket *b2)
290 {
291 return ((b1->h > b2->h) > 0) ? 1 : -1;
292 }
293
zend_jit_disasm(const char * name,const char * filename,const zend_op_array * op_array,zend_cfg * cfg,const void * start,size_t size)294 static int zend_jit_disasm(const char *name,
295 const char *filename,
296 const zend_op_array *op_array,
297 zend_cfg *cfg,
298 const void *start,
299 size_t size)
300 {
301 const void *end = (void *)((char *)start + size);
302 zval zv, *z;
303 zend_long n, m;
304 HashTable labels;
305 uint64_t addr;
306 int b;
307 #ifdef HAVE_CAPSTONE
308 csh cs;
309 cs_insn *insn;
310 # ifdef HAVE_CAPSTONE_ITER
311 const uint8_t *cs_code;
312 size_t cs_size;
313 uint64_t cs_addr;
314 # else
315 size_t count, i;
316 # endif
317 const char *sym;
318 int64_t offset = 0;
319 char *p, *q, *r;
320 #else
321 struct ud ud;
322 const struct ud_operand *op;
323 #endif
324
325 #ifdef HAVE_CAPSTONE
326 # if ZEND_JIT_TARGET_X86
327 # if defined(__x86_64__) || defined(_WIN64)
328 if (cs_open(CS_ARCH_X86, CS_MODE_64, &cs) != CS_ERR_OK)
329 return 0;
330 # else
331 if (cs_open(CS_ARCH_X86, CS_MODE_32, &cs) != CS_ERR_OK)
332 return 0;
333 # endif
334 cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
335 # if DISASM_INTEL_SYNTAX
336 cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
337 # else
338 cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
339 # endif
340 # elif ZEND_JIT_TARGET_ARM64
341 if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &cs) != CS_ERR_OK)
342 return 0;
343 cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
344 cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
345 # endif
346 #else
347 ud_init(&ud);
348 # if defined(__x86_64__) || defined(_WIN64)
349 ud_set_mode(&ud, 64);
350 # else
351 ud_set_mode(&ud, 32);
352 # endif
353 # if DISASM_INTEL_SYNTAX
354 ud_set_syntax(&ud, UD_SYN_INTEL);
355 # else
356 ud_set_syntax(&ud, UD_SYN_ATT);
357 # endif
358 ud_set_sym_resolver(&ud, zend_jit_disasm_resolver);
359 #endif /* HAVE_CAPSTONE */
360
361 if (name) {
362 fprintf(stderr, "%s: ; (%s)\n", name, filename ? filename : "unknown");
363 }
364
365 #ifndef HAVE_CAPSTONE
366 ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
367 ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
368 #endif
369
370 zend_hash_init(&labels, 8, NULL, NULL, 0);
371 if (op_array && cfg) {
372 ZVAL_FALSE(&zv);
373 for (b = 0; b < cfg->blocks_count; b++) {
374 if (cfg->blocks[b].flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
375 addr = (uint64_t)(uintptr_t)op_array->opcodes[cfg->blocks[b].start].handler;
376 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
377 zend_hash_index_add(&labels, addr, &zv);
378 }
379 }
380 }
381 }
382 #ifdef HAVE_CAPSTONE
383 ZVAL_TRUE(&zv);
384 # ifdef HAVE_CAPSTONE_ITER
385 cs_code = start;
386 cs_size = (uint8_t*)end - (uint8_t*)start;
387 cs_addr = (uint64_t)(uintptr_t)cs_code;
388 insn = cs_malloc(cs);
389 while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
390 if ((addr = zend_jit_disasm_branch_target(cs, insn))) {
391 # else
392 count = cs_disasm(cs, start, (uint8_t*)end - (uint8_t*)start, (uintptr_t)start, 0, &insn);
393 for (i = 0; i < count; i++) {
394 if ((addr = zend_jit_disasm_branch_target(cs, &(insn[i])))) {
395 # endif
396 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
397 zend_hash_index_add(&labels, addr, &zv);
398 }
399 }
400 }
401 #else
402 ZVAL_TRUE(&zv);
403 while (ud_disassemble(&ud)) {
404 op = ud_insn_opr(&ud, 0);
405 if (op && op->type == UD_OP_JIMM) {
406 addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
407 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
408 zend_hash_index_add(&labels, addr, &zv);
409 }
410 }
411 }
412 #endif
413
414 zend_hash_sort(&labels, zend_jit_cmp_labels, 0);
415
416 /* label numbering */
417 n = 0; m = 0;
418 ZEND_HASH_MAP_FOREACH_VAL(&labels, z) {
419 if (Z_TYPE_P(z) == IS_FALSE) {
420 m--;
421 ZVAL_LONG(z, m);
422 } else {
423 n++;
424 ZVAL_LONG(z, n);
425 }
426 } ZEND_HASH_FOREACH_END();
427
428 #ifdef HAVE_CAPSTONE
429 # ifdef HAVE_CAPSTONE_ITER
430 cs_code = start;
431 cs_size = (uint8_t*)end - (uint8_t*)start;
432 cs_addr = (uint64_t)(uintptr_t)cs_code;
433 while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
434 z = zend_hash_index_find(&labels, insn->address);
435 # else
436 for (i = 0; i < count; i++) {
437 z = zend_hash_index_find(&labels, insn[i].address);
438 # endif
439 if (z) {
440 if (Z_LVAL_P(z) < 0) {
441 fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
442 } else {
443 fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
444 }
445 }
446
447 # ifdef HAVE_CAPSTONE_ITER
448 if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
449 fprintf(stderr, " %" PRIx64 ":", insn->address);
450 }
451 fprintf(stderr, "\t%s ", insn->mnemonic);
452 p = insn->op_str;
453 # else
454 if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
455 fprintf(stderr, " %" PRIx64 ":", insn[i].address);
456 }
457 fprintf(stderr, "\t%s ", insn[i].mnemonic);
458 p = insn[i].op_str;
459 # endif
460 /* Try to replace the target addresses with a symbols */
461 while ((q = strchr(p, 'x')) != NULL) {
462 if (p != q && *(q-1) == '0') {
463 r = q + 1;
464 addr = 0;
465 while (1) {
466 if (*r >= '0' && *r <= '9') {
467 addr = addr * 16 + (*r - '0');
468 } else if (*r >= 'A' && *r <= 'F') {
469 addr = addr * 16 + (*r - 'A' + 10);
470 } else if (*r >= 'a' && *r <= 'f') {
471 addr = addr * 16 + (*r - 'a' + 10);
472 } else {
473 break;
474 }
475 r++;
476 }
477 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
478 if ((z = zend_hash_index_find(&labels, addr))) {
479 if (Z_LVAL_P(z) < 0) {
480 fwrite(p, 1, q - p - 1, stderr);
481 fprintf(stderr, ".ENTRY" ZEND_LONG_FMT, -Z_LVAL_P(z));
482 } else {
483 fwrite(p, 1, q - p - 1, stderr);
484 fprintf(stderr, ".L" ZEND_LONG_FMT, Z_LVAL_P(z));
485 }
486 } else {
487 fwrite(p, 1, r - p, stderr);
488 }
489 } else if ((sym = zend_jit_disasm_resolver(addr, &offset))) {
490 fwrite(p, 1, q - p - 1, stderr);
491 fputs(sym, stderr);
492 if (offset != 0) {
493 if (offset > 0) {
494 fprintf(stderr, "+%" PRIx64, offset);
495 } else {
496 fprintf(stderr, "-%" PRIx64, offset);
497 }
498 }
499 } else {
500 fwrite(p, 1, r - p, stderr);
501 }
502 p = r;
503 } else {
504 fwrite(p, 1, q - p + 1, stderr);
505 p = q + 1;
506 }
507 }
508 fprintf(stderr, "%s\n", p);
509 }
510 # ifdef HAVE_CAPSTONE_ITER
511 cs_free(insn, 1);
512 # else
513 cs_free(insn, count);
514 # endif
515 #else
516 ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
517 ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
518
519 while (ud_disassemble(&ud)) {
520 addr = ud_insn_off(&ud);
521 z = zend_hash_index_find(&labels, addr);
522 if (z) {
523 if (Z_LVAL_P(z) < 0) {
524 fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
525 } else {
526 fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
527 }
528 }
529 op = ud_insn_opr(&ud, 0);
530 if (op && op->type == UD_OP_JIMM) {
531 addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
532 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
533 z = zend_hash_index_find(&labels, addr);
534 if (z) {
535 const char *str = ud_insn_asm(&ud);
536 int len;
537
538 len = 0;
539 while (str[len] != 0 && str[len] != ' ' && str[len] != '\t') {
540 len++;
541 }
542 if (str[len] != 0) {
543 while (str[len] == ' ' || str[len] == '\t') {
544 len++;
545 }
546 if (Z_LVAL_P(z) < 0) {
547 fprintf(stderr, "\t%.*s.ENTRY" ZEND_LONG_FMT "\n", len, str, -Z_LVAL_P(z));
548 } else {
549 fprintf(stderr, "\t%.*s.L" ZEND_LONG_FMT "\n", len, str, Z_LVAL_P(z));
550 }
551 continue;
552 }
553 }
554 }
555 }
556 if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_ADDR) {
557 fprintf(stderr, " %" PRIx64 ":", ud_insn_off(&ud));
558 }
559 fprintf(stderr, "\t%s\n", ud_insn_asm(&ud));
560 }
561 #endif
562 fprintf(stderr, "\n");
563
564 zend_hash_destroy(&labels);
565
566 #ifdef HAVE_CAPSTONE
567 cs_close(&cs);
568 #endif
569
570 return 1;
571 }
572
573 static int zend_jit_disasm_init(void)
574 {
575 #ifndef ZTS
576 #define REGISTER_EG(n) \
577 zend_jit_disasm_add_symbol("EG("#n")", \
578 (uint64_t)(uintptr_t)&executor_globals.n, sizeof(executor_globals.n))
579 REGISTER_EG(uninitialized_zval);
580 REGISTER_EG(exception);
581 REGISTER_EG(vm_interrupt);
582 REGISTER_EG(exception_op);
583 REGISTER_EG(timed_out);
584 REGISTER_EG(current_execute_data);
585 REGISTER_EG(vm_stack_top);
586 REGISTER_EG(vm_stack_end);
587 REGISTER_EG(symbol_table);
588 REGISTER_EG(jit_trace_num);
589 #undef REGISTER_EG
590 #define REGISTER_CG(n) \
591 zend_jit_disasm_add_symbol("CG("#n")", \
592 (uint64_t)(uintptr_t)&compiler_globals.n, sizeof(compiler_globals.n))
593 REGISTER_CG(map_ptr_base);
594 #undef REGISTER_CG
595 #endif
596
597 /* Register JIT helper functions */
598 #define REGISTER_HELPER(n) \
599 zend_jit_disasm_add_symbol(#n, \
600 (uint64_t)(uintptr_t)n, sizeof(void*));
601 REGISTER_HELPER(memcmp);
602 REGISTER_HELPER(zend_jit_init_func_run_time_cache_helper);
603 REGISTER_HELPER(zend_jit_find_func_helper);
604 REGISTER_HELPER(zend_jit_find_ns_func_helper);
605 REGISTER_HELPER(zend_jit_find_method_helper);
606 REGISTER_HELPER(zend_jit_find_method_tmp_helper);
607 REGISTER_HELPER(zend_jit_push_static_metod_call_frame);
608 REGISTER_HELPER(zend_jit_push_static_metod_call_frame_tmp);
609 REGISTER_HELPER(zend_jit_invalid_method_call);
610 REGISTER_HELPER(zend_jit_invalid_method_call_tmp);
611 REGISTER_HELPER(zend_jit_unref_helper);
612 REGISTER_HELPER(zend_jit_extend_stack_helper);
613 REGISTER_HELPER(zend_jit_int_extend_stack_helper);
614 REGISTER_HELPER(zend_jit_leave_nested_func_helper);
615 REGISTER_HELPER(zend_jit_leave_top_func_helper);
616 REGISTER_HELPER(zend_jit_leave_func_helper);
617 REGISTER_HELPER(zend_jit_symtable_find);
618 REGISTER_HELPER(zend_jit_hash_index_lookup_rw_no_packed);
619 REGISTER_HELPER(zend_jit_hash_index_lookup_rw);
620 REGISTER_HELPER(zend_jit_hash_lookup_rw);
621 REGISTER_HELPER(zend_jit_symtable_lookup_rw);
622 REGISTER_HELPER(zend_jit_symtable_lookup_w);
623 REGISTER_HELPER(zend_jit_undefined_op_helper);
624 REGISTER_HELPER(zend_jit_fetch_dim_r_helper);
625 REGISTER_HELPER(zend_jit_fetch_dim_is_helper);
626 REGISTER_HELPER(zend_jit_fetch_dim_isset_helper);
627 REGISTER_HELPER(zend_jit_fetch_dim_str_offset_r_helper);
628 REGISTER_HELPER(zend_jit_fetch_dim_str_r_helper);
629 REGISTER_HELPER(zend_jit_fetch_dim_str_is_helper);
630 REGISTER_HELPER(zend_jit_fetch_dim_obj_r_helper);
631 REGISTER_HELPER(zend_jit_fetch_dim_obj_is_helper);
632 REGISTER_HELPER(zend_jit_fetch_dim_rw_helper);
633 REGISTER_HELPER(zend_jit_fetch_dim_w_helper);
634 REGISTER_HELPER(zend_jit_fetch_dim_obj_rw_helper);
635 REGISTER_HELPER(zend_jit_fetch_dim_obj_w_helper);
636 // REGISTER_HELPER(zend_jit_fetch_dim_obj_unset_helper);
637 REGISTER_HELPER(zend_jit_assign_dim_helper);
638 REGISTER_HELPER(zend_jit_assign_dim_op_helper);
639 REGISTER_HELPER(zend_jit_fast_assign_concat_helper);
640 REGISTER_HELPER(zend_jit_fast_concat_helper);
641 REGISTER_HELPER(zend_jit_fast_concat_tmp_helper);
642 REGISTER_HELPER(zend_jit_isset_dim_helper);
643 REGISTER_HELPER(zend_jit_free_call_frame);
644 REGISTER_HELPER(zend_jit_fetch_global_helper);
645 REGISTER_HELPER(zend_jit_verify_arg_slow);
646 REGISTER_HELPER(zend_jit_verify_return_slow);
647 REGISTER_HELPER(zend_jit_fetch_obj_r_slow);
648 REGISTER_HELPER(zend_jit_fetch_obj_r_dynamic);
649 REGISTER_HELPER(zend_jit_fetch_obj_is_slow);
650 REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
651 REGISTER_HELPER(zend_jit_fetch_obj_w_slow);
652 REGISTER_HELPER(zend_jit_check_array_promotion);
653 REGISTER_HELPER(zend_jit_create_typed_ref);
654 REGISTER_HELPER(zend_jit_extract_helper);
655 REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
656 REGISTER_HELPER(zend_jit_copy_extra_args_helper);
657 REGISTER_HELPER(zend_jit_deprecated_helper);
658 REGISTER_HELPER(zend_jit_undefined_long_key);
659 REGISTER_HELPER(zend_jit_undefined_string_key);
660 REGISTER_HELPER(zend_jit_assign_const_to_typed_ref);
661 REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref);
662 REGISTER_HELPER(zend_jit_assign_var_to_typed_ref);
663 REGISTER_HELPER(zend_jit_assign_cv_to_typed_ref);
664 REGISTER_HELPER(zend_jit_pre_inc_typed_ref);
665 REGISTER_HELPER(zend_jit_pre_dec_typed_ref);
666 REGISTER_HELPER(zend_jit_post_inc_typed_ref);
667 REGISTER_HELPER(zend_jit_post_dec_typed_ref);
668 REGISTER_HELPER(zend_jit_assign_op_to_typed_ref);
669 REGISTER_HELPER(zend_jit_assign_op_to_typed_ref_tmp);
670 REGISTER_HELPER(zend_jit_only_vars_by_reference);
671 REGISTER_HELPER(zend_jit_invalid_array_access);
672 REGISTER_HELPER(zend_jit_invalid_property_read);
673 REGISTER_HELPER(zend_jit_invalid_property_write);
674 REGISTER_HELPER(zend_jit_invalid_property_incdec);
675 REGISTER_HELPER(zend_jit_invalid_property_assign);
676 REGISTER_HELPER(zend_jit_invalid_property_assign_op);
677 REGISTER_HELPER(zend_jit_prepare_assign_dim_ref);
678 REGISTER_HELPER(zend_jit_pre_inc);
679 REGISTER_HELPER(zend_jit_pre_dec);
680 REGISTER_HELPER(zend_runtime_jit);
681 REGISTER_HELPER(zend_jit_hot_func);
682 REGISTER_HELPER(zend_jit_check_constant);
683 REGISTER_HELPER(zend_jit_get_constant);
684 REGISTER_HELPER(zend_jit_array_free);
685 REGISTER_HELPER(zend_jit_zval_array_dup);
686 REGISTER_HELPER(zend_jit_add_arrays_helper);
687 REGISTER_HELPER(zend_jit_assign_obj_helper);
688 REGISTER_HELPER(zend_jit_assign_obj_op_helper);
689 REGISTER_HELPER(zend_jit_assign_to_typed_prop);
690 REGISTER_HELPER(zend_jit_assign_op_to_typed_prop);
691 REGISTER_HELPER(zend_jit_inc_typed_prop);
692 REGISTER_HELPER(zend_jit_dec_typed_prop);
693 REGISTER_HELPER(zend_jit_pre_inc_typed_prop);
694 REGISTER_HELPER(zend_jit_pre_dec_typed_prop);
695 REGISTER_HELPER(zend_jit_post_inc_typed_prop);
696 REGISTER_HELPER(zend_jit_post_dec_typed_prop);
697 REGISTER_HELPER(zend_jit_pre_inc_obj_helper);
698 REGISTER_HELPER(zend_jit_pre_dec_obj_helper);
699 REGISTER_HELPER(zend_jit_post_inc_obj_helper);
700 REGISTER_HELPER(zend_jit_post_dec_obj_helper);
701 REGISTER_HELPER(zend_jit_rope_end);
702 #if (PHP_VERSION_ID <= 80100) && (SIZEOF_SIZE_T == 4)
703 REGISTER_HELPER(zval_jit_update_constant_ex);
704 #endif
705 REGISTER_HELPER(zend_jit_free_trampoline_helper);
706 REGISTER_HELPER(zend_jit_exception_in_interrupt_handler_helper);
707 #undef REGISTER_HELPER
708
709 #ifndef _WIN32
710 zend_elf_load_symbols();
711 #endif
712
713 if (zend_vm_kind() == ZEND_VM_KIND_HYBRID) {
714 zend_op opline;
715
716 memset(&opline, 0, sizeof(opline));
717
718 opline.opcode = ZEND_DO_UCALL;
719 opline.result_type = IS_UNUSED;
720 zend_vm_set_opcode_handler(&opline);
721 zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
722
723 opline.opcode = ZEND_DO_UCALL;
724 opline.result_type = IS_VAR;
725 zend_vm_set_opcode_handler(&opline);
726 zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
727
728 opline.opcode = ZEND_DO_FCALL_BY_NAME;
729 opline.result_type = IS_UNUSED;
730 zend_vm_set_opcode_handler(&opline);
731 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
732
733 opline.opcode = ZEND_DO_FCALL_BY_NAME;
734 opline.result_type = IS_VAR;
735 zend_vm_set_opcode_handler(&opline);
736 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
737
738 opline.opcode = ZEND_DO_FCALL;
739 opline.result_type = IS_UNUSED;
740 zend_vm_set_opcode_handler(&opline);
741 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
742
743 opline.opcode = ZEND_DO_FCALL;
744 opline.result_type = IS_VAR;
745 zend_vm_set_opcode_handler(&opline);
746 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
747
748 opline.opcode = ZEND_RETURN;
749 opline.op1_type = IS_CONST;
750 zend_vm_set_opcode_handler(&opline);
751 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CONST_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
752
753 opline.opcode = ZEND_RETURN;
754 opline.op1_type = IS_TMP_VAR;
755 zend_vm_set_opcode_handler(&opline);
756 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_TMP_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
757
758 opline.opcode = ZEND_RETURN;
759 opline.op1_type = IS_VAR;
760 zend_vm_set_opcode_handler(&opline);
761 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_VAR_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
762
763 opline.opcode = ZEND_RETURN;
764 opline.op1_type = IS_CV;
765 zend_vm_set_opcode_handler(&opline);
766 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CV_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
767
768 zend_jit_disasm_add_symbol("ZEND_HYBRID_HALT_LABEL", (uint64_t)(uintptr_t)zend_jit_halt_op->handler, sizeof(void*));
769 }
770
771 return 1;
772 }
773
774 static void zend_jit_disasm_shutdown(void)
775 {
776 if (JIT_G(symbols)) {
777 zend_jit_disasm_destroy_symbols(JIT_G(symbols));
778 JIT_G(symbols) = NULL;
779 }
780 }
781
782 #endif /* HAVE_DISASM */
783