root/eaccelerator/tags/0.9.5/ea_dasm.c

Revision 261, 23.2 kB (checked in by bart, 2 years ago)

ea_info and ea_dasm: if eaccelerator_mm_instance is NULL, just return

null and don't do something.

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