]> granicus.if.org Git - php/commitdiff
Add phpdbg_get_executable() (gets executable ops/lines)
authorBob Weinand <bobwei9@hotmail.com>
Wed, 22 Jul 2015 16:11:35 +0000 (18:11 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Wed, 22 Jul 2015 16:11:35 +0000 (18:11 +0200)
sapi/phpdbg/phpdbg.c
sapi/phpdbg/phpdbg_list.c
sapi/phpdbg/phpdbg_list.h

index 83425fe531a41edb80bd68cc2d40798dd83710e1..a4f36eecedf2e2738d001d8eb1536e55d731d053 100644 (file)
@@ -480,6 +480,114 @@ static void phpdbg_oplog_fill_executable(zend_op_array *op_array, HashTable *ins
        }
 }
 
+static inline HashTable* phpdbg_add_empty_array(HashTable *ht, zend_string *name) {
+       zval *ht_zv = zend_hash_find(ht, name);
+       if (!ht_zv) {
+               zval zv;
+               array_init(&zv);
+               ht_zv = zend_hash_add_new(ht, name, &zv);
+       }
+       return Z_ARR_P(ht_zv);
+}
+
+/* {{{ proto void phpdbg_end_oplog() */
+static PHP_FUNCTION(phpdbg_get_executable)
+{
+       HashTable *options = NULL;
+       zval *option_buffer;
+       zend_bool by_function = 0;
+       zend_bool by_opcode = 0;
+       HashTable *insert_ht;
+
+       zend_function *func;
+       zend_class_entry *ce;
+       zend_string *name;
+       HashTable *files = &PHPDBG_G(file_sources);
+       HashTable files_tmp;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "|H", &options) == FAILURE) {
+               return;
+       }
+
+       if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("functions")))) {
+               by_function = zend_is_true(option_buffer);
+       }
+
+       if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("opcodes")))) {
+               if (by_function) {
+                       by_opcode = zend_is_true(option_buffer);
+               }
+       }
+
+       if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("files")))) {
+               ZVAL_DEREF(option_buffer);
+               if (Z_TYPE_P(option_buffer) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(option_buffer)) > 0) {
+                       zval *filename;
+
+                       files = &files_tmp;
+                       zend_hash_init(files, 0, NULL, NULL, 0);
+
+                       ZEND_HASH_FOREACH_VAL(Z_ARR_P(option_buffer), filename) {
+                               zend_hash_add_empty_element(files, zval_get_string(filename));
+                       } ZEND_HASH_FOREACH_END();
+               } else {
+                       GC_REFCOUNT(files)++;
+               }
+       } else {
+               GC_REFCOUNT(files)++;
+       }
+
+       array_init(return_value);
+
+       ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), name, func) {
+               if (func->type == ZEND_USER_FUNCTION) {
+                       if (zend_hash_exists(files, func->op_array.filename)) {
+                               insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename);
+
+                               if (by_function) {
+                                       insert_ht = phpdbg_add_empty_array(insert_ht, name);
+                               }
+
+                               phpdbg_oplog_fill_executable(&func->op_array, insert_ht, by_opcode);
+                       }
+               }
+       } ZEND_HASH_FOREACH_END();
+
+       ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), name, ce) {
+               if (ce->type == ZEND_USER_CLASS) {
+                       if (zend_hash_exists(files, ce->info.user.filename)) {
+                               ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
+                                       if (func->type == ZEND_USER_FUNCTION) {
+                                               insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename);
+
+                                               if (by_function) {
+                                                       zend_string *fn_name = strpprintf(ZSTR_LEN(name) + ZSTR_LEN(func->op_array.function_name) + 2, "%.*s::%.*s", ZSTR_LEN(name), ZSTR_VAL(name), ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name));
+                                                       insert_ht = phpdbg_add_empty_array(insert_ht, fn_name);
+                                                       zend_string_release(fn_name);
+                                               }
+
+                                               phpdbg_oplog_fill_executable(&func->op_array, insert_ht, by_opcode);
+                                       }
+                               } ZEND_HASH_FOREACH_END();
+                       }
+               }
+       } ZEND_HASH_FOREACH_END();
+
+       ZEND_HASH_FOREACH_STR_KEY(files, name) {
+               phpdbg_file_source *source = zend_hash_find_ptr(&PHPDBG_G(file_sources), name);
+               if (source) {
+                       phpdbg_oplog_fill_executable(
+                               source->op_array,
+                               phpdbg_add_empty_array(Z_ARR_P(return_value), source->op_array->filename),
+                               by_opcode);
+               }
+       } ZEND_HASH_FOREACH_END();
+
+       if (!--GC_REFCOUNT(files)) {
+               zend_hash_destroy(files);
+       }
+}
+
 /* {{{ proto void phpdbg_end_oplog() */
 static PHP_FUNCTION(phpdbg_end_oplog)
 {
@@ -490,7 +598,6 @@ static PHP_FUNCTION(phpdbg_end_oplog)
        zval *option_buffer;
        zend_bool by_function = 0;
        zend_bool by_opcode = 0;
-       zend_bool show_unexecuted = 0;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "|H", &options) == FAILURE) {
                return;
@@ -517,18 +624,13 @@ static PHP_FUNCTION(phpdbg_end_oplog)
                }
        }
 
