php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zend_file_cache.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Zend OPcache |
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 +----------------------------------------------------------------------+
17*/
18
19#include "zend.h"
20#include "zend_virtual_cwd.h"
21#include "zend_compile.h"
22#include "zend_vm.h"
23#include "zend_interfaces.h"
24#include "zend_attributes.h"
25#include "zend_system_id.h"
26#include "zend_enum.h"
27
28#include "php.h"
29#ifdef ZEND_WIN32
30#include "ext/standard/md5.h"
31#endif
33
34#include "ZendAccelerator.h"
35#include "zend_file_cache.h"
36#include "zend_shared_alloc.h"
39
40#ifdef HAVE_JIT
41#include "jit/zend_jit.h"
42#endif
43
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <fcntl.h>
47
48#ifdef HAVE_UNISTD_H
49#include <unistd.h>
50#endif
51
52#ifdef HAVE_SYS_UIO_H
53# include <sys/uio.h>
54#endif
55
56#ifdef HAVE_SYS_FILE_H
57# include <sys/file.h>
58#endif
59
60#if __has_feature(memory_sanitizer)
61# include <sanitizer/msan_interface.h>
62#endif
63
64#ifndef ZEND_WIN32
65#define zend_file_cache_unlink unlink
66#define zend_file_cache_open open
67#else
68#define zend_file_cache_unlink php_win32_ioutil_unlink
69#define zend_file_cache_open php_win32_ioutil_open
70#endif
71
72#ifdef ZEND_WIN32
73# define LOCK_SH 0
74# define LOCK_EX 1
75# define LOCK_UN 2
76static int zend_file_cache_flock(int fd, int op)
77{
78 OVERLAPPED offset = {0,0,0,0,NULL};
79 if (op == LOCK_EX) {
80 if (LockFileEx((HANDLE)_get_osfhandle(fd),
81 LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset) == TRUE) {
82 return 0;
83 }
84 } else if (op == LOCK_SH) {
85 if (LockFileEx((HANDLE)_get_osfhandle(fd),
86 0, 0, 1, 0, &offset) == TRUE) {
87 return 0;
88 }
89 } else if (op == LOCK_UN) {
90 if (UnlockFileEx((HANDLE)_get_osfhandle(fd),
91 0, 1, 0, &offset) == TRUE) {
92 return 0;
93 }
94 }
95 return -1;
96}
97#elif defined(HAVE_FLOCK)
98# define zend_file_cache_flock flock
99#else
100# define LOCK_SH 0
101# define LOCK_EX 1
102# define LOCK_UN 2
103static int zend_file_cache_flock(int fd, int type)
104{
105 return 0;
106}
107#endif
108
109#ifndef O_BINARY
110# define O_BINARY 0
111#endif
112
113#define SUFFIX ".bin"
114
115#define IS_SERIALIZED_INTERNED(ptr) \
116 ((size_t)(ptr) & Z_UL(1))
117
118/* Allowing == on the upper bound accounts for a potential empty allocation at the end of the
119 * memory region. This can also happen for a return-type-only arg_info, where &arg_info[1] is
120 * stored, which may point to the end of the region. */
121#define IS_SERIALIZED(ptr) \
122 ((char*)(ptr) <= (char*)script->size)
123#define IS_UNSERIALIZED(ptr) \
124 (((char*)(ptr) >= (char*)script->mem && (char*)(ptr) <= (char*)script->mem + script->size) || \
125 IS_ACCEL_INTERNED(ptr))
126#define SERIALIZE_PTR(ptr) do { \
127 if (ptr) { \
128 ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
129 (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
130 } \
131 } while (0)
132#define UNSERIALIZE_PTR(ptr) do { \
133 if (ptr) { \
134 ZEND_ASSERT(IS_SERIALIZED(ptr)); \
135 (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
136 } \
137 } while (0)
138#define SERIALIZE_STR(ptr) do { \
139 if (ptr) { \
140 if (IS_ACCEL_INTERNED(ptr)) { \
141 (ptr) = zend_file_cache_serialize_interned((zend_string*)(ptr), info); \
142 } else { \
143 ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
144 /* script->corrupted shows if the script in SHM or not */ \
145 if (EXPECTED(script->corrupted)) { \
146 GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
147 GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
148 } \
149 (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
150 } \
151 } \
152 } while (0)
153#define UNSERIALIZE_STR(ptr) do { \
154 if (ptr) { \
155 if (IS_SERIALIZED_INTERNED(ptr)) { \
156 (ptr) = (void*)zend_file_cache_unserialize_interned((zend_string*)(ptr), !script->corrupted); \
157 } else { \
158 ZEND_ASSERT(IS_SERIALIZED(ptr)); \
159 (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
160 /* script->corrupted shows if the script in SHM or not */ \
161 if (EXPECTED(!script->corrupted)) { \
162 GC_ADD_FLAGS(ptr, IS_STR_INTERNED | IS_STR_PERMANENT); \
163 } else { \
164 GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
165 GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
166 } \
167 } \
168 } \
169 } while (0)
170
171#define SERIALIZE_ATTRIBUTES(attributes) do { \
172 if ((attributes) && !IS_SERIALIZED(attributes)) { \
173 HashTable *ht; \
174 SERIALIZE_PTR(attributes); \
175 ht = (attributes); \
176 UNSERIALIZE_PTR(ht); \
177 zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_attribute); \
178 } \
179} while (0)
180
181#define UNSERIALIZE_ATTRIBUTES(attributes) do { \
182 if ((attributes) && !IS_UNSERIALIZED(attributes)) { \
183 HashTable *ht; \
184 UNSERIALIZE_PTR(attributes); \
185 ht = (attributes); \
186 zend_file_cache_unserialize_hash(ht, script, buf, zend_file_cache_unserialize_attribute, NULL); \
187 } \
188} while (0)
189
190#define HOOKED_ITERATOR_PLACEHOLDER ((void*)1)
191
192static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
194
204
205static int zend_file_cache_mkdir(char *filename, size_t start)
206{
207 char *s = filename + start;
208
209 while (*s) {
210 if (IS_SLASH(*s)) {
211 char old = *s;
212 *s = '\000';
213#ifndef ZEND_WIN32
214 if (mkdir(filename, S_IRWXU) < 0 && errno != EEXIST) {
215#else
216 if (php_win32_ioutil_mkdir(filename, 0700) < 0 && errno != EEXIST) {
217#endif
218 *s = old;
219 return FAILURE;
220 }
221 *s = old;
222 }
223 s++;
224 }
225 return SUCCESS;
226}
227
231 void *buf);
232
235 void *buf);
236
237static void zend_file_cache_serialize_zval(zval *zv,
240 void *buf);
241static void zend_file_cache_unserialize_zval(zval *zv,
243 void *buf);
244
245static void *zend_file_cache_serialize_interned(zend_string *str,
247{
248 size_t len;
249 void *ret;
250
251 /* check if the same interned string was already stored */
253 if (ret) {
254 return ret;
255 }
256
258 ret = (void*)(info->str_size | Z_UL(1));
260
261 zend_string *s = (zend_string*)ZCG(mem);
262 if (info->str_size + len > ZSTR_LEN(s)) {
263 size_t new_len = info->str_size + len;
264 s = zend_string_realloc(
265 s,
266 ((_ZSTR_HEADER_SIZE + 1 + new_len + 4095) & ~0xfff) - (_ZSTR_HEADER_SIZE + 1),
267 0);
268 ZCG(mem) = (void*)s;
269 }
270
271 zend_string *new_str = (zend_string *) (ZSTR_VAL(s) + info->str_size);
272 memcpy(new_str, str, len);
275 info->str_size += len;
276 return ret;
277}
278
279static void *zend_file_cache_unserialize_interned(zend_string *str, bool in_shm)
280{
281 str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1)));
282 if (!in_shm) {
283 return str;
284 }
285
287 if (ret == str) {
288 /* We have to create new SHM allocated string */
289 size_t size = _ZSTR_STRUCT_SIZE(ZSTR_LEN(str));
291 if (!ret) {
294 }
295 memcpy(ret, str, size);
296 /* String wasn't interned but we will use it as interned anyway */
299 }
300 return ret;
301}
302
303static void zend_file_cache_serialize_hash(HashTable *ht,
306 void *buf,
308{
310 ht->arData = NULL;
311 return;
312 }
313 if (IS_SERIALIZED(ht->arData)) {
314 return;
315 }
316 if (HT_IS_PACKED(ht)) {
317 zval *p, *end;
318
319 SERIALIZE_PTR(ht->arPacked);
320 p = ht->arPacked;
322 end = p + ht->nNumUsed;
323 while (p < end) {
324 if (Z_TYPE_P(p) != IS_UNDEF) {
325 func(p, script, info, buf);
326 }
327 p++;
328 }
329 } else {
330 Bucket *p, *end;
331
332 SERIALIZE_PTR(ht->arData);
333 p = ht->arData;
335 end = p + ht->nNumUsed;
336 while (p < end) {
337 if (Z_TYPE(p->val) != IS_UNDEF) {
338 SERIALIZE_STR(p->key);
339 func(&p->val, script, info, buf);
340 }
341 p++;
342 }
343 }
344}
345
346static void zend_file_cache_serialize_ast(zend_ast *ast,
349 void *buf)
350{
351 uint32_t i;
352 zend_ast *tmp;
353
354 if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
355 zend_file_cache_serialize_zval(&((zend_ast_zval*)ast)->val, script, info, buf);
356 } else if (zend_ast_is_list(ast)) {
357 zend_ast_list *list = zend_ast_get_list(ast);
358 for (i = 0; i < list->children; i++) {
359 if (list->child[i] && !IS_SERIALIZED(list->child[i])) {
360 SERIALIZE_PTR(list->child[i]);
361 tmp = list->child[i];
362 UNSERIALIZE_PTR(tmp);
363 zend_file_cache_serialize_ast(tmp, script, info, buf);
364 }
365 }
366 } else {
367 uint32_t children = zend_ast_get_num_children(ast);
368 for (i = 0; i < children; i++) {
369 if (ast->child[i] && !IS_SERIALIZED(ast->child[i])) {
370 SERIALIZE_PTR(ast->child[i]);
371 tmp = ast->child[i];
372 UNSERIALIZE_PTR(tmp);
373 zend_file_cache_serialize_ast(tmp, script, info, buf);
374 }
375 }
376 }
377}
378
379static void zend_file_cache_serialize_zval(zval *zv,
382 void *buf)
383{
384 switch (Z_TYPE_P(zv)) {
385 case IS_STRING:
386 if (!IS_SERIALIZED(Z_STR_P(zv))) {
388 }
389 break;
390 case IS_ARRAY:
391 if (!IS_SERIALIZED(Z_ARR_P(zv))) {
392 HashTable *ht;
393
395 ht = Z_ARR_P(zv);
397 zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
398 }
399 break;
400 case IS_CONSTANT_AST:
401 if (!IS_SERIALIZED(Z_AST_P(zv))) {
402 zend_ast_ref *ast;
403
405 ast = Z_AST_P(zv);
406 UNSERIALIZE_PTR(ast);
407 zend_file_cache_serialize_ast(GC_AST(ast), script, info, buf);
408 }
409 break;
410 case IS_INDIRECT:
411 /* Used by static properties. */
413 break;
414 default:
416 break;
417 }
418}
419
420static void zend_file_cache_serialize_attribute(zval *zv,
423 void *buf)
424{
426 uint32_t i;
427
429 attr = Z_PTR_P(zv);
431
432 SERIALIZE_STR(attr->name);
433 SERIALIZE_STR(attr->lcname);
434
435 for (i = 0; i < attr->argc; i++) {
436 SERIALIZE_STR(attr->args[i].name);
437 zend_file_cache_serialize_zval(&attr->args[i].value, script, info, buf);
438 }
439}
440
441static void zend_file_cache_serialize_type(
443{
444 if (ZEND_TYPE_HAS_LIST(*type)) {
446 SERIALIZE_PTR(list);
447 ZEND_TYPE_SET_PTR(*type, list);
448 UNSERIALIZE_PTR(list);
449
450 zend_type *list_type;
451 ZEND_TYPE_LIST_FOREACH(list, list_type) {
452 zend_file_cache_serialize_type(list_type, script, info, buf);
454 } else if (ZEND_TYPE_HAS_NAME(*type)) {
455 zend_string *type_name = ZEND_TYPE_NAME(*type);
456 SERIALIZE_STR(type_name);
457 ZEND_TYPE_SET_PTR(*type, type_name);
458 }
459}
460
461static void zend_file_cache_serialize_op_array(zend_op_array *op_array,
464 void *buf)
465{
466 ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
467 ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
468
469 /* Check whether this op_array has already been serialized. */
470 if (IS_SERIALIZED(op_array->opcodes)) {
471 ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
472 return;
473 }
474
475 if (op_array->scope) {
477 op_array->refcount = (uint32_t*)(intptr_t)-1;
479 SERIALIZE_PTR(op_array->literals);
480 SERIALIZE_PTR(op_array->opcodes);
481 SERIALIZE_PTR(op_array->arg_info);
482 SERIALIZE_PTR(op_array->vars);
483 SERIALIZE_STR(op_array->function_name);
484 SERIALIZE_STR(op_array->filename);
485 SERIALIZE_PTR(op_array->live_range);
486 SERIALIZE_PTR(op_array->scope);
487 SERIALIZE_STR(op_array->doc_comment);
490 SERIALIZE_PTR(op_array->prototype);
491 SERIALIZE_PTR(op_array->prop_info);
492 return;
493 }
495 }
496
497 if (op_array->static_variables) {
498 HashTable *ht;
499
501 ht = op_array->static_variables;
503 zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
504 }
505
506 if (op_array->literals) {
507 zval *p, *end;
508
509 SERIALIZE_PTR(op_array->literals);
510 p = op_array->literals;
512 end = p + op_array->last_literal;
513 while (p < end) {
514 zend_file_cache_serialize_zval(p, script, info, buf);
515 p++;
516 }
517 }
518
519 {
520 zend_op *opline, *end;
521
522#if !ZEND_USE_ABS_CONST_ADDR
523 zval *literals = op_array->literals;
524 UNSERIALIZE_PTR(literals);
525#endif
526
527 SERIALIZE_PTR(op_array->opcodes);
528 opline = op_array->opcodes;
529 UNSERIALIZE_PTR(opline);
530 end = opline + op_array->last;
531 while (opline < end) {
532#if ZEND_USE_ABS_CONST_ADDR
533 if (opline->op1_type == IS_CONST) {
534 SERIALIZE_PTR(opline->op1.zv);
535 }
536 if (opline->op2_type == IS_CONST) {
537 SERIALIZE_PTR(opline->op2.zv);
538 }
539#else
540 if (opline->op1_type == IS_CONST) {
541 opline->op1.constant = RT_CONSTANT(opline, opline->op1) - literals;
542 }
543 if (opline->op2_type == IS_CONST) {
544 opline->op2.constant = RT_CONSTANT(opline, opline->op2) - literals;
545 }
546#endif
547#if ZEND_USE_ABS_JMP_ADDR
548 switch (opline->opcode) {
549 case ZEND_JMP:
550 case ZEND_FAST_CALL:
551 SERIALIZE_PTR(opline->op1.jmp_addr);
552 break;
553 case ZEND_JMPZ:
554 case ZEND_JMPNZ:
555 case ZEND_JMPZ_EX:
556 case ZEND_JMPNZ_EX:
557 case ZEND_JMP_SET:
558 case ZEND_COALESCE:
559 case ZEND_FE_RESET_R:
560 case ZEND_FE_RESET_RW:
562 case ZEND_JMP_NULL:
565 SERIALIZE_PTR(opline->op2.jmp_addr);
566 break;
567 case ZEND_CATCH:
568 if (!(opline->extended_value & ZEND_LAST_CATCH)) {
569 SERIALIZE_PTR(opline->op2.jmp_addr);
570 }
571 break;
572 case ZEND_FE_FETCH_R:
573 case ZEND_FE_FETCH_RW:
574 case ZEND_SWITCH_LONG:
576 case ZEND_MATCH:
577 /* relative extended_value don't have to be changed */
578 break;
579 }
580#endif
582 opline++;
583 }
584
585 if (op_array->arg_info) {
587 SERIALIZE_PTR(op_array->arg_info);
588 p = op_array->arg_info;
590 end = p + op_array->num_args;
591 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
592 p--;
593 }
594 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
595 end++;
596 }
597 while (p < end) {
598 if (!IS_SERIALIZED(p->name)) {
599 SERIALIZE_STR(p->name);
600 }
601 zend_file_cache_serialize_type(&p->type, script, info, buf);
602 p++;
603 }
604 }
605
606 if (op_array->vars) {
607 zend_string **p, **end;
608
609 SERIALIZE_PTR(op_array->vars);
610 p = op_array->vars;
612 end = p + op_array->last_var;
613 while (p < end) {
614 if (!IS_SERIALIZED(*p)) {
616 }
617 p++;
618 }
619 }
620
621 if (op_array->num_dynamic_func_defs) {
622 zend_op_array **defs;
624 defs = op_array->dynamic_func_defs;
625 UNSERIALIZE_PTR(defs);
626 for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
627 zend_op_array *def;
628 SERIALIZE_PTR(defs[i]);
629 def = defs[i];
630 UNSERIALIZE_PTR(def);
631 zend_file_cache_serialize_op_array(def, script, info, buf);
632 }
633 }
634
635 SERIALIZE_STR(op_array->function_name);
636 SERIALIZE_STR(op_array->filename);
637 SERIALIZE_PTR(op_array->live_range);
638 SERIALIZE_PTR(op_array->scope);
639 SERIALIZE_STR(op_array->doc_comment);
642 SERIALIZE_PTR(op_array->prototype);
643 SERIALIZE_PTR(op_array->prop_info);
644 }
645}
646
647static void zend_file_cache_serialize_func(zval *zv,
650 void *buf)
651{
654 func = Z_PTR_P(zv);
657 zend_file_cache_serialize_op_array(&func->op_array, script, info, buf);
658}
659
660static void zend_file_cache_serialize_prop_info(zval *zv,
663 void *buf)
664{
665 if (!IS_SERIALIZED(Z_PTR_P(zv))) {
666 zend_property_info *prop;
667
669 prop = Z_PTR_P(zv);
670 UNSERIALIZE_PTR(prop);
671
672 ZEND_ASSERT(prop->ce != NULL && prop->name != NULL);
673 if (!IS_SERIALIZED(prop->ce)) {
674 SERIALIZE_PTR(prop->ce);
675 SERIALIZE_STR(prop->name);
676 if (prop->doc_comment) {
678 }
681 if (prop->hooks) {
682 SERIALIZE_PTR(prop->hooks);
683 zend_function **hooks = prop->hooks;
684 UNSERIALIZE_PTR(hooks);
685 for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
686 if (hooks[i]) {
687 SERIALIZE_PTR(hooks[i]);
688 zend_function *hook = hooks[i];
689 UNSERIALIZE_PTR(hook);
690 zend_file_cache_serialize_op_array(&hook->op_array, script, info, buf);
691 }
692 }
693 }
694 zend_file_cache_serialize_type(&prop->type, script, info, buf);
695 }
696 }
697}
698
699static void zend_file_cache_serialize_class_constant(zval *zv,
702 void *buf)
703{
704 if (!IS_SERIALIZED(Z_PTR_P(zv))) {
706
708 c = Z_PTR_P(zv);
710
711 ZEND_ASSERT(c->ce != NULL);
712 if (!IS_SERIALIZED(c->ce)) {
713 SERIALIZE_PTR(c->ce);
714
715 zend_file_cache_serialize_zval(&c->value, script, info, buf);
716 if (c->doc_comment) {
718 }
719
721 zend_file_cache_serialize_type(&c->type, script, info, buf);
722 }
723 }
724}
725
726static void zend_file_cache_serialize_class(zval *zv,
729 void *buf)
730{
732
734 ce = Z_PTR_P(zv);
735 UNSERIALIZE_PTR(ce);
736
737 SERIALIZE_STR(ce->name);
738 if (ce->parent) {
739 if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
741 } else {
743 }
744 }
745 zend_file_cache_serialize_hash(&ce->function_table, script, info, buf, zend_file_cache_serialize_func);
746 if (ce->default_properties_table) {
747 zval *p, *end;
748
753 while (p < end) {
754 zend_file_cache_serialize_zval(p, script, info, buf);
755 p++;
756 }
757 }
759 zval *p, *end;
760
764
766 while (p < end) {
767 zend_file_cache_serialize_zval(p, script, info, buf);
768 p++;
769 }
770 }
771 zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_class_constant);
775 zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
776
777 if (ce->properties_info_table) {
778 uint32_t i;
779 zend_property_info **table;
780
782 table = ce->properties_info_table;
783 UNSERIALIZE_PTR(table);
784
785 for (i = 0; i < ce->default_properties_count; i++) {
786 SERIALIZE_PTR(table[i]);
787 }
788 }
789
790 if (ce->num_interfaces) {
791 uint32_t i;
792 zend_class_name *interface_names;
793
795
797 interface_names = ce->interface_names;
798 UNSERIALIZE_PTR(interface_names);
799
800 for (i = 0; i < ce->num_interfaces; i++) {
801 SERIALIZE_STR(interface_names[i].name);
802 SERIALIZE_STR(interface_names[i].lc_name);
803 }
804 }
805
806 if (ce->num_traits) {
807 uint32_t i;
808 zend_class_name *trait_names;
809
811 trait_names = ce->trait_names;
812 UNSERIALIZE_PTR(trait_names);
813
814 for (i = 0; i < ce->num_traits; i++) {
815 SERIALIZE_STR(trait_names[i].name);
816 SERIALIZE_STR(trait_names[i].lc_name);
817 }
818
819 if (ce->trait_aliases) {
820 zend_trait_alias **p, *q;
821
823 p = ce->trait_aliases;
825
826 while (*p) {
828 q = *p;
830
831 if (q->trait_method.method_name) {
833 }
834 if (q->trait_method.class_name) {
836 }
837
838 if (q->alias) {
840 }
841 p++;
842 }
843 }
844
845 if (ce->trait_precedences) {
847 uint32_t j;
848
850 p = ce->trait_precedences;
852
853 while (*p) {
855 q = *p;
857
858 if (q->trait_method.method_name) {
860 }
861 if (q->trait_method.class_name) {
863 }
864
865 for (j = 0; j < q->num_excludes; j++) {
867 }
868 p++;
869 }
870 }
871 }
872
875 SERIALIZE_PTR(ce->clone);
876 SERIALIZE_PTR(ce->__get);
877 SERIALIZE_PTR(ce->__set);
886
887 if (ce->iterator_funcs_ptr) {
895 }
896
897 if (ce->arrayaccess_funcs_ptr) {
903 }
904
905 ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
906 ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
907
909
910 if (ce->get_iterator) {
913 }
914}
915
916static void zend_file_cache_serialize_warnings(
918{
919 if (script->warnings) {
920 zend_error_info **warnings;
921 SERIALIZE_PTR(script->warnings);
922 warnings = script->warnings;
923 UNSERIALIZE_PTR(warnings);
924
925 for (uint32_t i = 0; i < script->num_warnings; i++) {
927 SERIALIZE_PTR(warnings[i]);
928 warning = warnings[i];
930 SERIALIZE_STR(warning->filename);
931 SERIALIZE_STR(warning->message);
932 }
933 }
934}
935
936static void zend_file_cache_serialize_early_bindings(
938{
939 if (script->early_bindings) {
941 zend_early_binding *early_bindings = script->early_bindings;
942 UNSERIALIZE_PTR(early_bindings);
943 for (uint32_t i = 0; i < script->num_early_bindings; i++) {
944 SERIALIZE_STR(early_bindings[i].lcname);
945 SERIALIZE_STR(early_bindings[i].rtd_key);
946 SERIALIZE_STR(early_bindings[i].lc_parent_name);
947 }
948 }
949}
950
951static void zend_file_cache_serialize(zend_persistent_script *script,
953 void *buf)
954{
955 zend_persistent_script *new_script;
956
957 memcpy(info->magic, "OPCACHE", 8);
958 memcpy(info->system_id, zend_system_id, 32);
959 info->mem_size = script->size;
960 info->str_size = 0;
961 info->script_offset = (char*)script - (char*)script->mem;
962 info->timestamp = script->timestamp;
963
964 memcpy(buf, script->mem, script->size);
965
966 new_script = (zend_persistent_script*)((char*)buf + info->script_offset);
967 SERIALIZE_STR(new_script->script.filename);
968
969 zend_file_cache_serialize_hash(&new_script->script.class_table, script, info, buf, zend_file_cache_serialize_class);
970 zend_file_cache_serialize_hash(&new_script->script.function_table, script, info, buf, zend_file_cache_serialize_func);
971 zend_file_cache_serialize_op_array(&new_script->script.main_op_array, script, info, buf);
972 zend_file_cache_serialize_warnings(new_script, info, buf);
973 zend_file_cache_serialize_early_bindings(new_script, info, buf);
974
975 new_script->mem = NULL;
976}
977
978static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
979{
980 size_t len;
981 char *filename;
982
983#ifndef ZEND_WIN32
984 len = strlen(ZCG(accel_directives).file_cache);
985 filename = emalloc(len + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
986 memcpy(filename, ZCG(accel_directives).file_cache, len);
987 filename[len] = '/';
988 memcpy(filename + len + 1, zend_system_id, 32);
989 memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
990 memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
991#else
992 len = strlen(ZCG(accel_directives).file_cache);
993
994 filename = emalloc(len + 33 + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
995
996 memcpy(filename, ZCG(accel_directives).file_cache, len);
997 filename[len] = '\\';
998 memcpy(filename + 1 + len, accel_uname_id, 32);
999 len += 1 + 32;
1000 filename[len] = '\\';
1001
1002 memcpy(filename + len + 1, zend_system_id, 32);
1003
1004 if (ZSTR_LEN(script_path) >= 7 && ':' == ZSTR_VAL(script_path)[4] && '/' == ZSTR_VAL(script_path)[5] && '/' == ZSTR_VAL(script_path)[6]) {
1005 /* phar:// or file:// */
1006 *(filename + len + 33) = '\\';
1007 memcpy(filename + len + 34, ZSTR_VAL(script_path), 4);
1008 if (ZSTR_LEN(script_path) - 7 >= 2 && ':' == ZSTR_VAL(script_path)[8]) {
1009 *(filename + len + 38) = '\\';
1010 *(filename + len + 39) = ZSTR_VAL(script_path)[7];
1011 memcpy(filename + len + 40, ZSTR_VAL(script_path) + 9, ZSTR_LEN(script_path) - 9);
1012 memcpy(filename + len + 40 + ZSTR_LEN(script_path) - 9, SUFFIX, sizeof(SUFFIX));
1013 } else {
1014 memcpy(filename + len + 38, ZSTR_VAL(script_path) + 7, ZSTR_LEN(script_path) - 7);
1015 memcpy(filename + len + 38 + ZSTR_LEN(script_path) - 7, SUFFIX, sizeof(SUFFIX));
1016 }
1017 } else if (ZSTR_LEN(script_path) >= 2 && ':' == ZSTR_VAL(script_path)[1]) {
1018 /* local fs */
1019 *(filename + len + 33) = '\\';
1020 *(filename + len + 34) = ZSTR_VAL(script_path)[0];
1021 memcpy(filename + len + 35, ZSTR_VAL(script_path) + 2, ZSTR_LEN(script_path) - 2);
1022 memcpy(filename + len + 35 + ZSTR_LEN(script_path) - 2, SUFFIX, sizeof(SUFFIX));
1023 } else {
1024 /* network path */
1025 memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
1026 memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
1027 }
1028#endif
1029
1030 return filename;
1031}
1032
1038static bool zend_file_cache_script_write(int fd, const zend_persistent_script *script, const zend_file_cache_metainfo *info, const void *buf, const zend_string *s)
1039{
1040 ssize_t written;
1041 const ssize_t total_size = (ssize_t)(sizeof(*info) + script->size + info->str_size);
1042
1043#ifdef HAVE_SYS_UIO_H
1044 const struct iovec vec[] = {
1045 { .iov_base = (void *)info, .iov_len = sizeof(*info) },
1046 { .iov_base = (void *)buf, .iov_len = script->size },
1047 { .iov_base = (void *)ZSTR_VAL(s), .iov_len = info->str_size },
1048 };
1049
1050 written = writev(fd, vec, sizeof(vec) / sizeof(vec[0]));
1051 if (EXPECTED(written == total_size)) {
1052 return true;
1053 }
1054
1055 errno = written == -1 ? errno : EAGAIN;
1056 return false;
1057#else
1058 if (UNEXPECTED(ZEND_LONG_MAX < (zend_long)total_size)) {
1059# ifdef EFBIG
1060 errno = EFBIG;
1061# else
1062 errno = ERANGE;
1063# endif
1064 return false;
1065 }
1066
1067 written = write(fd, info, sizeof(*info));
1068 if (UNEXPECTED(written != sizeof(*info))) {
1069 errno = written == -1 ? errno : EAGAIN;
1070 return false;
1071 }
1072
1073 written = write(fd, buf, script->size);
1074 if (UNEXPECTED(written != script->size)) {
1075 errno = written == -1 ? errno : EAGAIN;
1076 return false;
1077 }
1078
1079 written = write(fd, ZSTR_VAL(s), info->str_size);
1080 if (UNEXPECTED(written != info->str_size)) {
1081 errno = written == -1 ? errno : EAGAIN;
1082 return false;
1083 }
1084
1085 return true;
1086#endif
1087}
1088
1090{
1091 int fd;
1092 char *filename;
1094 void *mem, *buf;
1095
1096#ifdef HAVE_JIT
1097 /* FIXME: dump jited codes out to file cache? */
1098 if (JIT_G(on)) {
1099 return FAILURE;
1100 }
1101#endif
1102
1103 filename = zend_file_cache_get_bin_file_path(script->script.filename);
1104
1105 if (zend_file_cache_mkdir(filename, strlen(ZCG(accel_directives).file_cache)) != SUCCESS) {
1106 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create directory for file '%s', %s\n", filename, strerror(errno));
1107 efree(filename);
1108 return FAILURE;
1109 }
1110
1111 fd = zend_file_cache_open(filename, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
1112 if (fd < 0) {
1113 if (errno != EEXIST) {
1114 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create file '%s', %s\n", filename, strerror(errno));
1115 }
1116 efree(filename);
1117 return FAILURE;
1118 }
1119
1120 if (zend_file_cache_flock(fd, LOCK_EX) != 0) {
1121 close(fd);
1122 efree(filename);
1123 return FAILURE;
1124 }
1125
1126#if defined(__AVX__) || defined(__SSE2__)
1127 /* Align to 64-byte boundary */
1128 mem = emalloc(script->size + 64);
1129 buf = (void*)(((uintptr_t)mem + 63L) & ~63L);
1130#else
1131 mem = buf = emalloc(script->size);
1132#endif
1133
1134 ZCG(mem) = zend_string_alloc(4096 - (_ZSTR_HEADER_SIZE + 1), 0);
1135
1137 if (!in_shm) {
1138 script->corrupted = true; /* used to check if script restored to SHM or process memory */
1139 }
1140 zend_file_cache_serialize(script, &info, buf);
1141 if (!in_shm) {
1142 script->corrupted = false;
1143 }
1145
1146 zend_string *const s = (zend_string*)ZCG(mem);
1147
1148#if __has_feature(memory_sanitizer)
1149 /* The buffer may contain uninitialized regions. However, the uninitialized parts will not be
1150 * used when reading the cache. We should probably still try to get things fully initialized
1151 * for reproducibility, but for now ignore this issue. */
1152 __msan_unpoison(&info, sizeof(info));
1153 __msan_unpoison(buf, script->size);
1154#endif
1155
1156 info.checksum = zend_adler32(ADLER32_INIT, buf, script->size);
1157 info.checksum = zend_adler32(info.checksum, (unsigned char*)ZSTR_VAL(s), info.str_size);
1158
1159 if (!zend_file_cache_script_write(fd, script, &info, buf, s)) {
1160 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s': %s\n", filename, strerror(errno));
1162 close(fd);
1163 efree(mem);
1164 zend_file_cache_unlink(filename);
1165 efree(filename);
1166 return FAILURE;
1167 }
1168
1170 efree(mem);
1171 if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
1172 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s': %s\n", filename, strerror(errno));
1173 }
1174 close(fd);
1175 efree(filename);
1176
1177 return SUCCESS;
1178}
1179
1180static void zend_file_cache_unserialize_hash(HashTable *ht,
1181 zend_persistent_script *script,
1182 void *buf,
1184 dtor_func_t dtor)
1185{
1186 ht->pDestructor = dtor;
1188 if (EXPECTED(!file_cache_only)) {
1189 HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket));
1190 } else {
1191 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
1192 }
1193 return;
1194 }
1195 if (IS_UNSERIALIZED(ht->arData)) {
1196 return;
1197 }
1198 UNSERIALIZE_PTR(ht->arData);
1199 if (HT_IS_PACKED(ht)) {
1200 zval *p, *end;
1201
1202 p = ht->arPacked;
1203 end = p + ht->nNumUsed;
1204 while (p < end) {
1205 if (Z_TYPE_P(p) != IS_UNDEF) {
1206 func(p, script, buf);
1207 }
1208 p++;
1209 }
1210 } else {
1211 Bucket *p, *end;
1212
1213 p = ht->arData;
1214 end = p + ht->nNumUsed;
1215 while (p < end) {
1216 if (Z_TYPE(p->val) != IS_UNDEF) {
1217 UNSERIALIZE_STR(p->key);
1218 func(&p->val, script, buf);
1219 }
1220 p++;
1221 }
1222 }
1223}
1224
1225static void zend_file_cache_unserialize_ast(zend_ast *ast,
1226 zend_persistent_script *script,
1227 void *buf)
1228{
1229 uint32_t i;
1230
1231 if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
1232 zend_file_cache_unserialize_zval(&((zend_ast_zval*)ast)->val, script, buf);
1233 } else if (zend_ast_is_list(ast)) {
1234 zend_ast_list *list = zend_ast_get_list(ast);
1235 for (i = 0; i < list->children; i++) {
1236 if (list->child[i] && !IS_UNSERIALIZED(list->child[i])) {
1237 UNSERIALIZE_PTR(list->child[i]);
1238 zend_file_cache_unserialize_ast(list->child[i], script, buf);
1239 }
1240 }
1241 } else {
1242 uint32_t children = zend_ast_get_num_children(ast);
1243 for (i = 0; i < children; i++) {
1244 if (ast->child[i] && !IS_UNSERIALIZED(ast->child[i])) {
1245 UNSERIALIZE_PTR(ast->child[i]);
1246 zend_file_cache_unserialize_ast(ast->child[i], script, buf);
1247 }
1248 }
1249 }
1250}
1251
1252static void zend_file_cache_unserialize_zval(zval *zv,
1253 zend_persistent_script *script,
1254 void *buf)
1255{
1256 switch (Z_TYPE_P(zv)) {
1257 case IS_STRING:
1258 /* We can't use !IS_UNSERIALIZED here, because that does not recognize unserialized
1259 * interned strings in non-shm mode. */
1262 }
1263 break;
1264 case IS_ARRAY:
1265 if (!IS_UNSERIALIZED(Z_ARR_P(zv))) {
1266 HashTable *ht;
1267
1269 ht = Z_ARR_P(zv);
1270 zend_file_cache_unserialize_hash(ht,
1271 script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
1272 }
1273 break;
1274 case IS_CONSTANT_AST:
1275 if (!IS_UNSERIALIZED(Z_AST_P(zv))) {
1277 zend_file_cache_unserialize_ast(Z_ASTVAL_P(zv), script, buf);
1278 }
1279 break;
1280 case IS_INDIRECT:
1281 /* Used by static properties. */
1283 break;
1284 default:
1286 break;
1287 }
1288}
1289
1290static void zend_file_cache_unserialize_attribute(zval *zv, zend_persistent_script *script, void *buf)
1291{
1293 uint32_t i;
1294
1296 attr = Z_PTR_P(zv);
1297
1298 UNSERIALIZE_STR(attr->name);
1299 UNSERIALIZE_STR(attr->lcname);
1300
1301 for (i = 0; i < attr->argc; i++) {
1302 UNSERIALIZE_STR(attr->args[i].name);
1303 zend_file_cache_unserialize_zval(&attr->args[i].value, script, buf);
1304 }
1305}
1306
1307static void zend_file_cache_unserialize_type(
1309{
1310 if (ZEND_TYPE_HAS_LIST(*type)) {
1312 UNSERIALIZE_PTR(list);
1313 ZEND_TYPE_SET_PTR(*type, list);
1314
1315 zend_type *list_type;
1316 ZEND_TYPE_LIST_FOREACH(list, list_type) {
1317 zend_file_cache_unserialize_type(list_type, scope, script, buf);
1319 } else if (ZEND_TYPE_HAS_NAME(*type)) {
1320 zend_string *type_name = ZEND_TYPE_NAME(*type);
1321 UNSERIALIZE_STR(type_name);
1322 ZEND_TYPE_SET_PTR(*type, type_name);
1323 if (!script->corrupted) {
1325 } else {
1326 zend_alloc_ce_cache(type_name);
1327 }
1328 }
1329}
1330
1331static void zend_file_cache_unserialize_op_array(zend_op_array *op_array,
1332 zend_persistent_script *script,
1333 void *buf)
1334{
1335 if (!script->corrupted) {
1336 if (op_array != &script->script.main_op_array) {
1337 op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
1338 ZEND_MAP_PTR_NEW(op_array->run_time_cache);
1339 } else {
1340 ZEND_ASSERT(!(op_array->fn_flags & ZEND_ACC_IMMUTABLE));
1341 ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
1342 }
1343 if (op_array->static_variables) {
1344 ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
1345 }
1346 } else {
1347 op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
1348 ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
1349 ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
1350 }
1351
1352 /* Check whether this op_array has already been unserialized. */
1353 if (IS_UNSERIALIZED(op_array->opcodes)) {
1354 ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
1355 return;
1356 }
1357
1358 if (op_array->refcount) {
1359 op_array->refcount = NULL;
1361 UNSERIALIZE_PTR(op_array->literals);
1362 UNSERIALIZE_PTR(op_array->opcodes);
1363 UNSERIALIZE_PTR(op_array->arg_info);
1364 UNSERIALIZE_PTR(op_array->vars);
1365 UNSERIALIZE_STR(op_array->function_name);
1366 UNSERIALIZE_STR(op_array->filename);
1367 UNSERIALIZE_PTR(op_array->live_range);
1368 UNSERIALIZE_PTR(op_array->scope);
1369 UNSERIALIZE_STR(op_array->doc_comment);
1372 UNSERIALIZE_PTR(op_array->prototype);
1373 UNSERIALIZE_PTR(op_array->prop_info);
1374 return;
1375 }
1376
1377 if (op_array->static_variables) {
1378 HashTable *ht;
1379
1381 ht = op_array->static_variables;
1382 zend_file_cache_unserialize_hash(ht,
1383 script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
1384 }
1385
1386 if (op_array->literals) {
1387 zval *p, *end;
1388
1389 UNSERIALIZE_PTR(op_array->literals);
1390 p = op_array->literals;
1391 end = p + op_array->last_literal;
1392 while (p < end) {
1393 zend_file_cache_unserialize_zval(p, script, buf);
1394 p++;
1395 }
1396 }
1397
1398 {
1399 zend_op *opline, *end;
1400
1401 UNSERIALIZE_PTR(op_array->opcodes);
1402 opline = op_array->opcodes;
1403 end = opline + op_array->last;
1404 while (opline < end) {
1405#if ZEND_USE_ABS_CONST_ADDR
1406 if (opline->op1_type == IS_CONST) {
1407 UNSERIALIZE_PTR(opline->op1.zv);
1408 }
1409 if (opline->op2_type == IS_CONST) {
1410 UNSERIALIZE_PTR(opline->op2.zv);
1411 }
1412#else
1413 if (opline->op1_type == IS_CONST) {
1414 ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1);
1415 }
1416 if (opline->op2_type == IS_CONST) {
1417 ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op2);
1418 }
1419#endif
1420#if ZEND_USE_ABS_JMP_ADDR
1421 switch (opline->opcode) {
1422 case ZEND_JMP:
1423 case ZEND_FAST_CALL:
1424 UNSERIALIZE_PTR(opline->op1.jmp_addr);
1425 break;
1426 case ZEND_JMPZ:
1427 case ZEND_JMPNZ:
1428 case ZEND_JMPZ_EX:
1429 case ZEND_JMPNZ_EX:
1430 case ZEND_JMP_SET:
1431 case ZEND_COALESCE:
1432 case ZEND_FE_RESET_R:
1433 case ZEND_FE_RESET_RW:
1434 case ZEND_ASSERT_CHECK:
1435 case ZEND_JMP_NULL:
1437 case ZEND_JMP_FRAMELESS:
1438 UNSERIALIZE_PTR(opline->op2.jmp_addr);
1439 break;
1440 case ZEND_CATCH:
1441 if (!(opline->extended_value & ZEND_LAST_CATCH)) {
1442 UNSERIALIZE_PTR(opline->op2.jmp_addr);
1443 }
1444 break;
1445 case ZEND_FE_FETCH_R:
1446 case ZEND_FE_FETCH_RW:
1447 case ZEND_SWITCH_LONG:
1448 case ZEND_SWITCH_STRING:
1449 /* relative extended_value don't have to be changed */
1450 break;
1451 }
1452#endif
1454 opline++;
1455 }
1456
1457 UNSERIALIZE_PTR(op_array->scope);
1458
1459 if (op_array->arg_info) {
1460 zend_arg_info *p, *end;
1461 UNSERIALIZE_PTR(op_array->arg_info);
1462 p = op_array->arg_info;
1463 end = p + op_array->num_args;
1464 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1465 p--;
1466 }
1467 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
1468 end++;
1469 }
1470 while (p < end) {
1471 if (!IS_UNSERIALIZED(p->name)) {
1472 UNSERIALIZE_STR(p->name);
1473 }
1474 zend_file_cache_unserialize_type(&p->type, (op_array->fn_flags & ZEND_ACC_CLOSURE) ? NULL : op_array->scope, script, buf);
1475 p++;
1476 }
1477 }
1478
1479 if (op_array->vars) {
1480 zend_string **p, **end;
1481
1482 UNSERIALIZE_PTR(op_array->vars);
1483 p = op_array->vars;
1484 end = p + op_array->last_var;
1485 while (p < end) {
1486 if (!IS_UNSERIALIZED(*p)) {
1488 }
1489 p++;
1490 }
1491 }
1492
1493 if (op_array->num_dynamic_func_defs) {
1495 for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
1496 UNSERIALIZE_PTR(op_array->dynamic_func_defs[i]);
1497 zend_file_cache_unserialize_op_array(op_array->dynamic_func_defs[i], script, buf);
1498 }
1499 }
1500
1501 UNSERIALIZE_STR(op_array->function_name);
1502 UNSERIALIZE_STR(op_array->filename);
1503 UNSERIALIZE_PTR(op_array->live_range);
1504 UNSERIALIZE_STR(op_array->doc_comment);
1507 UNSERIALIZE_PTR(op_array->prototype);
1508 UNSERIALIZE_PTR(op_array->prop_info);
1509 }
1510}
1511
1512static void zend_file_cache_unserialize_func(zval *zv,
1513 zend_persistent_script *script,
1514 void *buf)
1515{
1518 func = Z_PTR_P(zv);
1520 zend_file_cache_unserialize_op_array(&func->op_array, script, buf);
1521}
1522
1523static void zend_file_cache_unserialize_prop_info(zval *zv,
1524 zend_persistent_script *script,
1525 void *buf)
1526{
1527 if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
1528 zend_property_info *prop;
1529
1531 prop = Z_PTR_P(zv);
1532
1533 ZEND_ASSERT(prop->ce != NULL && prop->name != NULL);
1534 if (!IS_UNSERIALIZED(prop->ce)) {
1535 UNSERIALIZE_PTR(prop->ce);
1536 UNSERIALIZE_STR(prop->name);
1537 if (prop->doc_comment) {
1539 }
1542 if (prop->hooks) {
1543 UNSERIALIZE_PTR(prop->hooks);
1544 for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
1545 if (prop->hooks[i]) {
1546 UNSERIALIZE_PTR(prop->hooks[i]);
1547 zend_file_cache_unserialize_op_array(&prop->hooks[i]->op_array, script, buf);
1548 }
1549 }
1550 }
1551 zend_file_cache_unserialize_type(&prop->type, prop->ce, script, buf);
1552 }
1553 }
1554}
1555
1556static void zend_file_cache_unserialize_class_constant(zval *zv,
1557 zend_persistent_script *script,
1558 void *buf)
1559{
1560 if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
1562
1564 c = Z_PTR_P(zv);
1565
1566 ZEND_ASSERT(c->ce != NULL);
1567 if (!IS_UNSERIALIZED(c->ce)) {
1568 UNSERIALIZE_PTR(c->ce);
1569
1570 zend_file_cache_unserialize_zval(&c->value, script, buf);
1571
1572 if (c->doc_comment) {
1574 }
1576 zend_file_cache_unserialize_type(&c->type, c->ce, script, buf);
1577 }
1578 }
1579}
1580
1581static void zend_file_cache_unserialize_class(zval *zv,
1582 zend_persistent_script *script,
1583 void *buf)
1584{
1585 zend_class_entry *ce;
1586
1588 ce = Z_PTR_P(zv);
1589
1590 UNSERIALIZE_STR(ce->name);
1591 if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)) {
1592 if (!script->corrupted) {
1594 } else {
1596 }
1597 }
1598 if (ce->parent) {
1599 if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
1601 } else {
1603 }
1604 }
1605 zend_file_cache_unserialize_hash(&ce->function_table,
1606 script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
1607 if (ce->default_properties_table) {
1608 zval *p, *end;
1609
1613 while (p < end) {
1614 zend_file_cache_unserialize_zval(p, script, buf);
1615 p++;
1616 }
1617 }
1619 zval *p, *end;
1623 while (p < end) {
1624 zend_file_cache_unserialize_zval(p, script, buf);
1625 p++;
1626 }
1627 }
1628 zend_file_cache_unserialize_hash(&ce->constants_table,
1629 script, buf, zend_file_cache_unserialize_class_constant, NULL);
1633 zend_file_cache_unserialize_hash(&ce->properties_info,
1634 script, buf, zend_file_cache_unserialize_prop_info, NULL);
1635
1636 if (ce->properties_info_table) {
1637 uint32_t i;
1639
1640 for (i = 0; i < ce->default_properties_count; i++) {
1642 }
1643 }
1644
1645 if (ce->num_interfaces) {
1646 uint32_t i;
1647
1650
1651 for (i = 0; i < ce->num_interfaces; i++) {
1654 }
1655 }
1656
1657 if (ce->num_traits) {
1658 uint32_t i;
1659
1661
1662 for (i = 0; i < ce->num_traits; i++) {
1665 }
1666
1667 if (ce->trait_aliases) {
1668 zend_trait_alias **p, *q;
1669
1671 p = ce->trait_aliases;
1672
1673 while (*p) {
1675 q = *p;
1676
1677 if (q->trait_method.method_name) {
1679 }
1680 if (q->trait_method.class_name) {
1682 }
1683
1684 if (q->alias) {
1686 }
1687 p++;
1688 }
1689 }
1690
1691 if (ce->trait_precedences) {
1693 uint32_t j;
1694
1696 p = ce->trait_precedences;
1697
1698 while (*p) {
1700 q = *p;
1701
1702 if (q->trait_method.method_name) {
1704 }
1705 if (q->trait_method.class_name) {
1707 }
1708
1709 for (j = 0; j < q->num_excludes; j++) {
1711 }
1712 p++;
1713 }
1714 }
1715 }
1716
1730
1731 if (ce->iterator_funcs_ptr) {
1739 }
1740 if (ce->arrayaccess_funcs_ptr) {
1746 }
1747
1748 if (!(script->corrupted)) {
1751 ZEND_MAP_PTR_NEW(ce->mutable_data);
1753 ZEND_MAP_PTR_NEW(ce->static_members_table);
1754 }
1755 } else {
1758 ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
1759 ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
1760 }
1761
1762 if (ce->get_iterator) {
1765 }
1766
1767 // Memory addresses of object handlers are not stable. They can change due to ASLR or order of linking dynamic. To
1768 // avoid pointing to invalid memory we relink default_object_handlers here.
1770}
1771
1772static void zend_file_cache_unserialize_warnings(zend_persistent_script *script, void *buf)
1773{
1774 if (script->warnings) {
1775 UNSERIALIZE_PTR(script->warnings);
1776 for (uint32_t i = 0; i < script->num_warnings; i++) {
1777 UNSERIALIZE_PTR(script->warnings[i]);
1778 UNSERIALIZE_STR(script->warnings[i]->filename);
1779 UNSERIALIZE_STR(script->warnings[i]->message);
1780 }
1781 }
1782}
1783
1784static void zend_file_cache_unserialize_early_bindings(zend_persistent_script *script, void *buf)
1785{
1786 if (script->early_bindings) {
1788 for (uint32_t i = 0; i < script->num_early_bindings; i++) {
1792 }
1793 }
1794}
1795
1796static void zend_file_cache_unserialize(zend_persistent_script *script,
1797 void *buf)
1798{
1799 script->mem = buf;
1800
1802
1803 zend_file_cache_unserialize_hash(&script->script.class_table,
1804 script, buf, zend_file_cache_unserialize_class, ZEND_CLASS_DTOR);
1805 zend_file_cache_unserialize_hash(&script->script.function_table,
1806 script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
1807 zend_file_cache_unserialize_op_array(&script->script.main_op_array, script, buf);
1808 zend_file_cache_unserialize_warnings(script, buf);
1809 zend_file_cache_unserialize_early_bindings(script, buf);
1810}
1811
1813{
1814 zend_string *full_path = file_handle->opened_path;
1815 int fd;
1816 char *filename;
1817 zend_persistent_script *script;
1819 zend_accel_hash_entry *bucket;
1820 void *mem, *checkpoint, *buf;
1821 bool cache_it = true;
1822 unsigned int actual_checksum;
1823 bool ok;
1824
1825 if (!full_path) {
1826 return NULL;
1827 }
1828 filename = zend_file_cache_get_bin_file_path(full_path);
1829
1830 fd = zend_file_cache_open(filename, O_RDONLY | O_BINARY);
1831 if (fd < 0) {
1832 efree(filename);
1833 return NULL;
1834 }
1835
1836 if (zend_file_cache_flock(fd, LOCK_SH) != 0) {
1837 close(fd);
1838 efree(filename);
1839 return NULL;
1840 }
1841
1842 if (read(fd, &info, sizeof(info)) != sizeof(info)) {
1843 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (info)\n", filename);
1844 zend_file_cache_flock(fd, LOCK_UN);
1845 close(fd);
1846 zend_file_cache_unlink(filename);
1847 efree(filename);
1848 return NULL;
1849 }
1850
1851 /* verify header */
1852 if (memcmp(info.magic, "OPCACHE", 8) != 0) {
1853 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong header)\n", filename);
1854 zend_file_cache_flock(fd, LOCK_UN);
1855 close(fd);
1856 zend_file_cache_unlink(filename);
1857 efree(filename);
1858 return NULL;
1859 }
1860 if (memcmp(info.system_id, zend_system_id, 32) != 0) {
1861 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
1862 zend_file_cache_flock(fd, LOCK_UN);
1863 close(fd);
1864 zend_file_cache_unlink(filename);
1865 efree(filename);
1866 return NULL;
1867 }
1868
1869 /* verify timestamp */
1870 if (ZCG(accel_directives).validate_timestamps &&
1871 zend_get_file_handle_timestamp(file_handle, NULL) != info.timestamp) {
1872 if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
1873 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
1874 }
1875 close(fd);
1876 zend_file_cache_unlink(filename);
1877 efree(filename);
1878 return NULL;
1879 }
1880
1881 checkpoint = zend_arena_checkpoint(CG(arena));
1882#if defined(__AVX__) || defined(__SSE2__)
1883 /* Align to 64-byte boundary */
1884 mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size + 64);
1885 mem = (void*)(((uintptr_t)mem + 63L) & ~63L);
1886#else
1887 mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size);
1888#endif
1889
1890 if (read(fd, mem, info.mem_size + info.str_size) != (ssize_t)(info.mem_size + info.str_size)) {
1891 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (mem)\n", filename);
1892 zend_file_cache_flock(fd, LOCK_UN);
1893 close(fd);
1894 zend_file_cache_unlink(filename);
1895 zend_arena_release(&CG(arena), checkpoint);
1896 efree(filename);
1897 return NULL;
1898 }
1899 if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
1900 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
1901 }
1902 close(fd);
1903
1904 /* verify checksum */
1905 if (ZCG(accel_directives).file_cache_consistency_checks &&
1906 (actual_checksum = zend_adler32(ADLER32_INIT, mem, info.mem_size + info.str_size)) != info.checksum) {
1907 zend_accel_error(ACCEL_LOG_WARNING, "corrupted file '%s' excepted checksum: 0x%08x actual checksum: 0x%08x\n", filename, info.checksum, actual_checksum);
1908 zend_file_cache_unlink(filename);
1909 zend_arena_release(&CG(arena), checkpoint);
1910 efree(filename);
1911 return NULL;
1912 }
1913
1914 if (!file_cache_only &&
1915 !ZCSG(restart_in_progress) &&
1916 !ZCSG(restart_pending) &&
1917 !ZSMMG(memory_exhausted) &&
1919 /* exclusive lock */
1921
1922 /* Check if we still need to put the file into the cache (may be it was
1923 * already stored by another process. This final check is done under
1924 * exclusive lock) */
1925 bucket = zend_accel_hash_find_entry(&ZCSG(hash), full_path);
1926 if (bucket) {
1927 script = (zend_persistent_script *)bucket->data;
1928 if (!script->corrupted) {
1930 zend_arena_release(&CG(arena), checkpoint);
1931 efree(filename);
1932 return script;
1933 }
1934 }
1935
1936 if (zend_accel_hash_is_full(&ZCSG(hash))) {
1937 zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
1938 ZSMMG(memory_exhausted) = 1;
1941 goto use_process_mem;
1942 }
1943
1944 buf = zend_shared_alloc_aligned(info.mem_size);
1945
1946 if (!buf) {
1949 goto use_process_mem;
1950 }
1951 memcpy(buf, mem, info.mem_size);
1952 zend_map_ptr_extend(ZCSG(map_ptr_last));
1953 } else {
1954use_process_mem:
1955 buf = mem;
1956 cache_it = false;
1957 }
1958
1959 ZCG(mem) = ((char*)mem + info.mem_size);
1960 script = (zend_persistent_script*)((char*)buf + info.script_offset);
1961 script->corrupted = !cache_it; /* used to check if script restored to SHM or process memory */
1962
1963 ok = true;
1964 zend_try {
1965 zend_file_cache_unserialize(script, buf);
1966 } zend_catch {
1967 ok = false;
1968 } zend_end_try();
1969 if (!ok) {
1970 if (cache_it) {
1972 goto use_process_mem;
1973 } else {
1974 zend_arena_release(&CG(arena), checkpoint);
1975 efree(filename);
1976 return NULL;
1977 }
1978 }
1979
1980 script->corrupted = false;
1981
1982 if (cache_it) {
1983 ZCSG(map_ptr_last) = CG(map_ptr_last);
1984 script->dynamic_members.last_used = ZCG(request_time);
1985
1986 zend_accel_hash_update(&ZCSG(hash), script->script.filename, 0, script);
1987
1989 zend_accel_error(ACCEL_LOG_INFO, "File cached script loaded into memory '%s'", ZSTR_VAL(script->script.filename));
1990
1991 zend_arena_release(&CG(arena), checkpoint);
1992 }
1993 efree(filename);
1994
1995 return script;
1996}
1997
1999{
2000 char *filename;
2001
2002 filename = zend_file_cache_get_bin_file_path(full_path);
2003
2004 zend_file_cache_unlink(filename);
2005 efree(filename);
2006}
accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size)
void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason)
zend_result accelerator_shm_read_lock(void)
bool file_cache_only
zend_string *ZEND_FASTCALL accel_new_interned_string(zend_string *str)
#define ZCSG(element)
#define ZCG(v)
struct _zend_persistent_script zend_persistent_script
@ ACCEL_RESTART_HASH
@ ACCEL_RESTART_OOM
struct _zend_early_binding zend_early_binding
time_t accel_time_t
size_t len
Definition apprentice.c:174
bool warning
Definition assert.c:29
mkdir(string $directory, int $permissions=0777, bool $recursive=false, $context=null)
char s[4]
Definition cdf.c:77
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
new_type size
Definition ffi.c:4365
memcpy(ptr1, ptr2, size)
new_type attr
Definition ffi.c:4364
zval * val
Definition ffi.c:4262
HashTable * ht
Definition ffi.c:4838
buf start
Definition ffi.c:4687
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define O_BINARY
Definition file.h:643
zend_long offset
#define TRUE
Definition gd_gd.c:7
#define NULL
Definition gdcache.h:45
hash(string $algo, string $data, bool $binary=false, array $options=[])
Definition hash.stub.php:12
#define SUCCESS
Definition hash_sha3.c:261
again j
char * arena
Definition php_bcmath.h:37
unsigned const char * end
Definition php_ffi.h:51
JMP_BUF bailout
Definition php_ffi.h:49
int fd
Definition phpdbg.h:282
zend_string * lcname
p
Definition session.c:1105
void * data
zend_ast * child[1]
Definition zend_ast.h:199
uint32_t children
Definition zend_ast.h:198
zend_ast_kind kind
Definition zend_ast.h:187
zend_ast * child[1]
Definition zend_ast.h:190
zend_class_entry * ce
zend_string * doc_comment
HashTable constants_table
Definition zend.h:165
zend_function * __debugInfo
Definition zend.h:182
zend_function * __set
Definition zend.h:176
zend_function * __tostring
Definition zend.h:181
zend_class_iterator_funcs * iterator_funcs_ptr
Definition zend.h:189
zval * default_static_members_table
Definition zend.h:161
struct _zend_class_entry::@126215362204241324314155352336150042254204116267::@166057154351252324007362117353350250255142166322 user
HashTable properties_info
Definition zend.h:164
zend_function * __isset
Definition zend.h:178
zend_trait_precedence ** trait_precedences
Definition zend.h:218
zend_object_iterator *(* get_iterator)(zend_class_entry *ce, zval *object, int by_ref)
Definition zend.h:198
zend_string * filename
Definition zend.h:228
zend_class_name * trait_names
Definition zend.h:216
zend_class_name * interface_names
Definition zend.h:213
zend_function * __unserialize
Definition zend.h:184
zend_string * name
Definition zend.h:149
union _zend_class_entry::@126215362204241324314155352336150042254204116267 info
zend_function * __call
Definition zend.h:179
uint32_t num_traits
Definition zend.h:206
uint32_t num_interfaces
Definition zend.h:205
zend_function * __unset
Definition zend.h:177
zend_class_arrayaccess_funcs * arrayaccess_funcs_ptr
Definition zend.h:191
zend_string * parent_name
Definition zend.h:153
uint32_t ce_flags
Definition zend.h:156
int default_properties_count
Definition zend.h:158
zend_function * __serialize
Definition zend.h:183
zend_trait_alias ** trait_aliases
Definition zend.h:217
zend_function * __get
Definition zend.h:175
int default_static_members_count
Definition zend.h:159
HashTable * attributes
Definition zend.h:219
zend_function * constructor
Definition zend.h:172
zend_inheritance_cache_entry * inheritance_cache
Definition zend.h:168
struct _zend_property_info ** properties_info_table
Definition zend.h:170
zend_class_entry * parent
Definition zend.h:152
zend_string * doc_comment
Definition zend.h:224
zval * default_properties_table
Definition zend.h:160
HashTable function_table
Definition zend.h:163
const zend_object_handlers * default_object_handlers
Definition zend.h:186
zend_function * __callstatic
Definition zend.h:180
zend_function * clone
Definition zend.h:174
zend_function * destructor
Definition zend.h:173
zend_function * zf_new_iterator
zend_string * lc_name
Definition zend.h:87
zend_string * name
Definition zend.h:86
zend_string * lc_parent_name
zend_string * message
Definition zend.h:133
zend_string * filename
Definition zend.h:132
zend_string * opened_path
Definition zend_stream.h:59
uint32_t * refcount
zend_function * prototype
HashTable * attributes
HashTable * static_variables
zend_op_array ** dynamic_func_defs
const zend_property_info * prop_info
zend_string * filename
zend_string * doc_comment
zend_class_entry * scope
zend_arg_info * arg_info
uint32_t num_args
zend_try_catch_element * try_catch_array
zend_string ** vars
zend_op * opcodes
zend_live_range * live_range
zend_string * function_name
uint32_t fn_flags
uint32_t num_dynamic_func_defs
znode_op op1
znode_op op2
uint8_t opcode
uint8_t op1_type
uint32_t extended_value
uint8_t op2_type
zend_early_binding * early_bindings
struct _zend_persistent_script::zend_persistent_script_dynamic_members dynamic_members
zend_error_info ** warnings
const zend_property_info * prototype
zend_string * doc_comment
zend_function ** hooks
zend_string * name
HashTable * attributes
zend_class_entry * ce
HashTable function_table
HashTable class_table
zend_string * filename
zend_op_array main_op_array
zend_trait_method_reference trait_method
Definition zend.h:102
zend_string * alias
Definition zend.h:107
zend_string * method_name
Definition zend.h:91
zend_string * class_name
Definition zend.h:92
zend_trait_method_reference trait_method
Definition zend.h:96
zend_string * exclude_class_names[1]
Definition zend.h:98
uint32_t num_excludes
Definition zend.h:97
zend_op_array op_array
uint32_t constant
#define close(a)
#define errno
#define EAGAIN
ZEND_API void zend_alloc_ce_cache(zend_string *type_name)
Definition zend.c:2070
ZEND_API void zend_map_ptr_extend(size_t last)
Definition zend.c:2053
struct _zend_class_name zend_class_name
struct _zend_trait_precedence zend_trait_precedence
struct _zend_error_info zend_error_info
#define zend_catch
Definition zend.h:277
struct _zend_trait_alias zend_trait_alias
#define zend_try
Definition zend.h:270
#define zend_end_try()
Definition zend.h:280
void zend_accel_error(int type, const char *format,...)
#define ACCEL_LOG_DEBUG
#define ACCEL_LOG_INFO
#define ACCEL_LOG_WARNING
zend_accel_hash_entry * zend_accel_hash_find_entry(zend_accel_hash *accel_hash, zend_string *key)
zend_accel_hash_entry * zend_accel_hash_update(zend_accel_hash *accel_hash, zend_string *key, bool indirect, void *data)
struct _zend_accel_hash_entry zend_accel_hash_entry
unsigned int zend_adler32(unsigned int checksum, unsigned char *buf, uint32_t len)
#define ADLER32_INIT
#define ZEND_MM_ALIGNED_SIZE(size)
Definition zend_alloc.h:35
#define efree(ptr)
Definition zend_alloc.h:155
#define emalloc(size)
Definition zend_alloc.h:151
struct _zend_ast_zval zend_ast_zval
struct _zend_ast_list zend_ast_list
@ ZEND_AST_CONSTANT
Definition zend_ast.h:37
@ ZEND_AST_ZVAL
Definition zend_ast.h:36
struct _zend_attribute zend_attribute
struct _zval_struct zval
strlen(string $string)
zend_string_release_ex(func->internal_function.function_name, 0)
execute_data func
#define ZEND_PROPERTY_HOOK_COUNT
#define ZEND_ACC_ENUM
struct _zend_op zend_op
#define ZEND_ACC_IMMUTABLE
#define IS_CONST
#define ZEND_ACC_LINKED
#define ZEND_CLASS_DTOR
#define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, node)
#define ZEND_FUNCTION_DTOR
#define ZEND_USER_FUNCTION
struct _zend_op_array zend_op_array
struct _zend_class_constant zend_class_constant
struct _zend_property_info zend_property_info
#define ZEND_ACC_ANON_CLASS
#define RT_CONSTANT(opline, node)
#define ZEND_ACC_HAS_RETURN_TYPE
struct _zend_arg_info zend_arg_info
#define ZEND_ACC_FILE_CACHED
#define ZEND_ACC_VARIADIC
#define ZEND_LAST_CATCH
#define ZEND_ACC_CLOSURE
ZEND_API zend_object_handlers zend_enum_object_handlers
Definition zend_enum.c:37
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define LOCK_UN
#define IS_UNSERIALIZED(ptr)
#define SERIALIZE_STR(ptr)
#define IS_SERIALIZED(ptr)
int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm)
void zend_file_cache_invalidate(zend_string *full_path)
#define SUFFIX
zend_persistent_script * zend_file_cache_script_load(zend_file_handle *file_handle)
#define LOCK_EX
#define UNSERIALIZE_ATTRIBUTES(attributes)
struct _zend_file_cache_metainfo zend_file_cache_metainfo
#define SERIALIZE_PTR(ptr)
#define UNSERIALIZE_PTR(ptr)
void(* serialize_callback_t)(zval *zv, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
#define LOCK_SH
void(* unserialize_callback_t)(zval *zv, zend_persistent_script *script, void *buf)
#define SERIALIZE_ATTRIBUTES(attributes)
#define UNSERIALIZE_STR(ptr)
#define HOOKED_ITERATOR_PLACEHOLDER
#define zend_file_cache_unlink
#define zend_file_cache_open
#define IS_SERIALIZED_INTERNED(ptr)
union _zend_function zend_function
#define CG(v)
#define EG(v)
#define HT_IS_PACKED(ht)
Definition zend_hash.h:59
#define HASH_FLAG_UNINITIALIZED
Definition zend_hash.h:42
#define HT_FLAGS(ht)
Definition zend_hash.h:50
struct _zend_file_handle zend_file_handle
#define JIT_G(v)
Definition zend_jit.h:151
int32_t zend_long
Definition zend_long.h:42
#define Z_UL(i)
Definition zend_long.h:49
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
#define ZEND_MAP_PTR_INIT(ptr, val)
#define ZEND_MAP_PTR_NEW(ptr)
ZEND_API const zend_object_handlers std_object_handlers
uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name)
#define EXPECTED(condition)
#define LONGJMP(a, b)
#define ZEND_ASSERT(c)
#define UNEXPECTED(condition)
ZEND_API zend_object_iterator * zend_hooked_object_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
struct _zend_class_entry zend_class_entry
void zend_shared_alloc_lock(void)
void zend_shared_alloc_init_xlat_table(void)
void * zend_shared_alloc_get_xlat_entry(const void *key_pointer)
void zend_shared_alloc_unlock(void)
void zend_shared_alloc_destroy_xlat_table(void)
void zend_shared_alloc_register_xlat_entry(const void *key_pointer, const void *value)
void * zend_shared_alloc(size_t size)
#define ZSMMG(element)
#define _ZSTR_STRUCT_SIZE(len)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define _ZSTR_HEADER_SIZE
ZEND_API char zend_system_id[32]
#define GC_STRING
Definition zend_types.h:785
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_STR_CLASS_NAME_MAP_PTR
Definition zend_types.h:816
#define IS_STR_PERMANENT
Definition zend_types.h:819
struct _zend_ast_ref zend_ast_ref
Definition zend_types.h:101
#define ZEND_TYPE_NAME(t)
Definition zend_types.h:198
#define GC_SET_REFCOUNT(p, rc)
Definition zend_types.h:708
#define IS_UNDEF
Definition zend_types.h:600
#define IS_STR_INTERNED
Definition zend_types.h:817
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define HT_INVALID_IDX
Definition zend_types.h:429
#define IS_ARRAY
Definition zend_types.h:607
#define ZEND_TYPE_HAS_NAME(t)
Definition zend_types.h:174
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_PTR_P(zval_p)
void(* dtor_func_t)(zval *pDest)
Definition zend_types.h:107
#define ZEND_TYPE_HAS_LIST(t)
Definition zend_types.h:180
#define ZEND_TYPE_LIST_FOREACH_END()
Definition zend_types.h:217
@ FAILURE
Definition zend_types.h:61
#define GC_AST(p)
struct _Bucket Bucket
#define Z_INDIRECT_P(zval_p)
#define HT_SET_DATA_ADDR(ht, ptr)
Definition zend_types.h:542
#define Z_AST_P(zval_p)
#define IS_CONSTANT_AST
Definition zend_types.h:611
#define ZEND_TYPE_SET_PTR(t, _ptr)
Definition zend_types.h:240
#define ZEND_TYPE_LIST_FOREACH(list, type_ptr)
Definition zend_types.h:211
#define Z_TYPE(zval)
Definition zend_types.h:659
#define IS_INDIRECT
Definition zend_types.h:623
#define ZEND_TYPE_LIST(t)
Definition zend_types.h:204
struct _zend_ast zend_ast
Definition zend_types.h:102
#define GC_DEL_FLAGS(p, flags)
Definition zend_types.h:762
#define HT_MIN_MASK
Definition zend_types.h:431
#define Z_ASTVAL_P(zval_p)
#define Z_ARR_P(zval_p)
Definition zend_types.h:984
#define IS_STR_PERSISTENT
Definition zend_types.h:818
#define GC_FLAGS_SHIFT
Definition zend_types.h:739
#define GC_ADD_FLAGS(p, flags)
Definition zend_types.h:759
#define GC_TYPE_INFO(p)
Definition zend_types.h:754
#define ZVAL_PTR_DTOR
#define IS_SLASH(c)
ZEND_API void ZEND_FASTCALL zend_serialize_opcode_handler(zend_op *op)
ZEND_API void ZEND_FASTCALL zend_deserialize_opcode_handler(zend_op *op)
zend_string * name
zval * ret
new_op_array scope
#define ZEND_SWITCH_LONG
#define ZEND_FE_FETCH_RW
#define ZEND_FE_RESET_RW
#define ZEND_FE_FETCH_R
#define ZEND_ASSERT_CHECK
#define ZEND_SWITCH_STRING
#define ZEND_JMPZ
#define ZEND_JMP_SET
#define ZEND_JMPZ_EX
#define ZEND_MATCH
#define ZEND_JMPNZ_EX
#define ZEND_FAST_CALL
#define ZEND_JMP_NULL
#define ZEND_BIND_INIT_STATIC_OR_JMP
#define ZEND_JMP
#define ZEND_FE_RESET_R
#define ZEND_JMP_FRAMELESS
#define ZEND_JMPNZ
#define ZEND_CATCH
#define ZEND_COALESCE