PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - sapi/phpdbg - phpdbg_print.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 63 174 36.2 %
Date: 2018-09-22 Functions: 6 14 42.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2018 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             : 
      21             : #include "phpdbg.h"
      22             : #include "phpdbg_print.h"
      23             : #include "phpdbg_utils.h"
      24             : #include "phpdbg_opcode.h"
      25             : #include "phpdbg_prompt.h"
      26             : 
      27             : ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
      28             : 
      29             : #define PHPDBG_PRINT_COMMAND_D(f, h, a, m, l, s, flags) \
      30             :         PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[8], flags)
      31             : 
      32             : const phpdbg_command_t phpdbg_print_commands[] = {
      33             :         PHPDBG_PRINT_COMMAND_D(exec,       "print out the instructions in the main execution context", 'e', print_exec,   NULL, 0, PHPDBG_ASYNC_SAFE),
      34             :         PHPDBG_PRINT_COMMAND_D(opline,     "print out the instruction in the current opline",          'o', print_opline, NULL, 0, PHPDBG_ASYNC_SAFE),
      35             :         PHPDBG_PRINT_COMMAND_D(class,      "print out the instructions in the specified class",        'c', print_class,  NULL, "s", PHPDBG_ASYNC_SAFE),
      36             :         PHPDBG_PRINT_COMMAND_D(method,     "print out the instructions in the specified method",       'm', print_method, NULL, "m", PHPDBG_ASYNC_SAFE),
      37             :         PHPDBG_PRINT_COMMAND_D(func,       "print out the instructions in the specified function",     'f', print_func,   NULL, "s", PHPDBG_ASYNC_SAFE),
      38             :         PHPDBG_PRINT_COMMAND_D(stack,      "print out the instructions in the current stack",          's', print_stack,  NULL, 0, PHPDBG_ASYNC_SAFE),
      39             :         PHPDBG_END_COMMAND
      40             : };
      41             : 
      42           1 : PHPDBG_PRINT(opline) /* {{{ */
      43             : {
      44           1 :         if (PHPDBG_G(in_execution) && EG(current_execute_data)) {
      45           2 :                 phpdbg_print_opline(phpdbg_user_execute_data(EG(current_execute_data)), 1);
      46             :         } else {
      47           0 :                 phpdbg_error("inactive", "type=\"execution\"", "Not Executing!");
      48             :         }
      49             : 
      50           1 :         return SUCCESS;
      51             : } /* }}} */
      52             : 
      53           5 : static inline void phpdbg_print_function_helper(zend_function *method) /* {{{ */
      54             : {
      55           5 :         switch (method->type) {
      56           5 :                 case ZEND_USER_FUNCTION: {
      57           5 :                         zend_op_array* op_array = &(method->op_array);
      58             : 
      59           5 :                         if (op_array) {
      60           5 :                                 zend_op *opline = &(op_array->opcodes[0]);
      61           5 :                                 uint32_t opcode = 0,
      62           5 :                                 end = op_array->last-1;
      63             : 
      64           5 :                                 if (method->common.scope) {
      65           2 :                                         phpdbg_writeln("printoplineinfo", "type=\"User\" startline=\"%d\" endline=\"%d\" method=\"%s::%s\" file=\"%s\" opline=\"%p\"", "L%d-%d %s::%s() %s - %p + %d ops",
      66             :                                                 op_array->line_start,
      67             :                                                 op_array->line_end,
      68             :                                                 ZSTR_VAL(method->common.scope->name),
      69             :                                                 ZSTR_VAL(method->common.function_name),
      70             :                                                 op_array->filename ? ZSTR_VAL(op_array->filename) : "unknown",
      71             :                                                 opline,
      72             :                                                 op_array->last);
      73             :                                 } else {
      74           3 :                                         phpdbg_writeln("printoplineinfo", "type=\"User\" startline=\"%d\" endline=\"%d\" function=\"%s\" file=\"%s\" opline=\"%p\"", "L%d-%d %s() %s - %p + %d ops",
      75             :                                                 op_array->line_start,
      76             :                                                 op_array->line_end,
      77             :                                                 method->common.function_name ? ZSTR_VAL(method->common.function_name) : "{main}",
      78             :                                                 op_array->filename ? ZSTR_VAL(op_array->filename) : "unknown",
      79             :                                                 opline,
      80             :                                                 op_array->last);
      81             :                                 }
      82             : 
      83             :                                 do {
      84          33 :                                         char *decode = phpdbg_decode_opline(op_array, opline);
      85          33 :                                         phpdbg_writeln("print", "line=\"%u\" opnum=\"%u\" op=\"%s\"", " L%-4u #%-5u %s",
      86             :                                                 opline->lineno,
      87             :                                                 opcode,
      88             :                                                 decode);
      89          33 :                                         efree(decode);
      90          33 :                                         opline++;
      91          33 :                                 } while (opcode++ < end);
      92             :                         }
      93           5 :                 } break;
      94             : 
      95           0 :                 default: {
      96           0 :                         if (method->common.scope) {
      97           0 :                                 phpdbg_writeln("printoplineinfo", "type=\"Internal\" method=\"%s::%s\"", "\tInternal %s::%s()", ZSTR_VAL(method->common.scope->name), ZSTR_VAL(method->common.function_name));
      98             :                         } else {
      99           0 :                                 phpdbg_writeln("printoplineinfo", "type=\"Internal\" function=\"%s\"", "\tInternal %s()", ZSTR_VAL(method->common.function_name));
     100             :                         }
     101             :                 }
     102             :         }
     103           5 : } /* }}} */
     104             : 
     105           1 : PHPDBG_PRINT(exec) /* {{{ */
     106             : {
     107           1 :         if (PHPDBG_G(exec)) {
     108           1 :                 if (!PHPDBG_G(ops) && !(PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER)) {
     109           0 :                         phpdbg_compile();
     110             :                 }
     111             : 
     112           1 :                 if (PHPDBG_G(ops)) {
     113           1 :                         phpdbg_notice("printinfo", "file=\"%s\" num=\"%d\"", "Context %s (%d ops)", PHPDBG_G(exec), PHPDBG_G(ops)->last);
     114             : 
     115           1 :                         phpdbg_print_function_helper((zend_function*) PHPDBG_G(ops));
     116             :                 }
     117             :         } else {
     118           0 :                 phpdbg_error("inactive", "type=\"nocontext\"", "No execution context set");
     119             :         }
     120             : 
     121           1 : return SUCCESS;
     122             : } /* }}} */
     123             : 
     124           2 : PHPDBG_PRINT(stack) /* {{{ */
     125             : {
     126           3 :         if (PHPDBG_G(in_execution) && EG(current_execute_data)) {
     127           2 :                 zend_op_array *ops = &phpdbg_user_execute_data(EG(current_execute_data))->func->op_array;
     128           1 :                 if (ops->function_name) {
     129           1 :                         if (ops->scope) {
     130           0 :                                 phpdbg_notice("printinfo", "method=\"%s::%s\" num=\"%d\"", "Stack in %s::%s() (%d ops)", ZSTR_VAL(ops->scope->name), ZSTR_VAL(ops->function_name), ops->last);
     131             :                         } else {
     132           1 :                                 phpdbg_notice("printinfo", "function=\"%s\" num=\"%d\"", "Stack in %s() (%d ops)", ZSTR_VAL(ops->function_name), ops->last);
     133             :                         }
     134             :                 } else {
     135           0 :                         if (ops->filename) {
     136           0 :                                 phpdbg_notice("printinfo", "file=\"%s\" num=\"%d\"", "Stack in %s (%d ops)", ZSTR_VAL(ops->filename), ops->last);
     137             :                         } else {
     138           0 :                                 phpdbg_notice("printinfo", "opline=\"%p\" num=\"%d\"", "Stack @ %p (%d ops)", ops, ops->last);
     139             :                         }
     140             :                 }
     141           1 :                 phpdbg_print_function_helper((zend_function*) ops);
     142             :         } else {
     143           1 :                 phpdbg_error("inactive", "type=\"execution\"", "Not Executing!");
     144             :         }
     145             : 
     146           2 :         return SUCCESS;
     147             : } /* }}} */
     148             : 
     149           1 : PHPDBG_PRINT(class) /* {{{ */
     150             : {
     151             :         zend_class_entry *ce;
     152             : 
     153           1 :         if (phpdbg_safe_class_lookup(param->str, param->len, &ce) == SUCCESS) {
     154           1 :                 phpdbg_notice("printinfo", "type=\"%s\" flag=\"%s\" class=\"%s\" num=\"%d\"", "%s %s: %s (%d methods)",
     155             :                         (ce->type == ZEND_USER_CLASS) ?
     156             :                                 "User" : "Internal",
     157             :                         (ce->ce_flags & ZEND_ACC_INTERFACE) ?
     158             :                                 "Interface" :
     159             :                                 (ce->ce_flags & ZEND_ACC_ABSTRACT) ?
     160             :                                         "Abstract Class" :
     161             :                                         "Class",
     162             :                         ZSTR_VAL(ce->name),
     163             :                         zend_hash_num_elements(&ce->function_table));
     164             : 
     165           1 :                 phpdbg_xml("<printmethods %r>");
     166             : 
     167           1 :                 if (zend_hash_num_elements(&ce->function_table)) {
     168             :                         zend_function *method;
     169             : 
     170           5 :                         ZEND_HASH_FOREACH_PTR(&ce->function_table, method) {
     171           2 :                                 phpdbg_print_function_helper(method);
     172             :                         } ZEND_HASH_FOREACH_END();
     173             :                 }
     174             : 
     175           1 :                 phpdbg_xml("</printmethods>");
     176             :         } else {
     177           0 :                 phpdbg_error("print", "type=\"noclass\" class=\"%s\"", "The class %s could not be found", param->str);
     178             :         }
     179             : 
     180           1 :         return SUCCESS;
     181             : } /* }}} */
     182             : 
     183           0 : PHPDBG_PRINT(method) /* {{{ */
     184             : {
     185             :         zend_class_entry *ce;
     186             : 
     187           0 :         if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce) == SUCCESS) {
     188             :                 zend_function *fbc;
     189           0 :                 zend_string *lcname = zend_string_alloc(strlen(param->method.name), 0);
     190           0 :                 zend_str_tolower_copy(ZSTR_VAL(lcname), param->method.name, ZSTR_LEN(lcname));
     191             : 
     192           0 :                 if ((fbc = zend_hash_find_ptr(&ce->function_table, lcname))) {
     193           0 :                         phpdbg_notice("printinfo", "type=\"%s\" flags=\"Method\" symbol=\"%s\" num=\"%d\"", "%s Method %s (%d ops)",
     194             :                                 (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal",
     195             :                                 ZSTR_VAL(fbc->common.function_name),
     196             :                                 (fbc->type == ZEND_USER_FUNCTION) ? fbc->op_array.last : 0);
     197             : 
     198           0 :                         phpdbg_print_function_helper(fbc);
     199             :                 } else {
     200           0 :                         phpdbg_error("print", "type=\"nomethod\" method=\"%s::%s\"", "The method %s::%s could not be found", param->method.class, param->method.name);
     201             :                 }
     202             : 
     203             :                 zend_string_release(lcname);
     204             :         } else {
     205           0 :                 phpdbg_error("print", "type=\"noclass\" class=\"%s\"", "The class %s could not be found", param->method.class);
     206             :         }
     207             : 
     208           0 :         return SUCCESS;
     209             : } /* }}} */
     210             : 
     211           1 : PHPDBG_PRINT(func) /* {{{ */
     212             : {
     213           1 :         HashTable *func_table = EG(function_table);
     214             :         zend_function* fbc;
     215           1 :         const char *func_name = param->str;
     216           1 :         size_t func_name_len = param->len;
     217             :         zend_string *lcname;
     218             :         /* search active scope if begins with period */
     219           1 :         if (func_name[0] == '.') {
     220           0 :                 zend_class_entry *scope = zend_get_executed_scope();
     221             : 
     222           0 :                 if (scope) {
     223           0 :                         func_name++;
     224           0 :                         func_name_len--;
     225             : 
     226           0 :                         func_table = &scope->function_table;
     227             :                 } else {
     228           0 :                         phpdbg_error("inactive", "type=\"noclasses\"", "No active class");
     229           0 :                         return SUCCESS;
     230             :                 }
     231           1 :         } else if (!EG(function_table)) {
     232           0 :                 phpdbg_error("inactive", "type=\"function_table\"", "No function table loaded");
     233           0 :                 return SUCCESS;
     234             :         } else {
     235           1 :                 func_table = EG(function_table);
     236             :         }
     237             : 
     238           1 :         lcname = zend_string_alloc(func_name_len, 0);
     239           1 :         zend_str_tolower_copy(ZSTR_VAL(lcname), func_name, ZSTR_LEN(lcname));
     240             : 
     241           1 :         phpdbg_try_access {
     242           1 :                 if ((fbc = zend_hash_find_ptr(func_table, lcname))) {
     243           1 :                         phpdbg_notice("printinfo", "type=\"%s\" flags=\"%s\" symbol=\"%s\" num=\"%d\"", "%s %s %s (%d ops)",
     244             :                                 (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal",
     245             :                                 (fbc->common.scope) ? "Method" : "Function",
     246             :                                 ZSTR_VAL(fbc->common.function_name),
     247             :                                 (fbc->type == ZEND_USER_FUNCTION) ? fbc->op_array.last : 0);
     248             : 
     249           1 :                         phpdbg_print_function_helper(fbc);
     250             :                 } else {
     251           0 :                         phpdbg_error("print", "type=\"nofunction\" function=\"%s\"", "The function %s could not be found", func_name);
     252             :                 }
     253           0 :         } phpdbg_catch_access {
     254           0 :                 phpdbg_error("signalsegv", "function=\"%.*s\"", "Couldn't fetch function %.*s, invalid data source", (int) func_name_len, func_name);
     255           1 :         } phpdbg_end_try_access();
     256             : 
     257           1 :         efree(lcname);
     258             : 
     259           1 :         return SUCCESS;
     260             : } /* }}} */
     261             : 
     262           0 : void phpdbg_print_opcodes_main() {
     263           0 :         phpdbg_out("function name: (null)\n");
     264           0 :         phpdbg_print_function_helper((zend_function *) PHPDBG_G(ops));
     265           0 : }
     266             : 
     267           0 : void phpdbg_print_opcodes_function(const char *function, size_t len) {
     268           0 :         zend_function *func = zend_hash_str_find_ptr(EG(function_table), function, len);
     269             : 
     270           0 :         if (!func) {
     271             :                 zend_string *rt_name;
     272           0 :                 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), rt_name, func) {
     273           0 :                         if (func->type == ZEND_USER_FUNCTION && *rt_name->val == '\0') {
     274           0 :                                 if (func->op_array.function_name->len == len && !zend_binary_strcasecmp(function, len, func->op_array.function_name->val, func->op_array.function_name->len)) {
     275           0 :                                         phpdbg_print_opcodes_function(rt_name->val, rt_name->len);
     276             :                                 }
     277             :                         }
     278             :                 } ZEND_HASH_FOREACH_END();
     279             : 
     280           0 :                 return;
     281             :         }
     282             : 
     283           0 :         phpdbg_out("function name: %.*s\n", (int) ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name));
     284           0 :         phpdbg_print_function_helper(func);
     285             : }
     286             : 
     287           0 : static void phpdbg_print_opcodes_method_ce(zend_class_entry *ce, const char *function) {
     288             :         zend_function *func;
     289             : 
     290           0 :         if (ce->type != ZEND_USER_CLASS) {
     291           0 :                 phpdbg_out("function name: %s::%s (internal)\n", ce->name->val, function);
     292           0 :                 return;
     293             :         }
     294             : 
     295           0 :         if (!(func = zend_hash_str_find_ptr(&ce->function_table, function, strlen(function)))) {
     296           0 :                 return;
     297             :         }
     298             : 
     299           0 :         phpdbg_out("function name: %s::%s\n", ce->name->val, function);
     300           0 :         phpdbg_print_function_helper(func);
     301             : }
     302             : 
     303           0 : void phpdbg_print_opcodes_method(const char *class, const char *function) {
     304             :         zend_class_entry *ce;
     305             : 
     306           0 :         if (phpdbg_safe_class_lookup(class, strlen(class), &ce) != SUCCESS) {
     307             :                 zend_string *rt_name;
     308           0 :                 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), rt_name, ce) {
     309           0 :                         if (ce->type == ZEND_USER_CLASS && *rt_name->val == '\0') {
     310           0 :                                 if (ce->name->len == strlen(class) && !zend_binary_strcasecmp(class, strlen(class), ce->name->val, ce->name->len)) {
     311           0 :                                         phpdbg_print_opcodes_method_ce(ce, function);
     312             :                                 }
     313             :                         }
     314             :                 } ZEND_HASH_FOREACH_END();
     315             : 
     316           0 :                 return;
     317             :         }
     318             : 
     319           0 :         phpdbg_print_opcodes_method_ce(ce, function);
     320             : }
     321             : 
     322           0 : static void phpdbg_print_opcodes_ce(zend_class_entry *ce) {
     323             :         zend_function *method;
     324             :         zend_string *method_name;
     325           0 :         zend_bool first = 1;
     326             : 
     327           0 :         phpdbg_out("%s %s: %s\n",
     328             :                 (ce->type == ZEND_USER_CLASS) ?
     329             :                         "user" : "internal",
     330             :                 (ce->ce_flags & ZEND_ACC_INTERFACE) ?
     331             :                         "interface" :
     332             :                         (ce->ce_flags & ZEND_ACC_ABSTRACT) ?
     333             :                                 "abstract Class" :
     334             :                                 "class",
     335             :                 ZSTR_VAL(ce->name));
     336             : 
     337           0 :         if (ce->type != ZEND_USER_CLASS) {
     338           0 :                 return;
     339             :         }
     340             : 
     341           0 :         phpdbg_out("%d methods: ", zend_hash_num_elements(&ce->function_table));
     342           0 :         ZEND_HASH_FOREACH_PTR(&ce->function_table, method) {
     343           0 :                 if (first) {
     344           0 :                         first = 0;
     345             :                 } else {
     346           0 :                         phpdbg_out(", ");
     347             :                 }
     348           0 :                 phpdbg_out("%s", ZSTR_VAL(method->common.function_name));
     349             :         } ZEND_HASH_FOREACH_END();
     350           0 :         if (first) {
     351           0 :                 phpdbg_out("-");
     352             :         }
     353           0 :         phpdbg_out("\n");
     354             : 
     355           0 :         ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, method_name, method) {
     356           0 :                 phpdbg_out("\nfunction name: %s\n", ZSTR_VAL(method_name));
     357           0 :                 phpdbg_print_function_helper(method);
     358             :         } ZEND_HASH_FOREACH_END();
     359             : }
     360             : 
     361           0 : void phpdbg_print_opcodes_class(const char *class) {
     362             :         zend_class_entry *ce;
     363             : 
     364           0 :         if (phpdbg_safe_class_lookup(class, strlen(class), &ce) != SUCCESS) {
     365             :                 zend_string *rt_name;
     366           0 :                 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), rt_name, ce) {
     367           0 :                         if (ce->type == ZEND_USER_CLASS && *rt_name->val == '\0') {
     368           0 :                                 if (ce->name->len == strlen(class) && !zend_binary_strcasecmp(class, strlen(class), ce->name->val, ce->name->len)) {
     369           0 :                                         phpdbg_print_opcodes_ce(ce);
     370             :                                 }
     371             :                         }
     372             :                 } ZEND_HASH_FOREACH_END();
     373             :                 
     374           0 :                 return;
     375             :         }
     376             : 
     377           0 :         phpdbg_print_opcodes_ce(ce);
     378             : }
     379             : 
     380           0 : PHPDBG_API void phpdbg_print_opcodes(char *function)
     381             : {
     382           0 :         if (function == NULL) {
     383           0 :                 phpdbg_print_opcodes_main();
     384           0 :         } else if (function[0] == '*' && function[1] == 0) {
     385             :                 /* all */
     386             :                 zend_string *name;
     387             :                 zend_function *func;
     388             :                 zend_class_entry *ce;
     389             : 
     390           0 :                 phpdbg_print_opcodes_main();
     391             : 
     392           0 :                 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), name, func) {
     393           0 :                         if (func->type == ZEND_USER_FUNCTION) {
     394           0 :                                 phpdbg_out("\n");
     395           0 :                                 phpdbg_print_opcodes_function(ZSTR_VAL(name), ZSTR_LEN(name));
     396             :                         }
     397             :                 } ZEND_HASH_FOREACH_END();
     398             : 
     399           0 :                 ZEND_HASH_FOREACH_PTR(EG(class_table), ce) {
     400           0 :                         if (ce->type == ZEND_USER_CLASS) {
     401           0 :                                 phpdbg_out("\n\n");
     402           0 :                                 phpdbg_print_opcodes_ce(ce);
     403             :                         }
     404             :                 } ZEND_HASH_FOREACH_END();
     405             :         } else {
     406           0 :                 function = zend_str_tolower_dup(function, strlen(function));
     407             : 
     408           0 :                 if (strstr(function, "::") == NULL) {
     409           0 :                         phpdbg_print_opcodes_function(function, strlen(function));
     410             :                 } else {
     411           0 :                         char *method_name, *class_name = strtok(function, "::");
     412           0 :                         if ((method_name = strtok(NULL, "::")) == NULL) {
     413           0 :                                 phpdbg_print_opcodes_class(class_name);
     414             :                         } else {
     415           0 :                                 phpdbg_print_opcodes_method(class_name, method_name);
     416             :                         }
     417             :                 }
     418             : 
     419           0 :                 efree(function);
     420             :         }
     421           0 : }

Generated by: LCOV version 1.10

Generated at Sat, 22 Sep 2018 10:27:04 +0000 (8 hours ago)

Copyright © 2005-2018 The PHP Group
All rights reserved.