root/sapi/phpdbg/phpdbg_info.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHPDBG_INFO
  2. PHPDBG_INFO
  3. PHPDBG_INFO
  4. PHPDBG_INFO
  5. phpdbg_arm_auto_global
  6. phpdbg_print_symbols
  7. PHPDBG_INFO
  8. PHPDBG_INFO
  9. PHPDBG_INFO
  10. PHPDBG_INFO
  11. phpdbg_print_class_name
  12. PHPDBG_INFO
  13. PHPDBG_INFO

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Felipe Pena <felipe@php.net>                                |
  16    | Authors: Joe Watkins <joe.watkins@live.co.uk>                        |
  17    | Authors: Bob Weinand <bwoebi@php.net>                                |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 #include "php.h"
  22 #include "phpdbg.h"
  23 #include "phpdbg_utils.h"
  24 #include "phpdbg_info.h"
  25 #include "phpdbg_bp.h"
  26 #include "phpdbg_prompt.h"
  27 
  28 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
  29 
  30 #define PHPDBG_INFO_COMMAND_D(f, h, a, m, l, s, flags) \
  31         PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[13], flags)
  32 
  33 const phpdbg_command_t phpdbg_info_commands[] = {
  34         PHPDBG_INFO_COMMAND_D(break,     "show breakpoints",              'b', info_break,     NULL, 0, PHPDBG_ASYNC_SAFE),
  35         PHPDBG_INFO_COMMAND_D(files,     "show included files",           'F', info_files,     NULL, 0, PHPDBG_ASYNC_SAFE),
  36         PHPDBG_INFO_COMMAND_D(classes,   "show loaded classes",           'c', info_classes,   NULL, 0, PHPDBG_ASYNC_SAFE),
  37         PHPDBG_INFO_COMMAND_D(funcs,     "show loaded classes",           'f', info_funcs,     NULL, 0, PHPDBG_ASYNC_SAFE),
  38         PHPDBG_INFO_COMMAND_D(error,     "show last error",               'e', info_error,     NULL, 0, PHPDBG_ASYNC_SAFE),
  39         PHPDBG_INFO_COMMAND_D(constants, "show user defined constants",   'd', info_constants, NULL, 0, PHPDBG_ASYNC_SAFE),
  40         PHPDBG_INFO_COMMAND_D(vars,      "show active variables",         'v', info_vars,      NULL, 0, PHPDBG_ASYNC_SAFE),
  41         PHPDBG_INFO_COMMAND_D(globals,   "show superglobals",             'g', info_globals,   NULL, 0, PHPDBG_ASYNC_SAFE),
  42         PHPDBG_INFO_COMMAND_D(literal,   "show active literal constants", 'l', info_literal,   NULL, 0, PHPDBG_ASYNC_SAFE),
  43         PHPDBG_INFO_COMMAND_D(memory,    "show memory manager stats",     'm', info_memory,    NULL, 0, PHPDBG_ASYNC_SAFE),
  44         PHPDBG_END_COMMAND
  45 };
  46 
  47 PHPDBG_INFO(break) /* {{{ */
  48 {
  49         phpdbg_print_breakpoints(PHPDBG_BREAK_FILE);
  50         phpdbg_print_breakpoints(PHPDBG_BREAK_SYM);
  51         phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD);
  52         phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE);
  53         phpdbg_print_breakpoints(PHPDBG_BREAK_FILE_OPLINE);
  54         phpdbg_print_breakpoints(PHPDBG_BREAK_FUNCTION_OPLINE);
  55         phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD_OPLINE);
  56         phpdbg_print_breakpoints(PHPDBG_BREAK_COND);
  57         phpdbg_print_breakpoints(PHPDBG_BREAK_OPCODE);
  58 
  59         return SUCCESS;
  60 } /* }}} */
  61 
  62 PHPDBG_INFO(files) /* {{{ */
  63 {
  64         zend_string *fname;
  65 
  66         phpdbg_try_access {
  67                 phpdbg_notice("includedfilecount", "num=\"%d\"", "Included files: %d", zend_hash_num_elements(&EG(included_files)));
  68         } phpdbg_catch_access {
  69                 phpdbg_error("signalsegv", "", "Could not fetch included file count, invalid data source");
  70                 return SUCCESS;
  71         } phpdbg_end_try_access();
  72 
  73         phpdbg_try_access {
  74                 ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), fname) {
  75                         phpdbg_writeln("includedfile", "name=\"%s\"", "File: %s", ZSTR_VAL(fname));
  76                 } ZEND_HASH_FOREACH_END();
  77         } phpdbg_catch_access {
  78                 phpdbg_error("signalsegv", "", "Could not fetch file name, invalid data source, aborting included file listing");
  79         } phpdbg_end_try_access();
  80 
  81         return SUCCESS;
  82 } /* }}} */
  83 
  84 PHPDBG_INFO(error) /* {{{ */
  85 {
  86         if (PG(last_error_message)) {
  87                 phpdbg_try_access {
  88                         phpdbg_writeln("lasterror", "error=\"%s\" file=\"%s\" line=\"%d\"", "Last error: %s at %s line %d", PG(last_error_message), PG(last_error_file), PG(last_error_lineno));
  89                 } phpdbg_catch_access {
  90                         phpdbg_notice("lasterror", "error=\"\"", "No error found!");
  91                 } phpdbg_end_try_access();
  92         } else {
  93                 phpdbg_notice("lasterror", "error=\"\"", "No error found!");
  94         }
  95         return SUCCESS;
  96 } /* }}} */
  97 
  98 PHPDBG_INFO(constants) /* {{{ */
  99 {
 100         HashTable consts;
 101         zend_constant *data;
 102 
 103         zend_hash_init(&consts, 8, NULL, NULL, 0);
 104 
 105         if (EG(zend_constants)) {
 106                 phpdbg_try_access {
 107                         ZEND_HASH_FOREACH_PTR(EG(zend_constants), data) {
 108                                 if (data->module_number == PHP_USER_CONSTANT) {
 109                                         zend_hash_update_ptr(&consts, data->name, data);
 110                                 }
 111                         } ZEND_HASH_FOREACH_END();
 112                 } phpdbg_catch_access {
 113                         phpdbg_error("signalsegv", "", "Cannot fetch all the constants, invalid data source");
 114                 } phpdbg_end_try_access();
 115         }
 116 
 117         phpdbg_notice("constantinfo", "num=\"%d\"", "User-defined constants (%d)", zend_hash_num_elements(&consts));
 118 
 119         if (zend_hash_num_elements(&consts)) {
 120                 phpdbg_out("Address            Refs    Type      Constant\n");
 121                 ZEND_HASH_FOREACH_PTR(&consts, data) {
 122 
 123 #define VARIABLEINFO(attrs, msg, ...) \
 124         phpdbg_writeln("constant", \
 125                 "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, \
 126                 "%-18p %-7d %-9s %.*s" msg, &data->value, \
 127                 Z_REFCOUNTED(data->value) ? Z_REFCOUNT(data->value) : 1, \
 128                 zend_zval_type_name(&data->value), \
 129                 (int) ZSTR_LEN(data->name), ZSTR_VAL(data->name), ##__VA_ARGS__)
 130 
 131                         switch (Z_TYPE(data->value)) {
 132                                 case IS_STRING:
 133                                         phpdbg_try_access {
 134                                                 VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN(data->value), Z_STRLEN(data->value) < 255 ? (int) Z_STRLEN(data->value) : 255, Z_STRVAL(data->value), Z_STRLEN(data->value) > 255 ? "..." : "");
 135                                         } phpdbg_catch_access {
 136                                                 VARIABLEINFO("", "");
 137                                         } phpdbg_end_try_access();
 138                                         break;
 139                                 case IS_TRUE:
 140                                         VARIABLEINFO("value=\"true\"", "\nbool (true)");
 141                                         break;
 142                                 case IS_FALSE:
 143                                         VARIABLEINFO("value=\"false\"", "\nbool (false)");
 144                                         break;
 145                                 case IS_LONG:
 146                                         VARIABLEINFO("value=\"%ld\"", "\nint (%ld)", Z_LVAL(data->value));
 147                                         break;
 148                                 case IS_DOUBLE:
 149                                         VARIABLEINFO("value=\"%lf\"", "\ndouble (%lf)", Z_DVAL(data->value));
 150                                         break;
 151                                 default:
 152                                         VARIABLEINFO("", "");
 153 
 154 #undef VARIABLEINFO
 155                         }
 156                 } ZEND_HASH_FOREACH_END();
 157         }
 158 
 159         return SUCCESS;
 160 } /* }}} */
 161 
 162 static int phpdbg_arm_auto_global(zval *ptrzv) {
 163         zend_auto_global *auto_global = Z_PTR_P(ptrzv);
 164 
 165         if (auto_global->armed) {
 166                 if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
 167                         phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", (int) ZSTR_LEN(auto_global->name), ZSTR_VAL(auto_global->name));
 168                 } else {
 169                         auto_global->armed = auto_global->auto_global_callback(auto_global->name);
 170                 }
 171         }
 172 
 173         return 0;
 174 }
 175 
 176 static int phpdbg_print_symbols(zend_bool show_globals) {
 177         HashTable vars;
 178         zend_array *symtable;
 179         zend_string *var;
 180         zval *data;
 181 
 182         if (!EG(current_execute_data) || !EG(current_execute_data)->func) {
 183                 phpdbg_error("inactive", "type=\"op_array\"", "No active op array!");
 184                 return SUCCESS;
 185         }
 186 
 187         if (show_globals) {
 188                 /* that array should only be manipulated during init, so safe for async access during execution */
 189                 zend_hash_apply(CG(auto_globals), (apply_func_t) phpdbg_arm_auto_global);
 190                 symtable = &EG(symbol_table);
 191         } else if (!(symtable = zend_rebuild_symbol_table())) {
 192                 phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!");
 193                 return SUCCESS;
 194         }
 195 
 196         zend_hash_init(&vars, 8, NULL, NULL, 0);
 197 
 198         phpdbg_try_access {
 199                 ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, var, data) {
 200                         if (zend_is_auto_global(var) ^ !show_globals) {
 201                                 zend_hash_update(&vars, var, data);
 202                         }
 203                 } ZEND_HASH_FOREACH_END();
 204         } phpdbg_catch_access {
 205                 phpdbg_error("signalsegv", "", "Cannot fetch all data from the symbol table, invalid data source");
 206         } phpdbg_end_try_access();
 207 
 208         if (show_globals) {
 209                 phpdbg_notice("variableinfo", "num=\"%d\"", "Superglobal variables (%d)", zend_hash_num_elements(&vars));
 210         } else {
 211                 zend_op_array *ops = &EG(current_execute_data)->func->op_array;
 212 
 213                 if (ops->function_name) {
 214                         if (ops->scope) {
 215                                 phpdbg_notice("variableinfo", "method=\"%s::%s\" num=\"%d\"", "Variables in %s::%s() (%d)", ops->scope->name->val, ops->function_name->val, zend_hash_num_elements(&vars));
 216                         } else {
 217                                 phpdbg_notice("variableinfo", "function=\"%s\" num=\"%d\"", "Variables in %s() (%d)", ZSTR_VAL(ops->function_name), zend_hash_num_elements(&vars));
 218                         }
 219                 } else {
 220                         if (ops->filename) {
 221                                 phpdbg_notice("variableinfo", "file=\"%s\" num=\"%d\"", "Variables in %s (%d)", ZSTR_VAL(ops->filename), zend_hash_num_elements(&vars));
 222                         } else {
 223                                 phpdbg_notice("variableinfo", "opline=\"%p\" num=\"%d\"", "Variables @ %p (%d)", ops, zend_hash_num_elements(&vars));
 224                         }
 225                 }
 226         }
 227 
 228         if (zend_hash_num_elements(&vars)) {
 229                 phpdbg_out("Address            Refs    Type      Variable\n");
 230                 ZEND_HASH_FOREACH_STR_KEY_VAL(&vars, var, data) {
 231                         phpdbg_try_access {
 232                                 const char *isref = "";
 233 #define VARIABLEINFO(attrs, msg, ...) \
 234         phpdbg_writeln("variable", \
 235                 "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%.*s\" " attrs, \
 236                 "%-18p %-7d %-9s %s$%.*s" msg, data, Z_REFCOUNTED_P(data) ? Z_REFCOUNT_P(data) : 1, zend_zval_type_name(data), isref, (int) ZSTR_LEN(var), ZSTR_VAL(var), ##__VA_ARGS__)
 237 retry_switch:
 238                                 switch (Z_TYPE_P(data)) {
 239                                         case IS_RESOURCE:
 240                                                 phpdbg_try_access {
 241                                                         const char *type = zend_rsrc_list_get_rsrc_type(Z_RES_P(data));
 242                                                         VARIABLEINFO("type=\"%s\"", "\n|-------(typeof)------> (%s)\n", type ? type : "unknown");
 243                                                 } phpdbg_catch_access {
 244                                                         VARIABLEINFO("type=\"unknown\"", "\n|-------(typeof)------> (unknown)\n");
 245                                                 } phpdbg_end_try_access();
 246                                                 break;
 247                                         case IS_OBJECT:
 248                                                 phpdbg_try_access {
 249                                                         VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", ZSTR_VAL(Z_OBJCE_P(data)->name));
 250                                                 } phpdbg_catch_access {
 251                                                         VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (unknown)\n");
 252                                                 } phpdbg_end_try_access();
 253                                                 break;
 254                                         case IS_STRING:
 255                                                 phpdbg_try_access {
 256                                                         VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN_P(data), Z_STRLEN_P(data) < 255 ? (int) Z_STRLEN_P(data) : 255, Z_STRVAL_P(data), Z_STRLEN_P(data) > 255 ? "..." : "");
 257                                                 } phpdbg_catch_access {
 258                                                         VARIABLEINFO("", "");
 259                                                 } phpdbg_end_try_access();
 260                                                 break;
 261                                         case IS_TRUE:
 262                                                 VARIABLEINFO("value=\"true\"", "\nbool (true)");
 263                                                 break;
 264                                         case IS_FALSE:
 265                                                 VARIABLEINFO("value=\"false\"", "\nbool (false)");
 266                                                 break;
 267                                         case IS_LONG:
 268                                                 VARIABLEINFO("value=\"%ld\"", "\nint (%ld)", Z_LVAL_P(data));
 269                                                 break;
 270                                         case IS_DOUBLE:
 271                                                 VARIABLEINFO("value=\"%lf\"", "\ndouble (%lf)", Z_DVAL_P(data));
 272                                                 break;
 273                                         case IS_REFERENCE:
 274                                                 isref = "&";
 275                                                 data = Z_REFVAL_P(data);
 276                                                 goto retry_switch;
 277                                         case IS_INDIRECT:
 278                                                 data = Z_INDIRECT_P(data);
 279                                                 goto retry_switch;
 280                                         default:
 281                                                 VARIABLEINFO("", "");
 282                                 }
 283 
 284 #undef VARIABLEINFO
 285                         } phpdbg_catch_access {
 286                                 phpdbg_writeln("variable", "address=\"%p\" name=\"%s\"", "%p\tn/a\tn/a\t$%s", data, ZSTR_VAL(var));
 287                         } phpdbg_end_try_access();
 288                 } ZEND_HASH_FOREACH_END();
 289         }
 290 
 291         zend_hash_destroy(&vars);
 292 
 293         return SUCCESS;
 294 } /* }}} */
 295 
 296 PHPDBG_INFO(vars) /* {{{ */
 297 {
 298         return phpdbg_print_symbols(0);
 299 }
 300 
 301 PHPDBG_INFO(globals) /* {{{ */
 302 {
 303         return phpdbg_print_symbols(1);
 304 }
 305 
 306 PHPDBG_INFO(literal) /* {{{ */
 307 {
 308         /* literals are assumed to not be manipulated during executing of their op_array and as such async safe */
 309         zend_bool in_executor = PHPDBG_G(in_execution) && EG(current_execute_data) && EG(current_execute_data)->func;
 310         if (in_executor || PHPDBG_G(ops)) {
 311                 zend_op_array *ops = in_executor ? &EG(current_execute_data)->func->op_array : PHPDBG_G(ops);
 312                 int literal = 0, count = ops->last_literal - 1;
 313 
 314                 if (ops->function_name) {
 315                         if (ops->scope) {
 316                                 phpdbg_notice("literalinfo", "method=\"%s::%s\" num=\"%d\"", "Literal Constants in %s::%s() (%d)", ops->scope->name->val, ops->function_name->val, count);
 317                         } else {
 318                                 phpdbg_notice("literalinfo", "function=\"%s\" num=\"%d\"", "Literal Constants in %s() (%d)", ops->function_name->val, count);
 319                         }
 320                 } else {
 321                         if (ops->filename) {
 322                                 phpdbg_notice("literalinfo", "file=\"%s\" num=\"%d\"", "Literal Constants in %s (%d)", ZSTR_VAL(ops->filename), count);
 323                         } else {
 324                                 phpdbg_notice("literalinfo", "opline=\"%p\" num=\"%d\"", "Literal Constants @ %p (%d)", ops, count);
 325                         }
 326                 }
 327 
 328                 while (literal < ops->last_literal) {
 329                         if (Z_TYPE(ops->literals[literal]) != IS_NULL) {
 330                                 phpdbg_write("literal", "id=\"%u\"", "|-------- C%u -------> [", literal);
 331                                 zend_print_zval(&ops->literals[literal], 0);
 332                                 phpdbg_out("]\n");
 333                         }
 334                         literal++;
 335                 }
 336         } else {
 337                 phpdbg_error("inactive", "type=\"execution\"", "Not executing!");
 338         }
 339 
 340         return SUCCESS;
 341 } /* }}} */
 342 
 343 PHPDBG_INFO(memory) /* {{{ */
 344 {
 345         size_t used, real, peak_used, peak_real;
 346         zend_mm_heap *heap;
 347         zend_bool is_mm;
 348 
 349         if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
 350                 heap = zend_mm_set_heap(phpdbg_original_heap_sigsafe_mem());
 351         }
 352         if ((is_mm = is_zend_mm())) {
 353                 used = zend_memory_usage(0);
 354                 real = zend_memory_usage(1);
 355                 peak_used = zend_memory_peak_usage(0);
 356                 peak_real = zend_memory_peak_usage(1);
 357         }
 358         if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
 359                 zend_mm_set_heap(heap);
 360         }
 361 
 362         if (is_mm) {
 363                 phpdbg_notice("meminfo", "", "Memory Manager Information");
 364                 phpdbg_notice("current", "", "Current");
 365                 phpdbg_writeln("used", "mem=\"%.3f\"", "|-------> Used:\t%.3f kB", (float) (used / 1024));
 366                 phpdbg_writeln("real", "mem=\"%.3f\"", "|-------> Real:\t%.3f kB", (float) (real / 1024));
 367                 phpdbg_notice("peak", "", "Peak");
 368                 phpdbg_writeln("used", "mem=\"%.3f\"", "|-------> Used:\t%.3f kB", (float) (peak_used / 1024));
 369                 phpdbg_writeln("real", "mem=\"%.3f\"", "|-------> Real:\t%.3f kB", (float) (peak_real / 1024));
 370         } else {
 371                 phpdbg_error("inactive", "type=\"memory_manager\"", "Memory Manager Disabled!");
 372         }
 373         return SUCCESS;
 374 } /* }}} */
 375 
 376 static inline void phpdbg_print_class_name(zend_class_entry *ce) /* {{{ */
 377 {
 378         const char *visibility = ce->type == ZEND_USER_CLASS ? "User" : "Internal";
 379         const char *type = (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : (ce->ce_flags & ZEND_ACC_ABSTRACT) ? "Abstract Class" : "Class";
 380 
 381         phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%.*s\" methodcount=\"%d\"", "%s %s %.*s (%d)", visibility, type, (int) ZSTR_LEN(ce->name), ZSTR_VAL(ce->name), zend_hash_num_elements(&ce->function_table));
 382 } /* }}} */
 383 
 384 PHPDBG_INFO(classes) /* {{{ */
 385 {
 386         zend_class_entry *ce;
 387         HashTable classes;
 388 
 389         zend_hash_init(&classes, 8, NULL, NULL, 0);
 390 
 391         phpdbg_try_access {
 392                 ZEND_HASH_FOREACH_PTR(EG(class_table), ce) {
 393                         if (ce->type == ZEND_USER_CLASS) {
 394                                 zend_hash_next_index_insert_ptr(&classes, ce);
 395                         }
 396                 } ZEND_HASH_FOREACH_END();
 397         } phpdbg_catch_access {
 398                 phpdbg_notice("signalsegv", "", "Not all classes could be fetched, possibly invalid data source");
 399         } phpdbg_end_try_access();
 400 
 401         phpdbg_notice("classinfo", "num=\"%d\"", "User Classes (%d)", zend_hash_num_elements(&classes));
 402 
 403         /* once added, assume that classes are stable... until shutdown. */
 404         ZEND_HASH_FOREACH_PTR(&classes, ce) {
 405                 phpdbg_print_class_name(ce);
 406 
 407                 if (ce->parent) {
 408                         zend_class_entry *pce;
 409                         phpdbg_xml("<parents %r>");
 410                         pce = ce->parent;
 411                         do {
 412                                 phpdbg_out("|-------- ");
 413                                 phpdbg_print_class_name(pce);
 414                         } while ((pce = pce->parent));
 415                         phpdbg_xml("</parents>");
 416                 }
 417 
 418                 if (ce->info.user.filename) {
 419                         phpdbg_writeln("classsource", "file=\"%s\" line=\"%u\"", "|---- in %s on line %u", ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start);
 420                 } else {
 421                         phpdbg_writeln("classsource", "", "|---- no source code");
 422                 }
 423         } ZEND_HASH_FOREACH_END();
 424 
 425         zend_hash_destroy(&classes);
 426 
 427         return SUCCESS;
 428 } /* }}} */
 429 
 430 PHPDBG_INFO(funcs) /* {{{ */
 431 {
 432         zend_function *zf;
 433         HashTable functions;
 434 
 435         zend_hash_init(&functions, 8, NULL, NULL, 0);
 436 
 437         phpdbg_try_access {
 438                 ZEND_HASH_FOREACH_PTR(EG(function_table), zf) {
 439                         if (zf->type == ZEND_USER_FUNCTION) {
 440                                 zend_hash_next_index_insert_ptr(&functions, zf);
 441                         }
 442                 } ZEND_HASH_FOREACH_END();
 443         } phpdbg_catch_access {
 444                 phpdbg_notice("signalsegv", "", "Not all functions could be fetched, possibly invalid data source");
 445         } phpdbg_end_try_access();
 446 
 447         phpdbg_notice("functioninfo", "num=\"%d\"", "User Functions (%d)", zend_hash_num_elements(&functions));
 448 
 449         ZEND_HASH_FOREACH_PTR(&functions, zf) {
 450                 zend_op_array *op_array = &zf->op_array;
 451 
 452                 phpdbg_write("function", "name=\"%s\"", "|-------- %s", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "{main}");
 453 
 454                 if (op_array->filename) {
 455                         phpdbg_writeln("functionsource", "file=\"%s\" line=\"%d\"", " in %s on line %d", ZSTR_VAL(op_array->filename), op_array->line_start);
 456                 } else {
 457                         phpdbg_writeln("functionsource", "", " (no source code)");
 458                 }
 459         } ZEND_HASH_FOREACH_END();
 460 
 461         zend_hash_destroy(&functions);
 462 
 463         return SUCCESS;
 464 } /* }}} */

/* [<][>][^][v][top][bottom][index][help] */