root/sapi/phpdbg/phpdbg_prompt.c

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

DEFINITIONS

This source file includes following definitions.
  1. phpdbg_call_register
  2. phpdbg_line_init
  3. phpdbg_string_init
  4. phpdbg_try_file_init
  5. phpdbg_init
  6. phpdbg_clean
  7. PHPDBG_COMMAND
  8. phpdbg_compile
  9. PHPDBG_COMMAND
  10. PHPDBG_COMMAND
  11. phpdbg_skip_line_helper
  12. PHPDBG_COMMAND
  13. PHPDBG_COMMAND
  14. phpdbg_seek_to_end
  15. PHPDBG_COMMAND
  16. PHPDBG_COMMAND
  17. PHPDBG_COMMAND
  18. phpdbg_handle_exception
  19. PHPDBG_COMMAND
  20. phpdbg_output_ev_variable
  21. PHPDBG_COMMAND
  22. PHPDBG_COMMAND
  23. PHPDBG_COMMAND
  24. PHPDBG_COMMAND
  25. PHPDBG_COMMAND
  26. PHPDBG_COMMAND
  27. PHPDBG_COMMAND
  28. add_module_info
  29. add_zendext_info
  30. phpdbg_load_module_or_extension
  31. PHPDBG_COMMAND
  32. PHPDBG_COMMAND
  33. PHPDBG_COMMAND
  34. PHPDBG_COMMAND
  35. PHPDBG_COMMAND
  36. PHPDBG_COMMAND
  37. PHPDBG_COMMAND
  38. PHPDBG_COMMAND
  39. PHPDBG_COMMAND
  40. phpdbg_interactive
  41. phpdbg_execute_ex
  42. phpdbg_force_interruption
  43. PHPDBG_COMMAND

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Felipe Pena <felipe@php.net>                                |
  16    | Authors: Joe Watkins <joe.watkins@live.co.uk>                        |
  17    | Authors: Bob Weinand <bwoebi@php.net>                                |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 #include <stdio.h>
  22 #include <string.h>
  23 #include "zend.h"
  24 #include "zend_compile.h"
  25 #include "zend_exceptions.h"
  26 #include "zend_vm.h"
  27 #include "zend_generators.h"
  28 #include "zend_interfaces.h"
  29 #include "phpdbg.h"
  30 
  31 #include "phpdbg_help.h"
  32 #include "phpdbg_print.h"
  33 #include "phpdbg_info.h"
  34 #include "phpdbg_break.h"
  35 #include "phpdbg_opcode.h"
  36 #include "phpdbg_list.h"
  37 #include "phpdbg_utils.h"
  38 #include "phpdbg_prompt.h"
  39 #include "phpdbg_cmd.h"
  40 #include "phpdbg_set.h"
  41 #include "phpdbg_frame.h"
  42 #include "phpdbg_lexer.h"
  43 #include "phpdbg_parser.h"
  44 #include "phpdbg_wait.h"
  45 #include "phpdbg_eol.h"
  46 
  47 #if ZEND_VM_KIND != ZEND_VM_KIND_CALL
  48 #error "phpdbg can only be built with CALL zend vm kind"
  49 #endif
  50 
  51 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
  52 extern int phpdbg_startup_run;
  53 
  54 #ifdef HAVE_LIBDL
  55 #ifdef PHP_WIN32
  56 #include "win32/param.h"
  57 #include "win32/winutil.h"
  58 #define GET_DL_ERROR()  php_win_err()
  59 #elif defined(NETWARE)
  60 #include <sys/param.h>
  61 #define GET_DL_ERROR()  dlerror()
  62 #else
  63 #include <sys/param.h>
  64 #define GET_DL_ERROR()  DL_ERROR()
  65 #endif
  66 #endif
  67 
  68 /* {{{ command declarations */
  69 const phpdbg_command_t phpdbg_prompt_commands[] = {
  70         PHPDBG_COMMAND_D(exec,    "set execution context",                    'e', NULL, "s", 0),
  71         PHPDBG_COMMAND_D(step,    "step through execution",                   's', NULL, 0, PHPDBG_ASYNC_SAFE),
  72         PHPDBG_COMMAND_D(continue,"continue execution",                       'c', NULL, 0, PHPDBG_ASYNC_SAFE),
  73         PHPDBG_COMMAND_D(run,     "attempt execution",                        'r', NULL, "|s", 0),
  74         PHPDBG_COMMAND_D(ev,      "evaluate some code",                        0 , NULL, "i", PHPDBG_ASYNC_SAFE), /* restricted ASYNC_SAFE */
  75         PHPDBG_COMMAND_D(until,   "continue past the current line",           'u', NULL, 0, 0),
  76         PHPDBG_COMMAND_D(finish,  "continue past the end of the stack",       'F', NULL, 0, 0),
  77         PHPDBG_COMMAND_D(leave,   "continue until the end of the stack",      'L', NULL, 0, 0),
  78         PHPDBG_COMMAND_D(print,   "print something",                          'p', phpdbg_print_commands, "|*c", 0),
  79         PHPDBG_COMMAND_D(break,   "set breakpoint",                           'b', phpdbg_break_commands, "|*c", 0),
  80         PHPDBG_COMMAND_D(back,    "show trace",                               't', NULL, "|n", PHPDBG_ASYNC_SAFE),
  81         PHPDBG_COMMAND_D(frame,   "switch to a frame",                        'f', NULL, "|n", PHPDBG_ASYNC_SAFE),
  82         PHPDBG_COMMAND_D(list,    "lists some code",                          'l', phpdbg_list_commands,  "*", PHPDBG_ASYNC_SAFE),
  83         PHPDBG_COMMAND_D(info,    "displays some informations",               'i', phpdbg_info_commands, "|s", PHPDBG_ASYNC_SAFE),
  84         PHPDBG_COMMAND_D(clean,   "clean the execution environment",          'X', NULL, 0, 0),
  85         PHPDBG_COMMAND_D(clear,   "clear breakpoints",                        'C', NULL, 0, 0),
  86         PHPDBG_COMMAND_D(help,    "show help menu",                           'h', phpdbg_help_commands, "|s", PHPDBG_ASYNC_SAFE),
  87         PHPDBG_COMMAND_D(set,     "set phpdbg configuration",                 'S', phpdbg_set_commands,   "s", PHPDBG_ASYNC_SAFE),
  88         PHPDBG_COMMAND_D(register,"register a function",                      'R', NULL, "s", 0),
  89         PHPDBG_COMMAND_D(source,  "execute a phpdbginit",                     '<', NULL, "s", 0),
  90         PHPDBG_COMMAND_D(export,  "export breaks to a .phpdbginit script",    '>', NULL, "s", PHPDBG_ASYNC_SAFE),
  91         PHPDBG_COMMAND_D(sh,      "shell a command",                           0 , NULL, "i", 0),
  92         PHPDBG_COMMAND_D(quit,    "exit phpdbg",                              'q', NULL, 0, PHPDBG_ASYNC_SAFE),
  93         PHPDBG_COMMAND_D(wait,    "wait for other process",                   'W', NULL, 0, 0),
  94         PHPDBG_COMMAND_D(watch,   "set watchpoint",                           'w', phpdbg_watch_commands, "|ss", 0),
  95         PHPDBG_COMMAND_D(next,    "step over next line",                      'n', NULL, 0, PHPDBG_ASYNC_SAFE),
  96         PHPDBG_COMMAND_D(eol,     "set EOL",                                  'E', NULL, "|s", 0),
  97         PHPDBG_END_COMMAND
  98 }; /* }}} */
  99 
 100 static inline int phpdbg_call_register(phpdbg_param_t *stack) /* {{{ */
 101 {
 102         phpdbg_param_t *name = NULL;
 103 
 104         if (stack->type == STACK_PARAM) {
 105                 char *lc_name;
 106 
 107                 name = stack->next;
 108 
 109                 if (!name || name->type != STR_PARAM) {
 110                         return FAILURE;
 111                 }
 112 
 113                 lc_name = zend_str_tolower_dup(name->str, name->len);
 114 
 115                 if (zend_hash_str_exists(&PHPDBG_G(registered), lc_name, name->len)) {
 116                         zval fretval;
 117                         zend_fcall_info fci;
 118 
 119                         memset(&fci, 0, sizeof(zend_fcall_info));
 120 
 121                         ZVAL_STRINGL(&fci.function_name, lc_name, name->len);
 122                         fci.size = sizeof(zend_fcall_info);
 123                         fci.function_table = &PHPDBG_G(registered);
 124                         //???fci.symbol_table = zend_rebuild_symbol_table();
 125                         fci.symbol_table = NULL;
 126                         fci.object = NULL;
 127                         fci.retval = &fretval;
 128                         fci.no_separation = 1;
 129 
 130                         if (name->next) {
 131                                 zval params;
 132                                 phpdbg_param_t *next = name->next;
 133 
 134                                 array_init(&params);
 135 
 136                                 while (next) {
 137                                         char *buffered = NULL;
 138 
 139                                         switch (next->type) {
 140                                                 case OP_PARAM:
 141                                                 case COND_PARAM:
 142                                                 case STR_PARAM:
 143                                                         add_next_index_stringl(&params, next->str, next->len);
 144                                                 break;
 145 
 146                                                 case NUMERIC_PARAM:
 147                                                         add_next_index_long(&params, next->num);
 148                                                 break;
 149 
 150                                                 case METHOD_PARAM:
 151                                                         spprintf(&buffered, 0, "%s::%s", next->method.class, next->method.name);
 152                                                         add_next_index_string(&params, buffered);
 153                                                 break;
 154 
 155                                                 case NUMERIC_METHOD_PARAM:
 156                                                         spprintf(&buffered, 0, "%s::%s#%ld", next->method.class, next->method.name, next->num);
 157                                                         add_next_index_string(&params, buffered);
 158                                                 break;
 159 
 160                                                 case NUMERIC_FUNCTION_PARAM:
 161                                                         spprintf(&buffered, 0, "%s#%ld", next->str, next->num);
 162                                                         add_next_index_string(&params, buffered);
 163                                                 break;
 164 
 165                                                 case FILE_PARAM:
 166                                                         spprintf(&buffered, 0, "%s:%ld", next->file.name, next->file.line);
 167                                                         add_next_index_string(&params, buffered);
 168                                                 break;
 169 
 170                                                 case NUMERIC_FILE_PARAM:
 171                                                         spprintf(&buffered, 0, "%s:#%ld", next->file.name, next->file.line);
 172                                                         add_next_index_string(&params, buffered);
 173                                                 break;
 174 
 175                                                 default: {
 176                                                         /* not yet */
 177                                                 }
 178                                         }
 179 
 180                                         next = next->next;
 181                                 }
 182 
 183                                 zend_fcall_info_args(&fci, &params);
 184                         } else {
 185                                 fci.params = NULL;
 186                                 fci.param_count = 0;
 187                         }
 188 
 189                         phpdbg_activate_err_buf(0);
 190                         phpdbg_free_err_buf();
 191 
 192                         phpdbg_debug("created %d params from arguments", fci.param_count);
 193 
 194                         if (zend_call_function(&fci, NULL) == SUCCESS) {
 195                                 zend_print_zval_r(&fretval, 0);
 196                                 phpdbg_out("\n");
 197                                 zval_ptr_dtor(&fretval);
 198                         }
 199 
 200                         zval_dtor(&fci.function_name);
 201                         efree(lc_name);
 202 
 203                         return SUCCESS;
 204                 }
 205 
 206                 efree(lc_name);
 207         }
 208 
 209         return FAILURE;
 210 } /* }}} */
 211 
 212 struct phpdbg_init_state {
 213         int line;
 214         zend_bool in_code;
 215         char *code;
 216         size_t code_len;
 217         const char *init_file;
 218 };
 219 
 220 static void phpdbg_line_init(char *cmd, struct phpdbg_init_state *state) {
 221         size_t cmd_len = strlen(cmd);
 222 
 223         state->line++;
 224 
 225         while (cmd_len > 0L && isspace(cmd[cmd_len-1])) {
 226                 cmd_len--;
 227         }
 228 
 229         cmd[cmd_len] = '\0';
 230 
 231         if (*cmd && cmd_len > 0L && cmd[0] != '#') {
 232                 if (cmd_len == 2) {
 233                         if (memcmp(cmd, "<:", sizeof("<:")-1) == SUCCESS) {
 234                                 state->in_code = 1;
 235                                 return;
 236                         } else {
 237                                 if (memcmp(cmd, ":>", sizeof(":>")-1) == SUCCESS) {
 238                                         state->in_code = 0;
 239                                         state->code[state->code_len] = '\0';
 240                                         zend_eval_stringl(state->code, state->code_len, NULL, "phpdbginit code");
 241                                         free(state->code);
 242                                         state->code = NULL;
 243                                         return;
 244                                 }
 245                         }
 246                 }
 247 
 248                 if (state->in_code) {
 249                         if (state->code == NULL) {
 250                                 state->code = malloc(cmd_len + 1);
 251                         } else {
 252                                 state->code = realloc(state->code, state->code_len + cmd_len + 1);
 253                         }
 254 
 255                         if (state->code) {
 256                                 memcpy(&state->code[state->code_len], cmd, cmd_len);
 257                                 state->code_len += cmd_len;
 258                         }
 259 
 260                         return;
 261                 }
 262 
 263                 zend_try {
 264                         char *input = phpdbg_read_input(cmd);
 265                         phpdbg_param_t stack;
 266 
 267                         phpdbg_init_param(&stack, STACK_PARAM);
 268 
 269                         phpdbg_activate_err_buf(1);
 270 
 271                         if (phpdbg_do_parse(&stack, input) <= 0) {
 272                                 switch (phpdbg_stack_execute(&stack, 1 /* allow_async_unsafe == 1 */)) {
 273                                         case FAILURE:
 274                                                 phpdbg_activate_err_buf(0);
 275                                                 if (phpdbg_call_register(&stack) == FAILURE) {
 276                                                         if (state->init_file) {
 277                                                                 phpdbg_output_err_buf("initfailure", "%b file=\"%s\" line=\"%d\" input=\"%s\"", "Unrecognized command in %s:%d: %s, %b!", state->init_file, state->line, input);
 278                                                         } else {
 279                                                                 phpdbg_output_err_buf("initfailure", "%b line=\"%d\" input=\"%s\"", "Unrecognized command on line %d: %s, %b!", state->line, input);
 280                                                         }
 281                                                 }
 282                                         break;
 283                                 }
 284                         }
 285 
 286                         phpdbg_activate_err_buf(0);
 287                         phpdbg_free_err_buf();
 288 
 289                         phpdbg_stack_free(&stack);
 290                         phpdbg_destroy_input(&input);
 291                 } zend_catch {
 292                         PHPDBG_G(flags) &= ~(PHPDBG_IS_RUNNING | PHPDBG_IS_CLEANING);
 293                         if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) {
 294                                 zend_bailout();
 295                         }
 296                 } zend_end_try();
 297         }
 298 
 299 }
 300 
 301 void phpdbg_string_init(char *buffer) {
 302         struct phpdbg_init_state state = {0};
 303         char *str = strtok(buffer, "\n");
 304 
 305         while (str) {
 306                 phpdbg_line_init(str, &state);
 307 
 308                 str = strtok(NULL, "\n");
 309         }
 310 
 311         if (state.code) {
 312                 free(state.code);
 313         }
 314 }
 315 
 316 void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init) /* {{{ */
 317 {
 318         zend_stat_t sb;
 319 
 320         if (init_file && VCWD_STAT(init_file, &sb) != -1) {
 321                 FILE *fp = fopen(init_file, "r");
 322                 if (fp) {
 323                         char cmd[PHPDBG_MAX_CMD];
 324                         struct phpdbg_init_state state = {0};
 325 
 326                         state.init_file = init_file;
 327 
 328                         while (fgets(cmd, PHPDBG_MAX_CMD, fp) != NULL) {
 329                                 phpdbg_line_init(cmd, &state);
 330                         }
 331 
 332                         if (state.code) {
 333                                 free(state.code);
 334                         }
 335 
 336                         fclose(fp);
 337                 } else {
 338                         phpdbg_error("initfailure", "type=\"openfile\" file=\"%s\"", "Failed to open %s for initialization", init_file);
 339                 }
 340 
 341                 if (free_init) {
 342                         free(init_file);
 343                 }
 344         }
 345 } /* }}} */
 346 
 347 void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default) /* {{{ */
 348 {
 349         if (!init_file && use_default) {
 350                 char *scan_dir = getenv("PHP_INI_SCAN_DIR");
 351                 char *sys_ini;
 352                 int i;
 353 
 354                 ZEND_IGNORE_VALUE(asprintf(&sys_ini, "%s/" PHPDBG_INIT_FILENAME, PHP_CONFIG_FILE_PATH));
 355                 phpdbg_try_file_init(sys_ini, strlen(sys_ini), 0);
 356                 free(sys_ini);
 357 
 358                 if (!scan_dir) {
 359                         scan_dir = PHP_CONFIG_FILE_SCAN_DIR;
 360                 }
 361                 while (*scan_dir != 0) {
 362                         i = 0;
 363                         while (scan_dir[i] != ':') {
 364                                 if (scan_dir[i++] == 0) {
 365                                         i = -1;
 366                                         break;
 367                                 }
 368                         }
 369                         if (i != -1) {
 370                                 scan_dir[i] = 0;
 371                         }
 372 
 373                         ZEND_IGNORE_VALUE(asprintf(&init_file, "%s/%s", scan_dir, PHPDBG_INIT_FILENAME));
 374                         phpdbg_try_file_init(init_file, strlen(init_file), 1);
 375                         if (i == -1) {
 376                                 break;
 377                         }
 378                         scan_dir += i + 1;
 379                 }
 380 
 381                 phpdbg_try_file_init(PHPDBG_STRL(PHPDBG_INIT_FILENAME), 0);
 382         } else {
 383                 phpdbg_try_file_init(init_file, init_file_len, 1);
 384         }
 385 }
 386 /* }}} */
 387 
 388 void phpdbg_clean(zend_bool full) /* {{{ */
 389 {
 390         /* this is implicitly required */
 391         if (PHPDBG_G(ops)) {
 392                 destroy_op_array(PHPDBG_G(ops));
 393                 efree(PHPDBG_G(ops));
 394                 PHPDBG_G(ops) = NULL;
 395         }
 396 
 397         if (full) {
 398                 PHPDBG_G(flags) |= PHPDBG_IS_CLEANING;
 399         }
 400 } /* }}} */
 401 
 402 PHPDBG_COMMAND(exec) /* {{{ */
 403 {
 404         zend_stat_t sb;
 405 
 406         if (VCWD_STAT(param->str, &sb) != FAILURE) {
 407                 if (sb.st_mode & (S_IFREG|S_IFLNK)) {
 408                         char *res = phpdbg_resolve_path(param->str);
 409                         size_t res_len = strlen(res);
 410 
 411                         if ((res_len != PHPDBG_G(exec_len)) || (memcmp(res, PHPDBG_G(exec), res_len) != SUCCESS)) {
 412                                 if (PHPDBG_G(in_execution)) {
 413                                         if (phpdbg_ask_user_permission("Do you really want to stop execution to set a new execution context?") == FAILURE) {
 414                                                 return FAILURE;
 415                                         }
 416                                 }
 417 
 418                                 if (PHPDBG_G(exec)) {
 419                                         phpdbg_notice("exec", "type=\"unset\" context=\"%s\"", "Unsetting old execution context: %s", PHPDBG_G(exec));
 420                                         efree(PHPDBG_G(exec));
 421                                         PHPDBG_G(exec) = NULL;
 422                                         PHPDBG_G(exec_len) = 0L;
 423                                 }
 424 
 425                                 if (PHPDBG_G(ops)) {
 426                                         phpdbg_notice("exec", "type=\"unsetops\"", "Destroying compiled opcodes");
 427                                         phpdbg_clean(0);
 428                                 }
 429 
 430                                 PHPDBG_G(exec) = res;
 431                                 PHPDBG_G(exec_len) = res_len;
 432 
 433                                 VCWD_CHDIR_FILE(res);
 434 
 435                                 *SG(request_info).argv = PHPDBG_G(exec);
 436                                 php_build_argv(NULL, &PG(http_globals)[TRACK_VARS_SERVER]);
 437 
 438                                 phpdbg_notice("exec", "type=\"set\" context=\"%s\"", "Set execution context: %s", PHPDBG_G(exec));
 439 
 440                                 if (PHPDBG_G(in_execution)) {
 441                                         phpdbg_clean(1);
 442                                         return SUCCESS;
 443                                 }
 444 
 445                                 phpdbg_compile();
 446                         } else {
 447                                 phpdbg_notice("exec", "type=\"unchanged\"", "Execution context not changed");
 448                         }
 449                 } else {
 450                         phpdbg_error("exec", "type=\"invalid\" context=\"%s\"", "Cannot use %s as execution context, not a valid file or symlink", param->str);
 451                 }
 452         } else {
 453                 phpdbg_error("exec", "type=\"notfound\" context=\"%s\"", "Cannot stat %s, ensure the file exists", param->str);
 454         }
 455         return SUCCESS;
 456 } /* }}} */
 457 
 458 int phpdbg_compile(void) /* {{{ */
 459 {
 460         zend_file_handle fh;
 461         char *buf;
 462         size_t len;
 463 
 464         if (!PHPDBG_G(exec)) {
 465                 phpdbg_error("inactive", "type=\"nocontext\"", "No execution context");
 466                 return FAILURE;
 467         }
 468 
 469         if (php_stream_open_for_zend_ex(PHPDBG_G(exec), &fh, USE_PATH|STREAM_OPEN_FOR_INCLUDE) == SUCCESS && zend_stream_fixup(&fh, &buf, &len) == SUCCESS) {
 470                 /* Skip #! line */
 471                 if (len >= 3 && buf[0] == '#' && buf[1] == '!') {
 472                         char *end = buf + len;
 473                         do {
 474                                 switch (fh.handle.stream.mmap.buf++[0]) {
 475                                         case '\r':
 476                                                 if (fh.handle.stream.mmap.buf[0] == '\n') {
 477                                                         fh.handle.stream.mmap.buf++;
 478                                                 }
 479                                         case '\n':
 480                                                 CG(start_lineno) = 2;
 481                                                 fh.handle.stream.mmap.len -= fh.handle.stream.mmap.buf - buf;
 482                                                 end = fh.handle.stream.mmap.buf;
 483                                 }
 484                         } while (fh.handle.stream.mmap.buf + 1 < end);
 485                 }
 486 
 487                 PHPDBG_G(ops) = zend_compile_file(&fh, ZEND_INCLUDE);
 488 
 489                 fh.handle.stream.mmap.buf = buf;
 490                 fh.handle.stream.mmap.len = len;
 491                 zend_destroy_file_handle(&fh);
 492                 if (EG(exception)) {
 493                         zend_exception_error(EG(exception), E_ERROR);
 494                         zend_bailout();
 495                 }
 496 
 497                 phpdbg_notice("compile", "context=\"%s\"", "Successful compilation of %s", PHPDBG_G(exec));
 498 
 499                 return SUCCESS;
 500         } else {
 501                 phpdbg_error("compile", "type=\"openfailure\" context=\"%s\"", "Could not open file %s", PHPDBG_G(exec));
 502         }
 503 
 504         return FAILURE;
 505 } /* }}} */
 506 
 507 PHPDBG_COMMAND(step) /* {{{ */
 508 {
 509         if (PHPDBG_G(in_execution)) {
 510                 PHPDBG_G(flags) |= PHPDBG_IS_STEPPING;
 511         }
 512 
 513         return PHPDBG_NEXT;
 514 } /* }}} */
 515 
 516 PHPDBG_COMMAND(continue) /* {{{ */
 517 {
 518         return PHPDBG_NEXT;
 519 } /* }}} */
 520 
 521 int phpdbg_skip_line_helper() /* {{{ */ {
 522         zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data));
 523         const zend_op_array *op_array = &ex->func->op_array;
 524         const zend_op *opline = op_array->opcodes;
 525 
 526         PHPDBG_G(flags) |= PHPDBG_IN_UNTIL;
 527         PHPDBG_G(seek_ex) = ex;
 528         do {
 529                 if (opline->lineno != ex->opline->lineno
 530                  || opline->opcode == ZEND_RETURN
 531                  || opline->opcode == ZEND_FAST_RET
 532                  || opline->opcode == ZEND_GENERATOR_RETURN
 533                  || opline->opcode == ZEND_EXIT
 534                  || opline->opcode == ZEND_YIELD
 535                  || opline->opcode == ZEND_YIELD_FROM
 536                 ) {
 537                         zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline);
 538                 }
 539         } while (++opline < op_array->opcodes + op_array->last);
 540 
 541         return PHPDBG_UNTIL;
 542 }
 543 /* }}} */
 544 
 545 PHPDBG_COMMAND(until) /* {{{ */
 546 {
 547         if (!PHPDBG_G(in_execution)) {
 548                 phpdbg_error("inactive", "type=\"noexec\"", "Not executing");
 549                 return SUCCESS;
 550         }
 551 
 552         return phpdbg_skip_line_helper();
 553 } /* }}} */
 554 
 555 PHPDBG_COMMAND(next) /* {{{ */
 556 {
 557         if (!PHPDBG_G(in_execution)) {
 558                 phpdbg_error("inactive", "type=\"noexec\"", "Not executing");
 559                 return SUCCESS;
 560         }
 561 
 562         PHPDBG_G(flags) |= PHPDBG_IS_STEPPING;
 563         return phpdbg_skip_line_helper();
 564 } /* }}} */
 565 
 566 static void phpdbg_seek_to_end(void) /* {{{ */ {
 567         zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data));
 568         const zend_op_array *op_array = &ex->func->op_array;
 569         const zend_op *opline = op_array->opcodes;
 570 
 571         PHPDBG_G(seek_ex) = ex;
 572         do {
 573                 switch (opline->opcode) {
 574                         case ZEND_RETURN:
 575                         case ZEND_FAST_RET:
 576                         case ZEND_GENERATOR_RETURN:
 577                         case ZEND_EXIT:
 578                         case ZEND_YIELD:
 579                         case ZEND_YIELD_FROM:
 580                                 zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline);
 581                 }
 582         } while (++opline < op_array->opcodes + op_array->last);
 583 }
 584 /* }}} */
 585 
 586 PHPDBG_COMMAND(finish) /* {{{ */
 587 {
 588         if (!PHPDBG_G(in_execution)) {
 589                 phpdbg_error("inactive", "type=\"noexec\"", "Not executing");
 590                 return SUCCESS;
 591         }
 592 
 593         phpdbg_seek_to_end();
 594         if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) {
 595                 zend_hash_clean(&PHPDBG_G(seek));
 596         } else {
 597                 PHPDBG_G(flags) |= PHPDBG_IN_FINISH;
 598         }
 599 
 600         return PHPDBG_FINISH;
 601 } /* }}} */
 602 
 603 PHPDBG_COMMAND(leave) /* {{{ */
 604 {
 605         if (!PHPDBG_G(in_execution)) {
 606                 phpdbg_error("inactive", "type=\"noexec\"", "Not executing");
 607                 return SUCCESS;
 608         }
 609 
 610         phpdbg_seek_to_end();
 611         if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) {
 612                 zend_hash_clean(&PHPDBG_G(seek));
 613                 phpdbg_notice("leave", "type=\"end\"", "Already at the end of the function");
 614                 return SUCCESS;
 615         } else {
 616                 PHPDBG_G(flags) |= PHPDBG_IN_LEAVE;
 617                 return PHPDBG_LEAVE;
 618         }
 619 } /* }}} */
 620 
 621 PHPDBG_COMMAND(frame) /* {{{ */
 622 {
 623         if (!param) {
 624                 phpdbg_notice("frame", "id=\"%d\"", "Currently in frame #%d", PHPDBG_G(frame).num);
 625         } else {
 626                 phpdbg_switch_frame(param->num);
 627         }
 628 
 629         return SUCCESS;
 630 } /* }}} */
 631 
 632 static inline void phpdbg_handle_exception(void) /* {{{ */
 633 {
 634         zend_object *ex = EG(exception);
 635         zend_string *msg, *file;
 636         zend_long line;
 637         zval zv, rv, tmp;
 638 
 639         EG(exception) = NULL;
 640 
 641         ZVAL_OBJ(&zv, ex);
 642         zend_call_method_with_0_params(&zv, ex->ce, NULL, "__tostring", &tmp);
 643         file = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("file"), 1, &rv));
 644         line = zval_get_long(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("line"), 1, &rv));
 645 
 646         if (EG(exception)) {
 647                 EG(exception) = NULL;
 648                 msg = ZSTR_EMPTY_ALLOC();
 649         } else {
 650                 zend_update_property_string(zend_get_exception_base(&zv), &zv, ZEND_STRL("string"), Z_STRVAL(tmp));
 651                 zval_ptr_dtor(&tmp);
 652                 msg = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("string"), 1, &rv));
 653         }
 654 
 655         phpdbg_error("exception", "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", "Uncaught %s in %s on line " ZEND_LONG_FMT, ZSTR_VAL(ex->ce->name), ZSTR_VAL(file), line);
 656         zend_string_release(file);
 657         phpdbg_writeln("exceptionmsg", "msg=\"%s\"", ZSTR_VAL(msg));
 658         zend_string_release(msg);
 659 
 660         if (EG(prev_exception)) {
 661                 OBJ_RELEASE(EG(prev_exception));
 662                 EG(prev_exception) = 0;
 663         }
 664         OBJ_RELEASE(ex);
 665         EG(opline_before_exception) = NULL;
 666 
 667         EG(exit_status) = 255;
 668 } /* }}} */
 669 
 670 PHPDBG_COMMAND(run) /* {{{ */
 671 {
 672         if (PHPDBG_G(ops) || PHPDBG_G(exec)) {
 673                 zend_execute_data *ex = EG(current_execute_data);
 674                 zend_bool restore = 1;
 675 
 676                 if (PHPDBG_G(in_execution)) {
 677                         if (phpdbg_ask_user_permission("Do you really want to restart execution?") == SUCCESS) {
 678                                 phpdbg_startup_run++;
 679                                 phpdbg_clean(1);
 680                         }
 681                         return SUCCESS;
 682                 }
 683 
 684                 if (!PHPDBG_G(ops)) {
 685                         if (phpdbg_compile() == FAILURE) {
 686                                 phpdbg_error("compile", "type=\"compilefailure\" context=\"%s\"", "Failed to compile %s, cannot run", PHPDBG_G(exec));
 687                                 goto out;
 688                         }
 689                 }
 690 
 691                 /* clean up from last execution */
 692                 if (ex && ex->symbol_table) {
 693                         zend_hash_clean(ex->symbol_table);
 694                 } else {
 695                         zend_rebuild_symbol_table();
 696                 }
 697                 PHPDBG_G(handled_exception) = NULL;
 698 
 699                 /* clean seek state */
 700                 PHPDBG_G(flags) &= ~PHPDBG_SEEK_MASK;
 701                 zend_hash_clean(&PHPDBG_G(seek));
 702 
 703                 /* reset hit counters */
 704                 phpdbg_reset_breakpoints();
 705 
 706                 if (param && param->type != EMPTY_PARAM && param->len != 0) {
 707                         char **argv = emalloc(5 * sizeof(char *));
 708                         int argc = 0;
 709                         int i;
 710                         /* TODO allow proper escaping with \,  "" and '' here */
 711                         char *argv_str = strtok(param->str, " ");
 712 
 713                         while (argv_str) {
 714                                 if (argc >= 4 && argc == (argc & -argc)) {
 715                                         argv = erealloc(argv, (argc * 2 + 1) * sizeof(char *));
 716                                 }
 717                                 argv[++argc] = argv_str;
 718                                 argv_str = strtok(0, " ");
 719                                 argv[argc] = estrdup(argv[argc]);
 720                         }
 721                         argv[0] = SG(request_info).argv[0];
 722                         for (i = SG(request_info).argc; --i;) {
 723                                 efree(SG(request_info).argv[i]);
 724                         }
 725                         efree(SG(request_info).argv);
 726                         SG(request_info).argv = erealloc(argv, ++argc * sizeof(char *));
 727                         SG(request_info).argc = argc;
 728 
 729                         php_build_argv(NULL, &PG(http_globals)[TRACK_VARS_SERVER]);
 730                 }
 731 
 732                 zend_try {
 733                         PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE;
 734                         PHPDBG_G(flags) |= PHPDBG_IS_RUNNING;
 735                         zend_execute(PHPDBG_G(ops), &PHPDBG_G(retval));
 736                         PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE;
 737                 } zend_catch {
 738                         PHPDBG_G(in_execution) = 0;
 739 
 740                         if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
 741                                 restore = 0;
 742                         } else {
 743                                 zend_bailout();
 744                         }
 745                 } zend_end_try();
 746 
 747                 if (PHPDBG_G(socket_fd) != -1) {
 748                         close(PHPDBG_G(socket_fd));
 749                         PHPDBG_G(socket_fd) = -1;
 750                 }
 751 
 752                 if (restore) {
 753                         zend_exception_restore();
 754                         zend_try {
 755                                 zend_try_exception_handler();
 756                                 PHPDBG_G(in_execution) = 1;
 757                         } zend_catch {
 758                                 PHPDBG_G(in_execution) = 0;
 759 
 760                                 if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) {
 761                                         zend_bailout();
 762                                 }
 763                         } zend_end_try();
 764 
 765                         if (EG(exception)) {
 766                                 phpdbg_handle_exception();
 767                         }
 768                 }
 769 
 770                 PHPDBG_G(flags) &= ~PHPDBG_IS_RUNNING;
 771 
 772                 phpdbg_clean(1);
 773         } else {
 774                 phpdbg_error("inactive", "type=\"nocontext\"", "Nothing to execute!");
 775         }
 776 
 777 out:
 778         PHPDBG_FRAME(num) = 0;
 779         return SUCCESS;
 780 } /* }}} */
 781 
 782 int phpdbg_output_ev_variable(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv) /* {{{ */ {
 783         phpdbg_notice("eval", "variable=\"%.*s\"", "Printing variable %.*s", (int) len, name);
 784         phpdbg_xml("<eval %r>");
 785         zend_print_zval_r(zv, 0);
 786         phpdbg_xml("</eval>");
 787         phpdbg_out("\n");
 788 
 789         efree(name);
 790         efree(keyname);
 791 
 792         return SUCCESS;
 793 }
 794 /* }}} */
 795 
 796 PHPDBG_COMMAND(ev) /* {{{ */
 797 {
 798         zend_bool stepping = ((PHPDBG_G(flags) & PHPDBG_IS_STEPPING) == PHPDBG_IS_STEPPING);
 799         zval retval;
 800 
 801         zend_execute_data *original_execute_data = EG(current_execute_data);
 802         zend_class_entry *original_scope = EG(scope);
 803         zend_vm_stack original_stack = EG(vm_stack);
 804         zend_object *ex = NULL;
 805 
 806         PHPDBG_OUTPUT_BACKUP();
 807 
 808         original_stack->top = EG(vm_stack_top);
 809 
 810         if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
 811                 phpdbg_try_access {
 812                         phpdbg_parse_variable(param->str, param->len, &EG(symbol_table), 0, phpdbg_output_ev_variable, 0);
 813                 } phpdbg_catch_access {
 814                         phpdbg_error("signalsegv", "", "Could not fetch data, invalid data source");
 815                 } phpdbg_end_try_access();
 816 
 817                 PHPDBG_OUTPUT_BACKUP_RESTORE();
 818                 return SUCCESS;
 819         }
 820 
 821         if (!(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) {
 822                 PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING;
 823         }
 824 
 825         /* disable stepping while eval() in progress */
 826         PHPDBG_G(flags) |= PHPDBG_IN_EVAL;
 827         zend_try {
 828                 if (zend_eval_stringl(param->str, param->len, &retval, "eval()'d code") == SUCCESS) {
 829                         if (EG(exception)) {
 830                                 ex = EG(exception);
 831                                 zend_exception_error(EG(exception), E_ERROR);
 832                         } else {
 833                                 phpdbg_xml("<eval %r>");
 834                                 if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) {
 835                                         zval *zvp = &retval;
 836                                         phpdbg_xml_var_dump(zvp);
 837                                 }
 838                                 zend_print_zval_r(&retval, 0);
 839                                 phpdbg_xml("</eval>");
 840                                 phpdbg_out("\n");
 841                                 zval_ptr_dtor(&retval);
 842                         }
 843                 }
 844         } zend_catch {
 845                 PHPDBG_G(unclean_eval) = 1;
 846                 if (ex) {
 847                         OBJ_RELEASE(ex);
 848                 }
 849                 EG(current_execute_data) = original_execute_data;
 850                 EG(scope) = original_scope;
 851                 EG(vm_stack_top) = original_stack->top;
 852                 EG(vm_stack_end) = original_stack->end;
 853                 EG(vm_stack) = original_stack;
 854                 EG(exit_status) = 0;
 855         } zend_end_try();
 856 
 857         PHPDBG_G(flags) &= ~PHPDBG_IN_EVAL;
 858 
 859         /* switch stepping back on */
 860         if (stepping && !(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) {
 861                 PHPDBG_G(flags) |= PHPDBG_IS_STEPPING;
 862         }
 863 
 864         CG(unclean_shutdown) = 0;
 865 
 866         PHPDBG_OUTPUT_BACKUP_RESTORE();
 867 
 868         return SUCCESS;
 869 } /* }}} */
 870 
 871 PHPDBG_COMMAND(back) /* {{{ */
 872 {
 873         if (!PHPDBG_G(in_execution)) {
 874                 phpdbg_error("inactive", "type=\"noexec\"", "Not executing!");
 875                 return SUCCESS;
 876         }
 877 
 878         if (!param) {
 879                 phpdbg_dump_backtrace(0);
 880         } else {
 881                 phpdbg_dump_backtrace(param->num);
 882         }
 883 
 884         return SUCCESS;
 885 } /* }}} */
 886 
 887 PHPDBG_COMMAND(print) /* {{{ */
 888 {
 889         if (!param || param->type == EMPTY_PARAM) {
 890                 return phpdbg_do_print_stack(param);
 891         } else switch (param->type) {
 892                 case STR_PARAM:
 893                         return phpdbg_do_print_func(param);
 894                 case METHOD_PARAM:
 895                         return phpdbg_do_print_method(param);
 896                 default:
 897                         phpdbg_error("print", "type=\"invalidarg\"", "Invalid arguments to print, expected nothing, function name or method name");
 898                         return SUCCESS;
 899         }
 900 } /* }}} */
 901 
 902 PHPDBG_COMMAND(info) /* {{{ */
 903 {
 904         phpdbg_out("Execution Context Information\n\n");
 905         phpdbg_xml("<printinfo %r>");
 906 #ifdef HAVE_LIBREADLINE
 907         phpdbg_writeln("info", "readline=\"yes\"", "Readline   yes");
 908 #else
 909         phpdbg_writeln("info", "readline=\"no\"", "Readline   no");
 910 #endif
 911 #ifdef HAVE_LIBEDIT
 912         phpdbg_writeln("info", "libedit=\"yes\"", "Libedit    yes");
 913 #else
 914         phpdbg_writeln("info", "libedit=\"no\"", "Libedit    no");
 915 #endif
 916 
 917         phpdbg_writeln("info", "context=\"%s\"", "Exec       %s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none");
 918         phpdbg_writeln("info", "compiled=\"%s\"", "Compiled   %s", PHPDBG_G(ops) ? "yes" : "no");
 919         phpdbg_writeln("info", "stepping=\"%s\"", "Stepping   %s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off");
 920         phpdbg_writeln("info", "quiet=\"%s\"", "Quietness  %s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off");
 921         phpdbg_writeln("info", "oplog=\"%s\"", "Oplog      %s", PHPDBG_G(oplog) ? "on" : "off");
 922 
 923         if (PHPDBG_G(ops)) {
 924                 phpdbg_writeln("info", "ops=\"%d\"", "Opcodes    %d", PHPDBG_G(ops)->last);
 925                 phpdbg_writeln("info", "vars=\"%d\"", "Variables  %d", PHPDBG_G(ops)->last_var ? PHPDBG_G(ops)->last_var - 1 : 0);
 926         }
 927 
 928         phpdbg_writeln("info", "executing=\"%d\"", "Executing  %s", PHPDBG_G(in_execution) ? "yes" : "no");
 929         if (PHPDBG_G(in_execution)) {
 930                 phpdbg_writeln("info", "vmret=\"%d\"", "VM Return  %d", PHPDBG_G(vmret));
 931         }
 932 
 933         phpdbg_writeln("info", "classes=\"%d\"", "Classes    %d", zend_hash_num_elements(EG(class_table)));
 934         phpdbg_writeln("info", "functions=\"%d\"", "Functions  %d", zend_hash_num_elements(EG(function_table)));
 935         phpdbg_writeln("info", "constants=\"%d\"", "Constants  %d", zend_hash_num_elements(EG(zend_constants)));
 936         phpdbg_writeln("info", "includes=\"%d\"", "Included   %d", zend_hash_num_elements(&EG(included_files)));
 937         phpdbg_xml("</printinfo>");
 938 
 939         return SUCCESS;
 940 } /* }}} */
 941 
 942 PHPDBG_COMMAND(set) /* {{{ */
 943 {
 944         phpdbg_error("set", "type=\"toofewargs\" expected=\"1\"", "No set command selected!");
 945 
 946         return SUCCESS;
 947 } /* }}} */
 948 
 949 PHPDBG_COMMAND(break) /* {{{ */
 950 {
 951         if (!param) {
 952                 phpdbg_set_breakpoint_file(
 953                         zend_get_executed_filename(),
 954                         zend_get_executed_lineno());
 955         } else switch (param->type) {
 956                 case ADDR_PARAM:
 957                         phpdbg_set_breakpoint_opline(param->addr);
 958                         break;
 959                 case NUMERIC_PARAM:
 960                         if (PHPDBG_G(exec)) {
 961                                 phpdbg_set_breakpoint_file(phpdbg_current_file(), param->num);
 962                         } else {
 963                                 phpdbg_error("inactive", "type=\"noexec\"", "Execution context not set!");
 964                         }
 965                         break;
 966                 case METHOD_PARAM:
 967                         phpdbg_set_breakpoint_method(param->method.class, param->method.name);
 968                         break;
 969                 case NUMERIC_METHOD_PARAM:
 970                         phpdbg_set_breakpoint_method_opline(param->method.class, param->method.name, param->num);
 971                         break;
 972                 case NUMERIC_FUNCTION_PARAM:
 973                         phpdbg_set_breakpoint_function_opline(param->str, param->num);
 974                         break;
 975                 case FILE_PARAM:
 976                         phpdbg_set_breakpoint_file(param->file.name, param->file.line);
 977                         break;
 978                 case NUMERIC_FILE_PARAM:
 979                         phpdbg_set_breakpoint_file_opline(param->file.name, param->file.line);
 980                         break;
 981                 case COND_PARAM:
 982                         phpdbg_set_breakpoint_expression(param->str, param->len);
 983                         break;
 984                 case STR_PARAM:
 985                         phpdbg_set_breakpoint_symbol(param->str, param->len);
 986                         break;
 987                 case OP_PARAM:
 988                         phpdbg_set_breakpoint_opcode(param->str, param->len);
 989                         break;
 990 
 991                 phpdbg_default_switch_case();
 992         }
 993 
 994         return SUCCESS;
 995 } /* }}} */
 996 
 997 PHPDBG_COMMAND(sh) /* {{{ */
 998 {
 999         FILE *fd = NULL;
1000         if ((fd=VCWD_POPEN((char*)param->str, "w"))) {
1001                 /* TODO: do something perhaps ?? do we want input ?? */
1002                 pclose(fd);
1003         } else {
1004                 phpdbg_error("sh", "type=\"failure\" smd=\"%s\"", "Failed to execute %s", param->str);
1005         }
1006 
1007         return SUCCESS;
1008 } /* }}} */
1009 
1010 static int add_module_info(zend_module_entry *module) /* {{{ */ {
1011         phpdbg_write("module", "name=\"%s\"", "%s\n", module->name);
1012         return 0;
1013 }
1014 /* }}} */
1015 
1016 static int add_zendext_info(zend_extension *ext) /* {{{ */ {
1017         phpdbg_write("extension", "name=\"%s\"", "%s\n", ext->name);
1018         return 0;
1019 }
1020 /* }}} */
1021 
1022 PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, char **name) /* {{{ */ {
1023         DL_HANDLE handle;
1024         char *extension_dir;
1025 
1026         extension_dir = INI_STR("extension_dir");
1027 
1028         if (strchr(*path, '/') != NULL || strchr(*path, DEFAULT_SLASH) != NULL) {
1029                 /* path is fine */
1030         } else if (extension_dir && extension_dir[0]) {
1031                 char *libpath;
1032                 int extension_dir_len = strlen(extension_dir);
1033                 if (IS_SLASH(extension_dir[extension_dir_len-1])) {
1034                         spprintf(&libpath, 0, "%s%s", extension_dir, *path); /* SAFE */
1035                 } else {
1036                         spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, *path); /* SAFE */
1037                 }
1038                 efree(*path);
1039                 *path = libpath;
1040         } else {
1041                 phpdbg_error("dl", "type=\"relpath\"", "Not a full path given or extension_dir ini setting is not set");
1042 
1043                 return NULL;
1044         }
1045 
1046         handle = DL_LOAD(*path);
1047 
1048         if (!handle) {
1049 #if PHP_WIN32
1050                 char *err = GET_DL_ERROR();
1051                 if (err && *err != "") {
1052                         phpdbg_error("dl", "type=\"unknown\"", "%s", err);
1053                         LocalFree(err);
1054                 } else {
1055                         phpdbg_error("dl", "type=\"unknown\"", "Unknown reason");
1056                 }
1057 #else
1058                 phpdbg_error("dl", "type=\"unknown\"", "%s", GET_DL_ERROR());
1059 #endif
1060                 return NULL;
1061         }
1062 
1063 #if ZEND_EXTENSIONS_SUPPORT
1064         do {
1065                 zend_extension *new_extension;
1066                 zend_extension_version_info *extension_version_info;
1067 
1068                 extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info");
1069                 if (!extension_version_info) {
1070                         extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "_extension_version_info");
1071                 }
1072                 new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry");
1073                 if (!new_extension) {
1074                         new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry");
1075                 }
1076                 if (!extension_version_info || !new_extension) {
1077                         break;
1078                 }
1079                 if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
1080                         phpdbg_error("dl", "type=\"wrongapi\" extension=\"%s\" apineeded=\"%d\" apiinstalled=\"%d\"", "%s requires Zend Engine API version %d, which does not match the installed Zend Engine API version %d", new_extension->name, extension_version_info->zend_extension_api_no, ZEND_EXTENSION_API_NO);
1081 
1082                         goto quit;
1083                 } else if (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) && (!new_extension->build_id_check || new_extension->build_id_check(ZEND_EXTENSION_BUILD_ID) != SUCCESS)) {
1084                         phpdbg_error("dl", "type=\"wrongbuild\" extension=\"%s\" buildneeded=\"%s\" buildinstalled=\"%s\"", "%s was built with configuration %s, whereas running engine is %s", new_extension->name, extension_version_info->build_id, ZEND_EXTENSION_BUILD_ID);
1085 
1086                         goto quit;
1087                 }
1088 
1089                 *name = new_extension->name;
1090 
1091                 zend_register_extension(new_extension, handle);
1092 
1093                 if (new_extension->startup) {
1094                         if (new_extension->startup(new_extension) != SUCCESS) {
1095                                 phpdbg_error("dl", "type=\"startupfailure\" extension=\"%s\"", "Unable to startup Zend extension %s", new_extension->name);
1096 
1097                                 goto quit;
1098                         }
1099                         zend_append_version_info(new_extension);
1100                 }
1101 
1102                 return "Zend extension";
1103         } while (0);
1104 #endif
1105 
1106         do {
1107                 zend_module_entry *module_entry;
1108                 zend_module_entry *(*get_module)(void);
1109 
1110                 get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module");
1111                 if (!get_module) {
1112                         get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module");
1113                 }
1114 
1115                 if (!get_module) {
1116                         break;
1117                 }
1118 
1119                 module_entry = get_module();
1120                 *name = (char *) module_entry->name;
1121 
1122                 if (strcmp(ZEND_EXTENSION_BUILD_ID, module_entry->build_id)) {
1123                         phpdbg_error("dl", "type=\"wrongbuild\" module=\"%s\" buildneeded=\"%s\" buildinstalled=\"%s\"",  "%s was built with configuration %s, whereas running engine is %s", module_entry->name, module_entry->build_id, ZEND_EXTENSION_BUILD_ID);
1124 
1125                         goto quit;
1126                 }
1127 
1128                 module_entry->type = MODULE_PERSISTENT;
1129                 module_entry->module_number = zend_next_free_module();
1130                 module_entry->handle = handle;
1131 
1132                 if ((module_entry = zend_register_module_ex(module_entry)) == NULL) {
1133                         phpdbg_error("dl", "type=\"registerfailure\" module=\"%s\"", "Unable to register module %s", module_entry->name);
1134 
1135                         goto quit;
1136                 }
1137 
1138                 if (zend_startup_module_ex(module_entry) == FAILURE) {
1139                         phpdbg_error("dl", "type=\"startupfailure\" module=\"%s\"", "Unable to startup module %s", module_entry->name);
1140 
1141                         goto quit;
1142                 }
1143 
1144                 if (module_entry->request_startup_func) {
1145                         if (module_entry->request_startup_func(MODULE_PERSISTENT, module_entry->module_number) == FAILURE) {
1146                                 phpdbg_error("dl", "type=\"initfailure\" module=\"%s\"", "Unable to initialize module %s", module_entry->name);
1147 
1148                                 goto quit;
1149                         }
1150                 }
1151 
1152                 return "module";
1153         } while (0);
1154 
1155         phpdbg_error("dl", "type=\"nophpso\"", "This shared object is nor a Zend extension nor a module");
1156 
1157 quit:
1158         DL_UNLOAD(handle);
1159         return NULL;
1160 }
1161 /* }}} */
1162 
1163 PHPDBG_COMMAND(dl) /* {{{ */
1164 {
1165         const char *type;
1166         char *name, *path;
1167 
1168         if (!param || param->type == EMPTY_PARAM) {
1169                 phpdbg_notice("dl", "extensiontype=\"Zend extension\"", "Zend extensions");
1170                 zend_llist_apply(&zend_extensions, (llist_apply_func_t) add_zendext_info);
1171                 phpdbg_out("\n");
1172                 phpdbg_notice("dl", "extensiontype=\"module\"", "Modules");
1173                 zend_hash_apply(&module_registry, (apply_func_t) add_module_info);
1174         } else switch (param->type) {
1175                 case STR_PARAM:
1176 #ifdef HAVE_LIBDL
1177                         path = estrndup(param->str, param->len);
1178 
1179                         phpdbg_activate_err_buf(1);
1180                         if ((type = phpdbg_load_module_or_extension(&path, &name)) == NULL) {
1181                                 phpdbg_error("dl", "path=\"%s\" %b", "Could not load %s, not found or invalid zend extension / module: %b", path);
1182                                 efree(name);
1183                         } else {
1184                                 phpdbg_notice("dl", "extensiontype=\"%s\" name=\"%s\" path=\"%s\"", "Successfully loaded the %s %s at path %s", type, name, path);
1185                         }
1186                         phpdbg_activate_err_buf(0);
1187                         phpdbg_free_err_buf();
1188                         efree(path);
1189 #else
1190                         phpdbg_error("dl", "type=\"unsupported\" path=\"%.*s\"", "Cannot dynamically load %.*s - dynamic modules are not supported", (int) param->len, param->str);
1191 #endif
1192                         break;
1193 
1194                 phpdbg_default_switch_case();
1195         }
1196 
1197         return SUCCESS;
1198 } /* }}} */
1199 
1200 PHPDBG_COMMAND(source) /* {{{ */
1201 {
1202         zend_stat_t sb;
1203 
1204         if (VCWD_STAT(param->str, &sb) != -1) {
1205                 phpdbg_try_file_init(param->str, param->len, 0);
1206         } else {
1207                 phpdbg_error("source", "type=\"notfound\" file=\"%s\"", "Failed to stat %s, file does not exist", param->str);
1208         }
1209 
1210         return SUCCESS;
1211 } /* }}} */
1212 
1213 PHPDBG_COMMAND(export) /* {{{ */
1214 {
1215         FILE *handle = VCWD_FOPEN(param->str, "w+");
1216 
1217         if (handle) {
1218                 phpdbg_export_breakpoints(handle);
1219                 fclose(handle);
1220         } else {
1221                 phpdbg_error("export", "type=\"openfailure\" file=\"%s\"", "Failed to open or create %s, check path and permissions", param->str);
1222         }
1223 
1224         return SUCCESS;
1225 } /* }}} */
1226 
1227 PHPDBG_COMMAND(register) /* {{{ */
1228 {
1229         zend_function *function;
1230         char *lcname = zend_str_tolower_dup(param->str, param->len);
1231         size_t lcname_len = strlen(lcname);
1232 
1233         if (!zend_hash_str_exists(&PHPDBG_G(registered), lcname, lcname_len)) {
1234                 if ((function = zend_hash_str_find_ptr(EG(function_table), lcname, lcname_len))) {
1235                         zend_hash_str_update_ptr(&PHPDBG_G(registered), lcname, lcname_len, function);
1236                         function_add_ref(function);
1237 
1238                         phpdbg_notice("register", "function=\"%s\"", "Registered %s", lcname);
1239                 } else {
1240                         phpdbg_error("register", "type=\"notfound\" function=\"%s\"", "The requested function (%s) could not be found", param->str);
1241                 }
1242         } else {
1243                 phpdbg_error("register", "type=\"inuse\" function=\"%s\"", "The requested name (%s) is already in use", lcname);
1244         }
1245 
1246         efree(lcname);
1247         return SUCCESS;
1248 } /* }}} */
1249 
1250 PHPDBG_COMMAND(quit) /* {{{ */
1251 {
1252         PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
1253         PHPDBG_G(flags) &= ~PHPDBG_IS_CLEANING;
1254 
1255         return SUCCESS;
1256 } /* }}} */
1257 
1258 PHPDBG_COMMAND(clean) /* {{{ */
1259 {
1260         if (PHPDBG_G(in_execution)) {
1261                 if (phpdbg_ask_user_permission("Do you really want to clean your current environment?") == FAILURE) {
1262                         return SUCCESS;
1263                 }
1264         }
1265 
1266         phpdbg_out("Cleaning Execution Environment\n");
1267         phpdbg_xml("<cleaninfo %r>");
1268 
1269         phpdbg_writeln("clean", "classes=\"%d\"", "Classes    %d", zend_hash_num_elements(EG(class_table)));
1270         phpdbg_writeln("clean", "functions=\"%d\"", "Functions  %d", zend_hash_num_elements(EG(function_table)));
1271         phpdbg_writeln("clean", "constants=\"%d\"", "Constants  %d", zend_hash_num_elements(EG(zend_constants)));
1272         phpdbg_writeln("clean", "includes=\"%d\"", "Includes   %d", zend_hash_num_elements(&EG(included_files)));
1273 
1274         phpdbg_clean(1);
1275 
1276         phpdbg_xml("</cleaninfo>");
1277 
1278         return SUCCESS;
1279 } /* }}} */
1280 
1281 PHPDBG_COMMAND(clear) /* {{{ */
1282 {
1283         phpdbg_out("Clearing Breakpoints\n");
1284         phpdbg_xml("<clearinfo %r>");
1285 
1286         phpdbg_writeln("clear", "files=\"%d\"", "File              %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]));
1287         phpdbg_writeln("clear", "functions=\"%d\"", "Functions         %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]));
1288         phpdbg_writeln("clear", "methods=\"%d\"", "Methods           %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]));
1289         phpdbg_writeln("clear", "oplines=\"%d\"", "Oplines           %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]));
1290         phpdbg_writeln("clear", "fileoplines=\"%d\"", "File oplines      %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE]));
1291         phpdbg_writeln("clear", "functionoplines=\"%d\"", "Function oplines  %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]));
1292         phpdbg_writeln("clear", "methodoplines=\"%d\"", "Method oplines    %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]));
1293         phpdbg_writeln("clear", "eval=\"%d\"", "Conditionals      %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]));
1294 
1295         phpdbg_clear_breakpoints();
1296 
1297         phpdbg_xml("</clearinfo>");
1298 
1299         return SUCCESS;
1300 } /* }}} */
1301 
1302 PHPDBG_COMMAND(list) /* {{{ */
1303 {
1304         if (!param) {
1305                 return PHPDBG_LIST_HANDLER(lines)(PHPDBG_COMMAND_ARGS);
1306         } else switch (param->type) {
1307                 case NUMERIC_PARAM:
1308                         return PHPDBG_LIST_HANDLER(lines)(PHPDBG_COMMAND_ARGS);
1309 
1310                 case FILE_PARAM:
1311                         return PHPDBG_LIST_HANDLER(lines)(PHPDBG_COMMAND_ARGS);
1312 
1313                 case STR_PARAM:
1314                         phpdbg_list_function_byname(param->str, param->len);
1315                         break;
1316 
1317                 case METHOD_PARAM:
1318                         return PHPDBG_LIST_HANDLER(method)(PHPDBG_COMMAND_ARGS);
1319 
1320                 phpdbg_default_switch_case();
1321         }
1322 
1323         return SUCCESS;
1324 } /* }}} */
1325 
1326 PHPDBG_COMMAND(watch) /* {{{ */
1327 {
1328         if (!param || param->type == EMPTY_PARAM) {
1329                 phpdbg_list_watchpoints();
1330         } else switch (param->type) {
1331                 case STR_PARAM:
1332                         if (phpdbg_create_var_watchpoint(param->str, param->len) != FAILURE) {
1333                                 phpdbg_notice("watch", "variable=\"%.*s\"", "Set watchpoint on %.*s", (int) param->len, param->str);
1334                         }
1335                         break;
1336 
1337                 phpdbg_default_switch_case();
1338         }
1339 
1340         return SUCCESS;
1341 } /* }}} */
1342 
1343 int phpdbg_interactive(zend_bool allow_async_unsafe) /* {{{ */
1344 {
1345         int ret = SUCCESS;
1346         char *input = NULL;
1347         phpdbg_param_t stack;
1348 
1349         PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE;
1350 
1351         while (ret == SUCCESS || ret == FAILURE) {
1352                 if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) {
1353                         zend_bailout();
1354                 }
1355 
1356                 if (!(input = phpdbg_read_input(NULL))) {
1357                         break;
1358                 }
1359 
1360 
1361                 phpdbg_init_param(&stack, STACK_PARAM);
1362 
1363                 if (phpdbg_do_parse(&stack, input) <= 0) {
1364                         phpdbg_activate_err_buf(1);
1365 
1366 #ifdef PHP_WIN32
1367 #define PARA ((phpdbg_param_t *)stack.next)->type
1368                         if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) {
1369                                 sigio_watcher_start();
1370                         }
1371 #endif
1372                         switch (ret = phpdbg_stack_execute(&stack, allow_async_unsafe)) {
1373                                 case FAILURE:
1374                                         if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
1375                                                 if (!allow_async_unsafe || phpdbg_call_register(&stack) == FAILURE) {
1376                                                         phpdbg_output_err_buf(NULL, "%b", "%b");
1377                                                 }
1378                                         }
1379                                 break;
1380 
1381                                 case PHPDBG_LEAVE:
1382                                 case PHPDBG_FINISH:
1383                                 case PHPDBG_UNTIL:
1384                                 case PHPDBG_NEXT: {
1385                                         phpdbg_activate_err_buf(0);
1386                                         phpdbg_free_err_buf();
1387                                         if (!PHPDBG_G(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
1388                                                 phpdbg_error("command", "type=\"noexec\"", "Not running");
1389                                         }
1390                                         break;
1391                                 }
1392                         }
1393 
1394                         phpdbg_activate_err_buf(0);
1395                         phpdbg_free_err_buf();
1396 #ifdef PHP_WIN32
1397                         if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) {
1398                                 sigio_watcher_stop();
1399                         }
1400 #undef PARA
1401 #endif
1402                 }
1403 
1404                 phpdbg_stack_free(&stack);
1405                 phpdbg_destroy_input(&input);
1406                 PHPDBG_G(req_id) = 0;
1407                 input = NULL;
1408         }
1409 
1410         if (input) {
1411                 phpdbg_stack_free(&stack);
1412                 phpdbg_destroy_input(&input);
1413                 PHPDBG_G(req_id) = 0;
1414         }
1415 
1416         if (PHPDBG_G(in_execution)) {
1417                 phpdbg_restore_frame();
1418         }
1419 
1420         PHPDBG_G(flags) &= ~PHPDBG_IS_INTERACTIVE;
1421 
1422         phpdbg_print_changed_zvals();
1423 
1424         return ret;
1425 } /* }}} */
1426 
1427 /* code may behave weirdly if EG(exception) is set; thus backup it */
1428 #define DO_INTERACTIVE(allow_async_unsafe) do { \
1429         const zend_op *backup_opline; \
1430         const zend_op *before_ex; \
1431         if (exception) { \
1432                 if (EG(current_execute_data) && EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { \
1433                         backup_opline = EG(current_execute_data)->opline; \
1434                 } \
1435                 before_ex = EG(opline_before_exception); \
1436                 ++GC_REFCOUNT(exception); \
1437                 zend_clear_exception(); \
1438         } \
1439         if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \
1440                 const char *file_char = zend_get_executed_filename(); \
1441                 zend_string *file = zend_string_init(file_char, strlen(file_char), 0); \
1442                 phpdbg_list_file(file, 3, zend_get_executed_lineno()-1, zend_get_executed_lineno()); \
1443                 efree(file); \
1444         } \
1445         \
1446         switch (phpdbg_interactive(allow_async_unsafe)) { \
1447                 zval zv; \
1448                 case PHPDBG_LEAVE: \
1449                 case PHPDBG_FINISH: \
1450                 case PHPDBG_UNTIL: \
1451                 case PHPDBG_NEXT: \
1452                         if (exception) { \
1453                                 if (EG(current_execute_data) && EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type) \
1454                                  && (backup_opline->opcode == ZEND_HANDLE_EXCEPTION || backup_opline->opcode == ZEND_CATCH)) { \
1455                                         EG(current_execute_data)->opline = backup_opline; \
1456                                         EG(exception) = exception; \
1457                                 } else { \
1458                                         Z_OBJ(zv) = exception; \
1459                                         zend_throw_exception_internal(&zv); \
1460                                 } \
1461                                 EG(opline_before_exception) = before_ex; \
1462                         } \
1463                         /* fallthrough */ \
1464                 default: \
1465                         goto next; \
1466         } \
1467 } while (0)
1468 
1469 void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */
1470 {
1471         zend_bool original_in_execution = PHPDBG_G(in_execution);
1472 
1473         if ((PHPDBG_G(flags) & PHPDBG_IS_STOPPING) && !(PHPDBG_G(flags) & PHPDBG_IS_RUNNING)) {
1474                 zend_bailout();
1475         }
1476 
1477         PHPDBG_G(in_execution) = 1;
1478 
1479         while (1) {
1480                 zend_object *exception = EG(exception);
1481 
1482                 if ((PHPDBG_G(flags) & PHPDBG_BP_RESOLVE_MASK)) {
1483                         /* resolve nth opline breakpoints */
1484                         phpdbg_resolve_op_array_breaks(&execute_data->func->op_array);
1485                 }
1486 
1487 #ifdef ZEND_WIN32
1488                 if (EG(timed_out)) {
1489                         zend_timeout(0);
1490                 }
1491 #endif
1492 
1493                 if (PHPDBG_G(flags) & PHPDBG_PREVENT_INTERACTIVE) {
1494                         phpdbg_print_opline_ex(execute_data, 0);
1495                         goto next;
1496                 }
1497 
1498                 /* check for uncaught exceptions */
1499                 if (exception && PHPDBG_G(handled_exception) != exception && !(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) {
1500                         zend_execute_data *prev_ex = execute_data;
1501                         zval zv, rv;
1502                         zend_string *file, *msg;
1503                         zend_long line;
1504 
1505                         do {
1506                                 prev_ex = zend_generator_check_placeholder_frame(prev_ex);
1507                                 /* assuming that no internal functions will silently swallow exceptions ... */
1508                                 if (!prev_ex->func || !ZEND_USER_CODE(prev_ex->func->common.type)) {
1509                                         continue;
1510                                 }
1511 
1512                                 if (phpdbg_check_caught_ex(prev_ex, exception)) {
1513                                         goto ex_is_caught;
1514                                 }
1515                         } while ((prev_ex = prev_ex->prev_execute_data));
1516 
1517                         PHPDBG_G(handled_exception) = exception;
1518 
1519                         ZVAL_OBJ(&zv, exception);
1520                         file = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("file"), 1, &rv));
1521                         line = zval_get_long(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("line"), 1, &rv));
1522                         msg = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("message"), 1, &rv));
1523 
1524                         phpdbg_error("exception",
1525                                 "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"",
1526                                 "Uncaught %s in %s on line " ZEND_LONG_FMT ": %.*s",
1527                                 ZSTR_VAL(exception->ce->name), ZSTR_VAL(file), line,
1528                                 ZSTR_LEN(msg) < 80 ? (int) ZSTR_LEN(msg) : 80, ZSTR_VAL(msg));
1529                         zend_string_release(msg);
1530                         zend_string_release(file);
1531 
1532                         DO_INTERACTIVE(1);
1533                 }
1534 ex_is_caught:
1535 
1536                 /* allow conditional breakpoints and initialization to access the vm uninterrupted */
1537                 if (PHPDBG_G(flags) & (PHPDBG_IN_COND_BP | PHPDBG_IS_INITIALIZING)) {
1538                         /* skip possible breakpoints */
1539                         goto next;
1540                 }
1541 
1542                 /* perform seek operation */
1543                 if ((PHPDBG_G(flags) & PHPDBG_SEEK_MASK) && !(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) {
1544                         /* current address */
1545                         zend_ulong address = (zend_ulong) execute_data->opline;
1546 
1547                         if (PHPDBG_G(seek_ex) != execute_data) {
1548                                 goto next;
1549                         }
1550 
1551 #define INDEX_EXISTS_CHECK (zend_hash_index_exists(&PHPDBG_G(seek), address) || (exception && phpdbg_check_caught_ex(execute_data, exception) == 0))
1552 
1553                         /* run to next line */
1554                         if (PHPDBG_G(flags) & PHPDBG_IN_UNTIL) {
1555                                 if (INDEX_EXISTS_CHECK) {
1556                                         PHPDBG_G(flags) &= ~PHPDBG_IN_UNTIL;
1557                                         zend_hash_clean(&PHPDBG_G(seek));
1558                                 } else {
1559                                         /* skip possible breakpoints */
1560                                         goto next;
1561                                 }
1562                         }
1563 
1564                         /* run to finish */
1565                         if (PHPDBG_G(flags) & PHPDBG_IN_FINISH) {
1566                                 if (INDEX_EXISTS_CHECK) {
1567                                         PHPDBG_G(flags) &= ~PHPDBG_IN_FINISH;
1568                                         zend_hash_clean(&PHPDBG_G(seek));
1569                                 }
1570                                 /* skip possible breakpoints */
1571                                 goto next;
1572                         }
1573 
1574                         /* break for leave */
1575                         if (PHPDBG_G(flags) & PHPDBG_IN_LEAVE) {
1576                                 if (INDEX_EXISTS_CHECK) {
1577                                         PHPDBG_G(flags) &= ~PHPDBG_IN_LEAVE;
1578                                         zend_hash_clean(&PHPDBG_G(seek));
1579                                         phpdbg_notice("breakpoint", "id=\"leave\" file=\"%s\" line=\"%u\"", "Breaking for leave at %s:%u",
1580                                                 zend_get_executed_filename(),
1581                                                 zend_get_executed_lineno()
1582                                         );
1583                                         DO_INTERACTIVE(1);
1584                                 } else {
1585                                         /* skip possible breakpoints */
1586                                         goto next;
1587                                 }
1588                         }
1589                 }
1590 
1591                 /* not while in conditionals */
1592                 phpdbg_print_opline_ex(execute_data, 0);
1593 
1594                 if (PHPDBG_G(flags) & PHPDBG_IS_STEPPING && (PHPDBG_G(flags) & PHPDBG_STEP_OPCODE || execute_data->opline->lineno != PHPDBG_G(last_line))) {
1595                         PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING;
1596                         DO_INTERACTIVE(1);
1597                 }
1598 
1599                 /* check if some watchpoint was hit */
1600                 {
1601                         if (phpdbg_print_changed_zvals() == SUCCESS) {
1602                                 DO_INTERACTIVE(1);
1603                         }
1604                 }
1605 
1606                 /* search for breakpoints */
1607                 {
1608                         phpdbg_breakbase_t *brake;
1609 
1610                         if ((PHPDBG_G(flags) & PHPDBG_BP_MASK)
1611                             && (brake = phpdbg_find_breakpoint(execute_data))
1612                             && (brake->type != PHPDBG_BREAK_FILE || execute_data->opline->lineno != PHPDBG_G(last_line))) {
1613                                 phpdbg_hit_breakpoint(brake, 1);
1614                                 DO_INTERACTIVE(1);
1615                         }
1616                 }
1617 
1618                 if (PHPDBG_G(flags) & PHPDBG_IS_SIGNALED) {
1619                         PHPDBG_G(flags) &= ~PHPDBG_IS_SIGNALED;
1620 
1621                         phpdbg_out("\n");
1622                         phpdbg_notice("signal", "type=\"SIGINT\"", "Program received signal SIGINT");
1623                         DO_INTERACTIVE(1);
1624                 }
1625 
1626 next:
1627 
1628                 PHPDBG_G(last_line) = execute_data->opline->lineno;
1629 
1630                 /* stupid hack to make zend_do_fcall_common_helper return ZEND_VM_ENTER() instead of recursively calling zend_execute() and eventually segfaulting */
1631                 if ((execute_data->opline->opcode == ZEND_DO_FCALL ||
1632                      execute_data->opline->opcode == ZEND_DO_UCALL ||
1633                      execute_data->opline->opcode == ZEND_DO_FCALL_BY_NAME) &&
1634                      execute_data->call->func->type == ZEND_USER_FUNCTION) {
1635                         zend_execute_ex = execute_ex;
1636                 }
1637                 PHPDBG_G(vmret) = zend_vm_call_opcode_handler(execute_data);            
1638                 zend_execute_ex = phpdbg_execute_ex;
1639 
1640                 if (PHPDBG_G(vmret) != 0) {
1641                         if (PHPDBG_G(vmret) < 0) {
1642                                 PHPDBG_G(in_execution) = original_in_execution;
1643                                 return;
1644                         } else {
1645                                 execute_data = EG(current_execute_data);
1646                         }
1647                 }
1648         }
1649         zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");
1650 } /* }}} */
1651 
1652 /* only if *not* interactive and while executing */
1653 void phpdbg_force_interruption(void) /* {{{ */ {
1654         zend_object *exception = EG(exception);
1655         zend_execute_data *data = EG(current_execute_data); /* should be always readable if not NULL */
1656 
1657         PHPDBG_G(flags) |= PHPDBG_IN_SIGNAL_HANDLER;
1658 
1659         if (data) {
1660                 if (data->func) {
1661                         if (ZEND_USER_CODE(data->func->type)) {
1662                                 phpdbg_notice("hardinterrupt", "opline=\"%p\" num=\"%lu\" file=\"%s\" line=\"%u\"", "Current opline: %p (op #%lu) in %s:%u", data->opline, (data->opline - data->func->op_array.opcodes) / sizeof(data->opline), data->func->op_array.filename->val, data->opline->lineno);
1663                         } else if (data->func->internal_function.function_name) {
1664                                 phpdbg_notice("hardinterrupt", "func=\"%s\"", "Current opline: in internal function %s", data->func->internal_function.function_name->val);
1665                         } else {
1666                                 phpdbg_notice("hardinterrupt", "", "Current opline: executing internal code");
1667                         }
1668                 } else {
1669                         phpdbg_notice("hardinterrupt", "opline=\"%p\"", "Current opline: %p (op_array information unavailable)", data->opline);
1670                 }
1671         } else {
1672                 phpdbg_notice("hardinterrupt", "", "No information available about executing context");
1673         }
1674 
1675         DO_INTERACTIVE(0);
1676 
1677 next:
1678         PHPDBG_G(flags) &= ~PHPDBG_IN_SIGNAL_HANDLER;
1679 
1680         if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) {
1681                 zend_bailout();
1682         }
1683 }
1684 /* }}} */
1685 
1686 PHPDBG_COMMAND(eol) /* {{{ */
1687 {
1688         if (!param || param->type == EMPTY_PARAM) {
1689                 phpdbg_notice("eol", "argument required", "argument required");
1690         } else switch (param->type) {
1691                 case STR_PARAM:
1692                         if (FAILURE == phpdbg_eol_global_update(param->str)) {
1693                                 phpdbg_notice("eol", "unknown EOL name '%s', give crlf, lf, cr", "unknown EOL name '%s', give  crlf, lf, cr", param->str);
1694                         }
1695                         break;
1696 
1697                 phpdbg_default_switch_case();
1698         }
1699 
1700         return SUCCESS;
1701 } /* }}} */

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