Remove the ugly hack via a temp file to store breakpoints

This commit is contained in:
Bob Weinand 2014-10-28 17:20:21 +01:00
parent fd8a70b1ee
commit 297baa0c18
5 changed files with 173 additions and 149 deletions

View File

@ -1039,13 +1039,7 @@ int main(int argc, char **argv) /* {{{ */
zend_bool remote = 0;
int step = 0;
zend_phpdbg_globals *settings = NULL;
#ifdef _WIN32
char *bp_tmp_file = NULL;
#else
char bp_tmp_file[] = "/tmp/phpdbg.XXXXXX";
#endif
char *bp_tmp = NULL;
char *address;
int listen = -1;
int server = -1;
@ -1081,29 +1075,6 @@ int main(int argc, char **argv) /* {{{ */
#endif
phpdbg_main:
if (!cleaning) {
#ifdef _WIN32
bp_tmp_file = malloc(L_tmpnam);
if (bp_tmp_file) {
if (!tmpnam(bp_tmp_file)) {
free(bp_tmp_file);
bp_tmp_file = NULL;
}
}
if (!bp_tmp_file) {
phpdbg_error("tmpfile", "", "Unable to create temporary file");
return 1;
}
#else
if (!mkstemp(bp_tmp_file)) {
memset(bp_tmp_file, 0, sizeof(bp_tmp_file));
}
#endif
}
ini_entries = NULL;
ini_entries_len = 0;
ini_ignore = 0;
@ -1502,9 +1473,13 @@ phpdbg_main:
PHPDBG_G(flags) |= PHPDBG_IS_INITIALIZING;
zend_try {
phpdbg_init(init_file, init_file_len, init_file_default TSRMLS_CC);
PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT;
phpdbg_try_file_init(bp_tmp_file, strlen(bp_tmp_file), 0 TSRMLS_CC);
PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT;
if (bp_tmp) {
PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT;
phpdbg_string_init(bp_tmp TSRMLS_CC);
free(bp_tmp);
bp_tmp = NULL;
PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT;
}
} zend_end_try();
PHPDBG_G(flags) &= ~PHPDBG_IS_INITIALIZING;
@ -1532,23 +1507,27 @@ phpdbg_interact:
do {
zend_try {
if (phpdbg_startup_run) {
zend_bool quit_immediately = phpdbg_startup_run > 1;
phpdbg_startup_run = 0;
PHPDBG_COMMAND_HANDLER(run)(NULL TSRMLS_CC);
if (phpdbg_startup_run > 1) {
if (quit_immediately) {
/* if -r is on the command line more than once just quit */
EG(bailout) = __orig_bailout; /* reset zend_try */
break;
}
phpdbg_startup_run = 0;
}
phpdbg_interactive(1 TSRMLS_CC);
} zend_catch {
if ((PHPDBG_G(flags) & PHPDBG_IS_CLEANING)) {
FILE *bp_tmp_fp = fopen(bp_tmp_file, "w");
char *bp_tmp_str;
PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT;
phpdbg_export_breakpoints(bp_tmp_fp TSRMLS_CC);
phpdbg_export_breakpoints_to_string(&bp_tmp_str TSRMLS_CC);
PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT;
fclose(bp_tmp_fp);
if (bp_tmp_str) {
bp_tmp = strdup(bp_tmp_str);
efree(bp_tmp_str);
}
cleaning = 1;
} else {
cleaning = 0;
@ -1688,11 +1667,5 @@ phpdbg_out:
free(PHPDBG_G(sapi_name_ptr));
}
#ifdef _WIN32
free(bp_tmp_file);
#else
unlink(bp_tmp_file);
#endif
return 0;
} /* }}} */

View File

@ -110,11 +110,20 @@ PHPDBG_API void phpdbg_reset_breakpoints(TSRMLS_D) /* {{{ */
} /* }}} */
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */
{
char *string;
phpdbg_export_breakpoints_to_string(&string TSRMLS_CC);
fputs(string, handle);
}
PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str TSRMLS_DC) /* {{{ */
{
HashPosition position[2];
HashTable **table = NULL;
zend_ulong id = 0L;
*str = "";
if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) {
phpdbg_notice("exportbreakpoint", "count=\"%d\"", "Exporting %d breakpoints", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]));
/* this only looks like magic, it isn't */
@ -126,55 +135,57 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */
zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], NULL, NULL, &id, 0, &position[0]);
for (zend_hash_internal_pointer_reset_ex((*table), &position[1]);
zend_hash_get_current_data_ex((*table), (void**)&brake, &position[1]) == SUCCESS;
zend_hash_move_forward_ex((*table), &position[1])) {
zend_hash_get_current_data_ex((*table), (void**)&brake, &position[1]) == SUCCESS;
zend_hash_move_forward_ex((*table), &position[1])) {
if (brake->id == id) {
char *new_str = NULL;
switch (brake->type) {
case PHPDBG_BREAK_FILE: {
fprintf(handle,
"break %s:%lu\n",
phpdbg_asprintf(&new_str,
"%sbreak %s:%lu\n", *str,
((phpdbg_breakfile_t*)brake)->filename,
((phpdbg_breakfile_t*)brake)->line);
} break;
case PHPDBG_BREAK_SYM: {
fprintf(handle,
"break %s\n",
phpdbg_asprintf(&new_str,
"%sbreak %s\n", *str,
((phpdbg_breaksymbol_t*)brake)->symbol);
} break;
case PHPDBG_BREAK_METHOD: {
fprintf(handle,
"break %s::%s\n",
phpdbg_asprintf(&new_str,
"%sbreak %s::%s\n", *str,
((phpdbg_breakmethod_t*)brake)->class_name,
((phpdbg_breakmethod_t*)brake)->func_name);
} break;
case PHPDBG_BREAK_METHOD_OPLINE: {
fprintf(handle,
"break %s::%s#%ld\n",
phpdbg_asprintf(&new_str,
"%sbreak %s::%s#%ld\n", *str,
((phpdbg_breakopline_t*)brake)->class_name,
((phpdbg_breakopline_t*)brake)->func_name,
((phpdbg_breakopline_t*)brake)->opline_num);
} break;
case PHPDBG_BREAK_FUNCTION_OPLINE: {
fprintf(handle,
"break %s#%ld\n",
phpdbg_asprintf(&new_str,
"%sbreak %s#%ld\n", *str,
((phpdbg_breakopline_t*)brake)->func_name,
((phpdbg_breakopline_t*)brake)->opline_num);
} break;
case PHPDBG_BREAK_FILE_OPLINE: {
fprintf(handle,
"break %s:#%ld\n",
phpdbg_asprintf(&new_str,
"%sbreak %s:#%ld\n", *str,
((phpdbg_breakopline_t*)brake)->class_name,
((phpdbg_breakopline_t*)brake)->opline_num);
} break;
case PHPDBG_BREAK_OPCODE: {
fprintf(handle,
"break %s\n",
phpdbg_asprintf(&new_str,
"%sbreak %s\n", *str,
((phpdbg_breakop_t*)brake)->name);
} break;
@ -184,20 +195,20 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */
if (conditional->paramed) {
switch (conditional->param.type) {
case STR_PARAM:
fprintf(handle,
"break at %s if %s\n", conditional->param.str, conditional->code);
phpdbg_asprintf(&new_str,
"%sbreak at %s if %s\n", *str, conditional->param.str, conditional->code);
break;
case METHOD_PARAM:
fprintf(handle,
"break at %s::%s if %s\n",
phpdbg_asprintf(&new_str,
"%sbreak at %s::%s if %s\n", *str,
conditional->param.method.class, conditional->param.method.name,
conditional->code);
break;
case FILE_PARAM:
fprintf(handle,
"break at %s:%lu if %s\n",
phpdbg_asprintf(&new_str,
"%sbreak at %s:%lu if %s\n", *str,
conditional->param.file.name, conditional->param.file.line,
conditional->code);
break;
@ -205,15 +216,23 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */
default: { /* do nothing */ } break;
}
} else {
fprintf(
handle, "break if %s\n", conditional->code);
phpdbg_asprintf(&new_str, "%sbreak if %s\n", str, conditional->code);
}
} break;
}
if ((*str)[0]) {
efree(*str);
}
*str = new_str;
}
}
}
}
if (!(*str)[0]) {
*str = NULL;
}
} /* }}} */
PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{{ */

View File

@ -157,6 +157,7 @@ PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase(zend_ulong id TSRMLS_DC);
PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable ***table, HashPosition *position TSRMLS_DC); /* }}} */
/* {{{ Breakpoint Exportation API */
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC); /* }}} */
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC);
PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str TSRMLS_DC); /* }}} */
#endif /* PHPDBG_BP_H */

View File

@ -208,6 +208,110 @@ static inline int phpdbg_call_register(phpdbg_param_t *stack TSRMLS_DC) /* {{{ *
return FAILURE;
} /* }}} */
struct phpdbg_init_state {
int line;
zend_bool in_code;
char *code;
size_t code_len;
const char *init_file;
};
static void phpdbg_line_init(char *cmd, struct phpdbg_init_state *state TSRMLS_DC) {
size_t cmd_len = strlen(cmd);
state->line++;
while (cmd_len > 0L && isspace(cmd[cmd_len-1])) {
cmd_len--;
}
cmd[cmd_len] = '\0';
if (*cmd && cmd_len > 0L && cmd[0] != '#') {
if (cmd_len == 2) {
if (memcmp(cmd, "<:", sizeof("<:")-1) == SUCCESS) {
state->in_code = 1;
return;
} else {
if (memcmp(cmd, ":>", sizeof(":>")-1) == SUCCESS) {
state->in_code = 0;
state->code[state->code_len] = '\0';
zend_eval_stringl(state->code, state->code_len, NULL, "phpdbginit code" TSRMLS_CC);
free(state->code);
state->code = NULL;
return;
}
}
}
if (state->in_code) {
if (state->code == NULL) {
state->code = malloc(cmd_len + 1);
} else {
state->code = realloc(state->code, state->code_len + cmd_len + 1);
}
if (state->code) {
memcpy(&state->code[state->code_len], cmd, cmd_len);
state->code_len += cmd_len;
}
return;
}
zend_try {
char *input = phpdbg_read_input(cmd TSRMLS_CC);
phpdbg_param_t stack;
phpdbg_init_param(&stack, STACK_PARAM);
phpdbg_activate_err_buf(1 TSRMLS_CC);
if (phpdbg_do_parse(&stack, input TSRMLS_CC) <= 0) {
switch (phpdbg_stack_execute(&stack, 1 /* allow_async_unsafe == 1 */ TSRMLS_CC)) {
case FAILURE:
phpdbg_activate_err_buf(0 TSRMLS_CC);
if (phpdbg_call_register(&stack TSRMLS_CC) == FAILURE) {
if (state->init_file) {
phpdbg_output_err_buf("initfailure", "%b file=\"%s\" line=\"%d\" input=\"%s\"", "Unrecognized command in %s:%d: %s, %b!" TSRMLS_CC, state->init_file, state->line, input);
} else {
phpdbg_output_err_buf("initfailure", "%b line=\"%d\" input=\"%s\"", "Unrecognized command on line %d: %s, %b!" TSRMLS_CC, state->line, input);
}
}
break;
}
}
phpdbg_activate_err_buf(0 TSRMLS_CC);
phpdbg_free_err_buf(TSRMLS_C);
phpdbg_stack_free(&stack);
phpdbg_destroy_input(&input TSRMLS_CC);
} zend_catch {
PHPDBG_G(flags) &= ~(PHPDBG_IS_RUNNING | PHPDBG_IS_CLEANING);
if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) {
zend_bailout();
}
} zend_end_try();
}
}
void phpdbg_string_init(char *buffer TSRMLS_DC) {
struct phpdbg_init_state state = {0};
char *str = strtok(buffer, "\n");
while (str) {
phpdbg_line_init(str, &state TSRMLS_CC);
str = strtok(NULL, "\n");
}
if (state.code) {
free(state.code);
}
}
void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init TSRMLS_DC) /* {{{ */
{
struct stat sb;
@ -215,91 +319,17 @@ void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_
if (init_file && VCWD_STAT(init_file, &sb) != -1) {
FILE *fp = fopen(init_file, "r");
if (fp) {
int line = 1;
char cmd[PHPDBG_MAX_CMD];
size_t cmd_len = 0L;
char *code = NULL;
size_t code_len = 0L;
zend_bool in_code = 0;
struct phpdbg_init_state state = {0};
state.init_file = init_file;
while (fgets(cmd, PHPDBG_MAX_CMD, fp) != NULL) {
cmd_len = strlen(cmd)-1;
while (cmd_len > 0L && isspace(cmd[cmd_len-1]))
cmd_len--;
cmd[cmd_len] = '\0';
if (*cmd && cmd_len > 0L && cmd[0] != '#') {
if (cmd_len == 2) {
if (memcmp(cmd, "<:", sizeof("<:")-1) == SUCCESS) {
in_code = 1;
goto next_line;
} else {
if (memcmp(cmd, ":>", sizeof(":>")-1) == SUCCESS) {
in_code = 0;
code[code_len] = '\0';
{
zend_eval_stringl(code, code_len, NULL, "phpdbginit code" TSRMLS_CC);
}
free(code);
code = NULL;
goto next_line;
}
}
}
if (in_code) {
if (code == NULL) {
code = malloc(cmd_len + 1);
} else code = realloc(code, code_len + cmd_len + 1);
if (code) {
memcpy(
&code[code_len], cmd, cmd_len);
code_len += cmd_len;
}
goto next_line;
}
zend_try {
char *input = phpdbg_read_input(cmd TSRMLS_CC);
phpdbg_param_t stack;
phpdbg_init_param(&stack, STACK_PARAM);
phpdbg_activate_err_buf(1 TSRMLS_CC);
if (phpdbg_do_parse(&stack, input TSRMLS_CC) <= 0) {
switch (phpdbg_stack_execute(&stack, 1 /* allow_async_unsafe == 1 */ TSRMLS_CC)) {
case FAILURE:
phpdbg_activate_err_buf(0 TSRMLS_CC);
if (phpdbg_call_register(&stack TSRMLS_CC) == FAILURE) {
phpdbg_output_err_buf("initfailure", "%b file=\"%s\" line=\"%d\" input=\"%s\"", "Unrecognized command in %s:%d: %s, %b!" TSRMLS_CC, init_file, line, input);
}
break;
}
}
phpdbg_activate_err_buf(0 TSRMLS_CC);
phpdbg_free_err_buf(TSRMLS_C);
phpdbg_stack_free(&stack);
phpdbg_destroy_input(&input TSRMLS_CC);
} zend_catch {
PHPDBG_G(flags) &= ~(PHPDBG_IS_RUNNING | PHPDBG_IS_CLEANING);
if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) {
zend_bailout();
}
} zend_end_try();
}
next_line:
line++;
phpdbg_line_init(cmd, &state TSRMLS_CC);
}
if (code) {
free(code);
if (state.code) {
free(state.code);
}
fclose(fp);

View File

@ -22,6 +22,7 @@
#define PHPDBG_PROMPT_H
/* {{{ */
void phpdbg_string_init(char *buffer TSRMLS_DC);
void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TSRMLS_DC);
void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init TSRMLS_DC);
int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC);