source: eaccelerator/trunk/ea_dasm.c @ 344

Revision 344, 22.3 KB checked in by bart, 2 years ago (diff)

Remove support for all php versions older than php 5.1

  • 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 - 2007 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 "ea_dasm.h"
29#include "eaccelerator.h"
30#include "opcodes.h"
31#include "zend.h"
32
33#ifdef WITH_EACCELERATOR_DISASSEMBLER
34
35extern eaccelerator_mm *eaccelerator_mm_instance;
36
37/* {{{ static const char *extopnames_declare[] */
38static const char *extopnames_declare[] = {
39        "",                                                     /* 0 */
40        "DECLARE_CLASS",                        /* 1 */
41        "DECLARE_FUNCTION",                     /* 2 */
42        "DECLARE_INHERITED_CLASS"       /* 3 */
43};
44/* }}} */
45
46/* {{{ static const char *extopnames_cast[] */
47static const char *extopnames_cast[] = {
48        "IS_NULL",                                      /* 0 */
49        "IS_LONG",                                      /* 1 */
50        "IS_DOUBLE",                            /* 2 */
51        "IS_STRING",                            /* 3 */
52        "IS_ARRAY",                                     /* 4 */
53        "IS_OBJECT",                            /* 5 */
54        "IS_BOOL",                                      /* 6 */
55        "IS_RESOURCE",                          /* 7 */
56        "IS_CONSTANT",                          /* 8 */
57        "IS_CONSTANT_ARRAY"                     /* 9 */
58};
59/* }}} */
60
61/* {{{ static const char *extopnames_fetch[] */
62static const char *extopnames_fetch[] = {
63        "FETCH_STANDARD",                       /* 0 */
64        "FETCH_ADD_LOCK"                        /* 1 */
65};
66/* }}} */
67
68/* {{{ static const char *extopnames_fetch_class[] */
69static const char *extopnames_fetch_class[] = {
70        "FETCH_CLASS_DEFAULT",          /* 0 */
71        "FETCH_CLASS_SELF",                     /* 1 */
72        "FETCH_CLASS_PARENT",           /* 2 */
73        "FETCH_CLASS_MAIN",                     /* 3 */
74        "FETCH_CLASS_GLOBAL",           /* 4 */
75        "FETCH_CLASS_AUTO"                      /* 5 */
76};
77/* }}} */
78
79/* {{{ static const char *extopnames_init_fcall[] */
80static const char *extopnames_init_fcall[] = {
81        "",                                             /* 0 */
82        "MEMBER_FUNC_CALL",                     /* 1 */
83        "CTOR_CALL",                            /* 2 */
84        "CTOR_CALL"                                     /* 3 */
85};
86/* }}} */
87
88/* {{{ static const char *extopnames_sendnoref[] */
89static const char *extopnames_sendnoref[] = {
90        " ",                                       /* 0 */
91        "ARG_SEND_BY_REF",                      /* 1 */
92        "ARG_COMPILE_TIME_BOUND",       /* 2 */
93        "ARG_SEND_BY_REF | ZEND_ARG_COMPILE_TIME_BOUND" /* 3 */
94};
95/* }}} */
96
97/* {{{ static const char *fetchtypename[] */
98static const char *fetchtypename[] = {
99        "FETCH_GLOBAL",                         /* 0 */
100        "FETCH_LOCAL",                          /* 1 */
101        "FETCH_STATIC",                         /* 2 */
102        "FETCH_STATIC_MEMBER",          /* 3 */
103    "UNKNOWN 1"                 /* 4 */
104};
105/* }}} */
106
107/* {{{ static const char *extopnames_fe[] */
108static const char *extopnames_fe[] = {
109        "",                                                     /* 0 */
110        "FE_FETCH_BYREF",                       /* 1 */
111        "FE_FETCH_WITH_KEY"                     /* 2 */
112};
113/* }}} */
114
115/* {{{ get_zval: create a string from the given zval */
116static char *get_zval(zval *v)
117{
118    char *str = NULL;
119    char buf[512];
120    size_t size;
121
122    switch (Z_TYPE_P(v) & ~IS_CONSTANT_INDEX) {
123        case IS_NULL:
124            str = emalloc(sizeof("null"));
125            strncpy(str, "null", sizeof("null"));
126            break;
127        case IS_LONG:
128            snprintf(buf, sizeof(buf), "long(%ld)", Z_LVAL_P(v));
129            str = emalloc(strlen(buf) + 1);
130            strcpy(str, buf);
131            break;
132        case IS_DOUBLE:
133            snprintf(buf, sizeof(buf), "double(%e)", Z_DVAL_P(v));
134            str = emalloc(strlen(buf) + 1);
135            strcpy(str, buf);
136            break;
137        case IS_STRING:
138            size = Z_STRLEN_P(v) + 1 + sizeof("string('')");
139            str = emalloc(size);
140            snprintf(str, size, "string('%s')", Z_STRVAL_P(v));
141            break;
142        case IS_BOOL:
143            if (Z_LVAL_P(v)) {
144                str = emalloc(sizeof("bool(true)"));
145                strcpy(str, "bool(true)");
146            } else {
147                str = emalloc(sizeof("bool(false)"));
148                strcpy(str, "bool(false)");
149            }
150            break;
151        case IS_ARRAY:
152            str = emalloc(sizeof("array(?)"));
153            strcpy(str, "array(?)");
154            break;
155        case IS_OBJECT:
156            str = emalloc(sizeof("object(?)"));
157            strcpy(str, "object(?)");
158            break;
159        case IS_RESOURCE:
160            str = emalloc(sizeof("resource(?)"));
161            strcpy(str, "resource(?)");
162            break;
163        case IS_CONSTANT:
164            size = Z_STRLEN_P(v) + 1 + sizeof("constant('')");
165            str = emalloc(size);
166            snprintf(str, size, "constant('%s')", Z_STRVAL_P(v));
167            break;
168        case IS_CONSTANT_ARRAY:
169            str = emalloc(sizeof("constant_array(?)"));
170            strcpy(str, "constant_array(?)");
171            break;
172        default:
173            snprintf(buf, sizeof(buf), "unknown(type=%d)", Z_TYPE_P(v));
174            str = emalloc(strlen(buf) + 1);
175            strcpy(str, buf);
176    }
177    return str;
178}
179/* }}} */
180
181/* {{{ get_op_array: return a php array with the given op_array structure
182 * array() { [0] .. [n] =>
183 *      array () {
184 *                      [lineno]                => // the line number in the source code
185 *          [opcode]        => // the opcode
186 *          [extended_value]=> // the extended value field
187 *          [op1]           => // the first opcode
188 *          [op2]           => // the second opcode
189 *          [result]        => // the result
190 *      }
191 * }
192 */
193static zval *get_op_array(ea_op_array *op_array TSRMLS_DC)
194{
195    zval *return_value;
196    MAKE_STD_ZVAL(return_value);
197    array_init(return_value);
198
199    if (op_array->opcodes) {
200        zend_op *opline;
201        zend_op *end;
202       
203        opline = op_array->opcodes;
204        end = opline + op_array->last;
205
206        for (; opline < end; ++opline) {
207            zval *el;
208            char buf[512];
209            const opcode_dsc *op = get_opcode_dsc(opline->opcode);
210            int zval_used = 0;
211
212            MAKE_STD_ZVAL(el);
213            array_init(el);
214
215                        /* lineno */
216                        add_assoc_long(el, "lineno", opline->lineno);
217           
218            /* opname */
219            if (op != NULL) {
220                add_assoc_string(el, "opcode", (char *)op->opname, 1);
221            } else {
222                snprintf(buf, sizeof(buf), "UNKNOWN OPCODE %d", opline->opcode);
223                add_assoc_string(el, "opcode", buf, 1);
224            }
225
226            /* extended value */
227            if ((op->ops & EXT_MASK) == EXT_OPLINE) {
228                snprintf(buf, sizeof(buf), "opline(%lu)", opline->extended_value);
229            } else if ((op->ops & EXT_MASK) == EXT_FCALL) {
230                snprintf(buf, sizeof(buf), "args(%lu)", opline->extended_value);
231            } else if ((op->ops & EXT_MASK) == EXT_ARG) {
232                snprintf(buf, sizeof(buf), "arg(%lu)", opline->extended_value);
233            } else if ((op->ops & EXT_MASK) == EXT_SEND) {
234                strncpy(buf, get_opcode_dsc(opline->extended_value)->opname, sizeof(buf));
235            } else if ((op->ops & EXT_MASK) == EXT_CAST) {
236                strncpy(buf, extopnames_cast[opline->extended_value], sizeof(buf));
237            } else if ((op->ops & EXT_MASK) == EXT_INIT_FCALL) {
238                strncpy(buf, extopnames_init_fcall[opline->extended_value], sizeof(buf));
239            } else if ((op->ops & EXT_MASK) == EXT_FETCH) {
240                strncpy(buf, extopnames_fetch[opline->extended_value], sizeof(buf));
241            } else if ((op->ops & EXT_MASK) == EXT_FE) {
242                strncpy(buf, extopnames_fe[opline->extended_value], sizeof(buf));
243            } else if ((op->ops & EXT_MASK) == EXT_DECLARE) {
244                strncpy(buf, extopnames_declare[opline->extended_value], sizeof(buf));
245            } else if ((op->ops & EXT_MASK) == EXT_SEND_NOREF) {
246                strncpy(buf, extopnames_sendnoref[opline->extended_value], sizeof(buf));
247            } else if ((op->ops & EXT_MASK) == EXT_FCLASS) {
248                // XXX: hack to prevent segfault
249                snprintf(buf, sizeof(buf), "%s", extopnames_fetch_class[opline->extended_value]);
250            } else if ((op->ops & EXT_MASK) == EXT_IFACE) {
251                snprintf(buf, sizeof(buf), "interface(%lu)", opline->extended_value);
252            } else if ((op->ops & EXT_MASK) == EXT_CLASS) {
253                snprintf(buf, sizeof(buf), "$class%u", VAR_NUM(opline->extended_value));
254            } else if ((op->ops & EXT_MASK) == EXT_BIT) {
255                if (opline->extended_value) {
256                    snprintf(buf, sizeof(buf), "true");
257                } else {
258                    snprintf(buf, sizeof(buf), "false");
259                }
260            } else if ((op->ops & EXT_MASK) == EXT_ISSET) {
261                if (opline->extended_value == ZEND_ISSET) {
262                    snprintf(buf, sizeof(buf), "ZEND_ISSET");
263                } else if (opline->extended_value == ZEND_ISEMPTY) {
264                    snprintf(buf, sizeof(buf), "ZEND_ISEMPTY");
265                } else {
266                                        buf[0] = '\0';
267                }
268            } else if ((op->ops & EXT_MASK) == EXT_ASSIGN) {
269                if (opline->extended_value == ZEND_ASSIGN_OBJ) {
270                    snprintf(buf, sizeof(buf), "ZEND_ASSIGN_OBJ");
271                } else if (opline->extended_value == ZEND_ASSIGN_DIM) {
272                    snprintf(buf, sizeof(buf), "ZEND_ASSIGN_DIM");
273                } else {
274                                        buf[0] = '\0';
275                }
276            } else if (opline->extended_value != 0) {
277                snprintf(buf, sizeof(buf), "%ld", opline->extended_value);
278            } else {
279                                buf[0] = '\0';
280            }
281            add_assoc_string(el, "extended_value", buf, 1);
282
283            /* op1 */
284            zval_used = 0;
285            if (opline->op1.op_type == IS_CV) {
286                snprintf(buf, sizeof(buf), "$cv%u(%s)", opline->op1.u.var, op_array->vars[opline->op1.u.var].name);
287            } else if ((op->ops & OP1_MASK) == OP1_OPLINE) {
288                snprintf(buf, sizeof(buf), "opline(%d)", opline->op1.u.opline_num);
289            } else if ((op->ops & OP1_MASK) == OP1_JMPADDR) {
290                snprintf(buf, sizeof(buf), "opline(%u)", (unsigned int)(opline->op1.u.jmp_addr - op_array->opcodes));
291            } else if ((op->ops & OP1_MASK) == OP1_CLASS) {
292                snprintf(buf, sizeof(buf), "$class%u", VAR_NUM(opline->op1.u.var));
293            } else if ((op->ops & OP1_MASK) == OP1_UCLASS) {
294                if (opline->op1.op_type == IS_UNUSED) {
295                                        buf[0] = '\0';
296                } else {
297                    snprintf(buf, sizeof(buf), "$class%u", VAR_NUM(opline->op1.u.var));
298                }
299            } else if ((op->ops & OP1_MASK) == OP1_BRK) {
300                if (opline->op1.u.opline_num != -1 && opline->op2.op_type == IS_CONST && opline->op2.u.constant.type == IS_LONG) {
301                    int level = opline->op2.u.constant.value.lval;
302                    zend_uint offset = opline->op1.u.opline_num;
303                    zend_brk_cont_element *jmp_to;
304                    do {
305                        if (offset >= op_array->last_brk_cont) {
306                            goto brk_failed;
307                        }
308                                                jmp_to = &op_array->brk_cont_array[offset];
309                        offset = jmp_to->parent;
310                    } while (--level > 0);
311                    snprintf(buf, sizeof(buf), "opline(%d)", jmp_to->brk);
312                } else {
313brk_failed:
314                    snprintf(buf, sizeof(buf), "brk_cont(%u)", opline->op1.u.opline_num);
315                }
316            } else if ((op->ops & OP1_MASK) == OP1_CONT) {
317                if (opline->op1.u.opline_num != -1 && opline->op2.op_type == IS_CONST && opline->op2.u.constant.type == IS_LONG) {
318                    int level = opline->op2.u.constant.value.lval;
319                    zend_uint offset = opline->op1.u.opline_num;
320                    zend_brk_cont_element *jmp_to;
321                    do {
322                        if (offset >= op_array->last_brk_cont) {
323                            goto cont_failed;
324                        }
325                        jmp_to = &op_array->brk_cont_array[offset];
326                        offset = jmp_to->parent;
327                    } while (--level > 0);
328                    snprintf(buf, sizeof(buf), "opline(%d)", jmp_to->cont);
329                } else {
330cont_failed:
331                    snprintf(buf, sizeof(buf), "brk_cont(%u)", opline->op1.u.opline_num);
332                }
333            } else if ((op->ops & OP1_MASK) == OP1_ARG) {
334                snprintf(buf, sizeof(buf), "arg(%ld)", opline->op1.u.constant.value.lval);
335            } else if ((op->ops & OP1_MASK) == OP1_VAR) {
336                snprintf(buf, sizeof(buf), "$var%u", VAR_NUM(opline->op1.u.var));
337            } else if ((op->ops & OP1_MASK) == OP1_TMP) {
338                snprintf(buf, sizeof(buf), "$tmp%u", VAR_NUM(opline->op1.u.var));
339            } else {
340                if (opline->op1.op_type == IS_CONST) {
341                    zval_used = 1;
342                    add_assoc_string(el, "op1", get_zval(&opline->op1.u.constant), 0);
343                } else if (opline->op1.op_type == IS_TMP_VAR) {
344                    snprintf(buf, sizeof(buf), "$tmp%u", VAR_NUM(opline->op1.u.var));
345                } else if (opline->op1.op_type == IS_VAR) {
346                    snprintf(buf, sizeof(buf), "$var%u", VAR_NUM(opline->op1.u.var));
347                } else if (opline->op1.op_type == IS_UNUSED) {
348                                        buf[0] = '\0';
349                } else {
350                    snprintf(buf, sizeof(buf), "UNKNOWN NODE %d", opline->op1.op_type);
351                }
352            }
353            if (zval_used == 0) {
354                add_assoc_string(el, "op1", buf, 1);
355            }
356
357            /* op2 */
358            zval_used = 0;
359            if (opline->op2.op_type == IS_CV) {
360                snprintf(buf, sizeof(buf), "$cv%u(%s)", opline->op2.u.var, op_array->vars[opline->op2.u.var].name);
361            } else if ((op->ops & OP2_MASK) == OP2_OPLINE) {
362                                snprintf(buf, sizeof(buf), "opline(%d)", opline->op2.u.opline_num);
363                        } else if ((op->ops & OP2_MASK) == OP2_JMPADDR) {
364                                snprintf(buf, sizeof(buf), "opline(%u)", (unsigned int) (opline->op2.u.jmp_addr - op_array->opcodes));
365                        } else if ((op->ops & OP2_MASK) == OP2_CLASS) {
366                                snprintf(buf, sizeof(buf), "$class%u", VAR_NUM(opline->op2.u.var));
367                        } else if ((op->ops & OP2_MASK) == OP2_VAR) {
368                                snprintf(buf, sizeof(buf), "$var%u", VAR_NUM(opline->op2.u.var));
369                        } else if ((op->ops & OP2_MASK) == OP2_FETCH) {
370                                if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
371                                        snprintf(buf, sizeof(buf), "%s $class%u", fetchtypename[opline->op2.u.EA.type], VAR_NUM(opline->op2.u.var));
372                                } else {
373                                        snprintf(buf, sizeof(buf), "%s", fetchtypename[opline->op2.u.EA.type]);
374                                }
375                        } else if ((op->ops & OP2_MASK) == OP2_INCLUDE) {
376                                if (opline->op2.u.constant.value.lval == ZEND_EVAL) {
377                                        snprintf(buf, sizeof(buf), "ZEND_EVAL");
378                                } else if (opline->op2.u.constant.value.lval == ZEND_INCLUDE) {
379                    snprintf(buf, sizeof(buf), "ZEND_INCLUDE");
380                                } else if (opline->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE) {
381                                        snprintf(buf, sizeof(buf), "ZEND_INCLUDE_ONCE");
382                                } else if (opline->op2.u.constant.value.lval == ZEND_REQUIRE) {
383                                    snprintf(buf, sizeof(buf), "ZEND_REQUIRE");
384                                } else if (opline->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE) {
385                                        snprintf(buf, sizeof(buf), "ZEND_REQUIRE_ONCE");
386                                } else {
387                                        buf[0] = '\0';
388                                }
389                        } else if ((op->ops & OP2_MASK) == OP2_ARG) {
390                            snprintf(buf, sizeof(buf), "arg(%u)", opline->op2.u.opline_num);
391                        } else if ((op->ops & OP2_MASK) == OP2_ISSET) {
392                                if (opline->op2.u.constant.value.lval == ZEND_ISSET) {
393                                        snprintf(buf, sizeof(buf), "ZEND_ISSET");
394                                } else if (opline->op2.u.constant.value.lval == ZEND_ISEMPTY) {
395                                        snprintf(buf, sizeof(buf), "ZEND_ISEMPTY");
396                                } else {
397                                        buf[0] = '\0';
398                                }
399                        } else {
400                if (opline->op2.op_type == IS_CONST) {
401                    zval_used = 1;
402                    add_assoc_string(el, "op2", get_zval(&opline->op2.u.constant), 0);
403                } else if (opline->op2.op_type == IS_TMP_VAR) {
404                                        snprintf(buf, sizeof(buf), "$tmp%u", VAR_NUM(opline->op2.u.var));
405                                } else if (opline->op2.op_type == IS_VAR) {
406                                        snprintf(buf, sizeof(buf), "$var%u", VAR_NUM(opline->op2.u.var));
407                                } else if (opline->op2.op_type == IS_UNUSED) {
408                                        buf[0] = '\0';
409                                } else {
410                                        snprintf(buf, sizeof(buf), "UNKNOWN NODE %d", opline->op2.op_type);
411                                }
412                        }
413            if (zval_used == 0) {
414                add_assoc_string(el, "op2", buf, 1);
415            }
416
417            /* result */
418            zval_used = 0;
419            if (opline->result.op_type == IS_CV) {
420                snprintf(buf, sizeof(buf), "$cv%u(%s)", opline->result.u.var, op_array->vars[opline->result.u.var].name);
421            } else
422                        switch (op->ops & RES_MASK) {
423                            case RES_STD:
424                                if (opline->result.op_type == IS_CONST) {
425                        zval_used = 1;
426                        add_assoc_string(el, "result", get_zval(&opline->result.u.constant), 0);
427                                } else if (opline->result.op_type == IS_TMP_VAR) {
428                                        snprintf(buf, sizeof(buf), "$tmp%u", VAR_NUM(opline->result.u.var));
429                    } else if (opline->result.op_type == IS_VAR) {
430                                        if ((opline->result.u.EA.type & EXT_TYPE_UNUSED) != 0) {
431                                                snprintf(buf, sizeof(buf), "$var%u (unused)", VAR_NUM(opline->result.u.var));
432                        } else {
433                                                snprintf(buf, sizeof(buf), "$var%u", VAR_NUM(opline->result.u.var));
434                        }
435                                } else if (opline->result.op_type == IS_UNUSED) {
436                                                buf[0] = '\0';
437                                } else {
438                                        snprintf(buf, sizeof(buf), "UNKNOWN NODE %d", opline->result.op_type);
439                                }
440                                break;
441                        case RES_CLASS:
442                                snprintf(buf, sizeof(buf), "$class%u", VAR_NUM(opline->result.u.var));
443                                break;
444                        case RES_TMP:
445                                snprintf(buf, sizeof(buf), "$tmp%u", VAR_NUM(opline->result.u.var));
446                                break;
447                        case RES_VAR:
448                                if ((opline->result.u.EA.type & EXT_TYPE_UNUSED) != 0) {
449                                        snprintf(buf, sizeof(buf), "$var%u (unused)", VAR_NUM(opline->result.u.var));
450                                } else {
451                                        snprintf(buf, sizeof(buf), "$var%u", VAR_NUM(opline->result.u.var));
452                                }
453                                break;
454                        case RES_UNUSED:
455                                        buf[0] = '\0';
456                                break;
457                        default:
458                                snprintf(buf, sizeof(buf), "UNKNOWN NODE %d", opline->result.op_type);
459                                break;
460                        }
461            if (zval_used == 0) {
462                add_assoc_string(el, "result", buf, 1);
463            }
464
465            add_next_index_zval(return_value, el);
466        }
467    }
468    return return_value;
469}
470/* }}} */
471
472/* {{{ get_cache_entry: get the cache_entry for the given file */
473static ea_cache_entry *get_cache_entry(const char *file) {
474    unsigned int slot;
475    ea_cache_entry *p;
476    ea_cache_entry *result = NULL;
477   
478        if (file != NULL) {
479                EACCELERATOR_UNPROTECT();
480                EACCELERATOR_LOCK_RD();
481                EACCELERATOR_PROTECT();
482                for (slot = 0; slot < EA_HASH_SIZE; slot++) {
483                        p = eaccelerator_mm_instance->hash[slot];
484                        while (p != NULL) {
485                                if (strcmp(p->realfilename, file) == 0) {
486                                        result = p;
487                                }
488                                p = p->next;
489                        }
490                }
491            EACCELERATOR_UNPROTECT();
492                EACCELERATOR_UNLOCK_RD();
493                EACCELERATOR_PROTECT();
494    }
495    return result;
496}
497/* }}} */
498
499/* {{{ PHP_FUNCTION(eaccelerator_dasm_file): get the op_arrays from a file that's cached
500 * This function will return an array with this elements:
501 * array() {
502 *      [op_array] => array() // the op_array
503 *      [classes]  => array() { // an array with classes
504 *          [class1] => array() { // an array with class methods
505 *                  [method1] => array() // the op_array of that method
506 *              }
507 *          }
508 *      [functions]=> array() {
509 *          [function1] => array() // the op_array of that function
510 *      }
511 */
512PHP_FUNCTION(eaccelerator_dasm_file)
513{
514    const char *file;
515    int file_len;
516        ea_cache_entry *p;
517    ea_fc_entry *fc;
518    zval *functions;
519    zval *classes;
520
521    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE)
522                return;
523
524        if (eaccelerator_mm_instance == NULL || php_check_open_basedir(file TSRMLS_CC)) {
525                RETURN_NULL();
526        }
527
528    p = get_cache_entry(file);
529    if (p == NULL) {
530        RETURN_NULL();
531    }
532 
533    array_init(return_value);
534   
535    /* file op_array */
536    add_assoc_zval(return_value, "op_array", get_op_array(p->op_array TSRMLS_CC));
537
538    /* file functions */
539        fc = p->f_head;
540    MAKE_STD_ZVAL(functions);
541    array_init(functions);
542        while (fc != NULL) {
543        add_assoc_zval(functions, fc->htabkey, get_op_array((ea_op_array *)fc->fc TSRMLS_CC));
544                fc = fc->next;
545        }
546    add_assoc_zval(return_value, "functions", functions);
547
548    /* file classes */
549        fc = p->c_head;
550    MAKE_STD_ZVAL(classes);
551    array_init(classes);
552        if (fc != NULL) {
553                while (fc != NULL) {
554                        ea_class_entry *c = (ea_class_entry *) fc->fc;
555            if (c->type == ZEND_USER_CLASS) { /* get methods */
556                zval *methods;
557                Bucket *q;
558
559                MAKE_STD_ZVAL(methods);
560                array_init(methods);
561                q = c->function_table.pListHead;
562                while (q) {
563                    ea_op_array *func = (ea_op_array *) q->pData;
564                    if (func->type == ZEND_USER_FUNCTION) {
565                        add_assoc_zval(methods, func->function_name, get_op_array(func TSRMLS_CC));
566                    }
567                    q = q->pListNext;
568                }
569                add_assoc_zval(classes, c->name, methods);
570            }
571            fc = fc->next;
572                }
573        }
574    add_assoc_zval(return_value, "classes", classes);
575}
576/* }}} */
577
578#endif
579
580/*
581 * Local variables:
582 * tab-width: 4
583 * c-basic-offset: 4
584 * End:
585 * vim600: noet sw=4 ts=4 fdm=marker
586 * vim<600: noet sw=4 ts=4
587 */
588
Note: See TracBrowser for help on using the repository browser.