root/eaccelerator/trunk/ea_restore.c

Revision 405, 29.6 kB (checked in by hans, 5 months ago)

Remove some leftover debug output that broke compilation with php-5.2 and --with-eaccelerator-debug

  • 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 - 2010 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    $Id$
26 */
27
28 #include "eaccelerator.h"
29
30 #ifdef HAVE_EACCELERATOR
31
32 #include "debug.h"
33 #include "ea_restore.h"
34 #include "opcodes.h"
35 #include "zend.h"
36 #include "zend_API.h"
37 #include "zend_extensions.h"
38 #include "zend_vm.h"
39
40 #ifndef INCOMPLETE_CLASS
41 define INCOMPLETE_CLASS "__PHP_Incomplete_Class"
42 #endif
43 #ifndef MAGIC_MEMBER
44 define MAGIC_MEMBER "__PHP_Incomplete_Class_Name"
45 #endif
46
47 extern zend_extension *ZendOptimizer;
48 #if HARDENING_PATCH_HASH_PROTECT
49 extern unsigned int zend_hash_canary;
50 #endif
51
52 /* pointer to the properties_info hashtable destructor */
53 dtor_func_t properties_info_dtor = NULL;
54
55 /* This function creates a dummy class entry to steal the pointer to the
56  * properties_info hashtable destructor because it's declared static */
57 dtor_func_t get_zend_destroy_property_info(TSRMLS_D)
58 {
59     dtor_func_t property_dtor;
60     zend_class_entry dummy_class_entry;
61     dummy_class_entry.type = ZEND_USER_CLASS;
62
63     zend_initialize_class_data(&dummy_class_entry, 1 TSRMLS_CC);
64
65     property_dtor = dummy_class_entry.properties_info.pDestructor;
66
67     zend_hash_destroy(&dummy_class_entry.default_properties);
68     zend_hash_destroy(&dummy_class_entry.function_table);
69     zend_hash_destroy(&dummy_class_entry.constants_table);
70     zend_hash_destroy(&dummy_class_entry.properties_info);
71     zend_hash_destroy(&dummy_class_entry.default_static_members);
72     return property_dtor;
73 }
74
75 /******************************************************************************/
76 /* Functions to restore a cached script from file cache                       */
77 /******************************************************************************/
78
79 typedef void (*fixup_bucket_t) (char *, void *TSRMLS_DC);
80
81 #define fixup_zval_hash(base, from) \
82     fixup_hash(base, from, (fixup_bucket_t)fixup_zval TSRMLS_CC)
83
84 static void fixup_property_info(char *base, zend_property_info * from TSRMLS_DC)
85 {
86     FIXUP(base, from->name);
87     FIXUP(base, from->doc_comment);
88 }
89
90 static void fixup_hash(char *base, HashTable * source,
91                        fixup_bucket_t fixup_bucket TSRMLS_DC)
92 {
93     unsigned int i;
94     Bucket *p;
95
96     if (source->nNumOfElements > 0) {
97         if (source->arBuckets != NULL) {
98             FIXUP(base, source->arBuckets);
99             for (i = 0; i < source->nTableSize; i++) {
100                 FIXUP(base, source->arBuckets[i]);
101             }
102         }
103         FIXUP(base, source->pListHead);
104         FIXUP(base, source->pListTail);
105
106         p = source->pListHead;
107         while (p) {
108             FIXUP(base, p->pNext);
109             FIXUP(base, p->pLast);
110             FIXUP(base, p->pData);
111             FIXUP(base, p->pDataPtr);
112             FIXUP(base, p->pListLast);
113             FIXUP(base, p->pListNext);
114             if (p->pDataPtr) {
115                 fixup_bucket(base, p->pDataPtr TSRMLS_CC);
116                 p->pData = &p->pDataPtr;
117             } else {
118                 fixup_bucket(base, p->pData TSRMLS_CC);
119             }
120             p = p->pListNext;
121         }
122         source->pInternalPointer = source->pListHead;
123     }
124 }
125
126 void fixup_zval(char *base, zval * zv TSRMLS_DC)
127 {
128     switch (EA_ZV_TYPE_P(zv)) {
129         case IS_CONSTANT:           /* fallthrough */
130         case IS_OBJECT:             /* fallthrough: object are serialized */
131         case IS_STRING:
132             FIXUP(base, Z_STRVAL_P(zv));
133             break;
134
135         case IS_ARRAY:              /* fallthrough */
136         case IS_CONSTANT_ARRAY:
137             FIXUP(base, Z_ARRVAL_P(zv));
138             fixup_zval_hash(base, Z_ARRVAL_P(zv));
139             break;
140
141         default:
142             break;
143     }
144 }
145
146 static void fixup_op_array(char *base, ea_op_array * from TSRMLS_DC)
147 {
148     zend_op *opline;
149     zend_op *end;
150
151     if (from->num_args > 0) {
152         zend_uint i;
153         FIXUP(base, from->arg_info);
154         for (i = 0; i < from->num_args; i++) {
155             FIXUP(base, from->arg_info[i].name);
156             FIXUP(base, from->arg_info[i].class_name);
157         }
158     }
159     FIXUP(base, from->function_name);
160     FIXUP(base, from->scope_name);
161     if (from->type == ZEND_INTERNAL_FUNCTION) {
162         return;
163     }
164
165     if (from->opcodes != NULL) {
166         FIXUP(base, from->opcodes);
167
168         opline = from->opcodes;
169         end = opline + from->last;
170         for (; opline < end; opline++) {
171             /*
172                if (opline->result.op_type == IS_CONST)
173                fixup_zval(&opline->result.u.constant TSRMLS_CC);
174              */
175             if (opline->op1.op_type == IS_CONST)
176                 fixup_zval(base, &opline->op1.u.constant TSRMLS_CC);
177             if (opline->op2.op_type == IS_CONST)
178                 fixup_zval(base, &opline->op2.u.constant TSRMLS_CC);
179             switch (opline->opcode) {
180 #ifdef ZEND_GOTO
181             case ZEND_GOTO:
182 #endif
183             case ZEND_JMP:
184                 FIXUP(base, opline->op1.u.jmp_addr);
185                 break;
186             case ZEND_JMPZ: /* fallthrough */
187             case ZEND_JMPNZ:
188             case ZEND_JMPZ_EX:
189             case ZEND_JMPNZ_EX:
190 #ifdef ZEND_ENGINE_2_3
191             case ZEND_JMP_SET:
192 #endif
193                 FIXUP(base, opline->op2.u.jmp_addr);
194                 break;
195             }
196             ZEND_VM_SET_OPCODE_HANDLER(opline);
197         }
198     }
199     FIXUP(base, from->brk_cont_array);
200     FIXUP(base, from->try_catch_array);
201     if (from->static_variables != NULL) {
202         FIXUP(base, from->static_variables);
203         fixup_zval_hash(base, from->static_variables);
204     }
205     if (from->vars != NULL) {
206         int i;
207         FIXUP(base, from->vars);
208         for (i = 0; i < from->last_var; i++) {
209             FIXUP(base, from->vars[i].name);
210         }
211     }
212     FIXUP(base, from->filename);
213 #ifdef INCLUDE_DOC_COMMENTS
214     FIXUP(base, from->doc_comment);
215 #endif
216 }
217
218 static void fixup_class_entry(char *base, ea_class_entry *from TSRMLS_DC)
219 {
220     FIXUP(base, from->name);
221     FIXUP(base, from->parent);
222     FIXUP(base, from->filename);
223     fixup_zval_hash(base, &from->constants_table);
224     fixup_zval_hash(base, &from->default_properties);
225     fixup_hash(base, &from->properties_info,
226                (fixup_bucket_t) fixup_property_info TSRMLS_CC);
227     fixup_zval_hash(base, &from->default_static_members);
228     if (from->static_members != NULL) {
229         FIXUP(base, from->static_members);
230         if (from->static_members != &from->default_static_members) {
231             fixup_zval_hash(base, from->static_members);
232         }
233     }
234     fixup_hash(base, &from->function_table,(fixup_bucket_t) fixup_op_array TSRMLS_CC);
235 }
236
237 void eaccelerator_fixup(ea_cache_entry *p TSRMLS_DC)
238 {
239     ea_fc_entry *q;
240     char *base;
241
242     base = (char *) ((long) p - (long) p->next);
243     p->next = NULL;
244     FIXUP(base, p->op_array);
245     FIXUP(base, p->f_head);
246     FIXUP(base, p->c_head);
247     fixup_op_array(base, p->op_array TSRMLS_CC);
248     q = p->f_head;
249     while (q != NULL) {
250         FIXUP(base, q->fc);
251         fixup_op_array(base, (ea_op_array *) q->fc TSRMLS_CC);
252         FIXUP(base, q->next);
253         q = q->next;
254     }
255     q = p->c_head;
256     while (q != NULL) {
257         FIXUP(base, q->fc);
258         fixup_class_entry(base, (ea_class_entry *) q->fc TSRMLS_CC);
259         FIXUP(base, q->next);
260         q = q->next;
261     }
262 }
263
264 /******************************************************************************/
265 /* Functions to restore a php script from shared memory                       */
266 /******************************************************************************/
267
268 typedef void *(*restore_bucket_t) (void *TSRMLS_DC);
269
270 #define restore_zval_hash(target, source) \
271     restore_hash(target, source, (restore_bucket_t)restore_zval_ptr TSRMLS_CC)
272
273 static zval *restore_zval_ptr(zval * from TSRMLS_DC)
274 {
275     zval *p;
276     ALLOC_ZVAL(p);
277     memcpy(p, from, sizeof(zval));
278     restore_zval(p TSRMLS_CC);
279     /* hrak: reset refcount to make sure there is one reference to this val, and prevent memleaks */
280 #ifdef ZEND_ENGINE_2_3
281     Z_SET_REFCOUNT_P(p, 1);
282 #else
283     p->refcount = 1;
284 #endif
285     return p;
286 }
287
288 static HashTable *restore_hash(HashTable * target, HashTable * source,
289                                restore_bucket_t copy_bucket TSRMLS_DC)
290 {
291     Bucket *p, *np, *prev_p;
292     int nIndex;
293
294     if (target == NULL) {
295         ALLOC_HASHTABLE(target);
296     }
297     memcpy(target, source, sizeof(HashTable));
298     target->arBuckets =
299         (Bucket **) emalloc(target->nTableSize * sizeof(Bucket *));
300     memset(target->arBuckets, 0, target->nTableSize * sizeof(Bucket *));
301     target->pDestructor = NULL;
302     target->persistent = 0;
303     target->pListHead = NULL;
304     target->pListTail = NULL;
305 #if HARDENING_PATCH_HASH_PROTECT
306     target->canary = zend_hash_canary;
307 #endif
308
309     p = source->pListHead;
310     prev_p = NULL;
311     np = NULL;
312     while (p) {
313         np = (Bucket *) emalloc(offsetof(Bucket, arKey) + p->nKeyLength);
314         /*    np = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength); */
315         nIndex = p->h % source->nTableSize;
316         if (target->arBuckets[nIndex]) {
317             np->pNext = target->arBuckets[nIndex];
318             np->pLast = NULL;
319             np->pNext->pLast = np;
320         } else {
321             np->pNext = NULL;
322             np->pLast = NULL;
323         }
324         target->arBuckets[nIndex] = np;
325         np->h = p->h;
326         np->nKeyLength = p->nKeyLength;
327
328         if (p->pDataPtr == NULL) {
329             np->pData = copy_bucket(p->pData TSRMLS_CC);
330             np->pDataPtr = NULL;
331         } else {
332             np->pDataPtr = copy_bucket(p->pDataPtr TSRMLS_CC);
333             np->pData = &np->pDataPtr;
334         }
335         np->pListLast = prev_p;
336         np->pListNext = NULL;
337
338         memcpy(np->arKey, p->arKey, p->nKeyLength);
339
340         if (prev_p) {
341             prev_p->pListNext = np;
342         } else {
343             target->pListHead = np;
344         }
345         prev_p = np;
346         p = p->pListNext;
347     }
348     target->pListTail = np;
349     target->pInternalPointer = target->pListHead;
350     return target;
351 }
352
353 void restore_zval(zval * zv TSRMLS_DC)
354 {
355     switch (EA_ZV_TYPE_P(zv)) {
356     case IS_CONSTANT:
357     case IS_OBJECT:
358     case IS_STRING:
359         if (Z_STRVAL_P(zv) == NULL || Z_STRVAL_P(zv) == "" || Z_STRLEN_P(zv) == 0) {
360             Z_STRLEN_P(zv) = 0;
361             Z_STRVAL_P(zv) = empty_string;
362             return;
363         } else {
364             char *p = emalloc(Z_STRLEN_P(zv) + 1);
365             memcpy(p, Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1);
366             Z_STRVAL_P(zv) = p;
367         }
368         return;
369
370     case IS_ARRAY:
371     case IS_CONSTANT_ARRAY:
372         if (Z_ARRVAL_P(zv) != NULL && Z_ARRVAL_P(zv) != &EG(symbol_table)) {
373             Z_ARRVAL_P(zv) = restore_zval_hash(NULL, Z_ARRVAL_P(zv));
374             Z_ARRVAL_P(zv)->pDestructor = ZVAL_PTR_DTOR;
375         }
376         return;
377     }
378 }
379
380 static void call_op_array_ctor_handler(zend_extension * extension,
381                                        zend_op_array * op_array TSRMLS_DC)
382 {
383     if (extension->op_array_ctor) {
384         extension->op_array_ctor(op_array);
385     }
386 }
387
388 zend_op_array *restore_op_array(zend_op_array * to, ea_op_array * from TSRMLS_DC)
389 {
390     union {
391         zend_function *v;
392         void *ptr;
393     } function;
394     int fname_len = 0;
395     char *fname_lc = NULL;
396
397     DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
398     DBG(ea_debug_printf, (EA_DEBUG, "[%d] restore_op_array: %s type=%x\n", getpid(),
399                     from->function_name ? from->function_name : "(top)", from->type));
400
401     if (from->type == ZEND_INTERNAL_FUNCTION) {
402         if (to == NULL) {
403             to = emalloc(sizeof(zend_internal_function));
404         }
405         memset(to, 0, sizeof(zend_internal_function));
406     } else {
407         if (to == NULL) {
408             to = emalloc(sizeof(zend_op_array));
409         }
410         memset(to, 0, sizeof(zend_op_array));
411         if (ZendOptimizer) {
412             zend_llist_apply_with_argument(&zend_extensions,
413                     (llist_apply_with_arg_func_t) call_op_array_ctor_handler, to TSRMLS_CC);
414         }
415     }
416     to->type = from->type;
417     to->num_args = from->num_args;
418     to->required_num_args = from->required_num_args;
419     to->arg_info = from->arg_info;
420     to->pass_rest_by_reference = from->pass_rest_by_reference;
421     to->function_name = from->function_name;
422
423     if (to->function_name) {
424         fname_len = strlen(to->function_name);
425         fname_lc = zend_str_tolower_dup(to->function_name, fname_len);
426     }
427
428     to->fn_flags = from->fn_flags;
429
430     /* segv74:
431      * to->scope = EAG(class_entry)
432      *
433      * if  from->scope_name == NULL,
434      *     ; EAG(class) == NULL  : we are in function or outside function.
435      *     ; EAG(class) != NULL  : inherited method not defined in current file, should have to find.
436      *                              just LINK (zend_op_array *) to to original entry in parent,
437      *                              but, with what? !!! I don't know PARENT CLASS NAME !!!!
438      *
439      *
440      * if  from->scope_name != NULL,
441      *     ; we are in class member function
442      *
443      *     ; we have to find appropriate (zend_class_entry*) to->scope for name from->scope_name
444      *     ; if we find in CG(class_table), link to it.
445      *     ; if fail, it should be EAG(class_entry)
446      *   
447      * am I right here ? ;-(
448      */
449     if (from->scope_name != NULL) {
450         union {
451             zend_class_entry *v;
452             void *ptr;
453         } scope;
454         char *from_scope_lc = zend_str_tolower_dup(from->scope_name, from->scope_name_len);
455         scope.v = to->scope;
456         if (zend_hash_find (CG(class_table), (void *) from_scope_lc, from->scope_name_len + 1, &scope.ptr) == SUCCESS &&
457                 to->scope != NULL) {
458             DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
459             DBG(ea_debug_printf, (EA_DEBUG, "[%d]                   found '%s' in hash\n", getpid(), from->scope_name));
460             DBG(ea_debug_printf, (EA_DEBUG, "name=%s :: to->scope is 0x%x", to->function_name, (unsigned int) to->scope));
461             to->scope = *(zend_class_entry **) to->scope;
462         } else {
463             DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
464             DBG(ea_debug_printf, (EA_DEBUG, "[%d]                   can't find '%s' in class_table. use EAG(class_entry).\n", getpid(), from->scope_name));
465             to->scope = EAG(class_entry);
466         }
467         efree(from_scope_lc);
468     } else {
469         DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
470         DBG(ea_debug_printf, (EA_DEBUG, "[%d]                   from is NULL\n", getpid()));
471         if (EAG(class_entry)) {
472             zend_class_entry *p;
473             for (p = EAG(class_entry)->parent; p; p = p->parent) {
474                 DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
475                 DBG(ea_debug_printf, (EA_DEBUG, "[%d]                   checking parent '%s' have '%s'\n", getpid(), p->name, fname_lc));
476                 if (zend_hash_find(&p->function_table, fname_lc, fname_len + 1, &function.ptr) == SUCCESS) {
477                     DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
478                     DBG(ea_debug_printf, (EA_DEBUG, "[%d]                                   '%s' has '%s' of scope '%s'\n",
479                             getpid(), p->name, fname_lc, function.v->common.scope->name));
480                     to->scope = function.v->common.scope;
481                     break;
482                 }
483             }
484         } else {
485             to->scope = NULL;
486         }
487     }
488
489     DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
490     DBG(ea_debug_printf, (EA_DEBUG, "[%d]                   %s's scope is '%s'\n", getpid(),
491             from->function_name ? from->function_name : "(top)", to->scope ? to->scope->name : "NULL"));
492     if (from->type == ZEND_INTERNAL_FUNCTION) {
493         zend_class_entry *class_entry = EAG(class_entry);
494         DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
495         DBG(ea_debug_printf, (EA_DEBUG, "[%d]                   [internal function from=%08x,to=%08x] class_entry='%s' [%08x]\n",
496                 getpid(), from, to, class_entry->name, class_entry));
497         if (class_entry) {
498             DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
499             DBG(ea_debug_printf, (EA_DEBUG, "[%d]                                       class_entry->parent='%s' [%08x]\n",
500                     getpid(), class_entry->parent->name, class_entry->parent));
501         }
502         if (class_entry != NULL && class_entry->parent != NULL &&
503                 zend_hash_find(&class_entry->parent->function_table,
504                 fname_lc, fname_len + 1,
505                 &function.ptr) == SUCCESS && function.v->type == ZEND_INTERNAL_FUNCTION) {
506             DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
507             DBG(ea_debug_printf, (EA_DEBUG, "[%d]                                       found in function table\n", getpid()));
508             ((zend_internal_function *) (to))->handler = ((zend_internal_function *) function.v)->handler;
509         } else {
510             /* FIXME. I don't know how to fix handler.
511              * TODO: must solve this somehow, to avoid returning damaged structure...
512              */
513             DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
514             DBG(ea_debug_printf, (EA_DEBUG, "[%d]                                       can't find\n", getpid()));
515         }       
516         /* hrak: slight memleak here. dont forget to free the lowercase function name! */
517         if (fname_lc != NULL) {
518             efree(fname_lc);
519         }
520         /* zend_internal_function also contains return_reference in ZE2 */
521         to->return_reference = from->return_reference;
522         /* this gets set by zend_do_inheritance */
523         to->prototype = NULL;
524         return to;
525     }
526     /* hrak: slight memleak here. dont forget to free the lowercase function name! */
527     if (fname_lc != NULL) {
528         efree(fname_lc);
529     }
530     to->opcodes = from->opcodes;
531     to->last = to->size = from->last;
532     to->T = from->T;
533     to->brk_cont_array = from->brk_cont_array;
534     to->last_brk_cont = from->last_brk_cont;
535
536     to->current_brk_cont = -1;
537     to->static_variables = from->static_variables;
538     to->backpatch_count  = 0;
539
540     to->return_reference = from->return_reference;
541     to->done_pass_two = 1;
542     to->filename = from->filename;
543
544     to->try_catch_array = from->try_catch_array;
545     to->last_try_catch = from->last_try_catch;
546 #ifdef ZEND_ENGINE_2_3
547     to->this_var = from->this_var;
548     to->early_binding = from->early_binding;
549 #else
550     to->uses_this = from->uses_this;
551 #endif
552
553     to->line_start = from->line_start;
554     to->line_end = from->line_end;
555 #ifdef INCLUDE_DOC_COMMENTS
556     to->doc_comment_len = from->doc_comment_len;
557     to->doc_comment = from->doc_comment;
558 #else
559     to->doc_comment_len = 0;
560     to->doc_comment = NULL;
561 #endif
562     if (from->static_variables) {
563         to->static_variables = restore_zval_hash(NULL, from->static_variables);
564         to->static_variables->pDestructor = ZVAL_PTR_DTOR;
565     }
566
567     to->vars             = from->vars;
568     to->last_var         = from->last_var;
569     to->size_var         = 0;
570
571     /* disable deletion in destroy_op_array */
572     ++EAG(refcount_helper);
573     to->refcount = &EAG(refcount_helper);
574
575     return to;
576 }
577
578 static zend_op_array *restore_op_array_ptr(ea_op_array *from TSRMLS_DC)
579 {
580     return restore_op_array(NULL, from TSRMLS_CC);
581 }
582
583 static zend_property_info *restore_property_info(zend_property_info *
584                                                  from TSRMLS_DC)
585 {
586     zend_property_info *to = emalloc(sizeof(zend_property_info));
587     memcpy(to, from, sizeof(zend_property_info));
588     to->name = emalloc(from->name_length + 1);
589     memcpy(to->name, from->name, from->name_length + 1);
590 #ifdef INCLUDE_DOC_COMMENTS
591     if (from->doc_comment != NULL) {
592         to->doc_comment = emalloc(from->doc_comment_len + 1);
593         memcpy(to->doc_comment, from->doc_comment, from->doc_comment_len + 1);
594     }
595 #endif
596 #ifdef ZEND_ENGINE_2_2
597     to->ce = EAG(class_entry);
598 #endif
599     return to;
600 }
601
602 /* restore the parent class with the given name for the given class */
603 static void restore_class_parent(char *parent, int len, zend_class_entry * to TSRMLS_DC)
604 {
605     zend_class_entry** parent_ptr = NULL;
606     if (zend_lookup_class(parent, len, &parent_ptr TSRMLS_CC) != SUCCESS)
607     {
608         ea_debug_error("[%d] EACCELERATOR can't restore parent class \"%s\" of class \"%s\"\n", getpid(), (char *) parent, to->name);
609         to->parent = NULL;
610     } else {
611         /* parent found */
612         to->parent = *parent_ptr;
613         DBG(ea_debug_printf, (EA_DEBUG, "restore_class_parent: found parent %s..\n", to->parent->name));
614         DBG(ea_debug_printf, (EA_DEBUG, "restore_class_parent: parent type=%d child type=%d\n", to->parent->type, to->type));
615     }
616 }
617
618 static void restore_class_methods(zend_class_entry * to TSRMLS_DC)
619 {
620     int cname_len = to->name_length;
621     char *cname_lc = zend_str_tolower_dup(to->name, cname_len);
622     int fname_len = 0;
623     char *fname_lc = NULL;
624     zend_function *f = NULL;
625     Bucket *p = to->function_table.pListHead;
626
627     to->constructor = NULL;
628
629     while (p != NULL) {
630         f = p->pData;
631         fname_len = strlen(f->common.function_name);
632         fname_lc = zend_str_tolower_dup(f->common.function_name, fname_len);
633        
634         /* only put the function that has the same name as the class as contructor if there isn't a __construct function */
635         if (fname_len == cname_len && !memcmp(fname_lc, cname_lc, fname_len) && f->common.scope != to->parent
636                 && to->constructor == NULL) {
637             to->constructor = f;
638         } else if (fname_lc[0] == '_' && fname_lc[1] == '_' && f->common.scope != to->parent) {
639             if (fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1 &&
640                     memcmp(fname_lc, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)) == 0)
641                 to->constructor = f;
642             else if (fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 &&
643                      memcmp(fname_lc, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) == 0)
644                 to->destructor = f;
645             else if (fname_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 &&
646                      memcmp(fname_lc, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) == 0)
647                 to->clone = f;
648             else if (fname_len == sizeof(ZEND_GET_FUNC_NAME) - 1 &&
649                      memcmp(fname_lc, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) == 0)
650                 to->__get = f;
651             else if (fname_len == sizeof(ZEND_SET_FUNC_NAME) - 1 &&
652                      memcmp(fname_lc, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) == 0)
653                 to->__set = f;
654             else if (fname_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 &&
655                     memcmp(fname_lc, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)) == 0)
656                 to->__unset = f;
657             else if (fname_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 &&
658                     memcmp(fname_lc, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)) == 0)
659                 to->__isset = f;
660             else if (fname_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 &&
661                      memcmp(fname_lc, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) == 0)
662                 to->__call = f;
663 ifdef ZEND_ENGINE_2_3
664             else if (fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
665                      memcmp(fname_lc, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)) == 0)
666                 to->__callstatic = f;
667 endif
668 ifdef ZEND_ENGINE_2_2
669             else if (fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
670                      memcmp(fname_lc, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)) == 0)
671                 to->__tostring = f;
672 endif
673         }
674         if (to->parent) {
675             /* clear the child's prototype and IMPLEMENTED_ABSTRACT flag,
676                these are properly restored by zend_do_inheritance() (see do_inherit_method_check) */
677             f->common.prototype = NULL;
678             f->common.fn_flags = f->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
679         }
680         efree(fname_lc);
681         p = p->pListNext;
682     }
683     efree(cname_lc);
684 }
685
686 static zend_class_entry *restore_class_entry(zend_class_entry * to, ea_class_entry * from TSRMLS_DC)
687 {
688     zend_class_entry *old;
689
690     DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
691     DBG(ea_debug_printf, (EA_DEBUG, "[%d] restore_class_entry: %s\n", getpid(), from->name ? from->name : "(top)"));
692 #ifdef DEBUG
693     EAG(xpad)++;
694 #endif
695     if (to == NULL) {
696         to = emalloc(sizeof(zend_class_entry));
697     }
698     memset(to, 0, sizeof(zend_class_entry));
699     to->type = from->type;
700
701     if (from->name != NULL) {
702         to->name_length = from->name_length;
703         to->name = emalloc(from->name_length + 1);
704         memcpy(to->name, from->name, from->name_length + 1);
705     }
706
707     old = EAG(class_entry);
708     EAG(class_entry) = to;
709
710     to->ce_flags = from->ce_flags;
711     to->num_interfaces = from->num_interfaces;
712     to->interfaces = NULL;
713     to->refcount = 1;
714     to->line_start = from->line_start;
715     to->line_end = from->line_end;
716    
717     if (to->num_interfaces > 0) {
718         /* hrak: Allocate the slots which will later be populated by ZEND_ADD_INTERFACE */
719         to->interfaces = (zend_class_entry **) emalloc(sizeof(zend_class_entry *) * to->num_interfaces);
720         memset(to->interfaces, 0, sizeof(zend_class_entry *) * to->num_interfaces);
721     }
722 #ifdef INCLUDE_DOC_COMMENTS
723     to->doc_comment_len = from->doc_comment_len;
724     if (from->doc_comment != NULL) {
725         to->doc_comment = emalloc(from->doc_comment_len + 1);
726         memcpy(to->doc_comment, from->doc_comment, from->doc_comment_len + 1);
727     }
728 #else
729     to->doc_comment_len = 0;
730     to->doc_comment = NULL;
731 #endif
732
733     to->filename = from->filename;
734
735     /* restore constants table */
736     restore_zval_hash(&to->constants_table, &from->constants_table);
737     to->constants_table.pDestructor = ZVAL_PTR_DTOR;
738    
739     /* restore properties */
740     restore_hash(&to->properties_info, &from->properties_info, (restore_bucket_t) restore_property_info TSRMLS_CC);
741     to->properties_info.pDestructor = properties_info_dtor;
742
743     /* restore default properties */
744     restore_zval_hash(&to->default_properties, &from->default_properties);
745     to->default_properties.pDestructor = ZVAL_PTR_DTOR;
746
747     /* restore default_static_members */
748     restore_zval_hash(&to->default_static_members, &from->default_static_members);
749     to->default_static_members.pDestructor = ZVAL_PTR_DTOR;
750    
751     if (from->static_members != &(from->default_static_members)) {
752         ALLOC_HASHTABLE(to->static_members);
753         restore_zval_hash(to->static_members, from->static_members);
754         to->static_members->pDestructor = ZVAL_PTR_DTOR;
755     } else {
756         to->static_members = &(to->default_static_members);
757     }
758
759     if (from->parent != NULL) {
760         restore_class_parent(from->parent, strlen(from->parent), to TSRMLS_CC);
761     } else {
762         DBG(ea_debug_pad, (EA_DEBUG TSRMLS_CC));
763         DBG(ea_debug_printf, (EA_DEBUG, "[%d] parent = NULL\n", getpid()));
764         to->parent = NULL;
765     }
766
767     restore_hash(&to->function_table, &from->function_table, (restore_bucket_t)restore_op_array_ptr TSRMLS_CC);
768     to->function_table.pDestructor = ZEND_FUNCTION_DTOR;
769
770     restore_class_methods(to TSRMLS_CC);
771
772     if (to->parent) {
773         zend_do_inheritance(to, to->parent TSRMLS_CC);
774     }
775     EAG(class_entry) = old;
776
777 #ifdef DEBUG
778     EAG(xpad)--;
779 #endif
780     return to;
781 }
782
783 void restore_function(ea_fc_entry * p TSRMLS_DC)
784 {
785     zend_op_array op_array;
786
787     if ((p->htabkey[0] == '\000') && zend_hash_exists(CG(function_table), p->htabkey, p->htablen)) {
788         return;
789     }
790     if (restore_op_array(&op_array, (ea_op_array *) p->fc TSRMLS_CC) != NULL) {
791         if (zend_hash_add(CG(function_table), p->htabkey, p->htablen, &op_array, sizeof(zend_op_array), NULL) == FAILURE) {
792             CG(in_compilation) = 1;
793             CG(compiled_filename) = EAG(mem);
794             CG(zend_lineno) = op_array.line_start;
795             zend_error(E_ERROR, "Cannot redeclare %s()", p->htabkey);
796         }
797     }
798 }
799
800 /*
801  * Class handling.
802  */
803 void restore_class(ea_fc_entry * p TSRMLS_DC)
804 {
805     zend_class_entry *ce;
806
807     if ((p->htabkey[0] == '\000') && zend_hash_exists(CG(class_table), p->htabkey, p->htablen)) {
808         return;
809     }
810     ce = restore_class_entry(NULL, (ea_class_entry *) p->fc TSRMLS_CC);
811     if (ce != NULL)
812     {
813         if (zend_hash_add(CG(class_table), p->htabkey, p->htablen, &ce, sizeof(zend_class_entry *), NULL) == FAILURE)
814         {
815             CG(in_compilation) = 1;
816             CG(compiled_filename) = EAG(mem);
817             CG(zend_lineno) = ce->line_start;
818             zend_error(E_ERROR, "Cannot redeclare class %s", p->htabkey);
819         }
820     }
821 }
822
823 #endif /* HAVE_EACCELERATOR */
Note: See TracBrowser for help on using the browser.