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    | http://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    +----------------------------------------------------------------------+
18 */
19 
20 #define HAVE_DISASM 1
21 #define DISASM_INTEL_SYNTAX 0
22 
23 #include "jit/libudis86/itab.c"
24 #include "jit/libudis86/decode.c"
25 #include "jit/libudis86/syn.c"
26 #if DISASM_INTEL_SYNTAX
27 # include "jit/libudis86/syn-intel.c"
28 #else
29 # include "jit/libudis86/syn-att.c"
30 #endif
31 #include "jit/libudis86/udis86.c"
32 
33 static void zend_jit_disasm_add_symbol(const char *name,
34                                        uint64_t    addr,
35                                        uint64_t    size);
36 
37 #ifndef _WIN32
38 # include "jit/zend_elf.c"
39 #endif
40 
41 #include "zend_sort.h"
42 
43 #ifndef _GNU_SOURCE
44 # define _GNU_SOURCE
45 #endif
46 
47 #ifndef _WIN32
48 #include <dlfcn.h>
49 #endif
50 
51 static struct ud ud;
52 
53 struct _sym_node {
54 	uint64_t          addr;
55 	uint64_t          end;
56 	struct _sym_node *parent;
57 	struct _sym_node *child[2];
58 	unsigned char     info;
59 	char              name[1];
60 };
61 
zend_syms_rotateleft(zend_sym_node * p)62 static void zend_syms_rotateleft(zend_sym_node *p) {
63 	zend_sym_node *r = p->child[1];
64 	p->child[1] = r->child[0];
65 	if (r->child[0]) {
66 		r->child[0]->parent = p;
67 	}
68 	r->parent = p->parent;
69 	if (p->parent == NULL) {
70 		JIT_G(symbols) = r;
71 	} else if (p->parent->child[0] == p) {
72 		p->parent->child[0] = r;
73 	} else {
74 		p->parent->child[1] = r;
75 	}
76 	r->child[0] = p;
77 	p->parent = r;
78 }
79 
zend_syms_rotateright(zend_sym_node * p)80 static void zend_syms_rotateright(zend_sym_node *p) {
81 	zend_sym_node *l = p->child[0];
82 	p->child[0] = l->child[1];
83 	if (l->child[1]) {
84 		l->child[1]->parent = p;
85 	}
86 	l->parent = p->parent;
87 	if (p->parent == NULL) {
88 		JIT_G(symbols) = l;
89 	} else if (p->parent->child[1] == p) {
90 		p->parent->child[1] = l;
91 	} else {
92 		p->parent->child[0] = l;
93 	}
94 	l->child[1] = p;
95 	p->parent = l;
96 }
97 
zend_jit_disasm_add_symbol(const char * name,uint64_t addr,uint64_t size)98 static void zend_jit_disasm_add_symbol(const char *name,
99                                        uint64_t    addr,
100                                        uint64_t    size)
101 {
102 	zend_sym_node *sym;
103 	size_t len = strlen(name);
104 
105 	sym = malloc(sizeof(zend_sym_node) + len + 1);
106 	if (!sym) {
107 		return;
108 	}
109 	sym->addr = addr;
110 	sym->end  = (addr + size - 1);
111 	memcpy((char*)&sym->name, name, len + 1);
112 	sym->parent = sym->child[0] = sym->child[1] = NULL;
113 	sym->info = 1;
114 	if (JIT_G(symbols)) {
115 		zend_sym_node *node = JIT_G(symbols);
116 
117 		/* insert it into rbtree */
118 		do {
119 			if (sym->addr > node->addr) {
120 				ZEND_ASSERT(sym->addr > (node->end));
121 				if (node->child[1]) {
122 					node = node->child[1];
123 				} else {
124 					node->child[1] = sym;
125 					sym->parent = node;
126 					break;
127 				}
128 			} else if (sym->addr < node->addr) {
129 				if (node->child[0]) {
130 					node = node->child[0];
131 				} else {
132 					node->child[0] = sym;
133 					sym->parent = node;
134 					break;
135 				}
136 			} else {
137 				ZEND_ASSERT(sym->addr == node->addr);
138 				if (strcmp(name, node->name) == 0 && sym->end < node->end) {
139 					/* reduce size of the existing symbol */
140 					node->end = sym->end;
141 				}
142 				free(sym);
143 				return;
144 			}
145 		} while (1);
146 
147 		/* fix rbtree after instering */
148 		while (sym && sym != JIT_G(symbols) && sym->parent->info == 1) {
149 			if (sym->parent == sym->parent->parent->child[0]) {
150 				node = sym->parent->parent->child[1];
151 				if (node && node->info == 1) {
152 					sym->parent->info = 0;
153 					node->info = 0;
154 					sym->parent->parent->info = 1;
155 					sym = sym->parent->parent;
156 				} else {
157 					if (sym == sym->parent->child[1]) {
158 						sym = sym->parent;
159 						zend_syms_rotateleft(sym);
160 					}
161 					sym->parent->info = 0;
162 					sym->parent->parent->info = 1;
163 					zend_syms_rotateright(sym->parent->parent);
164 				}
165 			} else {
166 				node = sym->parent->parent->child[0];
167 				if (node && node->info == 1) {
168 					sym->parent->info = 0;
169 					node->info = 0;
170 					sym->parent->parent->info = 1;
171 					sym = sym->parent->parent;
172 				} else {
173 					if (sym == sym->parent->child[0]) {
174 						sym = sym->parent;
175 						zend_syms_rotateright(sym);
176 					}
177 					sym->parent->info = 0;
178 					sym->parent->parent->info = 1;
179 					zend_syms_rotateleft(sym->parent->parent);
180 				}
181 			}
182 		}
183 	} else {
184 		JIT_G(symbols) = sym;
185 	}
186 	JIT_G(symbols)->info = 0;
187 }
188 
zend_jit_disasm_destroy_symbols(zend_sym_node * n)189 static void zend_jit_disasm_destroy_symbols(zend_sym_node *n) {
190 	if (n) {
191 		if (n->child[0]) {
192 			zend_jit_disasm_destroy_symbols(n->child[0]);
193 		}
194 		if (n->child[1]) {
195 			zend_jit_disasm_destroy_symbols(n->child[1]);
196 		}
197 		free(n);
198 	}
199 }
200 
zend_jit_disasm_find_symbol(uint64_t addr,int64_t * offset)201 static const char* zend_jit_disasm_find_symbol(uint64_t  addr,
202                                                int64_t  *offset) {
203 	zend_sym_node *node = JIT_G(symbols);
204 	while (node) {
205 		if (addr < node->addr) {
206 			node = node->child[0];
207 		} else if (addr > node->end) {
208 			node = node->child[1];
209 		} else {
210 			*offset = addr - node->addr;
211 			return node->name;
212 		}
213 	}
214 	return NULL;
215 }
216 
zend_jit_disasm_resolver(struct ud * ud,uint64_t addr,int64_t * offset)217 static const char* zend_jit_disasm_resolver(struct ud *ud,
218                                             uint64_t   addr,
219                                             int64_t   *offset)
220 {
221 #ifndef _WIN32
222 	((void)ud);
223 	const char *name;
224 	void *a = (void*)(zend_uintptr_t)(addr);
225 	Dl_info info;
226 
227 	name = zend_jit_disasm_find_symbol(addr, offset);
228 	if (name) {
229 		return name;
230 	}
231 
232 	if (dladdr(a, &info)
233 	 && info.dli_sname != NULL
234 	 && info.dli_saddr == a) {
235 		return info.dli_sname;
236 	}
237 #else
238 	const char *name;
239 	name = zend_jit_disasm_find_symbol(addr, offset);
240 	if (name) {
241 		return name;
242 	}
243 #endif
244 
245 	return NULL;
246 }
247 
zend_jit_cmp_labels(Bucket * b1,Bucket * b2)248 static int zend_jit_cmp_labels(Bucket *b1, Bucket *b2)
249 {
250 	return ((b1->h > b2->h) > 0) ? 1 : -1;
251 }
252 
zend_jit_disasm(const char * name,const char * filename,const zend_op_array * op_array,zend_cfg * cfg,const void * start,size_t size)253 static int zend_jit_disasm(const char    *name,
254                            const char    *filename,
255                            const zend_op_array *op_array,
256                            zend_cfg      *cfg,
257                            const void    *start,
258                            size_t         size)
259 {
260 	const void *end = (void *)((char *)start + size);
261 	zval zv, *z;
262 	zend_long n, m;
263 	HashTable labels;
264 	const struct ud_operand *op;
265 	uint64_t addr;
266 	int b;
267 
268 	if (name) {
269 		fprintf(stderr, "%s: ; (%s)\n", name, filename ? filename : "unknown");
270 	}
271 
272 	ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
273 	ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
274 
275 	zend_hash_init(&labels, 8, NULL, NULL, 0);
276 	if (op_array && cfg) {
277 		ZVAL_FALSE(&zv);
278 		for (b = 0; b < cfg->blocks_count; b++) {
279 			if (cfg->blocks[b].flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
280 				addr = (uint64_t)(uintptr_t)op_array->opcodes[cfg->blocks[b].start].handler;
281 				if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
282 					zend_hash_index_add(&labels, addr, &zv);
283 				}
284 			}
285 		}
286 	}
287 	ZVAL_TRUE(&zv);
288 	while (ud_disassemble(&ud)) {
289 		op = ud_insn_opr(&ud, 0);
290 		if (op && op->type == UD_OP_JIMM) {
291 			addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
292 			if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
293 				zend_hash_index_add(&labels, addr, &zv);
294 			}
295 		}
296 	}
297 
298 	zend_hash_sort(&labels, zend_jit_cmp_labels, 0);
299 
300 	/* label numbering */
301 	n = 0; m = 0;
302 	ZEND_HASH_FOREACH_VAL(&labels, z) {
303 		if (Z_TYPE_P(z) == IS_FALSE) {
304 			m--;
305 			ZVAL_LONG(z, m);
306 		} else {
307 			n++;
308 			ZVAL_LONG(z, n);
309 		}
310 	} ZEND_HASH_FOREACH_END();
311 
312 	ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
313 	ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
314 
315 	while (ud_disassemble(&ud)) {
316 		addr = ud_insn_off(&ud);
317 		z = zend_hash_index_find(&labels, addr);
318 		if (z) {
319 			if (Z_LVAL_P(z) < 0) {
320 				fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
321 			} else {
322 				fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
323 			}
324 		}
325 		op = ud_insn_opr(&ud, 0);
326 		if (op && op->type == UD_OP_JIMM) {
327 			addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
328 			if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
329 				z = zend_hash_index_find(&labels, addr);
330 				if (z) {
331 					const char *str = ud_insn_asm(&ud);
332 					int len;
333 
334 					len = 0;
335 					while (str[len] != 0 && str[len] != ' ' && str[len] != '\t') {
336 						len++;
337 					}
338 					if (str[len] != 0) {
339 						while (str[len] == ' ' || str[len] == '\t') {
340 							len++;
341 						}
342 						if (Z_LVAL_P(z) < 0) {
343 							fprintf(stderr, "\t%.*s.ENTRY" ZEND_LONG_FMT "\n", len, str, -Z_LVAL_P(z));
344 						} else {
345 							fprintf(stderr, "\t%.*s.L" ZEND_LONG_FMT "\n", len, str, Z_LVAL_P(z));
346 						}
347 						continue;
348 					}
349 				}
350 			}
351 		}
352 		fprintf(stderr, "\t%s\n", ud_insn_asm(&ud));
353 	}
354 	fprintf(stderr, "\n");
355 
356 	zend_hash_destroy(&labels);
357 
358 	return 1;
359 }
360 
zend_jit_disasm_init(void)361 static int zend_jit_disasm_init(void)
362 {
363 	ud_init(&ud);
364 #if defined(__x86_64__) || defined(_WIN64)
365 	ud_set_mode(&ud, 64);
366 #else
367 	ud_set_mode(&ud, 32);
368 #endif
369 #if DISASM_INTEL_SYNTAX
370 	ud_set_syntax(&ud, UD_SYN_INTEL);
371 #else
372 	ud_set_syntax(&ud, UD_SYN_ATT);
373 #endif
374 	ud_set_sym_resolver(&ud, zend_jit_disasm_resolver);
375 
376 #ifndef ZTS
377 #define REGISTER_EG(n)  \
378 	zend_jit_disasm_add_symbol("EG("#n")", \
379 		(uint64_t)(uintptr_t)&executor_globals.n, sizeof(executor_globals.n))
380 	REGISTER_EG(uninitialized_zval);
381 	REGISTER_EG(exception);
382 	REGISTER_EG(vm_interrupt);
383 	REGISTER_EG(exception_op);
384 	REGISTER_EG(timed_out);
385 	REGISTER_EG(current_execute_data);
386 	REGISTER_EG(vm_stack_top);
387 	REGISTER_EG(vm_stack_end);
388 	REGISTER_EG(symbol_table);
389 	REGISTER_EG(jit_trace_num);
390 #undef  REGISTER_EG
391 #endif
392 
393 	/* Register JIT helper functions */
394 #define REGISTER_HELPER(n)  \
395 	zend_jit_disasm_add_symbol(#n, \
396 		(uint64_t)(uintptr_t)n, sizeof(void*));
397 	REGISTER_HELPER(memcmp);
398 	REGISTER_HELPER(zend_jit_init_func_run_time_cache_helper);
399 	REGISTER_HELPER(zend_jit_find_func_helper);
400 	REGISTER_HELPER(zend_jit_find_ns_func_helper);
401 	REGISTER_HELPER(zend_jit_find_method_helper);
402 	REGISTER_HELPER(zend_jit_find_method_tmp_helper);
403 	REGISTER_HELPER(zend_jit_push_static_metod_call_frame);
404 	REGISTER_HELPER(zend_jit_push_static_metod_call_frame_tmp);
405 	REGISTER_HELPER(zend_jit_invalid_method_call);
406 	REGISTER_HELPER(zend_jit_invalid_method_call_tmp);
407 	REGISTER_HELPER(zend_jit_unref_helper);
408 	REGISTER_HELPER(zend_jit_extend_stack_helper);
409 	REGISTER_HELPER(zend_jit_int_extend_stack_helper);
410 	REGISTER_HELPER(zend_jit_leave_nested_func_helper);
411 	REGISTER_HELPER(zend_jit_leave_top_func_helper);
412 	REGISTER_HELPER(zend_jit_leave_func_helper);
413 	REGISTER_HELPER(zend_jit_symtable_find);
414 	REGISTER_HELPER(zend_jit_hash_index_lookup_rw_no_packed);
415 	REGISTER_HELPER(zend_jit_hash_index_lookup_rw);
416 	REGISTER_HELPER(zend_jit_hash_index_lookup_w);
417 	REGISTER_HELPER(zend_jit_hash_lookup_rw);
418 	REGISTER_HELPER(zend_jit_hash_lookup_w);
419 	REGISTER_HELPER(zend_jit_symtable_lookup_rw);
420 	REGISTER_HELPER(zend_jit_symtable_lookup_w);
421 	REGISTER_HELPER(zend_jit_undefined_op_helper);
422 	REGISTER_HELPER(zend_jit_fetch_dim_r_helper);
423 	REGISTER_HELPER(zend_jit_fetch_dim_is_helper);
424 	REGISTER_HELPER(zend_jit_fetch_dim_isset_helper);
425 	REGISTER_HELPER(zend_jit_fetch_dim_str_offset_r_helper);
426 	REGISTER_HELPER(zend_jit_fetch_dim_str_r_helper);
427 	REGISTER_HELPER(zend_jit_fetch_dim_str_is_helper);
428 	REGISTER_HELPER(zend_jit_fetch_dim_obj_r_helper);
429 	REGISTER_HELPER(zend_jit_fetch_dim_obj_is_helper);
430 	REGISTER_HELPER(zend_jit_fetch_dim_rw_helper);
431 	REGISTER_HELPER(zend_jit_fetch_dim_w_helper);
432 	REGISTER_HELPER(zend_jit_fetch_dim_obj_rw_helper);
433 	REGISTER_HELPER(zend_jit_fetch_dim_obj_w_helper);
434 //	REGISTER_HELPER(zend_jit_fetch_dim_obj_unset_helper);
435 	REGISTER_HELPER(zend_jit_assign_dim_helper);
436 	REGISTER_HELPER(zend_jit_assign_dim_op_helper);
437 	REGISTER_HELPER(zend_jit_fast_assign_concat_helper);
438 	REGISTER_HELPER(zend_jit_fast_concat_helper);
439 	REGISTER_HELPER(zend_jit_isset_dim_helper);
440 	REGISTER_HELPER(zend_jit_free_call_frame);
441 	REGISTER_HELPER(zend_jit_fetch_global_helper);
442 	REGISTER_HELPER(zend_jit_verify_arg_slow);
443 	REGISTER_HELPER(zend_jit_verify_return_slow);
444 	REGISTER_HELPER(zend_jit_fetch_obj_r_slow);
445 	REGISTER_HELPER(zend_jit_fetch_obj_r_dynamic);
446 	REGISTER_HELPER(zend_jit_fetch_obj_is_slow);
447 	REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
448 	REGISTER_HELPER(zend_jit_fetch_obj_w_slow);
449 	REGISTER_HELPER(zend_jit_check_array_promotion);
450 	REGISTER_HELPER(zend_jit_create_typed_ref);
451 	REGISTER_HELPER(zend_jit_extract_helper);
452 	REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
453 	REGISTER_HELPER(zend_jit_copy_extra_args_helper);
454 	REGISTER_HELPER(zend_jit_deprecated_helper);
455 	REGISTER_HELPER(zend_jit_assign_const_to_typed_ref);
456 	REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref);
457 	REGISTER_HELPER(zend_jit_assign_var_to_typed_ref);
458 	REGISTER_HELPER(zend_jit_assign_cv_to_typed_ref);
459 	REGISTER_HELPER(zend_jit_pre_inc_typed_ref);
460 	REGISTER_HELPER(zend_jit_pre_dec_typed_ref);
461 	REGISTER_HELPER(zend_jit_post_inc_typed_ref);
462 	REGISTER_HELPER(zend_jit_post_dec_typed_ref);
463 	REGISTER_HELPER(zend_jit_assign_op_to_typed_ref);
464 	REGISTER_HELPER(zend_jit_assign_op_to_typed_ref_tmp);
465 	REGISTER_HELPER(zend_jit_only_vars_by_reference);
466 	REGISTER_HELPER(zend_jit_invalid_array_access);
467 	REGISTER_HELPER(zend_jit_invalid_property_read);
468 	REGISTER_HELPER(zend_jit_invalid_property_write);
469 	REGISTER_HELPER(zend_jit_invalid_property_incdec);
470 	REGISTER_HELPER(zend_jit_invalid_property_assign);
471 	REGISTER_HELPER(zend_jit_invalid_property_assign_op);
472 	REGISTER_HELPER(zend_jit_prepare_assign_dim_ref);
473 	REGISTER_HELPER(zend_jit_pre_inc);
474 	REGISTER_HELPER(zend_jit_pre_dec);
475 	REGISTER_HELPER(zend_runtime_jit);
476 	REGISTER_HELPER(zend_jit_hot_func);
477 	REGISTER_HELPER(zend_jit_check_constant);
478 	REGISTER_HELPER(zend_jit_get_constant);
479 	REGISTER_HELPER(zend_jit_array_free);
480 	REGISTER_HELPER(zend_jit_zval_array_dup);
481 	REGISTER_HELPER(zend_jit_add_arrays_helper);
482 	REGISTER_HELPER(zend_jit_assign_obj_helper);
483 	REGISTER_HELPER(zend_jit_assign_obj_op_helper);
484 	REGISTER_HELPER(zend_jit_assign_to_typed_prop);
485 	REGISTER_HELPER(zend_jit_assign_op_to_typed_prop);
486 	REGISTER_HELPER(zend_jit_inc_typed_prop);
487 	REGISTER_HELPER(zend_jit_dec_typed_prop);
488 	REGISTER_HELPER(zend_jit_pre_inc_typed_prop);
489 	REGISTER_HELPER(zend_jit_pre_dec_typed_prop);
490 	REGISTER_HELPER(zend_jit_post_inc_typed_prop);
491 	REGISTER_HELPER(zend_jit_post_dec_typed_prop);
492 	REGISTER_HELPER(zend_jit_pre_inc_obj_helper);
493 	REGISTER_HELPER(zend_jit_pre_dec_obj_helper);
494 	REGISTER_HELPER(zend_jit_post_inc_obj_helper);
495 	REGISTER_HELPER(zend_jit_post_dec_obj_helper);
496 #if (PHP_VERSION_ID <= 80100) && (SIZEOF_SIZE_T == 4)
497 	REGISTER_HELPER(zval_jit_update_constant_ex);
498 #endif
499 	REGISTER_HELPER(zend_jit_free_trampoline_helper);
500 	REGISTER_HELPER(zend_jit_exception_in_interrupt_handler_helper);
501 #undef  REGISTER_HELPER
502 
503 #ifndef _WIN32
504 	zend_elf_load_symbols();
505 #endif
506 
507 	if (zend_vm_kind() == ZEND_VM_KIND_HYBRID) {
508 		zend_op opline;
509 
510 		memset(&opline, 0, sizeof(opline));
511 
512 		opline.opcode = ZEND_DO_UCALL;
513 		opline.result_type = IS_UNUSED;
514 		zend_vm_set_opcode_handler(&opline);
515 		zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
516 
517 		opline.opcode = ZEND_DO_UCALL;
518 		opline.result_type = IS_VAR;
519 		zend_vm_set_opcode_handler(&opline);
520 		zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
521 
522 		opline.opcode = ZEND_DO_FCALL_BY_NAME;
523 		opline.result_type = IS_UNUSED;
524 		zend_vm_set_opcode_handler(&opline);
525 		zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
526 
527 		opline.opcode = ZEND_DO_FCALL_BY_NAME;
528 		opline.result_type = IS_VAR;
529 		zend_vm_set_opcode_handler(&opline);
530 		zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
531 
532 		opline.opcode = ZEND_DO_FCALL;
533 		opline.result_type = IS_UNUSED;
534 		zend_vm_set_opcode_handler(&opline);
535 		zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
536 
537 		opline.opcode = ZEND_DO_FCALL;
538 		opline.result_type = IS_VAR;
539 		zend_vm_set_opcode_handler(&opline);
540 		zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
541 
542 		opline.opcode = ZEND_RETURN;
543 		opline.op1_type = IS_CONST;
544 		zend_vm_set_opcode_handler(&opline);
545 		zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CONST_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
546 
547 		opline.opcode = ZEND_RETURN;
548 		opline.op1_type = IS_TMP_VAR;
549 		zend_vm_set_opcode_handler(&opline);
550 		zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_TMP_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
551 
552 		opline.opcode = ZEND_RETURN;
553 		opline.op1_type = IS_VAR;
554 		zend_vm_set_opcode_handler(&opline);
555 		zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_VAR_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
556 
557 		opline.opcode = ZEND_RETURN;
558 		opline.op1_type = IS_CV;
559 		zend_vm_set_opcode_handler(&opline);
560 		zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CV_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
561 
562 		zend_jit_disasm_add_symbol("ZEND_HYBRID_HALT_LABEL", (uint64_t)(uintptr_t)zend_jit_halt_op->handler, sizeof(void*));
563 	}
564 
565 	return 1;
566 }
567 
zend_jit_disasm_shutdown(void)568 static void zend_jit_disasm_shutdown(void)
569 {
570 	if (JIT_G(symbols)) {
571 		zend_jit_disasm_destroy_symbols(JIT_G(symbols));
572 		JIT_G(symbols) = NULL;
573 	}
574 }
575