-       if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("show_unexecuted")))) {
-               show_unexecuted = zend_is_true(option_buffer);
-       }
-
        array_init(return_value);
 
        {
                zend_string *last_file = NULL;
-               zval *file_buf;
+               HashTable *file_ht;
                zend_string *last_function = (void *)~(uintptr_t)0;
                zend_class_entry *last_scope = NULL;
-               zval *fn_buf;
 
                HashTable *insert_ht;
                zend_long insert_idx;
@@ -540,23 +642,13 @@ static PHP_FUNCTION(phpdbg_end_oplog)
 
                        if (op_array->filename != last_file) {
                                last_file = op_array->filename;
-                               file_buf = zend_hash_find(Z_ARR_P(return_value), last_file);
-                               if (!file_buf) {
-                                       zval ht;
-                                       array_init(&ht);
-                                       file_buf = zend_hash_add_new(Z_ARR_P(return_value), last_file, &ht);
-
-                                       if (show_unexecuted) {
-                                               phpdbg_oplog_fill_executable(op_array, Z_ARR_P(file_buf), by_opcode);
-                                       }
-                               }
-                               insert_ht = Z_ARR_P(file_buf);
+                               file_ht = insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), last_file);
                        }
 
                        if (by_function) {
                                if (op_array->function_name == NULL) {
                                        if (last_function != NULL) {
-                                               insert_ht = Z_ARR_P(file_buf);
+                                               insert_ht = file_ht;
                                        }
                                        last_function = NULL;
                                } else if (op_array->function_name != last_function || op_array->scope != last_scope) {
@@ -568,17 +660,8 @@ static PHP_FUNCTION(phpdbg_end_oplog)
                                        } else {
                                                fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name), ZSTR_LEN(last_function), ZSTR_VAL(last_function));
                                        }
-                                       fn_buf = zend_hash_find(Z_ARR_P(return_value), fn_name);
-                                       if (!fn_buf) {
-                                               zval ht;
-                                               array_init(&ht);
-                                               fn_buf = zend_hash_add_new(Z_ARR_P(return_value), fn_name, &ht);
-
-                                               if (show_unexecuted) {
-                                                       phpdbg_oplog_fill_executable(op_array, Z_ARR_P(fn_buf), by_opcode);
-                                               }
-                                       }
-                                       insert_ht = Z_ARR_P(fn_buf);
+                                       insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), fn_name);
+                                       zend_string_release(fn_name);
                                }
                        }
 
@@ -642,6 +725,11 @@ ZEND_BEGIN_ARG_INFO_EX(phpdbg_start_oplog_arginfo, 0, 0, 0)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(phpdbg_end_oplog_arginfo, 0, 0, 0)
+       ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(phpdbg_get_executable_arginfo, 0, 0, 0)
+       ZEND_ARG_INFO(0, options)
 ZEND_END_ARG_INFO()
 
 zend_function_entry phpdbg_user_functions[] = {
@@ -655,6 +743,7 @@ zend_function_entry phpdbg_user_functions[] = {
        PHP_FE(phpdbg_prompt, phpdbg_prompt_arginfo)
        PHP_FE(phpdbg_start_oplog, phpdbg_start_oplog_arginfo)
        PHP_FE(phpdbg_end_oplog, phpdbg_end_oplog_arginfo)
+       PHP_FE(phpdbg_get_executable, phpdbg_get_executable_arginfo)
 #ifdef  PHP_FE_END
        PHP_FE_END
 #else
index 7b1bc8783b83103e0b03b92d3664b50d094182af..a2f5ff6cc5265b9711696af60dce847615010c15 100644 (file)
@@ -288,6 +288,9 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) {
        fake.opened_path = NULL;
        zend_file_handle_dtor(&fake);
 
+       dataptr->op_array = ret;
+       ++*dataptr->op_array->refcount;
+
        return ret;
 }
 
@@ -301,6 +304,10 @@ void phpdbg_free_file_source(phpdbg_file_source *data) {
                efree(data->buf);
        }
 
+       if (destroy_op_array(data->op_array)) {
+               efree(data->op_array);
+       }
+
        efree(data);
 }
 
index 3436ddd8fbc7d895b095e877cbec770e0e1fc72f..bfaef062486b141843919dae8f54eff36dacd33c 100644 (file)
@@ -47,6 +47,7 @@ typedef struct {
 #if HAVE_MMAP
        void *map;
 #endif
+       zend_op_array *op_array;
        uint lines;
        uint line[1];
 } phpdbg_file_source;