From 916164c80842ce05ec09d6ce9b2e37ea39ffc26e Mon Sep 17 00:00:00 2001 From: krakjoe Date: Thu, 21 Nov 2013 16:10:48 +0000 Subject: [PATCH 01/16] more on disassembler --- phpdbg_prompt.c | 71 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 4f557cdc9e5..e98f6cc8f2a 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -1029,22 +1029,21 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint { char *decode = NULL; - switch (type) { + switch (type &~ EXT_TYPE_UNUSED) { case IS_CV: asprintf(&decode, "$%s", ops->vars[op->var].name); break; case IS_VAR: case IS_TMP_VAR: { - zend_ulong id = 0; - if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &id) != SUCCESS) { + zend_ulong id = 0, *pid = NULL; + if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &pid) != SUCCESS) { id = zend_hash_num_elements(vars); zend_hash_index_update( vars, (zend_ulong) ops->vars - op->var, (void**) &id, sizeof(zend_ulong), NULL); - } - + } else id = *pid; asprintf(&decode, "@%lu", id); } break; @@ -1061,22 +1060,66 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC) /*{{{ */ { - char *decode[3]; - - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars TSRMLS_CC); - + char *decode[4] = {NULL, NULL, NULL, NULL}; + switch (op->opcode) { - default: asprintf( - &decode[0], "%-20s %-20s", - decode[1], decode[2] - ); + case ZEND_JMP: +#ifdef ZEND_GOTO + case ZEND_GOTO: +#endif +#ifdef ZEND_FAST_CALL + case ZEND_FAST_CALL: +#endif + asprintf(&decode[1], "#%lu", op->op1.jmp_addr - ops->opcodes); + goto format; + + + case ZEND_JMPZNZ: + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); + asprintf( + &decode[2], "#%lu or #%lu", op->op2.opline_num, op->extended_value); + goto result; + + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + +#ifdef ZEND_JMP_SET + case ZEND_JMP_SET: +#endif +#ifdef ZEND_JMP_SET_VAR + case ZEND_JMP_SET_VAR: +#endif + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); + asprintf( + &decode[2], "#%lu", op->op2.jmp_addr - ops->opcodes); + goto result; + + case ZEND_RECV_INIT: + goto result; + + default: { + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); + decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars TSRMLS_CC); +result: + decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars TSRMLS_CC); +format: + asprintf( + &decode[0], + "%-20s %-20s %-20s", + decode[1] ? decode[1] : "", + decode[2] ? decode[2] : "", + decode[3] ? decode[3] : ""); + } } if (decode[1]) free(decode[1]); if (decode[2]) free(decode[2]); + if (decode[3]) + free(decode[3]); return decode[0]; } /* }}} */ From a3bcdba660e3fb8b60fe67c9aee1029d6477f3fb Mon Sep 17 00:00:00 2001 From: krakjoe Date: Thu, 21 Nov 2013 16:30:27 +0000 Subject: [PATCH 02/16] ws --- phpdbg_prompt.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index e98f6cc8f2a..88c2f0ff550 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -1061,43 +1061,42 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC) /*{{{ */ { char *decode[4] = {NULL, NULL, NULL, NULL}; - + switch (op->opcode) { - case ZEND_JMP: + case ZEND_JMP: #ifdef ZEND_GOTO - case ZEND_GOTO: + case ZEND_GOTO: #endif #ifdef ZEND_FAST_CALL - case ZEND_FAST_CALL: + case ZEND_FAST_CALL: #endif - asprintf(&decode[1], "#%lu", op->op1.jmp_addr - ops->opcodes); - goto format; - - - case ZEND_JMPZNZ: - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - asprintf( - &decode[2], "#%lu or #%lu", op->op2.opline_num, op->extended_value); - goto result; + asprintf(&decode[1], "#%lu", op->op1.jmp_addr - ops->opcodes); + goto format; + + case ZEND_JMPZNZ: + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); + asprintf( + &decode[2], "#%lu or #%lu", op->op2.opline_num, op->extended_value); + goto result; - case ZEND_JMPZ: - case ZEND_JMPNZ: - case ZEND_JMPZ_EX: - case ZEND_JMPNZ_EX: + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: #ifdef ZEND_JMP_SET - case ZEND_JMP_SET: -#endif + case ZEND_JMP_SET: +#endif #ifdef ZEND_JMP_SET_VAR - case ZEND_JMP_SET_VAR: + case ZEND_JMP_SET_VAR: #endif decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); asprintf( &decode[2], "#%lu", op->op2.jmp_addr - ops->opcodes); goto result; - case ZEND_RECV_INIT: - goto result; + case ZEND_RECV_INIT: + goto result; default: { decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); @@ -1120,7 +1119,7 @@ format: free(decode[2]); if (decode[3]) free(decode[3]); - + return decode[0]; } /* }}} */ From a13583d1dfdb085b83500ce93733ee0349816ca8 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Thu, 21 Nov 2013 16:41:41 +0000 Subject: [PATCH 03/16] use constant numbers --- phpdbg_prompt.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 88c2f0ff550..016474b791d 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -1025,6 +1025,20 @@ out: return ret; } /* }}} */ +static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */ +{ + zend_uint iter = 0; + + while (iter < ops->last_literal) { + if (literal == &ops->literals[iter]) { + return iter; + } + iter++; + } + + return 0; +} /* }}} */ + static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint type, HashTable *vars TSRMLS_DC) /* {{{ */ { char *decode = NULL; @@ -1048,7 +1062,7 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint } break; case IS_CONST: - asprintf(&decode, ""); + asprintf(&decode, "C%lu", phpdbg_decode_literal(ops, op->literal TSRMLS_CC)); break; case IS_UNUSED: From 8743afbaa4c810cb0d137f0ff5602ecfa766fe7c Mon Sep 17 00:00:00 2001 From: krakjoe Date: Thu, 21 Nov 2013 16:45:12 +0000 Subject: [PATCH 04/16] move opcode stuff to opcode.c --- phpdbg_opcode.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ phpdbg_opcode.h | 1 + phpdbg_prompt.c | 112 ------------------------------------------------ 3 files changed, 113 insertions(+), 112 deletions(-) diff --git a/phpdbg_opcode.c b/phpdbg_opcode.c index fe9470f5d87..727f5e4c3de 100644 --- a/phpdbg_opcode.c +++ b/phpdbg_opcode.c @@ -21,6 +21,118 @@ #include "zend_compile.h" #include "phpdbg_opcode.h" +static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */ +{ + zend_uint iter = 0; + + while (iter < ops->last_literal) { + if (literal == &ops->literals[iter]) { + return iter; + } + iter++; + } + + return 0; +} /* }}} */ + +static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint type, HashTable *vars TSRMLS_DC) /* {{{ */ +{ + char *decode = NULL; + + switch (type &~ EXT_TYPE_UNUSED) { + case IS_CV: + asprintf(&decode, "$%s", ops->vars[op->var].name); + break; + + case IS_VAR: + case IS_TMP_VAR: { + zend_ulong id = 0, *pid = NULL; + if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &pid) != SUCCESS) { + id = zend_hash_num_elements(vars); + zend_hash_index_update( + vars, (zend_ulong) ops->vars - op->var, + (void**) &id, + sizeof(zend_ulong), NULL); + } else id = *pid; + asprintf(&decode, "@%lu", id); + } break; + + case IS_CONST: + asprintf(&decode, "C%lu", phpdbg_decode_literal(ops, op->literal TSRMLS_CC)); + break; + + case IS_UNUSED: + asprintf(&decode, ""); + break; + } + return decode; +} /* }}} */ + +char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC) /*{{{ */ +{ + char *decode[4] = {NULL, NULL, NULL, NULL}; + + switch (op->opcode) { + case ZEND_JMP: +#ifdef ZEND_GOTO + case ZEND_GOTO: +#endif +#ifdef ZEND_FAST_CALL + case ZEND_FAST_CALL: +#endif + asprintf(&decode[1], "#%lu", op->op1.jmp_addr - ops->opcodes); + goto format; + + case ZEND_JMPZNZ: + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); + asprintf( + &decode[2], "#%lu or #%lu", op->op2.opline_num, op->extended_value); + goto result; + + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + +#ifdef ZEND_JMP_SET + case ZEND_JMP_SET: +#endif +#ifdef ZEND_JMP_SET_VAR + case ZEND_JMP_SET_VAR: +#endif + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); + asprintf( + &decode[2], "#%lu", op->op2.jmp_addr - ops->opcodes); + goto result; + + case ZEND_RECV_INIT: + goto result; + + default: { + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); + decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars TSRMLS_CC); +result: + decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars TSRMLS_CC); +format: + asprintf( + &decode[0], + "%-20s %-20s %-20s", + decode[1] ? decode[1] : "", + decode[2] ? decode[2] : "", + decode[3] ? decode[3] : ""); + } + } + + if (decode[1]) + free(decode[1]); + if (decode[2]) + free(decode[2]); + if (decode[3]) + free(decode[3]); + + return decode[0]; +} /* }}} */ + const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */ { #define CASE(s) case s: return #s diff --git a/phpdbg_opcode.h b/phpdbg_opcode.h index 28fc806c1c0..83c0ac5addc 100644 --- a/phpdbg_opcode.h +++ b/phpdbg_opcode.h @@ -23,5 +23,6 @@ #include "zend_types.h" const char *phpdbg_decode_opcode(zend_uchar); +char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC); #endif /* PHPDBG_OPCODE_H */ diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 016474b791d..860183b101c 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -1025,118 +1025,6 @@ out: return ret; } /* }}} */ -static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */ -{ - zend_uint iter = 0; - - while (iter < ops->last_literal) { - if (literal == &ops->literals[iter]) { - return iter; - } - iter++; - } - - return 0; -} /* }}} */ - -static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint type, HashTable *vars TSRMLS_DC) /* {{{ */ -{ - char *decode = NULL; - - switch (type &~ EXT_TYPE_UNUSED) { - case IS_CV: - asprintf(&decode, "$%s", ops->vars[op->var].name); - break; - - case IS_VAR: - case IS_TMP_VAR: { - zend_ulong id = 0, *pid = NULL; - if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &pid) != SUCCESS) { - id = zend_hash_num_elements(vars); - zend_hash_index_update( - vars, (zend_ulong) ops->vars - op->var, - (void**) &id, - sizeof(zend_ulong), NULL); - } else id = *pid; - asprintf(&decode, "@%lu", id); - } break; - - case IS_CONST: - asprintf(&decode, "C%lu", phpdbg_decode_literal(ops, op->literal TSRMLS_CC)); - break; - - case IS_UNUSED: - asprintf(&decode, ""); - break; - } - return decode; -} /* }}} */ - -char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC) /*{{{ */ -{ - char *decode[4] = {NULL, NULL, NULL, NULL}; - - switch (op->opcode) { - case ZEND_JMP: -#ifdef ZEND_GOTO - case ZEND_GOTO: -#endif -#ifdef ZEND_FAST_CALL - case ZEND_FAST_CALL: -#endif - asprintf(&decode[1], "#%lu", op->op1.jmp_addr - ops->opcodes); - goto format; - - case ZEND_JMPZNZ: - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - asprintf( - &decode[2], "#%lu or #%lu", op->op2.opline_num, op->extended_value); - goto result; - - case ZEND_JMPZ: - case ZEND_JMPNZ: - case ZEND_JMPZ_EX: - case ZEND_JMPNZ_EX: - -#ifdef ZEND_JMP_SET - case ZEND_JMP_SET: -#endif -#ifdef ZEND_JMP_SET_VAR - case ZEND_JMP_SET_VAR: -#endif - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - asprintf( - &decode[2], "#%lu", op->op2.jmp_addr - ops->opcodes); - goto result; - - case ZEND_RECV_INIT: - goto result; - - default: { - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars TSRMLS_CC); -result: - decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars TSRMLS_CC); -format: - asprintf( - &decode[0], - "%-20s %-20s %-20s", - decode[1] ? decode[1] : "", - decode[2] ? decode[2] : "", - decode[3] ? decode[3] : ""); - } - } - - if (decode[1]) - free(decode[1]); - if (decode[2]) - free(decode[2]); - if (decode[3]) - free(decode[3]); - - return decode[0]; -} /* }}} */ - void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, zend_bool ignore_flags TSRMLS_DC) /* {{{ */ { /* force out a line while stepping so the user knows what is happening */ From cdd72cfda77b5770a10e57399c12c0e4f4360937 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Thu, 21 Nov 2013 19:47:31 +0000 Subject: [PATCH 05/16] housekeeping, moving stuff to appropriate units --- phpdbg.c | 6 ++++++ phpdbg_opcode.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ phpdbg_opcode.h | 2 ++ phpdbg_prompt.c | 51 +------------------------------------------------ phpdbg_prompt.h | 24 ++++++++++++----------- 5 files changed, 69 insertions(+), 61 deletions(-) diff --git a/phpdbg.c b/phpdbg.c index 6b219fa7561..d417a89158d 100644 --- a/phpdbg.c +++ b/phpdbg.c @@ -434,6 +434,12 @@ static void phpdbg_welcome(zend_bool cleaning TSRMLS_DC) /* {{{ */ } } /* }}} */ +static inline void phpdbg_sigint_handler(int signo) /* {{{ */ +{ + TSRMLS_FETCH(); + PHPDBG_G(flags) |= PHPDBG_IS_SIGNALED; +} /* }}} */ + int main(int argc, char **argv) /* {{{ */ { sapi_module_struct *phpdbg = &phpdbg_sapi_module; diff --git a/phpdbg_opcode.c b/phpdbg_opcode.c index 727f5e4c3de..9fa357c4fa5 100644 --- a/phpdbg_opcode.c +++ b/phpdbg_opcode.c @@ -17,9 +17,13 @@ +----------------------------------------------------------------------+ */ +#include "phpdbg.h" #include "zend_vm_opcodes.h" #include "zend_compile.h" #include "phpdbg_opcode.h" +#include "phpdbg_utils.h" + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg); static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */ { @@ -133,6 +137,49 @@ format: return decode[0]; } /* }}} */ +void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, zend_bool ignore_flags TSRMLS_DC) /* {{{ */ +{ + /* force out a line while stepping so the user knows what is happening */ + if (ignore_flags || + (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || + (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) || + (PHPDBG_G(oplog)))) { + + zend_op *opline = execute_data->opline; + char *decode = phpdbg_decode_opline(execute_data->op_array, opline, vars TSRMLS_CC); + + if (ignore_flags || + (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || + (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) { + /* output line info */ + phpdbg_notice("#%- 5lu %16p %-30s %s %s", + opline->lineno, + opline, + phpdbg_decode_opcode(opline->opcode), + decode, + execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); + } + + if (!ignore_flags && PHPDBG_G(oplog)) { + phpdbg_log_ex(PHPDBG_G(oplog), "#%- 5lu %16p %-30s %s %s", + opline->lineno, + opline, + phpdbg_decode_opcode(opline->opcode), + decode, + execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); + } + + if (decode) { + free(decode); + } + } +} /* }}} */ + +void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC) /* {{{ */ +{ + phpdbg_print_opline_ex(execute_data, NULL, ignore_flags TSRMLS_CC); +} /* }}} */ + const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */ { #define CASE(s) case s: return #s diff --git a/phpdbg_opcode.h b/phpdbg_opcode.h index 83c0ac5addc..dfa443a0644 100644 --- a/phpdbg_opcode.h +++ b/phpdbg_opcode.h @@ -24,5 +24,7 @@ const char *phpdbg_decode_opcode(zend_uchar); char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC); +void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC); +void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, zend_bool ignore_flags TSRMLS_DC); #endif /* PHPDBG_OPCODE_H */ diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 860183b101c..85222e8c5dc 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -34,7 +34,7 @@ #include "phpdbg_cmd.h" /* {{{ command declarations */ -static const phpdbg_command_t phpdbg_prompt_commands[] = { +const phpdbg_command_t phpdbg_prompt_commands[] = { PHPDBG_COMMAND_D(exec, "set execution context", 'e', NULL, 1), PHPDBG_COMMAND_D(compile, "attempt compilation", 'c', NULL, 0), PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, 1), @@ -1025,49 +1025,6 @@ out: return ret; } /* }}} */ -void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, zend_bool ignore_flags TSRMLS_DC) /* {{{ */ -{ - /* force out a line while stepping so the user knows what is happening */ - if (ignore_flags || - (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || - (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) || - (PHPDBG_G(oplog)))) { - - zend_op *opline = execute_data->opline; - char *decode = phpdbg_decode_opline(execute_data->op_array, opline, vars TSRMLS_CC); - - if (ignore_flags || - (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || - (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) { - /* output line info */ - phpdbg_notice("#%- 5lu %16p %-30s %s %s", - opline->lineno, - opline, - phpdbg_decode_opcode(opline->opcode), - decode, - execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); - } - - if (!ignore_flags && PHPDBG_G(oplog)) { - phpdbg_log_ex(PHPDBG_G(oplog), "#%- 5lu %16p %-30s %s %s", - opline->lineno, - opline, - phpdbg_decode_opcode(opline->opcode), - decode, - execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); - } - - if (decode) { - free(decode); - } - } -} /* }}} */ - -void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC) /* {{{ */ -{ - phpdbg_print_opline_ex(execute_data, NULL, ignore_flags TSRMLS_CC); -} /* }}} */ - void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */ { /* this is implicitly required */ @@ -1084,12 +1041,6 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */ } } /* }}} */ -void phpdbg_sigint_handler(int signo) -{ - TSRMLS_FETCH(); - PHPDBG_G(flags) |= PHPDBG_IS_SIGNALED; -} - static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ { #if PHP_VERSION_ID >= 50500 diff --git a/phpdbg_prompt.h b/phpdbg_prompt.h index a410cc4ec4a..89623d0835f 100644 --- a/phpdbg_prompt.h +++ b/phpdbg_prompt.h @@ -20,21 +20,13 @@ #ifndef PHPDBG_PROMPT_H #define PHPDBG_PROMPT_H +/* {{{ */ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TSRMLS_DC); int phpdbg_interactive(TSRMLS_D); -void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC); -char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC); int phpdbg_compile(TSRMLS_D); -void phpdbg_clean(zend_bool full TSRMLS_DC); -void phpdbg_sigint_handler(int signo); +void phpdbg_clean(zend_bool full TSRMLS_DC); /* }}} */ -#if PHP_VERSION_ID >= 50500 -void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC); -#else -void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC); -#endif - -/* {{{ */ +/* {{{ phpdbg command handlers */ PHPDBG_COMMAND(exec); PHPDBG_COMMAND(compile); PHPDBG_COMMAND(step); @@ -59,4 +51,14 @@ PHPDBG_COMMAND(oplog); PHPDBG_COMMAND(register); PHPDBG_COMMAND(quit); /* }}} */ +/* {{{ prompt commands */ +extern const phpdbg_command_t phpdbg_prompt_commands[]; /* }}} */ + +/* {{{ */ +#if PHP_VERSION_ID >= 50500 +void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC); +#else +void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC); +#endif /* }}} */ + #endif /* PHPDBG_PROMPT_H */ From 8350ca4621dae06d2b9c2813b26ba5d59bd9f4f6 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Thu, 21 Nov 2013 20:56:28 +0000 Subject: [PATCH 06/16] ... --- tutorials/Thumbs.db | Bin 47616 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tutorials/Thumbs.db diff --git a/tutorials/Thumbs.db b/tutorials/Thumbs.db deleted file mode 100644 index d64654ac9ea316fd5e9c0f9ba965086f4b460e13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47616 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 From bea935f56e2464ecc1f07cf8df9a0dddf3bf5866 Mon Sep 17 00:00:00 2001 From: Harald Lapp Date: Thu, 21 Nov 2013 22:15:47 +0100 Subject: [PATCH 07/16] Fixed typo in Makefile.frag --- Makefile.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.frag b/Makefile.frag index 5482a9e7fb6..8789bc782c7 100644 --- a/Makefile.frag +++ b/Makefile.frag @@ -8,7 +8,7 @@ install-phpdbg: $(BUILD_BINARY) @$(mkinstalldirs) $(INSTALL_ROOT)$(bindir) @$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/log @$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/run - @$(INSTALL) -m 0755 $(BUILD_BINARY) $(INSTALL_ROOT)$(sbindir)/$(program_prefix)phpdbg$(program_suffix)$(EXEEXT) + @$(INSTALL) -m 0755 $(BUILD_BINARY) $(INSTALL_ROOT)$(bindir)/$(program_prefix)phpdbg$(program_suffix)$(EXEEXT) clean-phpdbg: @echo "Cleaning phpdbg object files ..." From 62a104170c8b29e4ff9d44ad8ce4930dab64a5f3 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 21 Nov 2013 19:20:10 -0200 Subject: [PATCH 08/16] - Fixed compiler warning --- phpdbg_opcode.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/phpdbg_opcode.c b/phpdbg_opcode.c index 9fa357c4fa5..74b0c7e0e3f 100644 --- a/phpdbg_opcode.c +++ b/phpdbg_opcode.c @@ -28,14 +28,14 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */ { zend_uint iter = 0; - + while (iter < ops->last_literal) { if (literal == &ops->literals[iter]) { return iter; } iter++; } - + return 0; } /* }}} */ @@ -47,24 +47,24 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint case IS_CV: asprintf(&decode, "$%s", ops->vars[op->var].name); break; - + case IS_VAR: case IS_TMP_VAR: { zend_ulong id = 0, *pid = NULL; if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &pid) != SUCCESS) { id = zend_hash_num_elements(vars); zend_hash_index_update( - vars, (zend_ulong) ops->vars - op->var, - (void**) &id, + vars, (zend_ulong) ops->vars - op->var, + (void**) &id, sizeof(zend_ulong), NULL); } else id = *pid; asprintf(&decode, "@%lu", id); } break; - + case IS_CONST: - asprintf(&decode, "C%lu", phpdbg_decode_literal(ops, op->literal TSRMLS_CC)); + asprintf(&decode, "C%u", phpdbg_decode_literal(ops, op->literal TSRMLS_CC)); break; - + case IS_UNUSED: asprintf(&decode, ""); break; @@ -75,7 +75,7 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC) /*{{{ */ { char *decode[4] = {NULL, NULL, NULL, NULL}; - + switch (op->opcode) { case ZEND_JMP: #ifdef ZEND_GOTO @@ -86,18 +86,18 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRM #endif asprintf(&decode[1], "#%lu", op->op1.jmp_addr - ops->opcodes); goto format; - + case ZEND_JMPZNZ: decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); asprintf( - &decode[2], "#%lu or #%lu", op->op2.opline_num, op->extended_value); + &decode[2], "#%u or #%lu", op->op2.opline_num, op->extended_value); goto result; - + case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: - + #ifdef ZEND_JMP_SET case ZEND_JMP_SET: #endif @@ -111,22 +111,22 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRM case ZEND_RECV_INIT: goto result; - + default: { decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars TSRMLS_CC); result: - decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars TSRMLS_CC); + decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars TSRMLS_CC); format: asprintf( &decode[0], - "%-20s %-20s %-20s", - decode[1] ? decode[1] : "", + "%-20s %-20s %-20s", + decode[1] ? decode[1] : "", decode[2] ? decode[2] : "", decode[3] ? decode[3] : ""); } } - + if (decode[1]) free(decode[1]); if (decode[2]) @@ -147,7 +147,7 @@ void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, ze zend_op *opline = execute_data->opline; char *decode = phpdbg_decode_opline(execute_data->op_array, opline, vars TSRMLS_CC); - + if (ignore_flags || (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) { @@ -168,7 +168,7 @@ void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, ze decode, execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); } - + if (decode) { free(decode); } @@ -356,7 +356,7 @@ const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */ CASE(ZEND_RECV_VARIADIC); #endif CASE(ZEND_OP_DATA); - default: + default: return "UNKNOWN"; } } /* }}} */ From 601b75731a1ba51aa7f8c9c268e70dda9fb49dda Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 21 Nov 2013 21:19:55 -0200 Subject: [PATCH 09/16] - WS --- phpdbg_prompt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 85222e8c5dc..7099ecb6f72 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -511,7 +511,7 @@ PHPDBG_COMMAND(eval) /* {{{ */ PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; } } break; - + phpdbg_default_switch_case(); } @@ -612,7 +612,7 @@ PHPDBG_COMMAND(info) /* {{{ */ { phpdbg_error( "No information command selected !"); - + return SUCCESS; } /* }}} */ @@ -1115,7 +1115,7 @@ void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC) /* {{{ */ #endif zend_bool original_in_execution = EG(in_execution); HashTable vars; - + #if PHP_VERSION_ID < 50500 if (EG(exception)) { return; @@ -1265,8 +1265,8 @@ next: DO_INTERACTIVE(); } - PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC); - + PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC); + if (PHPDBG_G(vmret) > 0) { switch (PHPDBG_G(vmret)) { case 1: From a6bd3807c44fcd7e27c5d7135f843f2c69e536db Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 09:09:54 +0000 Subject: [PATCH 10/16] better handling of sigint info literals command --- phpdbg.c | 13 ++++++++++++- phpdbg.h | 1 + phpdbg_cmd.c | 10 ++++++---- phpdbg_info.c | 22 ++++++++++++++++++++++ phpdbg_info.h | 12 +++++++----- phpdbg_prompt.c | 6 +++++- 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/phpdbg.c b/phpdbg.c index d417a89158d..27fedee9b45 100644 --- a/phpdbg.c +++ b/phpdbg.c @@ -437,7 +437,18 @@ static void phpdbg_welcome(zend_bool cleaning TSRMLS_DC) /* {{{ */ static inline void phpdbg_sigint_handler(int signo) /* {{{ */ { TSRMLS_FETCH(); - PHPDBG_G(flags) |= PHPDBG_IS_SIGNALED; + + if (EG(in_execution)) { + /* we don't want to set signalled while phpdbg is interactive */ + if (!(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) { + PHPDBG_G(flags) |= PHPDBG_IS_SIGNALED; + } + } else { + /* if we are not executing then just provide advice */ + phpdbg_writeln(EMPTY); + phpdbg_error( + "Please leave phpdbg gracefully !"); + } } /* }}} */ int main(int argc, char **argv) /* {{{ */ diff --git a/phpdbg.h b/phpdbg.h index 967cd8fb0be..1cff51ee9f6 100644 --- a/phpdbg.h +++ b/phpdbg.h @@ -100,6 +100,7 @@ #define PHPDBG_IS_STEPONEVAL (1<<17) #define PHPDBG_IS_INITIALIZING (1<<18) #define PHPDBG_IS_SIGNALED (1<<19) +#define PHPDBG_IS_INTERACTIVE (1<<20) #ifndef _WIN32 # define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED) diff --git a/phpdbg_cmd.c b/phpdbg_cmd.c index d7d8c0d4fcd..75b55dfb693 100644 --- a/phpdbg_cmd.c +++ b/phpdbg_cmd.c @@ -377,10 +377,12 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, phpdbg_input_t *input TSRMLS_ } } - PHPDBG_G(lcmd) = (phpdbg_command_t*) command; - phpdbg_clear_param( - &PHPDBG_G(lparam) TSRMLS_CC); - PHPDBG_G(lparam) = param; + if (!(PHPDBG_G(flags) & PHPDBG_IS_INITIALIZING)) { + PHPDBG_G(lcmd) = (phpdbg_command_t*) command; + phpdbg_clear_param( + &PHPDBG_G(lparam) TSRMLS_CC); + PHPDBG_G(lparam) = param; + } rc = command->handler(¶m, input TSRMLS_CC); break; diff --git a/phpdbg_info.c b/phpdbg_info.c index 09c91d5af68..a3a3f01989e 100644 --- a/phpdbg_info.c +++ b/phpdbg_info.c @@ -144,6 +144,28 @@ PHPDBG_INFO(vars) /* {{{ */ return SUCCESS; } /* }}} */ +PHPDBG_INFO(literal) /* {{{ */ +{ + if (EG(in_execution) && EG(active_op_array)) { + zend_uint literal =0; + phpdbg_notice( + "Literal Constants %d", EG(active_op_array)->last_literal-1); + + while (literal < EG(active_op_array)->last_literal) { + phpdbg_write("|-------- C%lu -------> [", literal); + zend_print_zval( + &EG(active_op_array)->literals[literal].constant, 0); + phpdbg_write("]"); + phpdbg_writeln(EMPTY); + literal++; + } + } else { + phpdbg_error("Not executing !"); + } + + return SUCCESS; +} /* }}} */ + static inline void phpdbg_print_class_name(zend_class_entry **ce TSRMLS_DC) /* {{{ */ { phpdbg_write( diff --git a/phpdbg_info.h b/phpdbg_info.h index 5e88b731cb0..727a3d6f65d 100644 --- a/phpdbg_info.h +++ b/phpdbg_info.h @@ -29,13 +29,15 @@ PHPDBG_INFO(classes); PHPDBG_INFO(funcs); PHPDBG_INFO(error); PHPDBG_INFO(vars); +PHPDBG_INFO(literal); static const phpdbg_command_t phpdbg_info_commands[] = { - PHPDBG_COMMAND_D_EX(files, "lists included files", 'F', info_files, NULL, 0), - PHPDBG_COMMAND_D_EX(classes, "lists loaded classes", 'c', info_classes, NULL, 0), - PHPDBG_COMMAND_D_EX(funcs, "lists loaded classes", 'f', info_funcs, NULL, 0), - PHPDBG_COMMAND_D_EX(error, "show the last error", 'e', info_error, NULL, 0), - PHPDBG_COMMAND_D_EX(vars, "show active variables", 'v', info_vars, NULL, 0), + PHPDBG_COMMAND_D_EX(files, "lists included files", 'F', info_files, NULL, 0), + PHPDBG_COMMAND_D_EX(classes, "lists loaded classes", 'c', info_classes, NULL, 0), + PHPDBG_COMMAND_D_EX(funcs, "lists loaded classes", 'f', info_funcs, NULL, 0), + PHPDBG_COMMAND_D_EX(error, "show the last error", 'e', info_error, NULL, 0), + PHPDBG_COMMAND_D_EX(vars, "show active variables", 'v', info_vars, NULL, 0), + PHPDBG_COMMAND_D_EX(literal, "show active literal constants", 'l', info_literal, NULL, 0), PHPDBG_END_COMMAND }; diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 7099ecb6f72..fdd60449bf1 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -980,8 +980,10 @@ int phpdbg_interactive(TSRMLS_D) /* {{{ */ { int ret = SUCCESS; - phpdbg_input_t *input = phpdbg_read_input(NULL TSRMLS_CC); + PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE; + phpdbg_input_t *input = phpdbg_read_input(NULL TSRMLS_CC); + if (input && input->length > 0L) { do { switch (ret = phpdbg_do_cmd(phpdbg_prompt_commands, input TSRMLS_CC)) { @@ -1021,6 +1023,8 @@ last: out: phpdbg_destroy_input(&input TSRMLS_CC); + + PHPDBG_G(flags) &= ~PHPDBG_IS_INTERACTIVE; return ret; } /* }}} */ From 46a67d15fe5d50d56c1372b0d2518cbe3e3cace3 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 09:56:17 +0000 Subject: [PATCH 11/16] better info literal --- phpdbg_info.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/phpdbg_info.c b/phpdbg_info.c index a3a3f01989e..4b98267ab0f 100644 --- a/phpdbg_info.c +++ b/phpdbg_info.c @@ -18,9 +18,12 @@ */ #include "php.h" +#include "phpdbg.h" #include "phpdbg_utils.h" #include "phpdbg_info.h" +ZEND_EXTERN_MODULE_GLOBALS(phpdbg); + PHPDBG_INFO(files) /* {{{ */ { HashPosition pos; @@ -146,15 +149,32 @@ PHPDBG_INFO(vars) /* {{{ */ PHPDBG_INFO(literal) /* {{{ */ { - if (EG(in_execution) && EG(active_op_array)) { - zend_uint literal =0; - phpdbg_notice( - "Literal Constants %d", EG(active_op_array)->last_literal-1); + 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); + zend_uint literal =0, count = ops->last_literal-1; - while (literal < EG(active_op_array)->last_literal) { + if (ops->function_name) { + if (ops->scope) { + phpdbg_notice( + "Literal Constants in %s::%s() (%d)", ops->scope->name, ops->function_name, count); + } else { + phpdbg_notice( + "Literal Constants in %s() (%d)", ops->function_name, count); + } + } else { + if (ops->filename) { + phpdbg_notice( + "Literal Constants in %s (%d)", ops->filename, count); + } else { + phpdbg_notice( + "Literal Constants @ %p (%d)", ops, count); + } + } + + while (literal < ops->last_literal) { phpdbg_write("|-------- C%lu -------> [", literal); zend_print_zval( - &EG(active_op_array)->literals[literal].constant, 0); + &ops->literals[literal].constant, 0); phpdbg_write("]"); phpdbg_writeln(EMPTY); literal++; From c51e7e26e9155bda8674b464ea4c419a0c89013f Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 10:39:21 +0000 Subject: [PATCH 12/16] add readline completion tip to phpdbginit --- .phpdbginit | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.phpdbginit b/.phpdbginit index 10c831b0329..463a2c46e0d 100644 --- a/.phpdbginit +++ b/.phpdbginit @@ -31,6 +31,18 @@ function my_debugging_function() /* phpdbg_break(PHPDBG_METHOD, "phpdbg::method"); */ /* phpdbg_break(PHPDBG_FUNC, "my_global_function"); */ /* phpdbg_break(PHPDBG_FILE, "/path/to/file.php:10"); */ + +/* + If readline is loaded, you might want to setup completion for your project: +*/ +if (function_exists('readline_completion_function')) { + readline_completion_function(function(){ + return array_merge( + get_defined_functions()['user'], + array_keys(get_defined_constants()) + ); + }); +} :> ########################################################## # Now carry on initializing phpdbg ... From f1042cb028987a80df9aea530e19a185aa777fc8 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 10:40:24 +0000 Subject: [PATCH 13/16] ... --- .phpdbginit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.phpdbginit b/.phpdbginit index 463a2c46e0d..9e02c6d8a54 100644 --- a/.phpdbginit +++ b/.phpdbginit @@ -33,7 +33,7 @@ function my_debugging_function() /* phpdbg_break(PHPDBG_FILE, "/path/to/file.php:10"); */ /* - If readline is loaded, you might want to setup completion for your project: + If readline is loaded, you might want to setup completion: */ if (function_exists('readline_completion_function')) { readline_completion_function(function(){ From 4fd2edbeb42b842d0c7cdb00363c7b09aa89b906 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 12:38:40 +0000 Subject: [PATCH 14/16] initializing tut --- tutorials/initializing.md | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tutorials/initializing.md diff --git a/tutorials/initializing.md b/tutorials/initializing.md new file mode 100644 index 00000000000..de01bb23fa0 --- /dev/null +++ b/tutorials/initializing.md @@ -0,0 +1,82 @@ +phpdbginit +========== +*Setting up your debugging session automatically* + +By default, phpdbg looks for *.phpdbginit* in the current working directory, this location can be overrideen on the command line: + +``` +phpdbg -imy.phpdbginit +``` + +An init file should contain one command per line, any phpdbg command is supported during init. + +In addition, *.phpdbginit* can contain embedded code, allowing, for example + + - the setup of auto completion + - the registration of functions + - the acquisition and pre-compilation of code + - bootstrapping a web application + +It is common for C projects (PHP included) to include an init file for the GDB debugger; this would be a clever practice to adopt +for those distributing PHP library code. + +The default .phpdbginit +======================= + +We distribute the following init file by default, it should be copied to any directory you commonly execute in: + +``` +########################################################## +# .phpdbginit +# +# Lines starting with # are ignored +# Code must start and end with <: and :> respectively +########################################################## +# Place initialization commands one per line +########################################################## +# exec sapi/phpdbg/test.php + +########################################################## +# Embedding code in .phpdbginit +########################################################## +<: +/* + If readline is loaded, you might want to setup completion: +*/ +if (function_exists('readline_completion_function')) { + readline_completion_function(function(){ + return array_merge( + get_defined_functions()['user'], + array_keys(get_defined_constants()) + ); + }); +} +:> +########################################################## +# Now carry on initializing phpdbg ... +########################################################## +# R my_debugging_function + +########################################################## +# PHP has many functions that might be useful +# ... you choose ... +########################################################## +# R touch +# R unlink +# R scandir +# R glob + +########################################################## +# Remember: *you have access to the shell* +########################################################## +# The output of registered function calls is not, +# by default, very pretty (unless you implement +# and register a new implementation for phpdbg) +# The output of shell commands will usually be more +# readable on the console +########################################################## +# TLDR; if you have a good shell, use it ... +########################################################## +``` + + From e0c4f87a897e005f5927baa8a747e6266d052813 Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 13:49:35 +0000 Subject: [PATCH 15/16] another tut --- tutorials/simples.md | 132 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 tutorials/simples.md diff --git a/tutorials/simples.md b/tutorials/simples.md new file mode 100644 index 00000000000..d8b53d6979d --- /dev/null +++ b/tutorials/simples.md @@ -0,0 +1,132 @@ +Simples +======= +*Everything is simple ...* + +It is easy to imagine that debugging a whole web application might be difficult, in a console program, in fact this is not the case: + +A web application is just an instance of the PHP interpreter with some very specific super globals set. + +With everything in the correct place, your web application has no clue that it being served not to a client, but to you, probably in your underwear. + +With the facts established, you can use phpdbg to debug anything that is PHP, with a bit of cleverness in the right places. + +Very Simple +=========== +*A good starting place ...* + +``` +phpdbg -e/path/to/my/script.php +``` + +The command above will result in a phpdbg console that has executed *.phpdbginit* (if it exists) and is ready to compile, inspect, step through +and execute the code contained in */path/to/my/script.php* + +The first thing to do upon being presented with the console, is decide what to break for ... + +Many options exist for choosing (and setting) breakpoints: + +``` +phpdbg> b phpdbg::isGreat +phpdbg> b phpdbg_is_great +``` + +The commands above will be the most common for most developers; that is, specifying the entry point of a function or method on which to break execution. + +Introspection of code is supported on the console, for anything that is compiled, if help is required remembering the name of a particular method then issue: + +``` +phpdbg> compile +phpdbg> print class myClassName +``` + +Introspection doesn't only provide you with names, but the addresses of every opcode in every statement, which you may use to specify with as much precision as +is possible where to break execution. + +**There is a print command for particular methods, useful if a class is very large and your screen is not !** + +At this point, break points are set; the next thing to do is issue the run command: + +``` +phpdbg> run +``` + +This will cause execution of the context, if a breakpoint is reached, the interactive console returns such that more commands can be issued. + +When a breakpoint is reached, several options for continuation exist: + + - step through every instruction + - run past the end of the stack + - run to the end of the stack + +*Q: WTF is a stack?* + +*A: Generally the current codepath, more precisely: current function, method or file* + +Just quickly; an explanation of what "to" and "past" the end of a "stack" means: + +Assuming there is a break set for *my_function_somewhere* in the following code: + +``` +function my_function_somewhere($input = array()) /* break here on entry to the function */ +{ + /* ... the stack ... */ + + if (count($input)) + { + /* to -> */ return $input[1]; + } + else + { + /* to -> */ return rand(1, 100); + } +} + +/* past -> */ $result = my_function_somewhere(); +if ($result) +{ + /* and so on */ + var_dump($result); +} +``` + +The commands *finish* and *leave*, run *past* and *to* the end of the stack respecitively. + +**Note: the finish command does not automatically break; to break past the end of the stack enable stepping before issuing finish, the leave command breaks implicitly** + +On with execution ... +===================== +*Stepping, slowly, is sometimes the way forward ...* + +Should you want to inspect what happens during the execution of the stack, enable stepping: + +``` +phpdbg> step 1 +``` + +In case it wasn't obvious, the next thing to do is nearly always *next*: + +``` +phpdbg> next +``` + +Which will cause the vm to assume control and continue execution until the next break point, or completion. + +Stepping through every single instruction is not usually beneficial, issue: + +``` +phpdbg> step 0 +``` + +To disable stepping again, and only interrupt execution for breakpoints. + +As hard as it gets ... +====================== +*Web Applications* + +As mentioned, a web application is only a script executing with some specific super globals set; + +**The mocking of any web request just requires that you set the super globals of the script accordingly** + +We refer to this as "bootstrapping", mostly because I have always wanted a genuine reason to use that word. + +See the example, for help with bootstrapping ... From 022eb18d1de326fe5a5f8ea4c42b414c14d7ff7a Mon Sep 17 00:00:00 2001 From: krakjoe Date: Fri, 22 Nov 2013 16:15:24 +0000 Subject: [PATCH 16/16] ... --- phpdbg.c | 12 +++++++++++- phpdbg.h | 6 ++++++ phpdbg_cmd.c | 2 +- phpdbg_utils.h | 12 ++++++------ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/phpdbg.c b/phpdbg.c index 27fedee9b45..f15f49f589a 100644 --- a/phpdbg.c +++ b/phpdbg.c @@ -44,6 +44,9 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ pg->lcmd = NULL; pg->flags = PHPDBG_DEFAULT_FLAGS; pg->oplog = NULL; + pg->io[PHPDBG_STDIN] = NULL; + pg->io[PHPDBG_STDOUT] = NULL; + pg->io[PHPDBG_STDERR] = NULL; memset(&pg->lparam, 0, sizeof(phpdbg_param_t)); } /* }}} */ @@ -339,7 +342,9 @@ static inline int php_sapi_phpdbg_ub_write(const char *message, unsigned int len static inline void php_sapi_phpdbg_flush(void *context) /* {{{ */ { - fflush(stdout); + TSRMLS_FETCH(); + + fflush(PHPDBG_G(io)[PHPDBG_STDOUT]); } /* }}} */ /* {{{ sapi_module_struct phpdbg_sapi_module @@ -636,6 +641,11 @@ phpdbg_main: PG(modules_activated) = 0; + /* set up basic io here */ + PHPDBG_G(io)[PHPDBG_STDIN] = stdin; + PHPDBG_G(io)[PHPDBG_STDOUT] = stdout; + PHPDBG_G(io)[PHPDBG_STDERR] = stderr; + if (exec) { /* set execution context */ PHPDBG_G(exec) = phpdbg_resolve_path( exec TSRMLS_CC); diff --git a/phpdbg.h b/phpdbg.h index 1cff51ee9f6..aa6c7ca7c2d 100644 --- a/phpdbg.h +++ b/phpdbg.h @@ -112,6 +112,11 @@ #define PHPDBG_ISSUES "http://github.com/krakjoe/phpdbg/issues" #define PHPDBG_VERSION "0.0.2-dev" /* }}} */ +/* {{{ output descriptors */ +#define PHPDBG_STDIN 0 +#define PHPDBG_STDOUT 1 +#define PHPDBG_STDERR 2 /* }}} */ + /* {{{ structs */ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) HashTable bp[PHPDBG_BREAK_TABLES]; /* break points */ @@ -127,6 +132,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) HashTable seek; /* seek oplines */ zend_ulong flags; /* phpdbg flags */ HashTable registered; /* registered */ + FILE *io[3]; /* stdin/stdout/stderr */ ZEND_END_MODULE_GLOBALS(phpdbg) /* }}} */ #endif /* PHPDBG_H */ diff --git a/phpdbg_cmd.c b/phpdbg_cmd.c index 75b55dfb693..28f085e8dba 100644 --- a/phpdbg_cmd.c +++ b/phpdbg_cmd.c @@ -218,7 +218,7 @@ phpdbg_input_t *phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */ #ifndef HAVE_LIBREADLINE char buf[PHPDBG_MAX_CMD]; if (!phpdbg_write(PROMPT) || - !fgets(buf, PHPDBG_MAX_CMD, stdin)) { + !fgets(buf, PHPDBG_MAX_CMD, PHPDBG_G(io)[PHPDBG_STDIN])) { /* the user has gone away */ phpdbg_error("Failed to read console !"); PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; diff --git a/phpdbg_utils.h b/phpdbg_utils.h index 0a6ad4f4fa8..1178dcace86 100644 --- a/phpdbg_utils.h +++ b/phpdbg_utils.h @@ -44,11 +44,11 @@ enum { int phpdbg_print(int TSRMLS_DC, FILE*, const char*, ...); -#define phpdbg_error(fmt, ...) phpdbg_print(P_ERROR TSRMLS_CC, stdout, fmt, ##__VA_ARGS__) -#define phpdbg_notice(fmt, ...) phpdbg_print(P_NOTICE TSRMLS_CC, stdout, fmt, ##__VA_ARGS__) -#define phpdbg_writeln(fmt, ...) phpdbg_print(P_WRITELN TSRMLS_CC, stdout, fmt, ##__VA_ARGS__) -#define phpdbg_write(fmt, ...) phpdbg_print(P_WRITE TSRMLS_CC, stdout, fmt, ##__VA_ARGS__) -#define phpdbg_log(fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, stdout, fmt, ##__VA_ARGS__) +#define phpdbg_error(fmt, ...) phpdbg_print(P_ERROR TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) +#define phpdbg_notice(fmt, ...) phpdbg_print(P_NOTICE TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) +#define phpdbg_writeln(fmt, ...) phpdbg_print(P_WRITELN TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) +#define phpdbg_write(fmt, ...) phpdbg_print(P_WRITE TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) +#define phpdbg_log(fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) #define phpdbg_error_ex(out, fmt, ...) phpdbg_print(P_ERROR TSRMLS_CC, out, fmt, ##__VA_ARGS__) #define phpdbg_notice_ex(out, fmt, ...) phpdbg_print(P_NOTICE TSRMLS_CC, out, fmt, ##__VA_ARGS__) @@ -57,7 +57,7 @@ int phpdbg_print(int TSRMLS_DC, FILE*, const char*, ...); #define phpdbg_log_ex(out, fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, out, fmt, ##__VA_ARGS__) #if PHPDBG_DEBUG -# define phpdbg_debug(fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, stderr, fmt, ##__VA_ARGS__) +# define phpdbg_debug(fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDERR], fmt, ##__VA_ARGS__) #else # define phpdbg_debug(fmt, ...) #endif