php-src/phpdbg_info.c

354 lines
13 KiB
C
Raw Normal View History

2013-11-17 15:42:34 +00:00
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
2014-01-17 22:09:07 +00:00
| Copyright (c) 1997-2014 The PHP Group |
2013-11-17 15:42:34 +00:00
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Felipe Pena <felipe@php.net> |
| Authors: Joe Watkins <joe.watkins@live.co.uk> |
| Authors: Bob Weinand <bwoebi@php.net> |
2013-11-17 15:42:34 +00:00
+----------------------------------------------------------------------+
*/
#include "php.h"
2013-11-22 09:56:17 +00:00
#include "phpdbg.h"
2013-11-17 15:42:34 +00:00
#include "phpdbg_utils.h"
#include "phpdbg_info.h"
#include "phpdbg_bp.h"
#include "phpdbg_prompt.h"
2013-11-17 15:42:34 +00:00
2013-11-22 09:56:17 +00:00
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
#define PHPDBG_INFO_COMMAND_D(f, h, a, m, l, s) \
PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[14])
const phpdbg_command_t phpdbg_info_commands[] = {
PHPDBG_INFO_COMMAND_D(break, "show breakpoints", 'b', info_break, NULL, 0),
PHPDBG_INFO_COMMAND_D(files, "show included files", 'F', info_files, NULL, 0),
PHPDBG_INFO_COMMAND_D(classes, "show loaded classes", 'c', info_classes, NULL, 0),
PHPDBG_INFO_COMMAND_D(funcs, "show loaded classes", 'f', info_funcs, NULL, 0),
PHPDBG_INFO_COMMAND_D(error, "show last error", 'e', info_error, NULL, 0),
PHPDBG_INFO_COMMAND_D(vars, "show active variables", 'v', info_vars, NULL, 0),
2014-09-23 14:48:37 +00:00
PHPDBG_INFO_COMMAND_D(globals, "show superglobals", 'g', info_globals, NULL, 0),
PHPDBG_INFO_COMMAND_D(literal, "show active literal constants", 'l', info_literal, NULL, 0),
PHPDBG_INFO_COMMAND_D(memory, "show memory manager stats", 'm', info_memory, NULL, 0),
PHPDBG_END_COMMAND
};
PHPDBG_INFO(break) /* {{{ */
{
phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_SYM TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC);
2013-12-02 20:56:25 +00:00
phpdbg_print_breakpoints(PHPDBG_BREAK_FILE_OPLINE TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_FUNCTION_OPLINE TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD_OPLINE TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC);
phpdbg_print_breakpoints(PHPDBG_BREAK_OPCODE TSRMLS_CC);
return SUCCESS;
} /* }}} */
2013-11-17 15:42:34 +00:00
PHPDBG_INFO(files) /* {{{ */
{
2013-11-26 10:02:58 +00:00
HashPosition pos;
char *fname;
2013-11-17 15:42:34 +00:00
2014-09-21 02:17:19 +00:00
phpdbg_notice("includedfilecount", "num=\"%d\"", "Included files: %d",
2013-11-17 15:42:34 +00:00
zend_hash_num_elements(&EG(included_files)));
zend_hash_internal_pointer_reset_ex(&EG(included_files), &pos);
while (zend_hash_get_current_key_ex(&EG(included_files), &fname,
NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("includedfile", "name=\"%s\"", "File: %s", fname);
2013-11-17 15:42:34 +00:00
zend_hash_move_forward_ex(&EG(included_files), &pos);
}
return SUCCESS;
} /* }}} */
PHPDBG_INFO(error) /* {{{ */
{
2013-11-17 19:00:59 +00:00
if (PG(last_error_message)) {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("lasterror", "error=\"%s\" file=\"%s\" line=\"%d\"", "Last error: %s at %s line %d",
2013-11-17 19:00:59 +00:00
PG(last_error_message), PG(last_error_file), PG(last_error_lineno));
} else {
2014-09-21 02:17:19 +00:00
phpdbg_notice("lasterror", "error=\"\"", "No error found!");
2013-11-17 19:00:59 +00:00
}
return SUCCESS;
} /* }}} */
2014-09-23 14:48:37 +00:00
static int phpdbg_arm_auto_global(zend_auto_global *auto_global TSRMLS_DC) {
if (auto_global->armed) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
}
return 0;
}
static int phpdbg_print_symbols(zend_bool show_globals TSRMLS_DC) {
HashTable vars, *symtable;
HashPosition pos;
char *var;
2013-11-18 22:12:27 +00:00
zval **data;
if (!EG(active_op_array)) {
2014-09-21 02:17:19 +00:00
phpdbg_error("inactive", "type=\"op_array\"", "No active op array!");
return SUCCESS;
}
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
if (!EG(active_symbol_table)) {
2014-09-21 02:17:19 +00:00
phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!");
return SUCCESS;
}
}
2014-09-23 14:48:37 +00:00
if (show_globals) {
zend_hash_apply(CG(auto_globals), (apply_func_t) phpdbg_arm_auto_global TSRMLS_CC);
symtable = &EG(symbol_table);
} else {
symtable = EG(active_symbol_table);
}
2013-11-18 21:59:42 +00:00
zend_hash_init(&vars, 8, NULL, NULL, 0);
2014-09-23 14:48:37 +00:00
zend_hash_internal_pointer_reset_ex(symtable, &pos);
while (zend_hash_get_current_key_ex(symtable, &var,
NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) {
2014-09-23 14:48:37 +00:00
zend_hash_get_current_data_ex(symtable, (void **)&data, &pos);
if (zend_is_auto_global(var, strlen(var) TSRMLS_CC) ^ !show_globals) {
zend_hash_update(&vars, var, strlen(var)+1, (void**)data, sizeof(zval*), NULL);
}
2014-09-23 14:48:37 +00:00
zend_hash_move_forward_ex(symtable, &pos);
}
2013-11-18 22:12:27 +00:00
2014-09-23 14:48:37 +00:00
if (show_globals) {
phpdbg_notice("variableinfo", "num=\"%d\"", "Superglobal variables (%d)", zend_hash_num_elements(&vars));
2014-09-23 14:48:37 +00:00
} else {
2013-11-25 10:17:57 +00:00
zend_op_array *ops = EG(active_op_array);
2014-09-21 02:17:19 +00:00
2013-11-25 10:17:57 +00:00
if (ops->function_name) {
if (ops->scope) {
phpdbg_notice("variableinfo", "method=\"%s::%s\" num=\"%d\"", "Variables in %s::%s() (%d)", ops->scope->name, ops->function_name, zend_hash_num_elements(&vars));
2013-11-25 10:17:57 +00:00
} else {
phpdbg_notice("variableinfo", "function=\"%s\" num=\"%d\"", "Variables in %s() (%d)", ops->function_name, zend_hash_num_elements(&vars));
2013-11-25 10:17:57 +00:00
}
} else {
if (ops->filename) {
phpdbg_notice("variableinfo", "file=\"%s\" num=\"%d\"", "Variables in %s (%d)", ops->filename, zend_hash_num_elements(&vars));
2013-11-25 10:17:57 +00:00
} else {
phpdbg_notice("variableinfo", "opline=\"%p\" num=\"%d\"", "Variables @ %p (%d)", ops, zend_hash_num_elements(&vars));
2013-11-25 10:17:57 +00:00
}
}
}
2013-11-20 18:52:34 +00:00
2013-11-18 23:04:20 +00:00
if (zend_hash_num_elements(&vars)) {
2014-09-21 02:17:19 +00:00
phpdbg_out("Address\t\tRefs\tType\t\tVariable");
2013-11-18 23:04:20 +00:00
for (zend_hash_internal_pointer_reset_ex(&vars, &pos);
zend_hash_get_current_data_ex(&vars, (void**) &data, &pos) == SUCCESS;
zend_hash_move_forward_ex(&vars, &pos)) {
char *var;
2013-11-18 21:59:42 +00:00
2013-11-18 23:04:20 +00:00
zend_hash_get_current_key_ex(&vars, &var, NULL, NULL, 0, &pos);
2013-11-18 22:12:27 +00:00
2013-11-18 23:04:20 +00:00
if (*data) {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("variable", "address=\"%p\" refcount=\"%d\" type=\"%s\"", "%p\t%d\t(%s)", *data, Z_REFCOUNT_PP(data), zend_zval_type_name(*data));
2013-11-20 18:52:34 +00:00
2013-11-18 23:18:22 +00:00
if (Z_TYPE_PP(data) == IS_RESOURCE) {
int type;
2013-11-20 18:52:34 +00:00
2014-09-21 02:17:19 +00:00
phpdbg_writeln("variabledetails", "refstatus=\"%s\" name=\"%s\" type=\"%s\"", "%s$%s\n|-------(typeof)------> (%s)\n", Z_ISREF_PP(data) ? "&": "", var, zend_list_find(Z_RESVAL_PP(data), &type) ? zend_rsrc_list_get_rsrc_type(type TSRMLS_CC) : "unknown");
2013-11-18 23:18:22 +00:00
} else if (Z_TYPE_PP(data) == IS_OBJECT) {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("variabledetails", "refstatus=\"%s\" name=\"%s\" instanceof=\"%s\"", "%s$%s\n|-----(instanceof)----> (%s)\n", Z_ISREF_PP(data) ? "&": "", var, Z_OBJCE_PP(data)->name);
2013-11-18 23:04:20 +00:00
} else {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("variabledetails", "refstatus=\"%s\" name=\"%s\"", "%s$%s", Z_ISREF_PP(data) ? "&": "", var);
2013-11-18 23:04:20 +00:00
}
} else {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("variable", "address=\"\" type=\"unknown\" name=\"%s\"", "n/a\tn/a\tn/a\t$%s", var);
}
2013-11-18 21:59:42 +00:00
}
}
2013-11-18 22:12:27 +00:00
2013-11-18 21:59:42 +00:00
zend_hash_destroy(&vars);
2013-11-18 22:12:27 +00:00
return SUCCESS;
} /* }}} */
2013-11-17 18:45:08 +00:00
2014-09-23 14:48:37 +00:00
PHPDBG_INFO(vars) /* {{{ */
{
return phpdbg_print_symbols(0 TSRMLS_CC);
}
PHPDBG_INFO(globals) /* {{{ */
{
return phpdbg_print_symbols(1 TSRMLS_CC);
}
PHPDBG_INFO(literal) /* {{{ */
{
2013-11-22 09:56:17 +00:00
if ((EG(in_execution) && EG(active_op_array)) || PHPDBG_G(ops)) {
zend_op_array *ops = EG(active_op_array) ? EG(active_op_array) : PHPDBG_G(ops);
2013-11-24 12:17:51 +00:00
int literal = 0, count = ops->last_literal-1;
2013-11-24 01:49:48 +00:00
2013-11-22 09:56:17 +00:00
if (ops->function_name) {
if (ops->scope) {
phpdbg_notice("literalinfo", "method=\"%s::%s\" num=\"%d\"", "Literal Constants in %s::%s() (%d)", ops->scope->name, ops->function_name, count);
2013-11-22 09:56:17 +00:00
} else {
phpdbg_notice("literalinfo", "function=\"%s\" num=\"%d\"", "Literal Constants in %s() (%d)", ops->function_name, count);
2013-11-22 09:56:17 +00:00
}
} else {
if (ops->filename) {
phpdbg_notice("literalinfo", "file=\"%s\" num=\"%d\"", "Literal Constants in %s (%d)", ops->filename, count);
2013-11-22 09:56:17 +00:00
} else {
phpdbg_notice("literalinfo", "opline=\"%p\" num=\"%d\"", "Literal Constants @ %p (%d)", ops, count);
2013-11-22 09:56:17 +00:00
}
}
2013-11-24 01:49:48 +00:00
2013-11-22 09:56:17 +00:00
while (literal < ops->last_literal) {
2013-11-23 17:36:33 +00:00
if (Z_TYPE(ops->literals[literal].constant) != IS_NULL) {
2014-09-21 02:17:19 +00:00
phpdbg_write("literal", "id=\"%u\"", "|-------- C%u -------> [", literal);
2013-11-23 17:36:33 +00:00
zend_print_zval(
&ops->literals[literal].constant, 0);
2014-09-21 02:17:19 +00:00
phpdbg_out("]\n");
2013-11-23 17:36:33 +00:00
}
literal++;
}
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error("inactive", "type=\"execution\"", "Not executing!");
}
2013-11-24 01:49:48 +00:00
return SUCCESS;
} /* }}} */
2013-12-01 08:34:17 +00:00
PHPDBG_INFO(memory) /* {{{ */
{
if (is_zend_mm(TSRMLS_C)) {
2014-09-21 02:17:19 +00:00
phpdbg_notice("meminfo", "", "Memory Manager Information");
phpdbg_notice("current", "", "Current");
phpdbg_writeln("used", "mem=\"%.3f\"", "|-------> Used:\t%.3f kB", (float) (zend_memory_usage(0 TSRMLS_CC)/1024));
phpdbg_writeln("real", "mem=\"%.3f\"", "|-------> Real:\t%.3f kB", (float) (zend_memory_usage(1 TSRMLS_CC)/1024));
phpdbg_notice("peak", "", "Peak");
phpdbg_writeln("used", "mem=\"%.3f\"", "|-------> Used:\t%.3f kB", (float) (zend_memory_peak_usage(0 TSRMLS_CC)/1024));
phpdbg_writeln("real", "mem=\"%.3f\"", "|-------> Real:\t%.3f kB", (float) (zend_memory_peak_usage(1 TSRMLS_CC)/1024));
2013-12-01 08:34:17 +00:00
} else {
2014-09-21 02:17:19 +00:00
phpdbg_error("inactive", "type=\"memory_manager\"", "Memory Manager Disabled!");
2013-12-01 08:34:17 +00:00
}
return SUCCESS;
} /* }}} */
2013-11-20 18:52:34 +00:00
static inline void phpdbg_print_class_name(zend_class_entry **ce TSRMLS_DC) /* {{{ */
{
2014-09-21 02:17:19 +00:00
phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%s\" methodcount=\"%d\"", "%s %s %s (%d)",
2013-11-17 18:45:08 +00:00
((*ce)->type == ZEND_USER_CLASS) ?
2013-11-17 18:26:56 +00:00
"User" : "Internal",
2013-11-26 10:02:58 +00:00
((*ce)->ce_flags & ZEND_ACC_INTERFACE) ?
2013-11-17 18:26:56 +00:00
"Interface" :
2013-11-26 10:02:58 +00:00
((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ?
2013-11-17 18:26:56 +00:00
"Abstract Class" :
2013-11-17 18:45:08 +00:00
"Class",
2013-11-17 18:26:56 +00:00
(*ce)->name, zend_hash_num_elements(&(*ce)->function_table));
} /* }}} */
PHPDBG_INFO(classes) /* {{{ */
{
2013-11-26 10:02:58 +00:00
HashPosition position;
2013-11-17 18:26:56 +00:00
zend_class_entry **ce;
HashTable classes;
2013-11-17 18:45:08 +00:00
2013-11-17 18:26:56 +00:00
zend_hash_init(&classes, 8, NULL, NULL, 0);
2013-11-17 18:45:08 +00:00
for (zend_hash_internal_pointer_reset_ex(EG(class_table), &position);
2013-11-17 18:26:56 +00:00
zend_hash_get_current_data_ex(EG(class_table), (void**)&ce, &position) == SUCCESS;
zend_hash_move_forward_ex(EG(class_table), &position)) {
2013-11-26 10:02:58 +00:00
if ((*ce)->type == ZEND_USER_CLASS) {
2014-09-21 02:17:19 +00:00
zend_hash_next_index_insert(&classes, ce, sizeof(ce), NULL);
2013-11-26 10:02:58 +00:00
}
2013-11-17 18:26:56 +00:00
}
2013-11-17 18:45:08 +00:00
phpdbg_notice("classinfo", "num=\"%d\"", "User Classes (%d)", zend_hash_num_elements(&classes));
2013-11-17 18:26:56 +00:00
2013-11-17 18:45:08 +00:00
for (zend_hash_internal_pointer_reset_ex(&classes, &position);
2013-11-17 18:26:56 +00:00
zend_hash_get_current_data_ex(&classes, (void**)&ce, &position) == SUCCESS;
zend_hash_move_forward_ex(&classes, &position)) {
phpdbg_print_class_name(ce TSRMLS_CC);
2013-11-17 18:45:08 +00:00
2013-11-17 18:26:56 +00:00
if ((*ce)->parent) {
2014-09-21 02:17:19 +00:00
phpdbg_xml("<parents>");
2013-11-17 18:26:56 +00:00
zend_class_entry *pce = (*ce)->parent;
do {
2014-09-21 02:17:19 +00:00
phpdbg_out("|-------- ");
2013-11-17 18:26:56 +00:00
phpdbg_print_class_name(&pce TSRMLS_CC);
} while ((pce = pce->parent));
2014-09-21 02:17:19 +00:00
phpdbg_xml("</parents>");
2013-11-17 18:26:56 +00:00
}
2013-11-17 18:45:08 +00:00
2013-11-26 10:02:58 +00:00
if ((*ce)->info.user.filename) {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("classsource", "file=\"\" line=\"%u\"", "|---- in %s on line %u",
2013-11-26 10:02:58 +00:00
(*ce)->info.user.filename,
(*ce)->info.user.line_start);
} else {
2014-09-21 02:17:19 +00:00
phpdbg_writeln("classsource", "", "|---- no source code");
2013-11-26 10:02:58 +00:00
}
2013-11-17 18:26:56 +00:00
}
zend_hash_destroy(&classes);
2013-11-17 18:45:08 +00:00
2013-11-17 18:26:56 +00:00
return SUCCESS;
} /* }}} */
2013-11-17 18:55:06 +00:00
PHPDBG_INFO(funcs) /* {{{ */
{
2013-11-26 10:02:58 +00:00
HashPosition position;
2013-11-17 18:55:06 +00:00
zend_function *zf, **pzf;
HashTable functions;
2013-11-17 19:40:49 +00:00
2013-11-17 18:55:06 +00:00
zend_hash_init(&functions, 8, NULL, NULL, 0);
2013-11-17 19:40:49 +00:00
for (zend_hash_internal_pointer_reset_ex(EG(function_table), &position);
2013-11-17 18:55:06 +00:00
zend_hash_get_current_data_ex(EG(function_table), (void**)&zf, &position) == SUCCESS;
zend_hash_move_forward_ex(EG(function_table), &position)) {
2013-11-26 10:02:58 +00:00
if (zf->type == ZEND_USER_FUNCTION) {
zend_hash_next_index_insert(
&functions, (void**) &zf, sizeof(zend_function), NULL);
}
2013-11-17 18:55:06 +00:00
}
2013-11-17 19:40:49 +00:00
phpdbg_notice("functioninfo", "num=\"%d\"", "User Functions (%d)", zend_hash_num_elements(&functions));
2013-11-17 18:55:06 +00:00
2013-11-17 19:40:49 +00:00
for (zend_hash_internal_pointer_reset_ex(&functions, &position);
2013-11-17 18:55:06 +00:00
zend_hash_get_current_data_ex(&functions, (void**)&pzf, &position) == SUCCESS;
zend_hash_move_forward_ex(&functions, &position)) {
zend_op_array *op_array = &((*pzf)->op_array);
2013-11-17 19:40:49 +00:00
phpdbg_write("function", "name=\"%s\"", "|-------- %s", op_array->function_name ? op_array->function_name : "{main}");
if (op_array->filename) {
phpdbg_writeln("functionsource", "file=\"%s\" line=\"%d\"", " in %s on line %d",
op_array->filename,
op_array->line_start);
} else {
phpdbg_writeln("functionsource", "", " (no source code)");
}
2013-11-17 18:55:06 +00:00
}
zend_hash_destroy(&functions);
2013-11-17 19:40:49 +00:00
2013-11-17 18:55:06 +00:00
return SUCCESS;
} /* }}} */