root/eaccelerator/trunk/ea_dasm.c

Revision 355, 23.8 kB (checked in by bart, 1 month ago)

Fix disassembler

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