root/eaccelerator/tags/0.9.4-rc2/ea_restore.c

Revision 127, 28.2 kB (checked in by zoeloelip, 3 years ago)

Included some compile fixes. (Thanks Matt)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2    +----------------------------------------------------------------------+
3    | eAccelerator project                                                 |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 2004 - 2005 eAccelerator                               |
6    | http://eaccelerator.net                                              |
7    +----------------------------------------------------------------------+
8    | This program is free software; you can redistribute it and/or        |
9    | modify it under the terms of the GNU General Public License          |
10    | as published by the Free Software Foundation; either version 2       |
11    | of the License, or (at your option) any later version.               |
12    |                                                                      |
13    | This program is distributed in the hope that it will be useful,      |
14    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
16    | GNU General Public License for more details.                         |
17    |                                                                      |
18    | You should have received a copy of the GNU General Public License    |
19    | along with this program; if not, write to the Free Software          |
20    | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
21    | MA  02111-1307, USA.                                                 |
22    |                                                                      |
23    | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
24    +----------------------------------------------------------------------+
25    | Author(s): Dmitry Stogov <dstogov@users.sourceforge.net>             |
26    |            Seung Woo <segv@sayclub.com>                              |
27    |            Everaldo Canuto <everaldo_canuto@yahoo.com.br>            |
28    +----------------------------------------------------------------------+
29    $Id$
30 */
31
32 #include "eaccelerator.h"
33
34 #ifdef HAVE_EACCELERATOR
35
36 #include "debug.h"
37 #include "ea_restore.h"
38 #include "opcodes.h"
39 #include "zend.h"
40 #include "zend_API.h"
41 #include "zend_extensions.h"
42
43 #ifndef INCOMPLETE_CLASS
44 #  define INCOMPLETE_CLASS "__PHP_Incomplete_Class"
45 #endif
46 #ifndef MAGIC_MEMBER
47 #  define MAGIC_MEMBER "__PHP_Incomplete_Class_Name"
48 #endif
49
50 extern zend_extension *ZendOptimizer;
51 #if HARDENING_PATCH_HASH_PROTECT
52 extern unsigned int zend_hash_canary;
53 #endif
54
55 #ifdef ZEND_ENGINE_2
56 /* pointer to the properties_info hashtable destructor */
57 dtor_func_t properties_info_dtor = NULL;
58
59 /* This function creates a dummy class entry to steal the pointer to the
60  * properties_info hashtable destructor because it's declared static */
61 dtor_func_t get_zend_destroy_property_info(TSRMLS_D)
62 {
63         dtor_func_t property_dtor;
64         zend_class_entry dummy_class_entry;
65         dummy_class_entry.type = ZEND_USER_CLASS;
66
67         zend_initialize_class_data(&dummy_class_entry, 1 TSRMLS_CC);
68
69         property_dtor = dummy_class_entry.properties_info.pDestructor;
70
71         zend_hash_destroy(&dummy_class_entry.default_properties);
72         zend_hash_destroy(&dummy_class_entry.properties_info);
73         zend_hash_destroy(dummy_class_entry.static_members);
74         zend_hash_destroy(&dummy_class_entry.function_table);
75         FREE_HASHTABLE(dummy_class_entry.static_members);
76         zend_hash_destroy(&dummy_class_entry.constants_table);
77
78         return property_dtor;
79 }
80 #endif
81
82 /******************************************************************************/
83 /* Functions to restore a cached script from file cache                       */
84 /******************************************************************************/
85
86 typedef void (*fixup_bucket_t) (void *TSRMLS_DC);
87
88 #define fixup_zval_hash(from) \
89     fixup_hash(from, (fixup_bucket_t)fixup_zval TSRMLS_CC)
90
91 #ifdef ZEND_ENGINE_2
92 static void fixup_property_info(zend_property_info * from TSRMLS_DC)
93 {
94         FIXUP(from->name);
95 }
96 #endif
97
98 static void fixup_hash(HashTable * source,
99                                            fixup_bucket_t fixup_bucket TSRMLS_DC)
100 {
101         unsigned int i;
102         Bucket *p;
103
104         if (source->nNumOfElements > 0) {
105                 if (!EAG(compress)) {
106                         if (source->arBuckets != NULL) {
107                                 FIXUP(source->arBuckets);
108                                 for (i = 0; i < source->nTableSize; i++) {
109                                         FIXUP(source->arBuckets[i]);
110                                 }
111                         }
112                 }
113                 FIXUP(source->pListHead);
114                 FIXUP(source->pListTail);
115
116                 p = source->pListHead;
117                 while (p) {
118                         FIXUP(p->pNext);
119                         FIXUP(p->pLast);
120                         FIXUP(p->pData);
121                         FIXUP(p->pDataPtr);
122                         FIXUP(p->pListLast);
123                         FIXUP(p->pListNext);
124                         if (p->pDataPtr) {
125                                 fixup_bucket(p->pDataPtr TSRMLS_CC);
126                                 p->pData = &p->pDataPtr;
127                         } else {
128                                 fixup_bucket(p->pData TSRMLS_CC);
129                         }
130                         p = p->pListNext;
131                 }
132                 source->pInternalPointer = source->pListHead;
133         }
134 }
135
136 void fixup_zval(zval * zv TSRMLS_DC)
137 {
138         switch (zv->type & ~IS_CONSTANT_INDEX) {
139         case IS_CONSTANT:                       /* fallthrough */
140         case IS_STRING:
141                 if (zv->value.str.val == NULL || zv->value.str.len == 0) {
142                         zv->value.str.val = empty_string;
143                         zv->value.str.len = 0;
144                 } else {
145                         FIXUP(zv->value.str.val);
146                 }
147                 break;
148         case IS_ARRAY:                          /* fallthrough */
149         case IS_CONSTANT_ARRAY:
150                 if (zv->value.ht == NULL || zv->value.ht == &EG(symbol_table)) {
151                 } else {
152                         FIXUP(zv->value.ht);
153                         fixup_zval_hash(zv->value.ht);
154                 }
155                 break;
156         case IS_OBJECT:
157                 if (!EAG(compress)) {
158                         return;
159                 }
160 #ifndef ZEND_ENGINE_2
161                 FIXUP(zv->value.obj.ce);
162                 if (zv->value.obj.properties != NULL) {
163                         FIXUP(zv->value.obj.properties);
164                         fixup_zval_hash(zv->value.obj.properties);
165                 }
166 #endif
167         default:
168                 break;
169         }
170 }
171
172 void fixup_op_array(eaccelerator_op_array * from TSRMLS_DC)
173 {
174         zend_op *opline;
175         zend_op *end;
176
177 #ifdef ZEND_ENGINE_2
178         if (from->num_args > 0) {
179                 zend_uint i;
180                 FIXUP(from->arg_info);
181                 for (i = 0; i < from->num_args; i++) {
182                         FIXUP(from->arg_info[i].name);
183                         FIXUP(from->arg_info[i].class_name);
184                 }
185         }
186 #else
187         FIXUP(from->arg_types);
188 #endif
189         FIXUP(from->function_name);
190 #ifdef ZEND_ENGINE_2
191         FIXUP(from->scope_name);
192 #endif
193         if (from->type == ZEND_INTERNAL_FUNCTION) {
194                 return;
195         }
196
197         if (from->opcodes != NULL) {
198                 FIXUP(from->opcodes);
199
200                 opline = from->opcodes;
201                 end = opline + from->last;
202                 EAG(compress) = 0;
203                 for (; opline < end; opline++) {
204                         /*
205                            if (opline->result.op_type == IS_CONST)
206                            fixup_zval(&opline->result.u.constant TSRMLS_CC);
207                          */
208                         if (opline->op1.op_type == IS_CONST)
209                                 fixup_zval(&opline->op1.u.constant TSRMLS_CC);
210                         if (opline->op2.op_type == IS_CONST)
211                                 fixup_zval(&opline->op2.u.constant TSRMLS_CC);
212 #ifdef ZEND_ENGINE_2
213                         switch (opline->opcode) {
214                         case ZEND_JMP:
215                                 FIXUP(opline->op1.u.jmp_addr);
216                                 break;
217                         case ZEND_JMPZ: /* fallthrough */
218                         case ZEND_JMPNZ:
219                         case ZEND_JMPZ_EX:
220                         case ZEND_JMPNZ_EX:
221                                 FIXUP(opline->op2.u.jmp_addr);
222                                 break;
223                         }
224                         opline->handler = get_opcode_handler(opline->opcode TSRMLS_CC);
225 #endif
226                 }
227                 EAG(compress) = 1;
228         }
229         FIXUP(from->brk_cont_array);
230 #ifdef ZEND_ENGINE_2
231         FIXUP(from->try_catch_array);
232 #endif
233         if (from->static_variables != NULL) {
234                 FIXUP(from->static_variables);
235                 fixup_zval_hash(from->static_variables);
236         }
237         FIXUP(from->filename);
238 #ifdef ZEND_ENGINE_2
239         FIXUP(from->doc_comment);
240 #endif
241 }
242
243 void fixup_class_entry(eaccelerator_class_entry * from TSRMLS_DC)
244 {
245         FIXUP(from->name);
246         FIXUP(from->parent);
247 #ifdef ZEND_ENGINE_2
248         FIXUP(from->filename);
249         FIXUP(from->doc_comment);
250         fixup_zval_hash(&from->constants_table);
251         fixup_zval_hash(&from->default_properties);
252         fixup_hash(&from->properties_info,
253                            (fixup_bucket_t) fixup_property_info TSRMLS_CC);
254         if (from->static_members != NULL) {
255                 FIXUP(from->static_members);
256                 fixup_zval_hash(from->static_members);
257         }
258 #else
259         fixup_zval_hash(&from->default_properties);
260 #endif
261         fixup_hash(&from->function_table,
262                            (fixup_bucket_t) fixup_op_array TSRMLS_CC);
263 }
264
265 /******************************************************************************/
266 /* Functions to restore a php script from shared memory                       */
267 /******************************************************************************/
268
269 typedef void *(*restore_bucket_t) (void *TSRMLS_DC);
270
271 #define restore_zval_hash(target, source) \
272     restore_hash(target, source, (restore_bucket_t)restore_zval_ptr TSRMLS_CC)
273
274 static zval *restore_zval_ptr(zval * from TSRMLS_DC)
275 {
276         zval *p;
277         ALLOC_ZVAL(p);
278         memcpy(p, from, sizeof(zval));
279         restore_zval(p TSRMLS_CC);
280         return p;
281 }
282
283 static HashTable *restore_hash(HashTable * target, HashTable * source,
284                                                            restore_bucket_t copy_bucket TSRMLS_DC)
285 {
286         Bucket *p, *np, *prev_p;
287         int nIndex;
288
289         if (target == NULL) {
290                 ALLOC_HASHTABLE(target);
291         }
292         memcpy(target, source, sizeof(HashTable));
293         target->arBuckets =
294                 (Bucket **) emalloc(target->nTableSize * sizeof(Bucket *));
295         memset(target->arBuckets, 0, target->nTableSize * sizeof(Bucket *));
296         target->pDestructor = NULL;
297         target->persistent = 0;
298         target->pListHead = NULL;
299         target->pListTail = NULL;
300 #if HARDENING_PATCH_HASH_PROTECT
301     target->canary = zend_hash_canary;
302 #endif
303
304         p = source->pListHead;
305         prev_p = NULL;
306         np = NULL;
307         while (p) {
308                 np = (Bucket *) emalloc(offsetof(Bucket, arKey) + p->nKeyLength);
309                 /*    np = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength); */
310                 nIndex = p->h % source->nTableSize;
311                 if (target->arBuckets[nIndex]) {
312                         np->pNext = target->arBuckets[nIndex];
313                         np->pLast = NULL;
314                         np->pNext->pLast = np;
315                 } else {
316                         np->pNext = NULL;
317                         np->pLast = NULL;
318                 }
319                 target->arBuckets[nIndex] = np;
320                 np->h = p->h;
321                 np->nKeyLength = p->nKeyLength;
322
323                 if (p->pDataPtr == NULL) {
324                         np->pData = copy_bucket(p->pData TSRMLS_CC);
325                         np->pDataPtr = NULL;
326                 } else {
327                         np->pDataPtr = copy_bucket(p->pDataPtr TSRMLS_CC);
328                         np->pData = &np->pDataPtr;
329                 }
330                 np->pListLast = prev_p;
331                 np->pListNext = NULL;
332
333                 memcpy(np->arKey, p->arKey, p->nKeyLength);
334
335                 if (prev_p) {
336                         prev_p->pListNext = np;
337                 } else {
338                         target->pListHead = np;
339                 }
340                 prev_p = np;
341                 p = p->pListNext;
342         }
343         target->pListTail = np;
344         target->pInternalPointer = target->pListHead;
345         return target;
346 }
347
348 void restore_zval(zval * zv TSRMLS_DC)
349 {
350         switch (zv->type & ~IS_CONSTANT_INDEX) {
351         case IS_CONSTANT:
352         case IS_STRING:
353                 if (zv->value.str.val == NULL ||
354                 zv->value.str.val == empty_string || zv->value.str.len == 0) {
355                         zv->value.str.val = empty_string;
356                         return;
357                 } else {
358                         char *p = emalloc(zv->value.str.len + 1);
359                         memcpy(p, zv->value.str.val, zv->value.str.len + 1);
360                         zv->value.str.val = p;
361                 }
362                 return;
363
364         case IS_ARRAY:
365         case IS_CONSTANT_ARRAY:
366                 if (zv->value.ht != NULL && zv->value.ht != &EG(symbol_table)) {
367                         zv->value.ht = restore_zval_hash(NULL, zv->value.ht);
368                         zv->value.ht->pDestructor = ZVAL_PTR_DTOR;
369                 }
370                 return;
371
372         case IS_OBJECT:
373     {
374 #ifndef ZEND_ENGINE_2
375         zend_bool incomplete_class = 0;
376         char *class_name = (char *) zv->value.obj.ce;
377         int name_len = 0;
378         if (!EAG(compress)) {
379             return;
380         }
381         if (class_name != NULL) {
382             zend_class_entry *ce = NULL;
383             name_len = strlen(class_name);
384             if (zend_hash_find(CG(class_table), (void *) class_name, name_len + 1, (void **) &ce) != SUCCESS) {
385                 char *lowercase_name = estrndup(INCOMPLETE_CLASS, sizeof(INCOMPLETE_CLASS));
386                 zend_str_tolower(lowercase_name, sizeof(INCOMPLETE_CLASS));
387                 if (zend_hash_find(CG(class_table), lowercase_name,
388                             sizeof(INCOMPLETE_CLASS), (void **) &ce) != SUCCESS) {
389                     efree(lowercase_name);
390                     zend_error(E_ERROR, "EACCELERATOR can't restore object's class \"%s\"", class_name);
391                 } else {
392                     efree(lowercase_name);
393                     zv->value.obj.ce = ce;
394                     incomplete_class = 1;
395                 }
396             } else {
397                 zv->value.obj.ce = ce;
398             }
399         }
400         if (zv->value.obj.properties != NULL) {
401             zv->value.obj.properties = restore_zval_hash(NULL, zv->value.obj.properties);
402             zv->value.obj.properties->pDestructor = ZVAL_PTR_DTOR;
403             /* Clearing references */
404             {
405                 Bucket *p = zv->value.obj.properties->pListHead;
406                 while (p != NULL) {
407                     ((zval *) (p->pDataPtr))->refcount = 1;
408                     p = p->pListNext;
409                 }
410             }
411         }
412         if (incomplete_class && class_name != NULL) {
413             zval *val;
414             MAKE_STD_ZVAL(val);
415             Z_TYPE_P(val) = IS_STRING;
416             Z_STRVAL_P(val) = estrndup(class_name, name_len);
417             Z_STRLEN_P(val) = name_len;
418             zend_hash_update(Z_OBJPROP_P(zv), MAGIC_MEMBER, sizeof(MAGIC_MEMBER), &val, sizeof(val), NULL);
419         }
420 #endif
421         return;
422     }
423         }
424 }
425
426 static void call_op_array_ctor_handler(zend_extension * extension,
427                                                                            zend_op_array * op_array TSRMLS_DC)
428 {
429         if (extension->op_array_ctor) {
430                 extension->op_array_ctor(op_array);
431         }
432 }
433
434 zend_op_array *restore_op_array(zend_op_array * to,
435                                                                 eaccelerator_op_array * from TSRMLS_DC)
436 {
437         zend_function *function;
438 #ifdef ZEND_ENGINE_2
439         int fname_len = 0;
440         char *fname_lc = NULL;
441 #endif
442
443         ea_debug_pad(EA_DEBUG TSRMLS_CC);
444         ea_debug_printf(EA_DEBUG, "[%d] restore_op_array: %s\n", getpid(),
445                                         from->function_name ? from->function_name : "(top)");
446
447         if (from->type == ZEND_INTERNAL_FUNCTION) {
448                 if (to == NULL) {
449                         to = emalloc(sizeof(zend_internal_function));
450                 }
451                 memset(to, 0, sizeof(zend_internal_function));
452         } else {
453                 if (to == NULL) {
454                         to = emalloc(sizeof(zend_op_array));
455                 }
456                 memset(to, 0, sizeof(zend_op_array));
457                 if (ZendOptimizer) {
458                         zend_llist_apply_with_argument(&zend_extensions,
459                     (llist_apply_with_arg_func_t) call_op_array_ctor_handler, to TSRMLS_CC);
460                 }
461         }
462         to->type = from->type;
463 #ifdef ZEND_ENGINE_2
464         to->num_args = from->num_args;
465         to->required_num_args = from->required_num_args;
466         to->arg_info = from->arg_info;
467         to->pass_rest_by_reference = from->pass_rest_by_reference;
468 #else
469         to->arg_types = from->arg_types;
470 #endif
471         to->function_name = from->function_name;
472
473 #ifdef ZEND_ENGINE_2
474         if (to->function_name) {
475                 fname_len = strlen(to->function_name);
476                 fname_lc = zend_str_tolower_dup(to->function_name, fname_len);
477         }
478
479         to->fn_flags = from->fn_flags;
480
481         /* segv74:
482          * to->scope = EAG(class_entry)
483          *
484          * if  from->scope_name == NULL,
485          *     ; EAG(class) == NULL  : we are in function or outside function.
486          *     ; EAG(class) != NULL  : inherited method not defined in current file, should have to find.
487          *                              just LINK (zend_op_array *) to to original entry in parent,
488          *                              but, with what? !!! I don't know PARENT CLASS NAME !!!!
489          *
490          *
491          * if  from->scope_name != NULL,
492          *     ; we are in class member function
493          *
494          *     ; we have to find appropriate (zend_class_entry*) to->scope for name from->scope_name
495          *     ; if we find in CG(class_table), link to it.
496          *     ; if fail, it should be EAG(class_entry)
497          *   
498          * am I right here ? ;-(
499          */
500         if (from->scope_name != NULL) {
501                 char *from_scope_lc = zend_str_tolower_dup(from->scope_name, from->scope_name_len);
502                 if (zend_hash_find (CG(class_table), (void *) from_scope_lc,
503                     from->scope_name_len + 1, (void **) &to->scope) != SUCCESS) {
504                         ea_debug_pad(EA_DEBUG TSRMLS_CC);
505                         ea_debug_printf(EA_DEBUG, "[%d]                   can't find '%s' in hash. use EAG(class_entry).\n", getpid(), from_scope_lc);
506                         to->scope = EAG(class_entry);
507                 } else {
508                         ea_debug_pad(EA_DEBUG TSRMLS_CC);
509                         ea_debug_printf(EA_DEBUG, "[%d]                   found '%s' in hash\n", getpid(), from_scope_lc);
510                         to->scope = *(zend_class_entry **) to->scope;
511                 }
512                 efree(from_scope_lc);
513         } else {                                        // zoeloelip: is this needed? scope is always stored
514                 ea_debug_pad(EA_DEBUG TSRMLS_CC);
515                 ea_debug_printf(EA_DEBUG, "[%d]                   from is NULL\n", getpid());
516                 if (EAG(class_entry)) {
517                         zend_class_entry *p;
518                         for (p = EAG(class_entry)->parent; p; p = p->parent) {
519                                 ea_debug_pad(EA_DEBUG TSRMLS_CC);
520                                 ea_debug_printf(EA_DEBUG, "[%d]                   checking parent '%s' have '%s'\n", getpid(), p->name, fname_lc);
521                                 if (zend_hash_find(&p->function_table, fname_lc, fname_len + 1, (void **) &function) == SUCCESS) {
522                                         ea_debug_pad(EA_DEBUG TSRMLS_CC);
523                                         ea_debug_printf(EA_DEBUG, "[%d]                                   '%s' has '%s' of scope '%s'\n",
524                             getpid(), p->name, fname_lc, function->common.scope->name);
525                                         to->scope = function->common.scope;
526                                         break;
527                                 }
528                         }
529                 } else {
530                         to->scope = NULL;
531                 }
532         }
533
534         ea_debug_pad(EA_DEBUG TSRMLS_CC);
535         ea_debug_printf(EA_DEBUG, "[%d]                   %s's scope is '%s'\n", getpid(),
536             from->function_name ? from->function_name : "(top)", to->scope ? to->scope->name : "NULL");
537 #endif
538         if (from->type == ZEND_INTERNAL_FUNCTION) {
539                 zend_class_entry *class_entry = EAG(class_entry);
540                 ea_debug_pad(EA_DEBUG TSRMLS_CC);
541                 ea_debug_printf(EA_DEBUG, "[%d]                   [internal function from=%08x,to=%08x] class_entry='%s' [%08x]\n",
542                 getpid(), from, to, class_entry->name, class_entry);
543                 if (class_entry) {
544                         ea_debug_pad(EA_DEBUG TSRMLS_CC);
545                         ea_debug_printf(EA_DEBUG, "[%d]                                       class_entry->parent='%s' [%08x]\n",
546                     getpid(), class_entry->parent->name, class_entry->parent);
547                 }
548                 if (class_entry != NULL && class_entry->parent != NULL &&
549                 zend_hash_find(&class_entry->parent->function_table,
550 #ifdef ZEND_ENGINE_2
551                 fname_lc, fname_len + 1,
552 #else
553                 to->function_name, strlen(to->function_name) + 1,
554 #endif
555                                 (void **) &function) == SUCCESS && function->type == ZEND_INTERNAL_FUNCTION) {
556                         ea_debug_pad(EA_DEBUG TSRMLS_CC);
557                         ea_debug_printf(EA_DEBUG, "[%d]                                       found in function table\n", getpid());
558                         ((zend_internal_function *) (to))->handler = ((zend_internal_function *) function)->handler;
559                 } else {
560                         /* FIXME. I don't know how to fix handler.
561                          * TODO: must solve this somehow, to avoid returning damaged structure...
562                          */
563                         ea_debug_pad(EA_DEBUG TSRMLS_CC);
564                         ea_debug_printf(EA_DEBUG, "[%d]                                       can't find\n", getpid());
565                 }
566                 return to;
567         }
568         to->opcodes = from->opcodes;
569         to->last = to->size = from->last;
570         to->T = from->T;
571         to->brk_cont_array = from->brk_cont_array;
572         to->last_brk_cont = from->last_brk_cont;
573         /*
574            to->current_brk_cont = -1;
575            to->static_variables = from->static_variables;
576            to->start_op         = to->opcodes;
577            to->backpatch_count  = 0;
578          */
579         to->return_reference = from->return_reference;
580         to->done_pass_two = 1;
581         to->filename = from->filename;
582 #ifdef ZEND_ENGINE_2
583         /* HOESH: try & catch support */
584         to->try_catch_array = from->try_catch_array;
585         to->last_try_catch = from->last_try_catch;
586         to->uses_this = from->uses_this;
587
588         to->line_start = from->line_start;
589         to->line_end = from->line_end;
590         to->doc_comment_len = from->doc_comment_len;
591         to->doc_comment = from->doc_comment;
592         /*???
593            if (from->doc_comment != NULL) {
594            to->doc_comment = emalloc(from->doc_comment_len+1);
595            memcpy(to->doc_comment, from->doc_comment, from->doc_comment_len+1);
596            }
597          */
598 #else
599         to->uses_globals = from->uses_globals;
600 #endif
601         if (from->static_variables) {
602                 to->static_variables = restore_zval_hash(NULL, from->static_variables);
603                 to->static_variables->pDestructor = ZVAL_PTR_DTOR;
604 #ifndef ZEND_ENGINE_2
605                 if (EAG(class_entry) != NULL) {
606                         Bucket *p = to->static_variables->pListHead;
607                         while (p != NULL) {
608                                 ((zval *) (p->pDataPtr))->refcount = 1;
609                                 p = p->pListNext;
610                         }
611                 }
612 #endif
613         }
614
615         /* disable deletion in destroy_op_array */
616         ++EAG(refcount_helper);
617         to->refcount = &EAG(refcount_helper);
618
619         return to;
620 }
621
622 static zend_op_array *restore_op_array_ptr(eaccelerator_op_array *
623                                                                                    from TSRMLS_DC)
624 {
625         return restore_op_array(NULL, from TSRMLS_CC);
626 }
627
628 #ifdef ZEND_ENGINE_2
629 static zend_property_info *restore_property_info(zend_property_info *
630                                                                                                  from TSRMLS_DC)
631 {
632         zend_property_info *to = emalloc(sizeof(zend_property_info));
633         memcpy(to, from, sizeof(zend_property_info));
634         to->name = emalloc(from->name_length + 1);
635         memcpy(to->name, from->name, from->name_length + 1);
636         return to;
637 }
638 #endif
639
640 /* restore the parent class with the given name for the given class */
641 void restore_class_parent(char *parent, int len,
642                                                   zend_class_entry * to TSRMLS_DC)
643 {
644 #ifdef ZEND_ENGINE_2
645         char *name_lc = zend_str_tolower_dup(parent, len);
646         if (zend_hash_find(CG(class_table), (void *) name_lc, len + 1, (void **) &to->parent) != SUCCESS)
647 #else
648         if (zend_hash_find(CG(class_table), (void *) parent, len + 1, (void **) &to->parent) != SUCCESS)
649 #endif
650         {
651                 ea_debug_error("[%d] EACCELERATOR can't restore parent class \"%s\" of class \"%s\"\n",
652                 getpid(), (char *) parent, to->name);
653                 to->parent = NULL;
654         } else {
655 #ifdef ZEND_ENGINE_2
656                 /* inherit parent methods */
657                 to->parent = *(zend_class_entry **) to->parent;
658                 to->constructor = to->parent->constructor;
659                 to->destructor = to->parent->destructor;
660                 to->clone = to->parent->clone;
661                 to->__get = to->parent->__get;
662                 to->__set = to->parent->__set;
663                 to->__call = to->parent->__call;
664                 to->create_object = to->parent->create_object;
665 #else
666                 to->handle_property_get = to->parent->handle_property_get;
667                 to->handle_property_set = to->parent->handle_property_set;
668                 to->handle_function_call = to->parent->handle_function_call;
669 #endif
670         }
671 #ifdef ZEND_ENGINE_2
672         efree(name_lc);
673 #endif
674 }
675
676 #ifdef ZEND_ENGINE_2
677 void restore_class_methods(zend_class_entry * to TSRMLS_DC)
678 {
679         int cname_len = to->name_length;
680         char *cname_lc = zend_str_tolower_dup(to->name, cname_len);
681         int fname_len = 0;
682         char *fname_lc = NULL;
683         zend_function *f = NULL;
684         zend_function *old_ctor = to->constructor;
685         Bucket *p = to->function_table.pListHead;
686
687         while (p != NULL) {
688                 f = p->pData;
689                 fname_len = strlen(f->common.function_name);
690                 fname_lc = zend_str_tolower_dup(f->common.function_name, fname_len);
691
692                 if (fname_len == cname_len && !memcmp(fname_lc, cname_lc, fname_len) &&
693                 to->constructor == old_ctor && f->common.scope != to->parent) {
694                         to->constructor = f;
695                 } else if (fname_lc[0] == '_' && fname_lc[1] == '_' && f->common.scope != to->parent) {
696                         if (fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1 &&
697                     memcmp(fname_lc, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)) == 0)
698                                 to->constructor = f;
699                         else if (fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 &&
700                                          memcmp(fname_lc, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) == 0)
701                                 to->destructor = f;
702                         else if (fname_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 &&
703                                          memcmp(fname_lc, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) == 0)
704                                 to->clone = f;
705                         else if (fname_len == sizeof(ZEND_GET_FUNC_NAME) - 1 &&
706                                          memcmp(fname_lc, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) == 0)
707                                 to->__get = f;
708                         else if (fname_len == sizeof(ZEND_SET_FUNC_NAME) - 1 &&
709                                          memcmp(fname_lc, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) == 0)
710                                 to->__set = f;
711                         else if (fname_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 &&
712                                          memcmp(fname_lc, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) == 0)
713                                 to->__call = f;
714                 }
715                 efree(fname_lc);
716                 p = p->pListNext;
717         }
718         efree(cname_lc);
719 }
720 #endif
721
722 zend_class_entry *restore_class_entry(zend_class_entry * to,
723                                                                           eaccelerator_class_entry * from TSRMLS_DC)
724 {
725         zend_class_entry *old;
726         zend_function *f = NULL;
727         int fname_len = 0;
728         char *fname_lc = NULL;
729 #ifdef ZEND_ENGINE_2
730         int cname_len;
731         char *cname_lc;
732         Bucket *p;
733         union _zend_function *old_ctor;
734 #endif
735
736         ea_debug_pad(EA_DEBUG TSRMLS_CC);
737         ea_debug_printf(EA_DEBUG, "[%d] retore_class_entry: %s\n", getpid(), from->name ? from->name : "(top)");
738 #ifdef DEBUG
739         EAG(xpad)++;
740 #endif
741
742         if (to == NULL) {
743                 to = emalloc(sizeof(zend_class_entry));
744         }
745         memset(to, 0, sizeof(zend_class_entry));
746         to->type = from->type;
747         /*
748            to->name        = NULL;
749            to->name_length = from->name_length;
750            to->constants_updated = 0;
751            to->parent      = NULL;
752          */
753 #ifdef ZEND_ENGINE_2
754         to->ce_flags = from->ce_flags;
755         /*
756            to->static_members = NULL;
757          */
758         to->num_interfaces = from->num_interfaces;
759         if (to->num_interfaces > 0) {
760                 to->interfaces = (zend_class_entry **) emalloc(sizeof(zend_class_entry *) * to->num_interfaces);
761                 // should find out class entry. what the hell !!!
762                 memset(to->interfaces, 0, sizeof(zend_class_entry *) * to->num_interfaces);
763         } else {
764                 to->interfaces = NULL;
765         }
766
767         to->iterator_funcs = from->iterator_funcs;
768         to->get_iterator = from->get_iterator;
769         to->interface_gets_implemented = from->interface_gets_implemented;
770 #endif
771
772         if (from->name != NULL) {
773                 to->name_length = from->name_length;
774                 to->name = emalloc(from->name_length + 1);
775                 memcpy(to->name, from->name, from->name_length + 1);
776         }
777
778         if (from->parent != NULL) {
779                 restore_class_parent(from->parent, strlen(from->parent), to TSRMLS_CC);
780         } else {
781                 ea_debug_pad(EA_DEBUG TSRMLS_CC);
782                 ea_debug_printf(EA_DEBUG, "[%d] parent = NULL\n", getpid());
783                 to->parent = NULL;
784         }
785
786         old = EAG(class_entry);
787         EAG(class_entry) = to;
788
789 #ifdef ZEND_ENGINE_2
790         to->refcount = 1;
791
792         to->line_start = from->line_start;
793         to->line_end = from->line_end;
794         to->doc_comment_len = from->doc_comment_len;
795         if (from->filename != NULL) {
796                 size_t len = strlen(from->filename) + 1;
797                 to->filename = emalloc(len);
798                 memcpy(to->filename, from->filename, len);
799         }
800         if (from->doc_comment != NULL) {
801                 to->doc_comment = emalloc(from->doc_comment_len + 1);
802                 memcpy(to->doc_comment, from->doc_comment, from->doc_comment_len + 1);
803         }
804
805         /* restore constants table */
806         restore_zval_hash(&to->constants_table, &from->constants_table);
807         to->constants_table.pDestructor = ZVAL_PTR_DTOR;
808         /* restore default properties */
809         restore_zval_hash(&to->default_properties, &from->default_properties);
810         to->default_properties.pDestructor = ZVAL_PTR_DTOR;
811         /* restore properties */
812         restore_hash(&to->properties_info, &from->properties_info,
813             (restore_bucket_t) restore_property_info TSRMLS_CC);
814         to->properties_info.pDestructor = properties_info_dtor;
815
816         if (from->static_members != NULL) {
817                 ALLOC_HASHTABLE(to->static_members);
818                 restore_zval_hash(to->static_members, from->static_members);
819                 to->static_members->pDestructor = ZVAL_PTR_DTOR;
820                 /*
821                    } else {
822                    ALLOC_HASHTABLE(to->static_members);
823                    zend_hash_init_ex(to->static_members, 0, NULL, ZVAL_PTR_DTOR, 0, 0);
824                  */
825         }
826 #else
827         to->refcount = emalloc(sizeof(*to->refcount));
828         *to->refcount = 1;
829
830         restore_zval_hash(&to->default_properties, &from->default_properties);
831         to->default_properties.pDestructor = ZVAL_PTR_DTOR;
832         /* Clearing references */
833         {
834                 Bucket *p = to->default_properties.pListHead;
835                 while (p != NULL) {
836                         ((zval *) (p->pDataPtr))->refcount = 1;
837                         p = p->pListNext;
838                 }
839         }
840 #endif
841         restore_hash(&to->function_table, &from->function_table,
842                                  (restore_bucket_t) restore_op_array_ptr TSRMLS_CC);
843         to->function_table.pDestructor = ZEND_FUNCTION_DTOR;
844
845 #ifdef ZEND_ENGINE_2
846         restore_class_methods(to TSRMLS_CC);
847 #endif
848         EAG(class_entry) = old;
849
850 #ifdef DEBUG
851         EAG(xpad)--;
852 #endif
853
854         return to;
855 }
856
857 void restore_function(mm_fc_entry * p TSRMLS_DC)
858 {
859         zend_op_array op_array;
860
861         if ((p->htabkey[0] == '\000') && zend_hash_exists(CG(function_table), p->htabkey, p->htablen)) {
862                 return;
863         }
864         if (restore_op_array(&op_array, (eaccelerator_op_array *) p->fc TSRMLS_CC) != NULL) {
865                 if (zend_hash_add(CG(function_table), p->htabkey, p->htablen, &op_array, sizeof(zend_op_array), NULL) == FAILURE) {
866                         CG(in_compilation) = 1;
867                         CG(compiled_filename) = EAG(mem);
868 #ifdef ZEND_ENGINE_2
869                         CG(zend_lineno) = op_array.line_start;
870 #else
871                         CG(zend_lineno) = op_array.opcodes[0].lineno;
872 #endif
873                         zend_error(E_ERROR, "Cannot redeclare %s()", p->htabkey);
874                 }
875         }
876 }
877
878 /*
879  * Class handling.
880  */
881 void restore_class(mm_fc_entry * p TSRMLS_DC)
882 {
883 #ifdef ZEND_ENGINE_2
884         zend_class_entry *ce;
885 #else
886         zend_class_entry ce;
887 #endif
888
889         if ((p->htabkey[0] == '\000') && zend_hash_exists(CG(class_table), p->htabkey, p->htablen)) {
890                 return;
891         }
892 #ifdef ZEND_ENGINE_2
893         ce = restore_class_entry(NULL, (eaccelerator_class_entry *) p->fc TSRMLS_CC);
894         if (ce != NULL)
895 #else
896         if (restore_class_entry(&ce, (eaccelerator_class_entry *) p->fc TSRMLS_CC) != NULL)
897 #endif
898         {
899 #ifdef ZEND_ENGINE_2
900                 if (zend_hash_add(CG(class_table), p->htabkey, p->htablen, &ce, sizeof(zend_class_entry *), NULL) == FAILURE)
901 #else
902                 if (zend_hash_add(CG(class_table), p->htabkey, p->htablen, &ce, sizeof(zend_class_entry), NULL) == FAILURE)
903 #endif
904                 {
905                         CG(in_compilation) = 1;
906                         CG(compiled_filename) = EAG(mem);
907 #ifdef ZEND_ENGINE_2
908                         CG(zend_lineno) = ce->line_start;
909 #else
910                         CG(zend_lineno) = 0;
911 #endif
912                         zend_error(E_ERROR, "Cannot redeclare class %s", p->htabkey);
913                 }
914         }
915 }
916
917 #endif /* HAVE_EACCELERATOR */
Note: See TracBrowser for help on using the browser.