2013-11-09 22:35:03 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| PHP Version 5 |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Copyright (c) 1997-2013 The PHP Group |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| 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. |
|
|
|
|
+----------------------------------------------------------------------+
|
2013-11-17 12:40:51 +00:00
|
|
|
| Authors: Felipe Pena <felipe@php.net> |
|
2013-11-09 22:35:03 +00:00
|
|
|
| Authors: Joe Watkins <joe.watkins@live.co.uk> |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
2013-11-09 23:07:04 +00:00
|
|
|
|
2013-11-10 10:44:42 +00:00
|
|
|
#include "phpdbg.h"
|
2013-11-10 19:15:32 +00:00
|
|
|
#include "phpdbg_prompt.h"
|
2013-11-10 21:38:58 +00:00
|
|
|
#include "phpdbg_bp.h"
|
2013-11-15 16:24:22 +00:00
|
|
|
#include "phpdbg_break.h"
|
2013-11-12 22:39:39 +00:00
|
|
|
#include "phpdbg_utils.h"
|
2013-11-10 10:44:42 +00:00
|
|
|
|
|
|
|
ZEND_DECLARE_MODULE_GLOBALS(phpdbg);
|
|
|
|
|
2013-11-15 11:19:26 +00:00
|
|
|
#if PHP_VERSION_ID >= 50500
|
2013-11-10 13:01:46 +00:00
|
|
|
void (*zend_execute_old)(zend_execute_data *execute_data TSRMLS_DC);
|
2013-11-15 11:19:26 +00:00
|
|
|
#else
|
|
|
|
void (*zend_execute_old)(zend_op_array *op_array TSRMLS_DC);
|
|
|
|
#endif
|
2013-11-10 13:01:46 +00:00
|
|
|
|
2013-11-10 15:47:28 +00:00
|
|
|
static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */
|
|
|
|
{
|
2013-11-10 13:01:46 +00:00
|
|
|
pg->exec = NULL;
|
2013-11-10 21:28:12 +00:00
|
|
|
pg->exec_len = 0;
|
2013-11-10 13:01:46 +00:00
|
|
|
pg->ops = NULL;
|
2013-11-10 14:43:46 +00:00
|
|
|
pg->vmret = 0;
|
2013-11-10 19:15:32 +00:00
|
|
|
pg->bp_count = 0;
|
2013-11-10 21:49:37 +00:00
|
|
|
pg->last = NULL;
|
2013-11-16 14:34:49 +00:00
|
|
|
pg->lparam = NULL;
|
2013-11-12 06:03:37 +00:00
|
|
|
pg->flags = PHPDBG_DEFAULT_FLAGS;
|
2013-11-14 21:10:44 +00:00
|
|
|
pg->oplog = NULL;
|
2013-11-10 15:47:28 +00:00
|
|
|
} /* }}} */
|
2013-11-10 10:44:42 +00:00
|
|
|
|
2013-11-10 15:47:28 +00:00
|
|
|
static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */
|
|
|
|
{
|
2013-11-10 13:01:46 +00:00
|
|
|
ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL);
|
2013-11-15 11:19:26 +00:00
|
|
|
#if PHP_VERSION_ID >= 50500
|
2013-11-10 13:01:46 +00:00
|
|
|
zend_execute_old = zend_execute_ex;
|
|
|
|
zend_execute_ex = phpdbg_execute_ex;
|
2013-11-15 11:19:26 +00:00
|
|
|
#else
|
|
|
|
zend_execute_old = zend_execute;
|
|
|
|
zend_execute = phpdbg_execute_ex;
|
|
|
|
#endif
|
2013-11-10 14:36:30 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
REGISTER_LONG_CONSTANT("PHPDBG_FILE", FILE_PARAM, CONST_CS|CONST_PERSISTENT);
|
2013-11-15 16:24:22 +00:00
|
|
|
REGISTER_LONG_CONSTANT("PHPDBG_METHOD", METHOD_PARAM, CONST_CS|CONST_PERSISTENT);
|
2013-11-15 16:17:57 +00:00
|
|
|
REGISTER_LONG_CONSTANT("PHPDBG_LINENO", NUMERIC_PARAM, CONST_CS|CONST_PERSISTENT);
|
2013-11-15 15:54:14 +00:00
|
|
|
REGISTER_LONG_CONSTANT("PHPDBG_FUNC", STR_PARAM, CONST_CS|CONST_PERSISTENT);
|
2013-11-15 16:24:22 +00:00
|
|
|
|
2013-11-10 13:01:46 +00:00
|
|
|
return SUCCESS;
|
2013-11-10 15:47:28 +00:00
|
|
|
} /* }}} */
|
2013-11-10 14:36:30 +00:00
|
|
|
|
2013-11-10 21:38:58 +00:00
|
|
|
static void php_phpdbg_destroy_bp_file(void *brake) /* {{{ */
|
2013-11-10 15:47:28 +00:00
|
|
|
{
|
|
|
|
zend_llist_destroy((zend_llist*)brake);
|
|
|
|
} /* }}} */
|
2013-11-10 10:44:42 +00:00
|
|
|
|
2013-11-10 21:38:58 +00:00
|
|
|
static void php_phpdbg_destroy_bp_symbol(void *brake) /* {{{ */
|
|
|
|
{
|
2013-11-10 22:46:49 +00:00
|
|
|
efree((char*)((phpdbg_breaksymbol_t*)brake)->symbol);
|
2013-11-10 21:38:58 +00:00
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-12 00:27:48 +00:00
|
|
|
static void php_phpdbg_destroy_bp_methods(void *brake) /* {{{ */
|
|
|
|
{
|
|
|
|
zend_hash_destroy((HashTable*)brake);
|
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-13 14:22:01 +00:00
|
|
|
static void php_phpdbg_destroy_bp_condition(void *data) /* {{{ */
|
|
|
|
{
|
2013-11-13 14:32:36 +00:00
|
|
|
phpdbg_breakcond_t *brake = (phpdbg_breakcond_t*) data;
|
2013-11-13 23:36:02 +00:00
|
|
|
|
2013-11-13 14:22:01 +00:00
|
|
|
if (brake) {
|
|
|
|
if (brake->ops) {
|
|
|
|
TSRMLS_FETCH();
|
2013-11-13 23:36:02 +00:00
|
|
|
|
2013-11-13 14:22:01 +00:00
|
|
|
destroy_op_array(
|
|
|
|
brake->ops TSRMLS_CC);
|
|
|
|
efree(brake->ops);
|
|
|
|
}
|
|
|
|
zval_dtor(&brake->code);
|
|
|
|
}
|
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-10 15:47:28 +00:00
|
|
|
static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */
|
|
|
|
{
|
2013-11-12 01:51:50 +00:00
|
|
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], 8, NULL, php_phpdbg_destroy_bp_file, 0);
|
|
|
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0);
|
2013-11-12 13:07:35 +00:00
|
|
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], 8, NULL, NULL, 0);
|
2013-11-12 01:51:50 +00:00
|
|
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0);
|
2013-11-13 14:22:01 +00:00
|
|
|
zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], 8, NULL, php_phpdbg_destroy_bp_condition, 0);
|
2013-11-18 03:18:37 +00:00
|
|
|
zend_hash_init(&PHPDBG_G(seek), 8, NULL, NULL, 0);
|
2013-11-10 14:36:30 +00:00
|
|
|
return SUCCESS;
|
2013-11-10 15:47:28 +00:00
|
|
|
} /* }}} */
|
2013-11-10 10:44:42 +00:00
|
|
|
|
2013-11-10 15:47:28 +00:00
|
|
|
static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
|
|
|
|
{
|
2013-11-12 01:51:50 +00:00
|
|
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
|
|
|
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
|
|
|
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
|
|
|
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]);
|
2013-11-13 14:22:01 +00:00
|
|
|
zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]);
|
2013-11-18 03:18:37 +00:00
|
|
|
zend_hash_destroy(&PHPDBG_G(seek));
|
|
|
|
|
2013-11-10 13:01:46 +00:00
|
|
|
if (PHPDBG_G(exec)) {
|
|
|
|
efree(PHPDBG_G(exec));
|
2013-11-14 11:13:21 +00:00
|
|
|
PHPDBG_G(exec) = NULL;
|
2013-11-10 13:01:46 +00:00
|
|
|
}
|
2013-11-14 21:39:59 +00:00
|
|
|
|
2013-11-14 21:10:44 +00:00
|
|
|
if (PHPDBG_G(oplog)) {
|
|
|
|
fclose(
|
|
|
|
PHPDBG_G(oplog));
|
|
|
|
PHPDBG_G(oplog) = NULL;
|
|
|
|
}
|
2013-11-10 14:36:30 +00:00
|
|
|
|
2013-11-10 13:01:46 +00:00
|
|
|
if (PHPDBG_G(ops)) {
|
|
|
|
destroy_op_array(PHPDBG_G(ops) TSRMLS_CC);
|
|
|
|
efree(PHPDBG_G(ops));
|
2013-11-14 11:13:21 +00:00
|
|
|
PHPDBG_G(ops) = NULL;
|
2013-11-10 13:01:46 +00:00
|
|
|
}
|
2013-11-14 21:39:59 +00:00
|
|
|
|
2013-11-10 13:01:46 +00:00
|
|
|
return SUCCESS;
|
2013-11-10 15:47:28 +00:00
|
|
|
} /* }}} */
|
2013-11-09 22:35:03 +00:00
|
|
|
|
2013-11-15 16:22:20 +00:00
|
|
|
/* {{{ proto void phpdbg_break([integer type, string expression])
|
2013-11-12 13:07:35 +00:00
|
|
|
instructs phpdbg to insert a breakpoint at the next opcode */
|
2013-11-11 15:14:37 +00:00
|
|
|
static PHP_FUNCTION(phpdbg_break)
|
2013-11-11 14:33:53 +00:00
|
|
|
{
|
2013-11-15 15:54:14 +00:00
|
|
|
if (ZEND_NUM_ARGS() > 0) {
|
|
|
|
long type;
|
|
|
|
char *expr = NULL;
|
|
|
|
zend_uint expr_len = 0;
|
2013-11-16 14:34:49 +00:00
|
|
|
phpdbg_param_t param;
|
2013-11-15 16:24:22 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &type, &expr, &expr_len) == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
2013-11-17 12:40:51 +00:00
|
|
|
|
2013-11-16 14:34:49 +00:00
|
|
|
phpdbg_parse_param(expr, expr_len, ¶m TSRMLS_CC);
|
2013-11-17 12:40:51 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
switch (type) {
|
|
|
|
case METHOD_PARAM:
|
2013-11-16 14:34:49 +00:00
|
|
|
phpdbg_do_break_method(¶m TSRMLS_CC);
|
2013-11-15 15:54:14 +00:00
|
|
|
break;
|
2013-11-15 16:24:22 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
case FILE_PARAM:
|
2013-11-16 14:34:49 +00:00
|
|
|
phpdbg_do_break_file(¶m TSRMLS_CC);
|
2013-11-15 15:54:14 +00:00
|
|
|
break;
|
2013-11-15 16:24:22 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
case NUMERIC_PARAM:
|
2013-11-16 14:34:49 +00:00
|
|
|
phpdbg_do_break_lineno(¶m TSRMLS_CC);
|
2013-11-15 15:54:14 +00:00
|
|
|
break;
|
2013-11-15 16:24:22 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
case STR_PARAM:
|
2013-11-16 14:34:49 +00:00
|
|
|
phpdbg_do_break_func(¶m TSRMLS_CC);
|
2013-11-15 15:54:14 +00:00
|
|
|
break;
|
2013-11-15 16:24:22 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
default: zend_error(
|
2013-11-15 16:24:22 +00:00
|
|
|
E_WARNING, "unrecognized parameter type %ld", type);
|
2013-11-15 15:54:14 +00:00
|
|
|
}
|
2013-11-17 12:40:51 +00:00
|
|
|
|
2013-11-16 14:34:49 +00:00
|
|
|
phpdbg_clear_param(¶m TSRMLS_CC);
|
2013-11-17 12:40:51 +00:00
|
|
|
|
2013-11-15 15:54:14 +00:00
|
|
|
} else if (EG(current_execute_data) && EG(active_op_array)) {
|
2013-11-12 21:40:15 +00:00
|
|
|
zend_ulong opline_num = (EG(current_execute_data)->opline -
|
|
|
|
EG(active_op_array)->opcodes);
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-11 14:33:53 +00:00
|
|
|
phpdbg_set_breakpoint_opline_ex(
|
2013-11-11 14:55:36 +00:00
|
|
|
&EG(active_op_array)->opcodes[opline_num+1] TSRMLS_CC);
|
2013-11-11 14:33:53 +00:00
|
|
|
}
|
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-11 15:14:37 +00:00
|
|
|
/* {{{ proto void phpdbg_clear(void)
|
|
|
|
instructs phpdbg to clear breakpoints */
|
|
|
|
static PHP_FUNCTION(phpdbg_clear)
|
|
|
|
{
|
2013-11-12 01:51:50 +00:00
|
|
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
|
|
|
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
|
|
|
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
|
|
|
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]);
|
2013-11-14 09:18:06 +00:00
|
|
|
zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]);
|
2013-11-11 15:14:37 +00:00
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-15 16:22:20 +00:00
|
|
|
ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_arginfo, 0, 0, 0)
|
|
|
|
ZEND_ARG_INFO(0, type)
|
|
|
|
ZEND_ARG_INFO(0, expression)
|
|
|
|
ZEND_END_ARG_INFO()
|
|
|
|
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(phpdbg_clear_arginfo, 0, 0, 0)
|
|
|
|
ZEND_END_ARG_INFO()
|
|
|
|
|
2013-11-11 14:33:53 +00:00
|
|
|
zend_function_entry phpdbg_user_functions[] = {
|
2013-11-15 16:22:20 +00:00
|
|
|
PHP_FE(phpdbg_clear, phpdbg_clear_arginfo)
|
|
|
|
PHP_FE(phpdbg_break, phpdbg_break_arginfo)
|
2013-11-11 14:33:53 +00:00
|
|
|
#ifdef PHP_FE_END
|
|
|
|
PHP_FE_END
|
|
|
|
#else
|
|
|
|
{NULL,NULL,NULL}
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2013-11-09 22:47:39 +00:00
|
|
|
static zend_module_entry sapi_phpdbg_module_entry = {
|
2013-11-09 22:35:03 +00:00
|
|
|
STANDARD_MODULE_HEADER,
|
2013-11-09 22:47:39 +00:00
|
|
|
"phpdbg",
|
2013-11-11 14:33:53 +00:00
|
|
|
phpdbg_user_functions,
|
2013-11-10 10:44:42 +00:00
|
|
|
PHP_MINIT(phpdbg),
|
2013-11-09 22:35:03 +00:00
|
|
|
NULL,
|
2013-11-10 10:44:42 +00:00
|
|
|
PHP_RINIT(phpdbg),
|
|
|
|
PHP_RSHUTDOWN(phpdbg),
|
2013-11-09 22:35:03 +00:00
|
|
|
NULL,
|
|
|
|
"0.1",
|
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
static inline int php_sapi_phpdbg_module_startup(sapi_module_struct *module) /* {{{ */
|
|
|
|
{
|
2013-11-09 22:47:39 +00:00
|
|
|
if (php_module_startup(module, &sapi_phpdbg_module_entry, 1) == FAILURE) {
|
2013-11-09 22:35:03 +00:00
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-12 21:40:15 +00:00
|
|
|
static char* php_sapi_phpdbg_read_cookies(TSRMLS_D) /* {{{ */
|
|
|
|
{
|
2013-11-10 22:44:28 +00:00
|
|
|
return NULL;
|
|
|
|
} /* }}} */
|
|
|
|
|
|
|
|
static int php_sapi_phpdbg_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s TSRMLS_DC) /* {{{ */
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
static int php_sapi_phpdbg_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */
|
|
|
|
{
|
|
|
|
/* We do nothing here, this function is needed to prevent that the fallback
|
|
|
|
* header handling is called. */
|
|
|
|
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
static void php_sapi_phpdbg_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) /* {{{ */
|
|
|
|
{
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s\n", message);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
static int php_sapi_phpdbg_deactivate(TSRMLS_D) /* {{{ */
|
|
|
|
{
|
|
|
|
fflush(stdout);
|
|
|
|
if(SG(request_info).argv0) {
|
|
|
|
free(SG(request_info).argv0);
|
|
|
|
SG(request_info).argv0 = NULL;
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2013-11-10 23:30:52 +00:00
|
|
|
static void php_sapi_phpdbg_register_vars(zval *track_vars_array TSRMLS_DC) /* {{{ */
|
|
|
|
{
|
|
|
|
unsigned int len;
|
|
|
|
char *docroot = "";
|
|
|
|
|
|
|
|
/* In phpdbg mode, we consider the environment to be a part of the server variables
|
|
|
|
*/
|
|
|
|
php_import_environment_variables(track_vars_array TSRMLS_CC);
|
|
|
|
|
|
|
|
if (PHPDBG_G(exec)) {
|
|
|
|
len = PHPDBG_G(exec_len);
|
2013-11-12 21:40:15 +00:00
|
|
|
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF",
|
|
|
|
&PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) {
|
|
|
|
php_register_variable("PHP_SELF", PHPDBG_G(exec),
|
|
|
|
track_vars_array TSRMLS_CC);
|
2013-11-10 23:30:52 +00:00
|
|
|
}
|
2013-11-12 21:40:15 +00:00
|
|
|
if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME",
|
|
|
|
&PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) {
|
|
|
|
php_register_variable("SCRIPT_NAME", PHPDBG_G(exec),
|
|
|
|
track_vars_array TSRMLS_CC);
|
2013-11-10 23:30:52 +00:00
|
|
|
}
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-12 21:40:15 +00:00
|
|
|
if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME",
|
|
|
|
&PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) {
|
|
|
|
php_register_variable("SCRIPT_FILENAME", PHPDBG_G(exec),
|
|
|
|
track_vars_array TSRMLS_CC);
|
2013-11-10 23:30:52 +00:00
|
|
|
}
|
2013-11-12 21:40:15 +00:00
|
|
|
if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED",
|
|
|
|
&PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) {
|
|
|
|
php_register_variable("PATH_TRANSLATED", PHPDBG_G(exec),
|
|
|
|
track_vars_array TSRMLS_CC);
|
2013-11-10 23:30:52 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-10 23:30:52 +00:00
|
|
|
/* any old docroot will doo */
|
|
|
|
len = 0U;
|
2013-11-12 21:40:15 +00:00
|
|
|
if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT",
|
|
|
|
&docroot, len, &len TSRMLS_CC)) {
|
2013-11-10 23:30:52 +00:00
|
|
|
php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2013-11-09 22:47:39 +00:00
|
|
|
/* {{{ sapi_module_struct phpdbg_sapi_module
|
2013-11-09 22:35:03 +00:00
|
|
|
*/
|
2013-11-09 22:47:39 +00:00
|
|
|
static sapi_module_struct phpdbg_sapi_module = {
|
2013-11-09 23:07:04 +00:00
|
|
|
"phpdbg", /* name */
|
|
|
|
"phpdbg", /* pretty name */
|
2013-11-09 22:35:03 +00:00
|
|
|
|
2013-11-09 22:47:39 +00:00
|
|
|
php_sapi_phpdbg_module_startup, /* startup */
|
2013-11-09 22:35:03 +00:00
|
|
|
php_module_shutdown_wrapper, /* shutdown */
|
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
NULL, /* activate */
|
2013-11-10 22:44:28 +00:00
|
|
|
php_sapi_phpdbg_deactivate, /* deactivate */
|
2013-11-09 22:35:03 +00:00
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
NULL, /* unbuffered write */
|
|
|
|
NULL, /* flush */
|
|
|
|
NULL, /* get uid */
|
|
|
|
NULL, /* getenv */
|
2013-11-09 22:35:03 +00:00
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
php_error, /* error handler */
|
2013-11-09 22:35:03 +00:00
|
|
|
|
2013-11-10 22:44:28 +00:00
|
|
|
php_sapi_phpdbg_header_handler, /* header handler */
|
|
|
|
php_sapi_phpdbg_send_headers, /* send headers handler */
|
|
|
|
php_sapi_phpdbg_send_header, /* send header handler */
|
2013-11-09 22:35:03 +00:00
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
NULL, /* read POST data */
|
2013-11-10 22:44:28 +00:00
|
|
|
php_sapi_phpdbg_read_cookies, /* read Cookies */
|
2013-11-09 22:35:03 +00:00
|
|
|
|
2013-11-10 23:30:52 +00:00
|
|
|
php_sapi_phpdbg_register_vars, /* register server variables */
|
2013-11-10 22:44:28 +00:00
|
|
|
php_sapi_phpdbg_log_message, /* Log message */
|
2013-11-09 23:07:04 +00:00
|
|
|
NULL, /* Get request time */
|
|
|
|
NULL, /* Child terminate */
|
2013-11-09 22:35:03 +00:00
|
|
|
STANDARD_SAPI_MODULE_PROPERTIES
|
|
|
|
};
|
|
|
|
/* }}} */
|
|
|
|
|
2013-11-10 22:01:40 +00:00
|
|
|
const opt_struct OPTIONS[] = { /* {{{ */
|
2013-11-12 21:40:15 +00:00
|
|
|
{'c', 1, "ini path override"},
|
|
|
|
{'d', 1, "define ini entry on command line"},
|
|
|
|
{'n', 0, "no php.ini"},
|
|
|
|
{'z', 1, "load zend_extension"},
|
|
|
|
/* phpdbg options */
|
|
|
|
{'e', 1, "exec"},
|
2013-11-14 21:10:44 +00:00
|
|
|
{'v', 0, "disable quietness"},
|
|
|
|
{'s', 0, "enable stepping"},
|
2013-11-12 21:40:15 +00:00
|
|
|
{'b', 0, "boring colours"},
|
2013-11-14 21:10:44 +00:00
|
|
|
{'i', 1, "specify init"},
|
|
|
|
{'I', 0, "ignore init"},
|
|
|
|
{'O', 1, "opline log"},
|
2013-11-12 21:40:15 +00:00
|
|
|
{'-', 0, NULL}
|
2013-11-10 17:45:06 +00:00
|
|
|
}; /* }}} */
|
|
|
|
|
2013-11-10 22:44:28 +00:00
|
|
|
const char phpdbg_ini_hardcoded[] =
|
|
|
|
"html_errors=0\n"
|
|
|
|
"register_argc_argv=1\n"
|
|
|
|
"implicit_flush=1\n"
|
|
|
|
"output_buffering=0\n"
|
|
|
|
"max_execution_time=0\n"
|
|
|
|
"max_input_time=-1\n\0";
|
|
|
|
|
2013-11-10 17:45:06 +00:00
|
|
|
/* overwriteable ini defaults must be set in phpdbg_ini_defaults() */
|
|
|
|
#define INI_DEFAULT(name,value)\
|
|
|
|
Z_SET_REFCOUNT(tmp, 0);\
|
|
|
|
Z_UNSET_ISREF(tmp); \
|
|
|
|
ZVAL_STRINGL(&tmp, zend_strndup(value, sizeof(value)-1), sizeof(value)-1, 0);\
|
|
|
|
zend_hash_update(configuration_hash, name, sizeof(name), &tmp, sizeof(zval), NULL);\
|
|
|
|
|
2013-11-12 21:40:15 +00:00
|
|
|
void phpdbg_ini_defaults(HashTable *configuration_hash) /* {{{ */
|
|
|
|
{
|
2013-11-10 17:45:06 +00:00
|
|
|
zval tmp;
|
|
|
|
INI_DEFAULT("report_zend_debug", "0");
|
|
|
|
INI_DEFAULT("display_errors", "1");
|
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-18 01:07:57 +00:00
|
|
|
static void phpdbg_welcome(zend_bool cleaning TSRMLS_DC) /* {{{ */
|
|
|
|
{
|
|
|
|
/* print blurb */
|
|
|
|
if (!cleaning) {
|
|
|
|
phpdbg_notice("Welcome to phpdbg, the interactive PHP debugger, v%s",
|
|
|
|
PHPDBG_VERSION);
|
|
|
|
phpdbg_writeln("To get help using phpdbg type \"help\" and press enter");
|
|
|
|
phpdbg_notice("Please report bugs to <%s>", PHPDBG_ISSUES);
|
|
|
|
} else {
|
|
|
|
phpdbg_notice("Clean Execution Environment");
|
|
|
|
|
|
|
|
phpdbg_writeln("Classes\t\t\t%d", zend_hash_num_elements(EG(class_table)));
|
|
|
|
phpdbg_writeln("Functions\t\t%d", zend_hash_num_elements(EG(function_table)));
|
|
|
|
phpdbg_writeln("Constants\t\t%d", zend_hash_num_elements(EG(zend_constants)));
|
|
|
|
phpdbg_writeln("Includes\t\t%d", zend_hash_num_elements(&EG(included_files)));
|
|
|
|
}
|
|
|
|
} /* }}} */
|
|
|
|
|
2013-11-12 21:40:15 +00:00
|
|
|
int main(int argc, char **argv) /* {{{ */
|
2013-11-09 23:07:04 +00:00
|
|
|
{
|
2013-11-10 00:34:38 +00:00
|
|
|
sapi_module_struct *phpdbg = &phpdbg_sapi_module;
|
2013-11-14 11:13:21 +00:00
|
|
|
char *ini_entries;
|
|
|
|
int ini_entries_len;
|
|
|
|
char *exec;
|
|
|
|
size_t exec_len;
|
2013-11-14 14:14:13 +00:00
|
|
|
char *init_file;
|
|
|
|
size_t init_file_len;
|
2013-11-14 16:58:50 +00:00
|
|
|
zend_bool init_file_default;
|
2013-11-14 21:10:44 +00:00
|
|
|
char *oplog_file;
|
|
|
|
size_t oplog_file_len;
|
2013-11-14 11:13:21 +00:00
|
|
|
zend_ulong flags;
|
|
|
|
char *php_optarg;
|
2013-11-18 01:08:53 +00:00
|
|
|
int php_optind;
|
|
|
|
int opt;
|
|
|
|
long cleaning = 0;
|
2013-11-09 22:35:03 +00:00
|
|
|
#ifdef ZTS
|
2013-11-09 23:07:04 +00:00
|
|
|
void ***tsrm_ls;
|
2013-11-09 22:35:03 +00:00
|
|
|
#endif
|
2013-11-09 23:07:04 +00:00
|
|
|
|
2013-11-09 22:47:39 +00:00
|
|
|
#ifdef PHP_WIN32
|
2013-11-18 00:23:04 +00:00
|
|
|
HWND console;
|
|
|
|
RECT consoleRect;
|
2013-11-09 23:07:04 +00:00
|
|
|
_fmode = _O_BINARY; /* sets default for file streams to binary */
|
|
|
|
setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
|
|
|
|
setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
|
|
|
|
setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
|
2013-11-18 01:07:57 +00:00
|
|
|
|
2013-11-18 00:23:04 +00:00
|
|
|
console = GetConsoleWindow();
|
|
|
|
if (console) {
|
|
|
|
GetWindowRect(console, &consoleRect);
|
|
|
|
MoveWindow(
|
2013-11-18 01:07:57 +00:00
|
|
|
console, consoleRect.left, consoleRect.top, 800,600, TRUE);
|
2013-11-18 00:23:04 +00:00
|
|
|
}
|
2013-11-09 22:47:39 +00:00
|
|
|
#endif
|
|
|
|
|
2013-11-10 22:44:28 +00:00
|
|
|
#ifdef ZTS
|
2013-11-18 01:18:12 +00:00
|
|
|
tsrm_startup(1, 1, 0, NULL);
|
2013-11-10 22:44:28 +00:00
|
|
|
|
|
|
|
tsrm_ls = ts_resource(0);
|
|
|
|
#endif
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-14 11:13:21 +00:00
|
|
|
phpdbg_main:
|
2013-11-18 01:18:12 +00:00
|
|
|
ini_entries = NULL;
|
|
|
|
ini_entries_len = 0;
|
|
|
|
exec = NULL;
|
|
|
|
exec_len = 0;
|
|
|
|
init_file = NULL;
|
|
|
|
init_file_len = 0;
|
|
|
|
init_file_default = 1;
|
|
|
|
oplog_file = NULL;
|
|
|
|
oplog_file_len = 0;
|
|
|
|
flags = PHPDBG_DEFAULT_FLAGS;
|
|
|
|
php_optarg = NULL;
|
|
|
|
php_optind = 1;
|
|
|
|
opt = 0;
|
|
|
|
|
|
|
|
while ((opt = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
|
|
|
|
switch (opt) {
|
|
|
|
case 'n':
|
|
|
|
phpdbg->php_ini_ignore = 1;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
if (phpdbg->php_ini_path_override) {
|
|
|
|
free(phpdbg->php_ini_path_override);
|
|
|
|
}
|
|
|
|
phpdbg->php_ini_path_override = strdup(php_optarg);
|
|
|
|
break;
|
|
|
|
case 'd': {
|
|
|
|
int len = strlen(php_optarg);
|
|
|
|
char *val;
|
|
|
|
|
|
|
|
if ((val = strchr(php_optarg, '='))) {
|
|
|
|
val++;
|
|
|
|
if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
|
|
|
|
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
|
|
|
|
memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
|
|
|
|
ini_entries_len += (val - php_optarg);
|
|
|
|
memcpy(ini_entries + ini_entries_len, "\"", 1);
|
|
|
|
ini_entries_len++;
|
|
|
|
memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg));
|
|
|
|
ini_entries_len += len - (val - php_optarg);
|
|
|
|
memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
|
|
|
|
ini_entries_len += sizeof("\n\0\"") - 2;
|
|
|
|
} else {
|
|
|
|
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\n\0"));
|
|
|
|
memcpy(ini_entries + ini_entries_len, php_optarg, len);
|
|
|
|
memcpy(ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
|
|
|
|
ini_entries_len += len + sizeof("\n\0") - 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
|
|
|
|
memcpy(ini_entries + ini_entries_len, php_optarg, len);
|
|
|
|
memcpy(ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
|
|
|
|
ini_entries_len += len + sizeof("=1\n\0") - 2;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 'z':
|
|
|
|
zend_load_extension(php_optarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* begin phpdbg options */
|
|
|
|
|
|
|
|
case 'e': { /* set execution context */
|
|
|
|
exec_len = strlen(php_optarg);
|
|
|
|
if (exec_len) {
|
|
|
|
exec = strdup(php_optarg);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case 'I': { /* ignore .phpdbginit */
|
|
|
|
init_file_default = 0;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case 'i': { /* set init file */
|
|
|
|
init_file_len = strlen(php_optarg);
|
|
|
|
if (init_file_len) {
|
|
|
|
init_file = strdup(php_optarg);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case 'O': { /* set oplog output */
|
|
|
|
oplog_file_len = strlen(php_optarg);
|
|
|
|
if (oplog_file_len) {
|
|
|
|
oplog_file = strdup(php_optarg);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case 'v': /* set quietness off */
|
|
|
|
flags &= ~PHPDBG_IS_QUIET;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's': /* set stepping on */
|
|
|
|
flags |= PHPDBG_IS_STEPPING;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'b': /* set colours off */
|
|
|
|
flags &= ~PHPDBG_IS_COLOURED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-11-10 17:51:20 +00:00
|
|
|
|
2013-11-18 01:18:12 +00:00
|
|
|
phpdbg->ini_defaults = phpdbg_ini_defaults;
|
2013-11-10 17:45:06 +00:00
|
|
|
phpdbg->phpinfo_as_text = 1;
|
|
|
|
phpdbg->php_ini_ignore_cwd = 1;
|
2013-11-09 23:07:04 +00:00
|
|
|
|
|
|
|
sapi_startup(phpdbg);
|
|
|
|
|
2013-11-18 01:18:12 +00:00
|
|
|
phpdbg->executable_location = argv[0];
|
|
|
|
phpdbg->phpinfo_as_text = 1;
|
|
|
|
phpdbg->php_ini_ignore = 0;
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-18 01:18:12 +00:00
|
|
|
if (ini_entries) {
|
2013-11-10 22:44:28 +00:00
|
|
|
ini_entries = realloc(ini_entries, ini_entries_len + sizeof(phpdbg_ini_hardcoded));
|
|
|
|
memmove(ini_entries + sizeof(phpdbg_ini_hardcoded) - 2, ini_entries, ini_entries_len + 1);
|
|
|
|
memcpy(ini_entries, phpdbg_ini_hardcoded, sizeof(phpdbg_ini_hardcoded) - 2);
|
|
|
|
} else {
|
|
|
|
ini_entries = malloc(sizeof(phpdbg_ini_hardcoded));
|
|
|
|
memcpy(ini_entries, phpdbg_ini_hardcoded, sizeof(phpdbg_ini_hardcoded));
|
|
|
|
}
|
|
|
|
ini_entries_len += sizeof(phpdbg_ini_hardcoded) - 2;
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-18 01:18:12 +00:00
|
|
|
phpdbg->ini_entries = ini_entries;
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
if (phpdbg->startup(phpdbg) == SUCCESS) {
|
|
|
|
zend_activate(TSRMLS_C);
|
2013-11-09 22:35:03 +00:00
|
|
|
|
|
|
|
#ifdef ZEND_SIGNALS
|
2013-11-09 23:07:04 +00:00
|
|
|
zend_try {
|
|
|
|
zend_signals_activate(TSRMLS_C);
|
|
|
|
} zend_end_try();
|
2013-11-09 22:35:03 +00:00
|
|
|
#endif
|
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
PG(modules_activated) = 0;
|
|
|
|
|
2013-11-12 04:53:04 +00:00
|
|
|
if (exec) { /* set execution context */
|
2013-11-14 11:13:21 +00:00
|
|
|
PHPDBG_G(exec) = phpdbg_resolve_path(
|
|
|
|
exec TSRMLS_CC);
|
|
|
|
PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec));
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-12 04:53:04 +00:00
|
|
|
free(exec);
|
|
|
|
}
|
2013-11-14 21:39:59 +00:00
|
|
|
|
2013-11-18 01:18:12 +00:00
|
|
|
if (oplog_file) { /* open oplog */
|
|
|
|
PHPDBG_G(oplog) = fopen(oplog_file, "w+");
|
|
|
|
if (!PHPDBG_G(oplog)) {
|
|
|
|
phpdbg_error(
|
|
|
|
"Failed to open oplog %s", oplog_file);
|
|
|
|
}
|
|
|
|
free(oplog_file);
|
|
|
|
}
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-12 04:53:04 +00:00
|
|
|
/* set flags from command line */
|
|
|
|
PHPDBG_G(flags) = flags;
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
zend_try {
|
|
|
|
zend_activate_modules(TSRMLS_C);
|
|
|
|
} zend_end_try();
|
2013-11-13 23:36:02 +00:00
|
|
|
|
2013-11-14 21:51:55 +00:00
|
|
|
/* print blurb */
|
|
|
|
phpdbg_welcome(cleaning TSRMLS_CC);
|
|
|
|
|
2013-11-14 14:14:13 +00:00
|
|
|
/* initialize from file */
|
2013-11-14 17:03:36 +00:00
|
|
|
zend_try {
|
|
|
|
phpdbg_init(init_file, init_file_len, init_file_default TSRMLS_CC);
|
|
|
|
} zend_catch {
|
|
|
|
if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) {
|
|
|
|
goto phpdbg_out;
|
|
|
|
}
|
|
|
|
} zend_end_try();
|
2013-11-14 14:14:13 +00:00
|
|
|
|
2013-11-14 11:13:21 +00:00
|
|
|
/* phpdbg main() */
|
2013-11-11 08:02:04 +00:00
|
|
|
do {
|
|
|
|
zend_try {
|
2013-11-11 08:08:26 +00:00
|
|
|
phpdbg_interactive(TSRMLS_C);
|
2013-11-11 08:02:04 +00:00
|
|
|
} zend_catch {
|
2013-11-14 11:13:21 +00:00
|
|
|
if ((PHPDBG_G(flags) & PHPDBG_IS_CLEANING)) {
|
|
|
|
cleaning = 1;
|
2013-11-14 12:21:28 +00:00
|
|
|
goto phpdbg_out;
|
2013-11-14 11:13:21 +00:00
|
|
|
} else cleaning = 0;
|
2013-11-14 21:39:59 +00:00
|
|
|
|
2013-11-14 12:21:28 +00:00
|
|
|
if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) {
|
|
|
|
goto phpdbg_out;
|
|
|
|
}
|
2013-11-11 08:02:04 +00:00
|
|
|
} zend_end_try();
|
2013-11-12 01:24:53 +00:00
|
|
|
} while(!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING));
|
2013-11-12 13:07:35 +00:00
|
|
|
|
2013-11-14 12:21:28 +00:00
|
|
|
phpdbg_out:
|
|
|
|
|
2013-11-10 17:45:06 +00:00
|
|
|
if (ini_entries) {
|
|
|
|
free(ini_entries);
|
|
|
|
}
|
2013-11-09 23:07:04 +00:00
|
|
|
|
|
|
|
if (PG(modules_activated)) {
|
|
|
|
zend_try {
|
|
|
|
zend_deactivate_modules(TSRMLS_C);
|
|
|
|
} zend_end_try();
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_deactivate(TSRMLS_C);
|
|
|
|
|
|
|
|
zend_try {
|
|
|
|
zend_post_deactivate_modules(TSRMLS_C);
|
|
|
|
} zend_end_try();
|
|
|
|
|
2013-11-09 22:35:03 +00:00
|
|
|
#ifdef ZEND_SIGNALS
|
2013-11-09 23:07:04 +00:00
|
|
|
zend_try {
|
|
|
|
zend_signal_deactivate(TSRMLS_C);
|
|
|
|
} zend_end_try();
|
2013-11-09 22:35:03 +00:00
|
|
|
#endif
|
|
|
|
|
2013-11-14 11:30:31 +00:00
|
|
|
zend_try {
|
|
|
|
php_module_shutdown(TSRMLS_C);
|
|
|
|
} zend_end_try();
|
2013-11-09 23:07:04 +00:00
|
|
|
|
|
|
|
sapi_shutdown();
|
|
|
|
}
|
2013-11-14 21:39:59 +00:00
|
|
|
|
2013-11-14 11:13:21 +00:00
|
|
|
if (cleaning) {
|
|
|
|
goto phpdbg_main;
|
|
|
|
}
|
2013-11-09 23:07:04 +00:00
|
|
|
|
2013-11-09 22:35:03 +00:00
|
|
|
#ifdef ZTS
|
2013-11-14 21:39:59 +00:00
|
|
|
/* bugggy */
|
|
|
|
/* tsrm_shutdown(); */
|
2013-11-09 22:35:03 +00:00
|
|
|
#endif
|
|
|
|
|
2013-11-09 23:07:04 +00:00
|
|
|
return 0;
|
2013-11-09 22:35:03 +00:00
|
|
|
} /* }}} */
|