source: eaccelerator/tags/0.9.4-rc1/ea_restore.c @ 127

Revision 127, 28.2 KB checked in by zoeloelip, 5 years ago (diff)

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
50extern zend_extension *ZendOptimizer;
51#if HARDENING_PATCH_HASH_PROTECT
52extern unsigned int zend_hash_canary;
53#endif
54
55#ifdef ZEND_ENGINE_2
56/* pointer to the properties_info hashtable destructor */
57dtor_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 */
61dtor_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
86typedef 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
92static void fixup_property_info(zend_property_info * from TSRMLS_DC)
93{
94        FIXUP(from->name);
95}
96#endif
97
98static 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
136void 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
172void 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
243void 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
269typedef 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
274static 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
283static 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
348void 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
426static 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
434zend_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
622static 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
629static 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 */
641void 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
677void 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
722zend_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
857void 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 */
881void 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 repository browser.