root/eaccelerator/trunk/ea_dasm.c

Revision 377, 26.1 kB (checked in by hans, 6 months ago)

* Some more work on delayed early binding. This fixes ticket #388
* Some reformatting in ea_dasm.c

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