You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1328 lines
34 KiB

13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2013 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. #include <stdio.h>
  21. #include <string.h>
  22. #include "zend.h"
  23. #include "zend_compile.h"
  24. #include "phpdbg.h"
  25. #include "phpdbg_help.h"
  26. #include "phpdbg_print.h"
  27. #include "phpdbg_info.h"
  28. #include "phpdbg_break.h"
  29. #include "phpdbg_bp.h"
  30. #include "phpdbg_opcode.h"
  31. #include "phpdbg_list.h"
  32. #include "phpdbg_utils.h"
  33. #include "phpdbg_prompt.h"
  34. #include "phpdbg_cmd.h"
  35. #include "phpdbg_set.h"
  36. #include "phpdbg_frame.h"
  37. /* {{{ command declarations */
  38. const phpdbg_command_t phpdbg_prompt_commands[] = {
  39. PHPDBG_COMMAND_D(exec, "set execution context", 'e', NULL, 1),
  40. PHPDBG_COMMAND_D(compile, "attempt compilation", 'c', NULL, 0),
  41. PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, 1),
  42. PHPDBG_COMMAND_D(next, "continue execution", 'n', NULL, 0),
  43. PHPDBG_COMMAND_D(run, "attempt execution", 'r', NULL, 0),
  44. PHPDBG_COMMAND_D(eval, "evaluate some code", 'E', NULL, 1),
  45. PHPDBG_COMMAND_D(until, "continue past the current line", 'u', NULL, 0),
  46. PHPDBG_COMMAND_D(finish, "continue past the end of the stack", 'F', NULL, 0),
  47. PHPDBG_COMMAND_D(leave, "continue until the end of the stack", 'L', NULL, 0),
  48. PHPDBG_COMMAND_D(print, "print something", 'p', phpdbg_print_commands, 2),
  49. PHPDBG_COMMAND_D(break, "set breakpoint", 'b', phpdbg_break_commands, 1),
  50. PHPDBG_COMMAND_D(back, "show trace", 't', NULL, 0),
  51. PHPDBG_COMMAND_D(frame, "switch to a frame", 'f', NULL, 1),
  52. PHPDBG_COMMAND_D(list, "lists some code", 'l', phpdbg_list_commands, 2),
  53. PHPDBG_COMMAND_D(info, "displays some informations", 'i', phpdbg_info_commands, 1),
  54. PHPDBG_COMMAND_D(clean, "clean the execution environment", 'X', NULL, 0),
  55. PHPDBG_COMMAND_D(clear, "clear breakpoints", 'C', NULL, 0),
  56. PHPDBG_COMMAND_D(help, "show help menu", 'h', phpdbg_help_commands, 2),
  57. PHPDBG_COMMAND_D(quiet, "silence some output", 'Q', NULL, 1),
  58. PHPDBG_COMMAND_D(aliases, "show alias list", 'a', NULL, 0),
  59. PHPDBG_COMMAND_D(set, "set phpdbg configuration", 'S', phpdbg_set_commands, 1),
  60. PHPDBG_COMMAND_D(register,"register a function", 'R', NULL, 1),
  61. PHPDBG_COMMAND_D(source, "execute a phpdbginit", '.', NULL, 1),
  62. PHPDBG_COMMAND_D(shell, "shell a command", '-', NULL, 1),
  63. PHPDBG_COMMAND_D(quit, "exit phpdbg", 'q', NULL, 0),
  64. PHPDBG_END_COMMAND
  65. }; /* }}} */
  66. ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
  67. static inline int phpdbg_call_register(phpdbg_input_t *input TSRMLS_DC) /* {{{ */
  68. {
  69. phpdbg_input_t *function = input->argv[0];
  70. if (zend_hash_exists(
  71. &PHPDBG_G(registered), function->string, function->length+1)) {
  72. zval fname, *fretval;
  73. zend_fcall_info fci;
  74. ZVAL_STRINGL(&fname, function->string, function->length, 1);
  75. memset(&fci, 0, sizeof(zend_fcall_info));
  76. fci.size = sizeof(zend_fcall_info);
  77. fci.function_table = &PHPDBG_G(registered);
  78. fci.function_name = &fname;
  79. fci.symbol_table = EG(active_symbol_table);
  80. fci.object_ptr = NULL;
  81. fci.retval_ptr_ptr = &fretval;
  82. fci.no_separation = 1;
  83. if (input->argc > 1) {
  84. int param;
  85. zval params;
  86. array_init(&params);
  87. for (param = 0; param < (input->argc-1); param++) {
  88. add_next_index_stringl(
  89. &params,
  90. input->argv[param+1]->string,
  91. input->argv[param+1]->length, 1);
  92. phpdbg_debug(
  93. "created param[%d] from argv[%d]: %s",
  94. param, param+1, input->argv[param+1]->string);
  95. }
  96. zend_fcall_info_args(&fci, &params TSRMLS_CC);
  97. } else {
  98. fci.params = NULL;
  99. fci.param_count = 0;
  100. }
  101. phpdbg_debug(
  102. "created %d params from %d arguments",
  103. fci.param_count, input->argc);
  104. zend_call_function(&fci, NULL TSRMLS_CC);
  105. if (fretval) {
  106. zend_print_zval_r(
  107. fretval, 0 TSRMLS_CC);
  108. phpdbg_writeln(EMPTY);
  109. }
  110. zval_dtor(&fname);
  111. return SUCCESS;
  112. }
  113. return FAILURE;
  114. } /* }}} */
  115. void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init TSRMLS_DC) /* {{{ */
  116. {
  117. struct stat sb;
  118. if (init_file && VCWD_STAT(init_file, &sb) != -1) {
  119. FILE *fp = fopen(init_file, "r");
  120. if (fp) {
  121. int line = 1;
  122. char cmd[PHPDBG_MAX_CMD];
  123. size_t cmd_len = 0L;
  124. char *code = NULL;
  125. size_t code_len = 0L;
  126. zend_bool in_code = 0;
  127. while (fgets(cmd, PHPDBG_MAX_CMD, fp) != NULL) {
  128. cmd_len = strlen(cmd)-1;
  129. while (cmd_len > 0L && isspace(cmd[cmd_len-1]))
  130. cmd_len--;
  131. cmd[cmd_len] = '\0';
  132. if (*cmd && cmd_len > 0L && cmd[0] != '#') {
  133. if (cmd_len == 2) {
  134. if (memcmp(cmd, "<:", sizeof("<:")-1) == SUCCESS) {
  135. in_code = 1;
  136. goto next_line;
  137. } else {
  138. if (memcmp(cmd, ":>", sizeof(":>")-1) == SUCCESS) {
  139. in_code = 0;
  140. code[code_len] = '\0';
  141. {
  142. zend_eval_stringl(
  143. code, code_len, NULL, "phpdbginit code" TSRMLS_CC);
  144. }
  145. free(code);
  146. code = NULL;
  147. goto next_line;
  148. }
  149. }
  150. }
  151. if (in_code) {
  152. if (code == NULL) {
  153. code = malloc(cmd_len + 1);
  154. } else code = realloc(code, code_len + cmd_len + 1);
  155. if (code) {
  156. memcpy(
  157. &code[code_len], cmd, cmd_len);
  158. code_len += cmd_len;
  159. }
  160. goto next_line;
  161. }
  162. {
  163. phpdbg_input_t *input = phpdbg_read_input(cmd TSRMLS_CC);
  164. switch (phpdbg_do_cmd(phpdbg_prompt_commands, input TSRMLS_CC)) {
  165. case FAILURE:
  166. if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
  167. if (phpdbg_call_register(input TSRMLS_CC) == FAILURE) {
  168. phpdbg_error("Unrecognized command in %s:%d: %s!", init_file, line, input->string);
  169. }
  170. }
  171. break;
  172. }
  173. phpdbg_destroy_input(&input TSRMLS_CC);
  174. }
  175. }
  176. next_line:
  177. line++;
  178. }
  179. if (code) {
  180. free(code);
  181. }
  182. fclose(fp);
  183. } else {
  184. phpdbg_error(
  185. "Failed to open %s for initialization", init_file);
  186. }
  187. if (free_init) {
  188. free(init_file);
  189. }
  190. }
  191. } /* }}} */
  192. void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TSRMLS_DC) /* {{{ */
  193. {
  194. if (!init_file && use_default) {
  195. char *scan_dir = getenv("PHP_INI_SCAN_DIR");
  196. int i;
  197. phpdbg_try_file_init(PHPDBG_STRL(PHP_CONFIG_FILE_PATH "/" PHPDBG_INIT_FILENAME), 0 TSRMLS_CC);
  198. if (!scan_dir) {
  199. scan_dir = PHP_CONFIG_FILE_SCAN_DIR;
  200. }
  201. while (*scan_dir != 0) {
  202. i = 0;
  203. while (scan_dir[i] != ':') {
  204. if (scan_dir[i++] == 0) {
  205. i = -1;
  206. break;
  207. }
  208. }
  209. if (i != -1) {
  210. scan_dir[i] = 0;
  211. }
  212. asprintf(
  213. &init_file, "%s/%s", scan_dir, PHPDBG_INIT_FILENAME);
  214. phpdbg_try_file_init(init_file, strlen(init_file), 1 TSRMLS_CC);
  215. if (i == -1) {
  216. break;
  217. }
  218. scan_dir += i + 1;
  219. }
  220. phpdbg_try_file_init(PHPDBG_STRL(PHPDBG_INIT_FILENAME), 0 TSRMLS_CC);
  221. } else {
  222. phpdbg_try_file_init(init_file, init_file_len, 1 TSRMLS_CC);
  223. }
  224. }
  225. PHPDBG_COMMAND(exec) /* {{{ */
  226. {
  227. switch (param->type) {
  228. case STR_PARAM: {
  229. struct stat sb;
  230. if (VCWD_STAT(param->str, &sb) != FAILURE) {
  231. if (sb.st_mode & (S_IFREG|S_IFLNK)) {
  232. char *res = phpdbg_resolve_path(param->str TSRMLS_CC);
  233. size_t res_len = strlen(res);
  234. if ((res_len != PHPDBG_G(exec_len)) || (memcmp(res, PHPDBG_G(exec), res_len) != SUCCESS)) {
  235. if (PHPDBG_G(exec)) {
  236. phpdbg_notice("Unsetting old execution context: %s", PHPDBG_G(exec));
  237. efree(PHPDBG_G(exec));
  238. PHPDBG_G(exec) = NULL;
  239. PHPDBG_G(exec_len) = 0L;
  240. }
  241. if (PHPDBG_G(ops)) {
  242. phpdbg_notice("Destroying compiled opcodes");
  243. phpdbg_clean(0 TSRMLS_CC);
  244. }
  245. PHPDBG_G(exec) = res;
  246. PHPDBG_G(exec_len) = res_len;
  247. phpdbg_notice("Set execution context: %s", PHPDBG_G(exec));
  248. } else {
  249. phpdbg_notice("Execution context not changed");
  250. }
  251. } else {
  252. phpdbg_error("Cannot use %s as execution context, not a valid file or symlink", param->str);
  253. }
  254. } else {
  255. phpdbg_error("Cannot stat %s, ensure the file exists", param->str);
  256. }
  257. } break;
  258. phpdbg_default_switch_case();
  259. }
  260. return SUCCESS;
  261. } /* }}} */
  262. int phpdbg_compile(TSRMLS_D) /* {{{ */
  263. {
  264. zend_file_handle fh;
  265. if (EG(in_execution)) {
  266. phpdbg_error("Cannot compile while in execution");
  267. return FAILURE;
  268. }
  269. phpdbg_notice("Attempting compilation of %s", PHPDBG_G(exec));
  270. if (php_stream_open_for_zend_ex(PHPDBG_G(exec), &fh,
  271. USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC) == SUCCESS) {
  272. PHPDBG_G(ops) = zend_compile_file(&fh, ZEND_INCLUDE TSRMLS_CC);
  273. zend_destroy_file_handle(&fh TSRMLS_CC);
  274. phpdbg_notice("Success");
  275. return SUCCESS;
  276. } else {
  277. phpdbg_error("Could not open file %s", PHPDBG_G(exec));
  278. }
  279. return FAILURE;
  280. } /* }}} */
  281. PHPDBG_COMMAND(compile) /* {{{ */
  282. {
  283. if (!PHPDBG_G(exec)) {
  284. phpdbg_error("No execution context");
  285. return SUCCESS;
  286. }
  287. if (!EG(in_execution)) {
  288. if (PHPDBG_G(ops)) {
  289. phpdbg_error("Destroying previously compiled opcodes");
  290. phpdbg_clean(0 TSRMLS_CC);
  291. }
  292. }
  293. phpdbg_compile(TSRMLS_C);
  294. return SUCCESS;
  295. } /* }}} */
  296. PHPDBG_COMMAND(step) /* {{{ */
  297. {
  298. switch (param->type) {
  299. case EMPTY_PARAM:
  300. case NUMERIC_PARAM: {
  301. if (param->type == NUMERIC_PARAM && param->num) {
  302. PHPDBG_G(flags) |= PHPDBG_IS_STEPPING;
  303. } else {
  304. PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING;
  305. }
  306. phpdbg_notice("Stepping %s",
  307. (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off");
  308. } break;
  309. phpdbg_default_switch_case();
  310. }
  311. return SUCCESS;
  312. } /* }}} */
  313. PHPDBG_COMMAND(next) /* {{{ */
  314. {
  315. return PHPDBG_NEXT;
  316. } /* }}} */
  317. PHPDBG_COMMAND(until) /* {{{ */
  318. {
  319. if (!EG(in_execution)) {
  320. phpdbg_error("Not executing");
  321. return SUCCESS;
  322. }
  323. PHPDBG_G(flags) |= PHPDBG_IN_UNTIL;
  324. {
  325. zend_uint next = 0,
  326. self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes);
  327. zend_op *opline = &EG(active_op_array)->opcodes[self];
  328. for (next = self; next < EG(active_op_array)->last; next++) {
  329. if (EG(active_op_array)->opcodes[next].lineno != opline->lineno) {
  330. zend_hash_index_update(
  331. &PHPDBG_G(seek),
  332. (zend_ulong) &EG(active_op_array)->opcodes[next],
  333. &EG(active_op_array)->opcodes[next],
  334. sizeof(zend_op), NULL);
  335. break;
  336. }
  337. }
  338. }
  339. return PHPDBG_UNTIL;
  340. } /* }}} */
  341. PHPDBG_COMMAND(finish) /* {{{ */
  342. {
  343. if (!EG(in_execution)) {
  344. phpdbg_error("Not executing");
  345. return SUCCESS;
  346. }
  347. PHPDBG_G(flags) |= PHPDBG_IN_FINISH;
  348. {
  349. zend_uint next = 0,
  350. self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes);
  351. for (next = self; next < EG(active_op_array)->last; next++) {
  352. switch (EG(active_op_array)->opcodes[next].opcode) {
  353. case ZEND_RETURN:
  354. case ZEND_THROW:
  355. case ZEND_EXIT:
  356. #ifdef ZEND_YIELD
  357. case ZEND_YIELD:
  358. #endif
  359. zend_hash_index_update(
  360. &PHPDBG_G(seek),
  361. (zend_ulong) &EG(active_op_array)->opcodes[next],
  362. &EG(active_op_array)->opcodes[next],
  363. sizeof(zend_op), NULL);
  364. break;
  365. }
  366. }
  367. }
  368. return PHPDBG_FINISH;
  369. } /* }}} */
  370. PHPDBG_COMMAND(leave) /* {{{ */
  371. {
  372. if (!EG(in_execution)) {
  373. phpdbg_error("Not executing");
  374. return SUCCESS;
  375. }
  376. PHPDBG_G(flags) |= PHPDBG_IN_LEAVE;
  377. {
  378. zend_uint next = 0,
  379. self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes);
  380. for (next = self; next < EG(active_op_array)->last; next++) {
  381. switch (EG(active_op_array)->opcodes[next].opcode) {
  382. case ZEND_RETURN:
  383. case ZEND_THROW:
  384. case ZEND_EXIT:
  385. #ifdef ZEND_YIELD
  386. case ZEND_YIELD:
  387. #endif
  388. zend_hash_index_update(
  389. &PHPDBG_G(seek),
  390. (zend_ulong) &EG(active_op_array)->opcodes[next],
  391. &EG(active_op_array)->opcodes[next],
  392. sizeof(zend_op), NULL);
  393. break;
  394. }
  395. }
  396. }
  397. return PHPDBG_LEAVE;
  398. } /* }}} */
  399. PHPDBG_COMMAND(frame) /* {{{ */
  400. {
  401. switch (param->type) {
  402. case NUMERIC_PARAM:
  403. phpdbg_switch_frame(param->num TSRMLS_CC);
  404. break;
  405. case EMPTY_PARAM:
  406. phpdbg_notice("Currently in frame #%d", PHPDBG_G(frame).num);
  407. break;
  408. phpdbg_default_switch_case();
  409. }
  410. return SUCCESS;
  411. } /* }}} */
  412. static inline void phpdbg_handle_exception(TSRMLS_D) /* }}} */
  413. {
  414. zend_fcall_info fci;
  415. zval fname,
  416. *trace,
  417. exception;
  418. /* get filename and linenumber before unsetting exception */
  419. const char *filename = zend_get_executed_filename(TSRMLS_C);
  420. zend_uint lineno = zend_get_executed_lineno(TSRMLS_C);
  421. /* copy exception */
  422. exception = *EG(exception);
  423. zval_copy_ctor(&exception);
  424. EG(exception) = NULL;
  425. phpdbg_error(
  426. "Uncaught %s!",
  427. Z_OBJCE(exception)->name);
  428. /* call __toString */
  429. ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring")-1, 1);
  430. fci.size = sizeof(fci);
  431. fci.function_table = &Z_OBJCE(exception)->function_table;
  432. fci.function_name = &fname;
  433. fci.symbol_table = NULL;
  434. fci.object_ptr = &exception;
  435. fci.retval_ptr_ptr = &trace;
  436. fci.param_count = 0;
  437. fci.params = NULL;
  438. fci.no_separation = 1;
  439. zend_call_function(&fci, NULL TSRMLS_CC);
  440. if (trace) {
  441. phpdbg_writeln(
  442. "Uncaught %s", Z_STRVAL_P(trace));
  443. /* remember to dtor trace */
  444. zval_ptr_dtor(&trace);
  445. }
  446. /* output useful information about address */
  447. phpdbg_writeln(
  448. "Stacked entered at %p in %s on line %u",
  449. EG(active_op_array)->opcodes, filename, lineno);
  450. zval_dtor(&fname);
  451. zval_dtor(&exception);
  452. } /* }}} */
  453. PHPDBG_COMMAND(run) /* {{{ */
  454. {
  455. if (EG(in_execution)) {
  456. phpdbg_error("Cannot start another execution while one is in progress");
  457. return SUCCESS;
  458. }
  459. if (PHPDBG_G(ops) || PHPDBG_G(exec)) {
  460. zend_op **orig_opline = EG(opline_ptr);
  461. zend_op_array *orig_op_array = EG(active_op_array);
  462. zval **orig_retval_ptr = EG(return_value_ptr_ptr);
  463. if (!PHPDBG_G(ops)) {
  464. if (phpdbg_compile(TSRMLS_C) == FAILURE) {
  465. phpdbg_error("Failed to compile %s, cannot run", PHPDBG_G(exec));
  466. goto out;
  467. }
  468. }
  469. EG(active_op_array) = PHPDBG_G(ops);
  470. EG(return_value_ptr_ptr) = &PHPDBG_G(retval);
  471. if (!EG(active_symbol_table)) {
  472. zend_rebuild_symbol_table(TSRMLS_C);
  473. }
  474. /* clean seek state */
  475. PHPDBG_G(flags) &= ~PHPDBG_SEEK_MASK;
  476. zend_hash_clean(
  477. &PHPDBG_G(seek));
  478. /* reset hit counters */
  479. phpdbg_reset_breakpoints(TSRMLS_C);
  480. zend_try {
  481. php_output_activate(TSRMLS_C);
  482. PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE;
  483. zend_execute(EG(active_op_array) TSRMLS_CC);
  484. PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE;
  485. php_output_deactivate(TSRMLS_C);
  486. } zend_catch {
  487. EG(active_op_array) = orig_op_array;
  488. EG(opline_ptr) = orig_opline;
  489. EG(return_value_ptr_ptr) = orig_retval_ptr;
  490. if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
  491. phpdbg_error("Caught exit/error from VM");
  492. goto out;
  493. }
  494. } zend_end_try();
  495. if (EG(exception)) {
  496. phpdbg_handle_exception(TSRMLS_C);
  497. }
  498. EG(active_op_array) = orig_op_array;
  499. EG(opline_ptr) = orig_opline;
  500. EG(return_value_ptr_ptr) = orig_retval_ptr;
  501. } else {
  502. phpdbg_error("Nothing to execute!");
  503. }
  504. out:
  505. PHPDBG_FRAME(num) = 0;
  506. return SUCCESS;
  507. } /* }}} */
  508. PHPDBG_COMMAND(eval) /* {{{ */
  509. {
  510. switch (param->type) {
  511. case STR_PARAM: {
  512. zend_bool stepping = ((PHPDBG_G(flags) & PHPDBG_IS_STEPPING)==PHPDBG_IS_STEPPING);
  513. zval retval;
  514. if (!(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) {
  515. PHPDBG_G(flags) &= ~ PHPDBG_IS_STEPPING;
  516. }
  517. /* disable stepping while eval() in progress */
  518. PHPDBG_G(flags) |= PHPDBG_IN_EVAL;
  519. zend_try {
  520. if (zend_eval_stringl(param->str, param->len,
  521. &retval, "eval()'d code" TSRMLS_CC) == SUCCESS) {
  522. zend_print_zval_r(
  523. &retval, 0 TSRMLS_CC);
  524. phpdbg_writeln(EMPTY);
  525. zval_dtor(&retval);
  526. }
  527. } zend_end_try();
  528. PHPDBG_G(flags) &= ~PHPDBG_IN_EVAL;
  529. /* switch stepping back on */
  530. if (stepping &&
  531. !(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) {
  532. PHPDBG_G(flags) |= PHPDBG_IS_STEPPING;
  533. }
  534. CG(unclean_shutdown) = 0;
  535. } break;
  536. phpdbg_default_switch_case();
  537. }
  538. return SUCCESS;
  539. } /* }}} */
  540. PHPDBG_COMMAND(back) /* {{{ */
  541. {
  542. if (!EG(in_execution)) {
  543. phpdbg_error("Not executing!");
  544. return SUCCESS;
  545. }
  546. switch (param->type) {
  547. case EMPTY_PARAM:
  548. case NUMERIC_PARAM:
  549. phpdbg_dump_backtrace(
  550. (param->type == NUMERIC_PARAM) ? param->num : 0 TSRMLS_CC);
  551. break;
  552. phpdbg_default_switch_case();
  553. }
  554. return SUCCESS;
  555. } /* }}} */
  556. PHPDBG_COMMAND(print) /* {{{ */
  557. {
  558. switch (param->type) {
  559. case EMPTY_PARAM: {
  560. phpdbg_writeln(SEPARATE);
  561. phpdbg_notice("Execution Context Information");
  562. #ifdef HAVE_LIBREADLINE
  563. phpdbg_writeln("Readline\tyes");
  564. #else
  565. phpdbg_writeln("Readline\tno");
  566. #endif
  567. phpdbg_writeln("Exec\t\t%s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none");
  568. phpdbg_writeln("Compiled\t%s", PHPDBG_G(ops) ? "yes" : "no");
  569. phpdbg_writeln("Stepping\t%s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off");
  570. phpdbg_writeln("Quietness\t%s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off");
  571. phpdbg_writeln("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off");
  572. if (PHPDBG_G(ops)) {
  573. phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last);
  574. if (PHPDBG_G(ops)->last_var) {
  575. phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1);
  576. } else {
  577. phpdbg_writeln("Variables\tNone");
  578. }
  579. }
  580. phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no");
  581. if (EG(in_execution)) {
  582. phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret));
  583. }
  584. phpdbg_writeln("Classes\t\t%d", zend_hash_num_elements(EG(class_table)));
  585. phpdbg_writeln("Functions\t%d", zend_hash_num_elements(EG(function_table)));
  586. phpdbg_writeln("Constants\t%d", zend_hash_num_elements(EG(zend_constants)));
  587. phpdbg_writeln("Included\t%d", zend_hash_num_elements(&EG(included_files)));
  588. phpdbg_writeln(SEPARATE);
  589. } break;
  590. phpdbg_default_switch_case();
  591. }
  592. return SUCCESS;
  593. } /* }}} */
  594. PHPDBG_COMMAND(info) /* {{{ */
  595. {
  596. phpdbg_error(
  597. "No information command selected!");
  598. return SUCCESS;
  599. } /* }}} */
  600. PHPDBG_COMMAND(set) /* {{{ */
  601. {
  602. phpdbg_error(
  603. "No information command selected!");
  604. return SUCCESS;
  605. } /* }}} */
  606. PHPDBG_COMMAND(break) /* {{{ */
  607. {
  608. switch (param->type) {
  609. case EMPTY_PARAM:
  610. phpdbg_set_breakpoint_file(
  611. zend_get_executed_filename(TSRMLS_C),
  612. zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
  613. break;
  614. case ADDR_PARAM:
  615. phpdbg_set_breakpoint_opline(param->addr TSRMLS_CC);
  616. break;
  617. case NUMERIC_PARAM:
  618. if (PHPDBG_G(exec)) {
  619. phpdbg_set_breakpoint_file(phpdbg_current_file(TSRMLS_C), param->num TSRMLS_CC);
  620. } else {
  621. phpdbg_error("Execution context not set!");
  622. }
  623. break;
  624. case METHOD_PARAM:
  625. phpdbg_set_breakpoint_method(param->method.class, param->method.name TSRMLS_CC);
  626. break;
  627. case NUMERIC_METHOD_PARAM:
  628. phpdbg_set_breakpoint_method_opline(param->method.class, param->method.name, param->num TSRMLS_CC);
  629. break;
  630. case NUMERIC_FUNCTION_PARAM:
  631. phpdbg_set_breakpoint_function_opline(param->str, param->num TSRMLS_CC);
  632. break;
  633. case FILE_PARAM:
  634. phpdbg_set_breakpoint_file(param->file.name, param->file.line TSRMLS_CC);
  635. break;
  636. case STR_PARAM:
  637. phpdbg_set_breakpoint_symbol(param->str, param->len TSRMLS_CC);
  638. break;
  639. phpdbg_default_switch_case();
  640. }
  641. return SUCCESS;
  642. } /* }}} */
  643. PHPDBG_COMMAND(shell) /* {{{ */
  644. {
  645. /* don't allow this to loop, ever ... */
  646. switch (param->type) {
  647. case STR_PARAM: {
  648. FILE *fd = NULL;
  649. if ((fd=VCWD_POPEN((char*)param->str, "w"))) {
  650. /* do something perhaps ?? do we want input ?? */
  651. fclose(fd);
  652. } else {
  653. phpdbg_error(
  654. "Failed to execute %s", param->str);
  655. }
  656. } break;
  657. phpdbg_default_switch_case();
  658. }
  659. return SUCCESS;
  660. } /* }}} */
  661. PHPDBG_COMMAND(source) /* {{{ */
  662. {
  663. switch (param->type) {
  664. case STR_PARAM: {
  665. if (input->argc > 2) {
  666. if (phpdbg_argv_is(1, "export")) {
  667. FILE *h = VCWD_FOPEN(input->argv[2]->string, "w+");
  668. if (h) {
  669. phpdbg_export_breakpoints(h TSRMLS_CC);
  670. fclose(h);
  671. } else phpdbg_error("Failed to open %s", input->argv[1]->string);
  672. } else {
  673. phpdbg_error(
  674. "Incorrect usage of source command, see help");
  675. }
  676. } else {
  677. struct stat sb;
  678. if (VCWD_STAT(param->str, &sb) != -1) {
  679. phpdbg_try_file_init(param->str, param->len, 0 TSRMLS_CC);
  680. } else phpdbg_error("Cannot stat %s", param->str);
  681. }
  682. } break;
  683. phpdbg_default_switch_case();
  684. }
  685. return SUCCESS;
  686. } /* }}} */
  687. PHPDBG_COMMAND(register) /* {{{ */
  688. {
  689. switch (param->type) {
  690. case STR_PARAM: {
  691. zend_function *function;
  692. char *lcname = zend_str_tolower_dup(param->str, param->len);
  693. size_t lcname_len = strlen(lcname);
  694. if (!zend_hash_exists(&PHPDBG_G(registered), lcname, lcname_len+1)) {
  695. if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void**) &function) == SUCCESS) {
  696. zend_hash_update(
  697. &PHPDBG_G(registered), lcname, lcname_len+1, (void*)&function, sizeof(zend_function), NULL);
  698. function_add_ref(function);
  699. phpdbg_notice(
  700. "Registered %s", lcname);
  701. } else {
  702. phpdbg_error("The requested function (%s) could not be found", param->str);
  703. }
  704. } else {
  705. phpdbg_error(
  706. "The requested name (%s) is already in use", lcname);
  707. }
  708. efree(lcname);
  709. } break;
  710. phpdbg_default_switch_case();
  711. }
  712. return SUCCESS;
  713. } /* }}} */
  714. PHPDBG_COMMAND(quit) /* {{{ */
  715. {
  716. /* don't allow this to loop, ever ... */
  717. if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
  718. phpdbg_destroy_input((phpdbg_input_t**)&input TSRMLS_CC);
  719. PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
  720. zend_bailout();
  721. }
  722. return SUCCESS;
  723. } /* }}} */
  724. PHPDBG_COMMAND(clean) /* {{{ */
  725. {
  726. if (EG(in_execution)) {
  727. phpdbg_error("Cannot clean environment while executing");
  728. return SUCCESS;
  729. }
  730. phpdbg_notice("Cleaning Execution Environment");
  731. phpdbg_writeln("Classes\t\t\t%d", zend_hash_num_elements(EG(class_table)));
  732. phpdbg_writeln("Functions\t\t%d", zend_hash_num_elements(EG(function_table)));
  733. phpdbg_writeln("Constants\t\t%d", zend_hash_num_elements(EG(zend_constants)));
  734. phpdbg_writeln("Includes\t\t%d", zend_hash_num_elements(&EG(included_files)));
  735. phpdbg_clean(1 TSRMLS_CC);
  736. return SUCCESS;
  737. } /* }}} */
  738. PHPDBG_COMMAND(clear) /* {{{ */
  739. {
  740. phpdbg_notice("Clearing Breakpoints");
  741. phpdbg_writeln("File\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]));
  742. phpdbg_writeln("Functions\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]));
  743. phpdbg_writeln("Methods\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]));
  744. phpdbg_writeln("Oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]));
  745. phpdbg_writeln("File oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE]));
  746. phpdbg_writeln("Function oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]));
  747. phpdbg_writeln("Method oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]));
  748. phpdbg_writeln("Conditionals\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]));
  749. phpdbg_clear_breakpoints(TSRMLS_C);
  750. return SUCCESS;
  751. } /* }}} */
  752. PHPDBG_COMMAND(aliases) /* {{{ */
  753. {
  754. const phpdbg_command_t *prompt_command = phpdbg_prompt_commands;
  755. phpdbg_help_header();
  756. phpdbg_writeln("Below are the aliased, short versions of all supported commands");
  757. while (prompt_command && prompt_command->name) {
  758. if (prompt_command->alias) {
  759. if (prompt_command->subs) {
  760. const phpdbg_command_t *sub_command = prompt_command->subs;
  761. phpdbg_writeln(EMPTY);
  762. phpdbg_writeln(" %c -> %9s", prompt_command->alias, prompt_command->name);
  763. while (sub_command && sub_command->name) {
  764. if (sub_command->alias) {
  765. phpdbg_writeln(" |-------- %c -> %15s\t%s", sub_command->alias,
  766. sub_command->name, sub_command->tip);
  767. }
  768. ++sub_command;
  769. }
  770. phpdbg_writeln(EMPTY);
  771. } else {
  772. phpdbg_writeln(" %c -> %9s\t\t\t%s", prompt_command->alias,
  773. prompt_command->name, prompt_command->tip);
  774. }
  775. }
  776. ++prompt_command;
  777. }
  778. phpdbg_help_footer();
  779. return SUCCESS;
  780. } /* }}} */
  781. PHPDBG_COMMAND(help) /* {{{ */
  782. {
  783. switch (param->type) {
  784. case EMPTY_PARAM: {
  785. const phpdbg_command_t *prompt_command = phpdbg_prompt_commands;
  786. const phpdbg_command_t *help_command = phpdbg_help_commands;
  787. phpdbg_help_header();
  788. phpdbg_writeln("To get help regarding a specific command type \"help command\"");
  789. phpdbg_notice("Commands");
  790. while (prompt_command && prompt_command->name) {
  791. phpdbg_writeln(
  792. " %10s\t%s", prompt_command->name, prompt_command->tip);
  793. ++prompt_command;
  794. }
  795. phpdbg_notice("Help Commands");
  796. while (help_command && help_command->name) {
  797. phpdbg_writeln(" %10s\t%s", help_command->name, help_command->tip);
  798. ++help_command;
  799. }
  800. phpdbg_help_footer();
  801. } break;
  802. default: {
  803. phpdbg_error(
  804. "No help can be found for the subject \"%s\"", param->str);
  805. }
  806. }
  807. return SUCCESS;
  808. } /* }}} */
  809. PHPDBG_COMMAND(quiet) /* {{{ */
  810. {
  811. switch (param->type) {
  812. case NUMERIC_PARAM: {
  813. if (param->num) {
  814. PHPDBG_G(flags) |= PHPDBG_IS_QUIET;
  815. } else {
  816. PHPDBG_G(flags) &= ~PHPDBG_IS_QUIET;
  817. }
  818. phpdbg_notice("Quietness %s",
  819. (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "enabled" : "disabled");
  820. } break;
  821. phpdbg_default_switch_case();
  822. }
  823. return SUCCESS;
  824. } /* }}} */
  825. PHPDBG_COMMAND(list) /* {{{ */
  826. {
  827. switch (param->type) {
  828. case NUMERIC_PARAM:
  829. case EMPTY_PARAM:
  830. return PHPDBG_LIST_HANDLER(lines)(PHPDBG_COMMAND_ARGS);
  831. case FILE_PARAM:
  832. return PHPDBG_LIST_HANDLER(lines)(PHPDBG_COMMAND_ARGS);
  833. case STR_PARAM:
  834. phpdbg_list_function_byname(param->str, param->len TSRMLS_CC);
  835. break;
  836. case METHOD_PARAM:
  837. return PHPDBG_LIST_HANDLER(method)(PHPDBG_COMMAND_ARGS);
  838. phpdbg_default_switch_case();
  839. }
  840. return SUCCESS;
  841. } /* }}} */
  842. int phpdbg_interactive(TSRMLS_D) /* {{{ */
  843. {
  844. int ret = SUCCESS;
  845. phpdbg_input_t *input;
  846. PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE;
  847. input = phpdbg_read_input(NULL TSRMLS_CC);
  848. if (input && input->length > 0L) {
  849. do {
  850. switch (ret = phpdbg_do_cmd(phpdbg_prompt_commands, input TSRMLS_CC)) {
  851. case FAILURE:
  852. if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
  853. if (phpdbg_call_register(input TSRMLS_CC) == FAILURE) {
  854. phpdbg_error("Failed to execute %s!", input->string);
  855. }
  856. }
  857. break;
  858. case PHPDBG_LEAVE:
  859. case PHPDBG_FINISH:
  860. case PHPDBG_UNTIL:
  861. case PHPDBG_NEXT: {
  862. if (!EG(in_execution)) {
  863. phpdbg_error("Not running");
  864. }
  865. goto out;
  866. }
  867. }
  868. phpdbg_destroy_input(&input TSRMLS_CC);
  869. } while ((input = phpdbg_read_input(NULL TSRMLS_CC)) && (input->length > 0L));
  870. if (input && !input->length)
  871. goto last;
  872. } else {
  873. last:
  874. if (PHPDBG_G(lcmd)) {
  875. ret = PHPDBG_G(lcmd)->handler(
  876. &PHPDBG_G(lparam), input TSRMLS_CC);
  877. goto out;
  878. }
  879. }
  880. out:
  881. phpdbg_destroy_input(&input TSRMLS_CC);
  882. if (EG(in_execution)) {
  883. phpdbg_restore_frame(TSRMLS_C);
  884. }
  885. PHPDBG_G(flags) &= ~PHPDBG_IS_INTERACTIVE;
  886. return ret;
  887. } /* }}} */
  888. void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */
  889. {
  890. /* this is implicitly required */
  891. if (PHPDBG_G(ops)) {
  892. destroy_op_array(PHPDBG_G(ops) TSRMLS_CC);
  893. efree(PHPDBG_G(ops));
  894. PHPDBG_G(ops) = NULL;
  895. }
  896. if (full) {
  897. PHPDBG_G(flags) |= PHPDBG_IS_CLEANING;
  898. zend_bailout();
  899. }
  900. } /* }}} */
  901. static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
  902. {
  903. #if PHP_VERSION_ID >= 50500
  904. return zend_create_execute_data_from_op_array(op_array, nested TSRMLS_CC);
  905. #else
  906. #undef EX
  907. #define EX(element) execute_data->element
  908. #undef EX_CV
  909. #define EX_CV(var) EX(CVs)[var]
  910. #undef EX_CVs
  911. #define EX_CVs() EX(CVs)
  912. #undef EX_T
  913. #define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
  914. #undef EX_Ts
  915. #define EX_Ts() EX(Ts)
  916. zend_execute_data *execute_data = (zend_execute_data *)zend_vm_stack_alloc(
  917. ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) +
  918. ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) +
  919. ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC);
  920. EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)));
  921. memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var);
  922. EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)));
  923. EX(fbc) = NULL;
  924. EX(called_scope) = NULL;
  925. EX(object) = NULL;
  926. EX(old_error_reporting) = NULL;
  927. EX(op_array) = op_array;
  928. EX(symbol_table) = EG(active_symbol_table);
  929. EX(prev_execute_data) = EG(current_execute_data);
  930. EG(current_execute_data) = execute_data;
  931. EX(nested) = nested;
  932. if (!op_array->run_time_cache && op_array->last_cache_slot) {
  933. op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
  934. }
  935. if (op_array->this_var != -1 && EG(This)) {
  936. Z_ADDREF_P(EG(This)); /* For $this pointer */
  937. if (!EG(active_symbol_table)) {
  938. EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var);
  939. *EX_CV(op_array->this_var) = EG(This);
  940. } else {
  941. if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) {
  942. Z_DELREF_P(EG(This));
  943. }
  944. }
  945. }
  946. EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
  947. EG(opline_ptr) = &EX(opline);
  948. EX(function_state).function = (zend_function *) op_array;
  949. EX(function_state).arguments = NULL;
  950. return execute_data;
  951. #endif
  952. } /* }}} */
  953. #if PHP_VERSION_ID >= 50500
  954. void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
  955. {
  956. #else
  957. void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC) /* {{{ */
  958. {
  959. long long flags = 0;
  960. zend_ulong address = 0L;
  961. zend_execute_data *execute_data;
  962. zend_bool nested = 0;
  963. #endif
  964. zend_bool original_in_execution = EG(in_execution);
  965. HashTable vars;
  966. #if PHP_VERSION_ID < 50500
  967. if (EG(exception)) {
  968. return;
  969. }
  970. #endif
  971. EG(in_execution) = 1;
  972. #if PHP_VERSION_ID >= 50500
  973. if (0) {
  974. zend_vm_enter:
  975. execute_data = phpdbg_create_execute_data(EG(active_op_array), 1 TSRMLS_CC);
  976. }
  977. zend_hash_init(&vars, EG(active_op_array)->last, NULL, NULL, 0);
  978. #else
  979. zend_vm_enter:
  980. execute_data = phpdbg_create_execute_data(op_array, nested TSRMLS_CC);
  981. nested = 1;
  982. zend_hash_init(&vars, EG(active_op_array)->last, NULL, NULL, 0);
  983. #endif
  984. while (1) {
  985. if ((PHPDBG_G(flags) & PHPDBG_BP_RESOLVE_MASK)) {
  986. /* resolve nth opline breakpoints */
  987. phpdbg_resolve_op_array_breaks(EG(active_op_array) TSRMLS_CC);
  988. }
  989. #ifdef ZEND_WIN32
  990. if (EG(timed_out)) {
  991. zend_timeout(0);
  992. }
  993. #endif
  994. #define DO_INTERACTIVE() do { \
  995. if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \
  996. phpdbg_list_file( \
  997. zend_get_executed_filename(TSRMLS_C), \
  998. 3, \
  999. zend_get_executed_lineno(TSRMLS_C)-1, \
  1000. zend_get_executed_lineno(TSRMLS_C) \
  1001. TSRMLS_CC \
  1002. ); \
  1003. } \
  1004. \
  1005. do { \
  1006. switch (phpdbg_interactive(TSRMLS_C)) { \
  1007. case PHPDBG_LEAVE: \
  1008. case PHPDBG_FINISH: \
  1009. case PHPDBG_UNTIL: \
  1010. case PHPDBG_NEXT:{ \
  1011. goto next; \
  1012. } \
  1013. } \
  1014. } while (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); \
  1015. } while (0)
  1016. /* allow conditional breakpoints and
  1017. initialization to access the vm uninterrupted */
  1018. if ((PHPDBG_G(flags) & PHPDBG_IN_COND_BP) ||
  1019. (PHPDBG_G(flags) & PHPDBG_IS_INITIALIZING)) {
  1020. /* skip possible breakpoints */
  1021. goto next;
  1022. }
  1023. /* perform seek operation */
  1024. if (PHPDBG_G(flags) & PHPDBG_SEEK_MASK) {
  1025. /* current address */
  1026. zend_ulong address = (zend_ulong) execute_data->opline;
  1027. /* run to next line */
  1028. if (PHPDBG_G(flags) & PHPDBG_IN_UNTIL) {
  1029. if (zend_hash_index_exists(&PHPDBG_G(seek), address)) {
  1030. PHPDBG_G(flags) &= ~PHPDBG_IN_UNTIL;
  1031. zend_hash_clean(
  1032. &PHPDBG_G(seek));
  1033. } else {
  1034. /* skip possible breakpoints */
  1035. goto next;
  1036. }
  1037. }
  1038. /* run to finish */
  1039. if (PHPDBG_G(flags) & PHPDBG_IN_FINISH) {
  1040. if (zend_hash_index_exists(&PHPDBG_G(seek), address)) {
  1041. PHPDBG_G(flags) &= ~PHPDBG_IN_FINISH;
  1042. zend_hash_clean(
  1043. &PHPDBG_G(seek));
  1044. }
  1045. /* skip possible breakpoints */
  1046. goto next;
  1047. }
  1048. /* break for leave */
  1049. if (PHPDBG_G(flags) & PHPDBG_IN_LEAVE) {
  1050. if (zend_hash_index_exists(&PHPDBG_G(seek), address)) {
  1051. PHPDBG_G(flags) &= ~PHPDBG_IN_LEAVE;
  1052. zend_hash_clean(
  1053. &PHPDBG_G(seek));
  1054. phpdbg_notice(
  1055. "Breaking for leave at %s:%u",
  1056. zend_get_executed_filename(TSRMLS_C),
  1057. zend_get_executed_lineno(TSRMLS_C)
  1058. );
  1059. DO_INTERACTIVE();
  1060. } else {
  1061. /* skip possible breakpoints */
  1062. goto next;
  1063. }
  1064. }
  1065. }
  1066. /* not while in conditionals */
  1067. phpdbg_print_opline_ex(
  1068. execute_data, &vars, 0 TSRMLS_CC);
  1069. /* search for breakpoints */
  1070. {
  1071. phpdbg_breakbase_t *brake;
  1072. if ((PHPDBG_G(flags) & PHPDBG_BP_MASK) &&
  1073. (brake = phpdbg_find_breakpoint(execute_data TSRMLS_CC))) {
  1074. phpdbg_hit_breakpoint(
  1075. brake, 1 TSRMLS_CC);
  1076. DO_INTERACTIVE();
  1077. }
  1078. }
  1079. if (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) {
  1080. DO_INTERACTIVE();
  1081. }
  1082. next:
  1083. if (PHPDBG_G(flags) & PHPDBG_IS_SIGNALED) {
  1084. phpdbg_writeln(EMPTY);
  1085. phpdbg_notice("Program received signal SIGINT");
  1086. PHPDBG_G(flags) &= ~PHPDBG_IS_SIGNALED;
  1087. DO_INTERACTIVE();
  1088. }
  1089. PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC);
  1090. if (PHPDBG_G(vmret) > 0) {
  1091. switch (PHPDBG_G(vmret)) {
  1092. case 1:
  1093. EG(in_execution) = original_in_execution;
  1094. zend_hash_destroy(&vars);
  1095. return;
  1096. case 2:
  1097. #if PHP_VERSION_ID < 50500
  1098. op_array = EG(active_op_array);
  1099. #endif
  1100. zend_hash_destroy(&vars);
  1101. goto zend_vm_enter;
  1102. break;
  1103. case 3:
  1104. execute_data = EG(current_execute_data);
  1105. break;
  1106. default:
  1107. break;
  1108. }
  1109. }
  1110. }
  1111. zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");
  1112. } /* }}} */