diff options
author | Anatol Belski <ab@php.net> | 2014-11-18 21:18:52 +0100 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2014-11-18 21:18:52 +0100 |
commit | c6bad96f306df8e8b656472e618283ced5083cdb (patch) | |
tree | 7e5b52aa07777f0336b0944a228bf66f8f56b31f /sapi/phpdbg/phpdbg_bp.c | |
parent | 4262663e4caa82ba17666781a95bdcb872b4e109 (diff) | |
parent | 64a39dc7b07d4b54d050a3a5c15045fe91c0b651 (diff) | |
download | php-git-c6bad96f306df8e8b656472e618283ced5083cdb.tar.gz |
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: (398 commits)
NEWS
add test for bug #68381
Fixed bug #68381 Set FPM log level earlier during init
proper dllexport
move to size_t where zend_string is used internally
fix some datatype mismatches
return after the warning, to fix uninitialized salt usage
fix datatype mismatches
add missing type specifier
fix datatype mismatches
fix unsigned check
"extern" shouldn't be used for definitions
joined identical conditional blocks
simplify fpm tests
SEND_VAR_NO_REF optimization
Add test for bug #68442
Add various tests for FPM - covering recent bugs (68420, 68421, 68423, 68428) - for UDS - for ping and status URI - for multi pool and multi mode
Include small MIT FastCGI client library from https://github.com/adoy/PHP-FastCGI-Client
Get rid of zend_free_op structure (use zval* instead). Get rid of useless TSRMLS arguments.
Add new FPM test for IPv4/IPv6
...
Conflicts:
win32/build/config.w32
Diffstat (limited to 'sapi/phpdbg/phpdbg_bp.c')
-rw-r--r-- | sapi/phpdbg/phpdbg_bp.c | 232 |
1 files changed, 184 insertions, 48 deletions
diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index aaeaee13fd..cd40510c79 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -104,9 +104,18 @@ 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) /* {{{ */ +{ HashTable *table; 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])); @@ -116,52 +125,54 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ ZEND_HASH_FOREACH_PTR(table, brake) { 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#%llu\n", + phpdbg_asprintf(&new_str, + "%sbreak %s::%s#%llu\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#%llu\n", + phpdbg_asprintf(&new_str, + "%sbreak %s#%llu\n", *str, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_FILE_OPLINE: { - fprintf(handle, - "break %s:#%llu\n", + phpdbg_asprintf(&new_str, + "%sbreak %s:#%llu\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; @@ -171,20 +182,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; @@ -192,65 +203,163 @@ 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; } } ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END(); } + + if (!(*str)[0]) { + *str = NULL; + } } /* }}} */ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{{ */ { php_stream_statbuf ssb; char realpath[MAXPATHLEN]; + const char *original_path = path; + zend_bool pending = 0; - if (php_stream_stat_path(path, &ssb) != FAILURE) { - if (ssb.sb.st_mode & (S_IFREG|S_IFLNK)) { - HashTable *broken; - phpdbg_breakfile_t new_break; - size_t path_len = 0L; + HashTable *broken, *file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE]; + phpdbg_breakfile_t new_break; + size_t path_len = 0L; - if (VCWD_REALPATH(path, realpath)) { - path = realpath; + if (VCWD_REALPATH(path, realpath)) { + path = realpath; + } + path_len = strlen(path); + + phpdbg_debug("file path: %s, resolved path: %s, was compiled: %d\n", original_path, path, zend_hash_exists(&PHPDBG_G(file_sources), path, path_len)); + + if (!zend_hash_str_exists(&PHPDBG_G(file_sources), path, path_len)) { + if (php_stream_stat_path(path, &ssb) == FAILURE) { + if (original_path[0] == '/') { + phpdbg_error("breakpoint", "type=\"nofile\" add=\"fail\" file=\"%s\"", "Cannot stat %s, it does not exist", original_path); + return; } + + file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]; + path = original_path; path_len = strlen(path); + pending = 1; + } else if (!(ssb.sb.st_mode & (S_IFREG|S_IFLNK))) { + phpdbg_error("breakpoint", "type=\"notregular\" add=\"fail\" file=\"%s\"", "Cannot set breakpoint in %s, it is not a regular file", path); + return; + } else { + phpdbg_debug("File exists, but not compiled\n"); + } + } - if (!(broken = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len))) { - HashTable breaks; + if (!(broken = zend_hash_str_find_ptr(file_breaks, path, path_len))) { + HashTable breaks; + zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); - zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); + broken = zend_hash_str_add_mem(file_breaks, path, path_len, &breaks, sizeof(HashTable)); + } - broken = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len, &breaks, sizeof(HashTable)); - } + if (!zend_hash_index_exists(broken, line_num)) { + PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_FILE); + new_break.filename = estrndup(path, path_len); + new_break.line = line_num; - if (!zend_hash_index_exists(broken, line_num)) { - PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + zend_hash_index_update_mem(broken, line_num, &new_break, sizeof(phpdbg_breakfile_t)); - PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_FILE); - new_break.filename = estrndup(path, path_len); - new_break.line = line_num; + PHPDBG_BREAK_MAPPING(new_break.id, broken); - zend_hash_index_update_mem(broken, line_num, &new_break, sizeof(phpdbg_breakfile_t)); + if (pending) { + zend_string *file, *path_str = zend_string_init(path, path_len, 0); + ZEND_HASH_FOREACH_STR_KEY(&PHPDBG_G(file_sources), file) { + HashTable *fileht; - phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"", "Breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); + phpdbg_debug("Compare against loaded %s\n", file); - PHPDBG_BREAK_MAPPING(new_break.id, broken); - } else { - phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"", "Breakpoint at %s:%ld exists", path, line_num); - } + if (!(pending = ((fileht = phpdbg_resolve_pending_file_break_ex(file->val, file->len, path_str, broken TSRMLS_CC)) == NULL))) { + new_break = *(phpdbg_breakfile_t *) zend_hash_index_find_ptr(broken, line_num); + break; + } + } ZEND_HASH_FOREACH_END(); + zend_string_release(path_str); + } + if (pending) { + PHPDBG_G(flags) |= PHPDBG_HAS_PENDING_FILE_BP; + + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\" pending=\"pending\"", "Pending breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); } else { - phpdbg_error("breakpoint", "type=\"notregular\" add=\"fail\" file=\"%s\"", "Cannot set breakpoint in %s, it is not a regular file", path); + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"", "Breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); } } else { - phpdbg_error("breakpoint", "type=\"nofile\" add=\"fail\" file=\"%s\"", "Cannot stat %s, it does not exist", path); + phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"", "Breakpoint at %s:%ld exists", path, line_num); } } /* }}} */ +PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uint filelen, zend_string *cur, HashTable *fileht TSRMLS_DC) /* {{{ */ +{ + phpdbg_debug("file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d\n", file, filelen, cur, curlen, filelen > curlen ? file[filelen - curlen - 1] : '?', filelen > curlen ? memcmp(file + filelen - curlen, cur, curlen) : 0); + + if (((cur->len < filelen && file[filelen - cur->len - 1] == '/') || filelen == cur->len) && !memcmp(file + filelen - cur->len, cur->val, cur->len)) { + phpdbg_breakfile_t *brake, new_brake; + HashTable *master; + + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + + if (!(master = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen))) { + HashTable new_ht; + zend_hash_init(&new_ht, 8, NULL, phpdbg_file_breaks_dtor, 0); + master = zend_hash_str_add_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen, &new_ht, sizeof(HashTable)); + } + + ZEND_HASH_FOREACH_PTR(fileht, brake) { + new_brake = *brake; + new_brake.filename = estrndup(file, filelen); + PHPDBG_BREAK_UNMAPPING(brake->id); + + if (master) { + zend_hash_index_update_mem(master, brake->line, &new_brake, sizeof(phpdbg_breakfile_t)); + PHPDBG_BREAK_MAPPING(brake->id, master); + } + } ZEND_HASH_FOREACH_END(); + + zend_hash_del(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], cur); + + if (!zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING])) { + PHPDBG_G(flags) &= ~PHPDBG_HAS_PENDING_FILE_BP; + } + + phpdbg_debug("compiled file: %s, cur bp file: %s\n", file, cur); + + return master; + } + + return NULL; +} /* }}} */ + +PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file TSRMLS_DC) /* {{{ */ +{ + HashTable *fileht; + uint filelen = strlen(file); + zend_string *cur; + + phpdbg_debug("was compiled: %s\n", file); + + ZEND_HASH_FOREACH_STR_KEY_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], cur, fileht) { + phpdbg_debug("check bp: %s\n", cur); + + phpdbg_resolve_pending_file_break_ex(file, filelen, cur, fileht TSRMLS_CC); + } ZEND_HASH_FOREACH_END(); +} /* }}} */ + PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len TSRMLS_DC) /* {{{ */ { if (!zend_hash_str_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], name, name_len)) { @@ -732,8 +841,21 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_ { HashTable *breaks; phpdbg_breakbase_t *brake; + size_t path_len; + char realpath[MAXPATHLEN]; + const char *path = op_array->filename->val; + + if (VCWD_REALPATH(path, realpath)) { + path = realpath; + } - if (!(breaks = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename))) { + path_len = strlen(path); + +#if 0 + phpdbg_debug("Op at: %.*s %d\n", path_len, path, (*EG(opline_ptr))->lineno); +#endif + + if (!(breaks = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len))) { return NULL; } @@ -1048,6 +1170,7 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D) /* {{{ */ { zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); + zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); @@ -1283,7 +1406,20 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */ ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); } ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END(); + } if ((PHPDBG_G(flags) & PHPDBG_HAS_PENDING_FILE_BP)) { + HashTable *points; + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Pending File Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], points) { + phpdbg_breakfile_t *brake; + + ZEND_HASH_FOREACH_PTR(points, brake) { + phpdbg_writeln("file", "id=\"%d\" name=\"%s\" line=\"%lu\" disabled=\"%s\" pending=\"pending\"", "#%d\t\t%s:%lu%s", + brake->id, brake->filename, brake->line, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP)) { |