phpdbg_prompt.c 35 KB

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