phpdbg_info.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 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. #include "php.h"
  21. #include "phpdbg.h"
  22. #include "phpdbg_utils.h"
  23. #include "phpdbg_info.h"
  24. #include "phpdbg_bp.h"
  25. #include "phpdbg_prompt.h"
  26. ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
  27. #define PHPDBG_INFO_COMMAND_D(f, h, a, m, l, s) \
  28. PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[14])
  29. const phpdbg_command_t phpdbg_info_commands[] = {
  30. PHPDBG_INFO_COMMAND_D(break, "show breakpoints", 'b', info_break, NULL, 0),
  31. PHPDBG_INFO_COMMAND_D(files, "show included files", 'F', info_files, NULL, 0),
  32. PHPDBG_INFO_COMMAND_D(classes, "show loaded classes", 'c', info_classes, NULL, 0),
  33. PHPDBG_INFO_COMMAND_D(funcs, "show loaded classes", 'f', info_funcs, NULL, 0),
  34. PHPDBG_INFO_COMMAND_D(error, "show last error", 'e', info_error, NULL, 0),
  35. PHPDBG_INFO_COMMAND_D(vars, "show active variables", 'v', info_vars, NULL, 0),
  36. PHPDBG_INFO_COMMAND_D(literal, "show active literal constants", 'l', info_literal, NULL, 0),
  37. PHPDBG_INFO_COMMAND_D(memory, "show memory manager stats", 'm', info_memory, NULL, 0),
  38. PHPDBG_END_COMMAND
  39. };
  40. PHPDBG_INFO(break) /* {{{ */
  41. {
  42. phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC);
  43. phpdbg_print_breakpoints(PHPDBG_BREAK_SYM TSRMLS_CC);
  44. phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC);
  45. phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC);
  46. phpdbg_print_breakpoints(PHPDBG_BREAK_FILE_OPLINE TSRMLS_CC);
  47. phpdbg_print_breakpoints(PHPDBG_BREAK_FUNCTION_OPLINE TSRMLS_CC);
  48. phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD_OPLINE TSRMLS_CC);
  49. phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC);
  50. phpdbg_print_breakpoints(PHPDBG_BREAK_OPCODE TSRMLS_CC);
  51. return SUCCESS;
  52. } /* }}} */
  53. PHPDBG_INFO(files) /* {{{ */
  54. {
  55. HashPosition pos;
  56. char *fname;
  57. phpdbg_notice("Included files: %d",
  58. zend_hash_num_elements(&EG(included_files)));
  59. zend_hash_internal_pointer_reset_ex(&EG(included_files), &pos);
  60. while (zend_hash_get_current_key_ex(&EG(included_files), &fname,
  61. NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) {
  62. phpdbg_writeln("File: %s", fname);
  63. zend_hash_move_forward_ex(&EG(included_files), &pos);
  64. }
  65. return SUCCESS;
  66. } /* }}} */
  67. PHPDBG_INFO(error) /* {{{ */
  68. {
  69. if (PG(last_error_message)) {
  70. phpdbg_writeln("Last error: %s at %s line %d",
  71. PG(last_error_message), PG(last_error_file), PG(last_error_lineno));
  72. } else {
  73. phpdbg_notice("No error found!");
  74. }
  75. return SUCCESS;
  76. } /* }}} */
  77. PHPDBG_INFO(vars) /* {{{ */
  78. {
  79. HashTable vars;
  80. HashPosition pos;
  81. char *var;
  82. zval **data;
  83. if (!EG(active_op_array)) {
  84. phpdbg_error("No active op array!");
  85. return SUCCESS;
  86. }
  87. if (!EG(active_symbol_table)) {
  88. zend_rebuild_symbol_table(TSRMLS_C);
  89. if (!EG(active_symbol_table)) {
  90. phpdbg_error("No active symbol table!");
  91. return SUCCESS;
  92. }
  93. }
  94. zend_hash_init(&vars, 8, NULL, NULL, 0);
  95. zend_hash_internal_pointer_reset_ex(EG(active_symbol_table), &pos);
  96. while (zend_hash_get_current_key_ex(EG(active_symbol_table), &var,
  97. NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) {
  98. zend_hash_get_current_data_ex(EG(active_symbol_table), (void **)&data, &pos);
  99. if (*var != '_') {
  100. zend_hash_update(
  101. &vars, var, strlen(var)+1, (void**)data, sizeof(zval*), NULL);
  102. }
  103. zend_hash_move_forward_ex(EG(active_symbol_table), &pos);
  104. }
  105. {
  106. zend_op_array *ops = EG(active_op_array);
  107. if (ops->function_name) {
  108. if (ops->scope) {
  109. phpdbg_notice(
  110. "Variables in %s::%s() (%d)", ops->scope->name, ops->function_name, zend_hash_num_elements(&vars));
  111. } else {
  112. phpdbg_notice(
  113. "Variables in %s() (%d)", ops->function_name, zend_hash_num_elements(&vars));
  114. }
  115. } else {
  116. if (ops->filename) {
  117. phpdbg_notice(
  118. "Variables in %s (%d)", ops->filename, zend_hash_num_elements(&vars));
  119. } else {
  120. phpdbg_notice(
  121. "Variables @ %p (%d)", ops, zend_hash_num_elements(&vars));
  122. }
  123. }
  124. }
  125. if (zend_hash_num_elements(&vars)) {
  126. phpdbg_writeln("Address\t\tRefs\tType\t\tVariable");
  127. for (zend_hash_internal_pointer_reset_ex(&vars, &pos);
  128. zend_hash_get_current_data_ex(&vars, (void**) &data, &pos) == SUCCESS;
  129. zend_hash_move_forward_ex(&vars, &pos)) {
  130. char *var;
  131. zend_hash_get_current_key_ex(&vars, &var, NULL, NULL, 0, &pos);
  132. if (*data) {
  133. phpdbg_write(
  134. "%p\t%d\t",
  135. *data,
  136. Z_REFCOUNT_PP(data));
  137. switch (Z_TYPE_PP(data)) {
  138. case IS_STRING: phpdbg_write("(string)\t"); break;
  139. case IS_LONG: phpdbg_write("(integer)\t"); break;
  140. case IS_DOUBLE: phpdbg_write("(float)\t"); break;
  141. case IS_RESOURCE: phpdbg_write("(resource)\t"); break;
  142. case IS_ARRAY: phpdbg_write("(array)\t"); break;
  143. case IS_OBJECT: phpdbg_write("(object)\t"); break;
  144. case IS_NULL: phpdbg_write("(null)\t"); break;
  145. }
  146. if (Z_TYPE_PP(data) == IS_RESOURCE) {
  147. int type;
  148. phpdbg_writeln(
  149. "%s$%s", Z_ISREF_PP(data) ? "&": "", var);
  150. if (zend_list_find(Z_RESVAL_PP(data), &type)) {
  151. phpdbg_write(
  152. "|-------(typeof)------> (%s)",
  153. zend_rsrc_list_get_rsrc_type(type TSRMLS_CC));
  154. } else {
  155. phpdbg_write(
  156. "|-------(typeof)------> (unknown)");
  157. }
  158. phpdbg_writeln(EMPTY);
  159. } else if (Z_TYPE_PP(data) == IS_OBJECT) {
  160. phpdbg_writeln(
  161. "%s$%s", Z_ISREF_PP(data) ? "&": "", var);
  162. phpdbg_write(
  163. "|-----(instanceof)----> (%s)", Z_OBJCE_PP(data)->name);
  164. phpdbg_writeln(EMPTY);
  165. } else {
  166. phpdbg_write(
  167. "%s$%s", Z_ISREF_PP(data) ? "&": "", var);
  168. }
  169. } else {
  170. phpdbg_write(
  171. "n/a\tn/a\tn/a\t$%s", var);
  172. }
  173. phpdbg_writeln(EMPTY);
  174. }
  175. }
  176. zend_hash_destroy(&vars);
  177. return SUCCESS;
  178. } /* }}} */
  179. PHPDBG_INFO(literal) /* {{{ */
  180. {
  181. if ((EG(in_execution) && EG(active_op_array)) || PHPDBG_G(ops)) {
  182. zend_op_array *ops = EG(active_op_array) ? EG(active_op_array) : PHPDBG_G(ops);
  183. int literal = 0, count = ops->last_literal-1;
  184. if (ops->function_name) {
  185. if (ops->scope) {
  186. phpdbg_notice(
  187. "Literal Constants in %s::%s() (%d)", ops->scope->name, ops->function_name, count);
  188. } else {
  189. phpdbg_notice(
  190. "Literal Constants in %s() (%d)", ops->function_name, count);
  191. }
  192. } else {
  193. if (ops->filename) {
  194. phpdbg_notice(
  195. "Literal Constants in %s (%d)", ops->filename, count);
  196. } else {
  197. phpdbg_notice(
  198. "Literal Constants @ %p (%d)", ops, count);
  199. }
  200. }
  201. while (literal < ops->last_literal) {
  202. if (Z_TYPE(ops->literals[literal].constant) != IS_NULL) {
  203. phpdbg_write("|-------- C%u -------> [", literal);
  204. zend_print_zval(
  205. &ops->literals[literal].constant, 0);
  206. phpdbg_write("]");
  207. phpdbg_writeln(EMPTY);
  208. }
  209. literal++;
  210. }
  211. } else {
  212. phpdbg_error("Not executing!");
  213. }
  214. return SUCCESS;
  215. } /* }}} */
  216. PHPDBG_INFO(memory) /* {{{ */
  217. {
  218. if (is_zend_mm(TSRMLS_C)) {
  219. phpdbg_notice("Memory Manager Information");
  220. phpdbg_notice("Current");
  221. phpdbg_writeln("|-------> Used:\t%.3f kB",
  222. (float) (zend_memory_usage(0 TSRMLS_CC)/1024));
  223. phpdbg_writeln("|-------> Real:\t%.3f kB",
  224. (float) (zend_memory_usage(1 TSRMLS_CC)/1024));
  225. phpdbg_notice("Peak");
  226. phpdbg_writeln("|-------> Used:\t%.3f kB",
  227. (float) (zend_memory_peak_usage(0 TSRMLS_CC)/1024));
  228. phpdbg_writeln("|-------> Real:\t%.3f kB",
  229. (float) (zend_memory_peak_usage(1 TSRMLS_CC)/1024));
  230. } else {
  231. phpdbg_error("Memory Manager Disabled!");
  232. }
  233. return SUCCESS;
  234. } /* }}} */
  235. static inline void phpdbg_print_class_name(zend_class_entry **ce TSRMLS_DC) /* {{{ */
  236. {
  237. phpdbg_write(
  238. "%s %s %s (%d)",
  239. ((*ce)->type == ZEND_USER_CLASS) ?
  240. "User" : "Internal",
  241. ((*ce)->ce_flags & ZEND_ACC_INTERFACE) ?
  242. "Interface" :
  243. ((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ?
  244. "Abstract Class" :
  245. "Class",
  246. (*ce)->name, zend_hash_num_elements(&(*ce)->function_table));
  247. } /* }}} */
  248. PHPDBG_INFO(classes) /* {{{ */
  249. {
  250. HashPosition position;
  251. zend_class_entry **ce;
  252. HashTable classes;
  253. zend_hash_init(&classes, 8, NULL, NULL, 0);
  254. for (zend_hash_internal_pointer_reset_ex(EG(class_table), &position);
  255. zend_hash_get_current_data_ex(EG(class_table), (void**)&ce, &position) == SUCCESS;
  256. zend_hash_move_forward_ex(EG(class_table), &position)) {
  257. if ((*ce)->type == ZEND_USER_CLASS) {
  258. zend_hash_next_index_insert(
  259. &classes, ce, sizeof(ce), NULL);
  260. }
  261. }
  262. phpdbg_notice("User Classes (%d)",
  263. zend_hash_num_elements(&classes));
  264. for (zend_hash_internal_pointer_reset_ex(&classes, &position);
  265. zend_hash_get_current_data_ex(&classes, (void**)&ce, &position) == SUCCESS;
  266. zend_hash_move_forward_ex(&classes, &position)) {
  267. phpdbg_print_class_name(ce TSRMLS_CC);
  268. phpdbg_writeln(EMPTY);
  269. if ((*ce)->parent) {
  270. zend_class_entry *pce = (*ce)->parent;
  271. do {
  272. phpdbg_write("|-------- ");
  273. phpdbg_print_class_name(&pce TSRMLS_CC);
  274. phpdbg_writeln(EMPTY);
  275. } while ((pce = pce->parent));
  276. }
  277. if ((*ce)->info.user.filename) {
  278. phpdbg_writeln(
  279. "|---- in %s on line %u",
  280. (*ce)->info.user.filename,
  281. (*ce)->info.user.line_start);
  282. } else {
  283. phpdbg_writeln("|---- no source code");
  284. }
  285. phpdbg_writeln(EMPTY);
  286. }
  287. zend_hash_destroy(&classes);
  288. return SUCCESS;
  289. } /* }}} */
  290. PHPDBG_INFO(funcs) /* {{{ */
  291. {
  292. HashPosition position;
  293. zend_function *zf, **pzf;
  294. HashTable functions;
  295. zend_hash_init(&functions, 8, NULL, NULL, 0);
  296. for (zend_hash_internal_pointer_reset_ex(EG(function_table), &position);
  297. zend_hash_get_current_data_ex(EG(function_table), (void**)&zf, &position) == SUCCESS;
  298. zend_hash_move_forward_ex(EG(function_table), &position)) {
  299. if (zf->type == ZEND_USER_FUNCTION) {
  300. zend_hash_next_index_insert(
  301. &functions, (void**) &zf, sizeof(zend_function), NULL);
  302. }
  303. }
  304. phpdbg_notice("User Functions (%d)",
  305. zend_hash_num_elements(&functions));
  306. for (zend_hash_internal_pointer_reset_ex(&functions, &position);
  307. zend_hash_get_current_data_ex(&functions, (void**)&pzf, &position) == SUCCESS;
  308. zend_hash_move_forward_ex(&functions, &position)) {
  309. zend_op_array *op_array = &((*pzf)->op_array);
  310. phpdbg_writeln(
  311. "|-------- %s in %s on line %d",
  312. op_array->function_name ? op_array->function_name : "{main}",
  313. op_array->filename ? op_array->filename : "(no source code)",
  314. op_array->line_start);
  315. }
  316. zend_hash_destroy(&functions);
  317. return SUCCESS;
  318. } /* }}} */