summaryrefslogtreecommitdiff
path: root/sapi/phpdbg/phpdbg_bp.c
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2014-11-18 21:18:52 +0100
committerAnatol Belski <ab@php.net>2014-11-18 21:18:52 +0100
commitc6bad96f306df8e8b656472e618283ced5083cdb (patch)
tree7e5b52aa07777f0336b0944a228bf66f8f56b31f /sapi/phpdbg/phpdbg_bp.c
parent4262663e4caa82ba17666781a95bdcb872b4e109 (diff)
parent64a39dc7b07d4b54d050a3a5c15045fe91c0b651 (diff)
downloadphp-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.c232
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)) {