PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/xdebug_trace_textual.c

http://github.com/derickr/xdebug
C | 355 lines | 279 code | 56 blank | 20 comment | 52 complexity | f2bdfe8394a4bf1a6cf359938854002f MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Xdebug |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2002-2016 Derick Rethans |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 1.0 of the Xdebug license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://xdebug.derickrethans.nl/license.php |
  11. | If you did not receive a copy of the Xdebug license and are unable |
  12. | to obtain it through the world-wide-web, please send a note to |
  13. | xdebug@derickrethans.nl so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Derick Rethans <derick@xdebug.org> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "xdebug_tracing.h"
  19. #include "xdebug_trace_textual.h"
  20. #include "xdebug_var.h"
  21. #include "ext/standard/php_string.h"
  22. extern ZEND_DECLARE_MODULE_GLOBALS(xdebug);
  23. void *xdebug_trace_textual_init(char *fname, long options TSRMLS_DC)
  24. {
  25. xdebug_trace_textual_context *tmp_textual_context;
  26. char *used_fname;
  27. tmp_textual_context = xdmalloc(sizeof(xdebug_trace_textual_context));
  28. tmp_textual_context->trace_file = xdebug_trace_open_file(fname, options, (char**) &used_fname TSRMLS_CC);
  29. tmp_textual_context->trace_filename = used_fname;
  30. return tmp_textual_context->trace_file ? tmp_textual_context : NULL;
  31. }
  32. void xdebug_trace_textual_deinit(void *ctxt TSRMLS_DC)
  33. {
  34. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  35. fclose(context->trace_file);
  36. context->trace_file = NULL;
  37. xdfree(context->trace_filename);
  38. xdfree(context);
  39. }
  40. void xdebug_trace_textual_write_header(void *ctxt TSRMLS_DC)
  41. {
  42. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  43. char *str_time;
  44. str_time = xdebug_get_time();
  45. fprintf(context->trace_file, "TRACE START [%s]\n", str_time);
  46. fflush(context->trace_file);
  47. xdfree(str_time);
  48. }
  49. void xdebug_trace_textual_write_footer(void *ctxt TSRMLS_DC)
  50. {
  51. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  52. char *str_time;
  53. double u_time;
  54. char *tmp;
  55. u_time = xdebug_get_utime();
  56. tmp = xdebug_sprintf("%10.4F ", u_time - XG(start_time));
  57. fprintf(context->trace_file, "%s", tmp);
  58. xdfree(tmp);
  59. #if WIN32|WINNT
  60. fprintf(context->trace_file, "%10Iu", zend_memory_usage(0 TSRMLS_CC));
  61. #else
  62. fprintf(context->trace_file, "%10zu", zend_memory_usage(0 TSRMLS_CC));
  63. #endif
  64. fprintf(context->trace_file, "\n");
  65. str_time = xdebug_get_time();
  66. fprintf(context->trace_file, "TRACE END [%s]\n\n", str_time);
  67. fflush(context->trace_file);
  68. xdfree(str_time);
  69. }
  70. char *xdebug_trace_textual_get_filename(void *ctxt TSRMLS_DC)
  71. {
  72. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  73. return context->trace_filename;
  74. }
  75. void add_single_value(xdebug_str *str, zval *zv, int collection_level TSRMLS_DC)
  76. {
  77. char *tmp_value;
  78. switch (collection_level) {
  79. case 1: /* synopsis */
  80. case 2:
  81. tmp_value = xdebug_get_zval_synopsis(zv, 0, NULL);
  82. break;
  83. case 3: /* full */
  84. case 4: /* full (with var) */
  85. default:
  86. tmp_value = xdebug_get_zval_value(zv, 0, NULL);
  87. break;
  88. case 5: /* serialized */
  89. tmp_value = xdebug_get_zval_value_serialized(zv, 0, NULL TSRMLS_CC);
  90. break;
  91. }
  92. if (tmp_value) {
  93. xdebug_str_add(str, tmp_value, 1);
  94. } else {
  95. xdebug_str_add(str, "???", 0);
  96. }
  97. }
  98. void xdebug_trace_textual_function_entry(void *ctxt, function_stack_entry *fse, int function_nr TSRMLS_DC)
  99. {
  100. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  101. int c = 0; /* Comma flag */
  102. unsigned int j = 0; /* Counter */
  103. char *tmp_name;
  104. xdebug_str str = XDEBUG_STR_INITIALIZER;
  105. tmp_name = xdebug_show_fname(fse->function, 0, 0 TSRMLS_CC);
  106. xdebug_str_add(&str, xdebug_sprintf("%10.4F ", fse->time - XG(start_time)), 1);
  107. xdebug_str_add(&str, xdebug_sprintf("%10lu ", fse->memory), 1);
  108. if (XG(show_mem_delta)) {
  109. xdebug_str_add(&str, xdebug_sprintf("%+8ld ", fse->memory - fse->prev_memory), 1);
  110. }
  111. for (j = 0; j < fse->level; j++) {
  112. xdebug_str_addl(&str, " ", 2, 0);
  113. }
  114. xdebug_str_add(&str, xdebug_sprintf("-> %s(", tmp_name), 1);
  115. xdfree(tmp_name);
  116. /* Printing vars */
  117. if (XG(collect_params) > 0) {
  118. int variadic_opened = 0;
  119. int variadic_count = 0;
  120. for (j = 0; j < fse->varc; j++) {
  121. if (c) {
  122. xdebug_str_addl(&str, ", ", 2, 0);
  123. } else {
  124. c = 1;
  125. }
  126. if (
  127. (fse->var[j].is_variadic && fse->var[j].addr)
  128. #if PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 70000
  129. || (!fse->var[j].addr && fse->is_variadic && j == fse->varc - 1)
  130. #endif
  131. ) {
  132. xdebug_str_add(&str, "...", 0);
  133. variadic_opened = 1;
  134. #if PHP_VERSION_ID >= 70000
  135. c = 0;
  136. #endif
  137. }
  138. if (fse->var[j].name && XG(collect_params) == 4) {
  139. xdebug_str_add(&str, xdebug_sprintf("$%s = ", fse->var[j].name), 1);
  140. }
  141. if (fse->var[j].is_variadic && fse->var[j].addr) {
  142. xdebug_str_add(&str, "variadic(", 0);
  143. #if PHP_VERSION_ID >= 70000
  144. continue;
  145. #endif
  146. }
  147. if (
  148. (variadic_opened && XG(collect_params) != 5)
  149. #if PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 70000
  150. && (!(!fse->var[j].addr && fse->is_variadic && j == fse->varc - 1))
  151. #endif
  152. ) {
  153. xdebug_str_add(&str, xdebug_sprintf("%d => ", variadic_count++), 1);
  154. }
  155. if (fse->var[j].addr) {
  156. add_single_value(&str, fse->var[j].addr, XG(collect_params) TSRMLS_CC);
  157. #if PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 70000
  158. } else if (fse->is_variadic && j == fse->varc - 1) {
  159. xdebug_str_addl(&str, "variadic(", 9, 0);
  160. #endif
  161. } else {
  162. xdebug_str_addl(&str, "???", 3, 0);
  163. }
  164. }
  165. if (variadic_opened) {
  166. xdebug_str_add(&str, ")", 0);
  167. }
  168. }
  169. if (fse->include_filename) {
  170. if (fse->function.type == XFUNC_EVAL) {
  171. #if PHP_VERSION_ID >= 70000
  172. zend_string *i_filename = zend_string_init(fse->include_filename, strlen(fse->include_filename), 0);
  173. zend_string *escaped;
  174. escaped = php_addcslashes(i_filename, 0, "'\\\0..\37", 6);
  175. xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped->val), 1);
  176. zend_string_release(escaped);
  177. zend_string_release(i_filename);
  178. #else
  179. int tmp_len;
  180. char *escaped;
  181. escaped = php_addcslashes(fse->include_filename, strlen(fse->include_filename), &tmp_len, 0, "'\\\0..\37", 6 TSRMLS_CC);
  182. xdebug_str_add(&str, xdebug_sprintf("'%s'", escaped), 1);
  183. efree(escaped);
  184. #endif
  185. } else {
  186. xdebug_str_add(&str, fse->include_filename, 0);
  187. }
  188. }
  189. xdebug_str_add(&str, xdebug_sprintf(") %s:%d\n", fse->filename, fse->lineno), 1);
  190. fprintf(context->trace_file, "%s", str.d);
  191. fflush(context->trace_file);
  192. xdfree(str.d);
  193. }
  194. /* Used for normal return values, and generator return values */
  195. static void xdebug_return_trace_stack_common(xdebug_str *str, function_stack_entry *fse TSRMLS_DC)
  196. {
  197. unsigned int j = 0; /* Counter */
  198. xdebug_str_add(str, xdebug_sprintf("%10.4F ", xdebug_get_utime() - XG(start_time)), 1);
  199. xdebug_str_add(str, xdebug_sprintf("%10lu ", zend_memory_usage(0 TSRMLS_CC)), 1);
  200. if (XG(show_mem_delta)) {
  201. xdebug_str_addl(str, " ", 8, 0);
  202. }
  203. for (j = 0; j < fse->level; j++) {
  204. xdebug_str_addl(str, " ", 2, 0);
  205. }
  206. xdebug_str_addl(str, " >=> ", 5, 0);
  207. }
  208. void xdebug_trace_textual_function_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zval *return_value TSRMLS_DC)
  209. {
  210. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  211. xdebug_str str = XDEBUG_STR_INITIALIZER;
  212. char *tmp_value;
  213. xdebug_return_trace_stack_common(&str, fse TSRMLS_CC);
  214. tmp_value = xdebug_get_zval_value(return_value, 0, NULL);
  215. if (tmp_value) {
  216. xdebug_str_add(&str, tmp_value, 1);
  217. }
  218. xdebug_str_addl(&str, "\n", 2, 0);
  219. fprintf(context->trace_file, "%s", str.d);
  220. fflush(context->trace_file);
  221. xdfree(str.d);
  222. }
  223. #if PHP_VERSION_ID >= 50500
  224. void xdebug_trace_textual_generator_return_value(void *ctxt, function_stack_entry *fse, int function_nr, zend_generator *generator TSRMLS_DC)
  225. {
  226. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  227. xdebug_str str = XDEBUG_STR_INITIALIZER;
  228. char *tmp_value = NULL;
  229. /* Generator key */
  230. #if PHP_VERSION_ID >= 70000
  231. tmp_value = xdebug_get_zval_value(&generator->key, 0, NULL);
  232. #else
  233. tmp_value = xdebug_get_zval_value(generator->key, 0, NULL);
  234. #endif
  235. if (tmp_value) {
  236. xdebug_return_trace_stack_common(&str, fse TSRMLS_CC);
  237. xdebug_str_addl(&str, "(", 1, 0);
  238. xdebug_str_add(&str, tmp_value, 1);
  239. xdebug_str_addl(&str, " => ", 4, 0);
  240. #if PHP_VERSION_ID >= 70000
  241. tmp_value = xdebug_get_zval_value(&generator->value, 0, NULL);
  242. #else
  243. tmp_value = xdebug_get_zval_value(generator->value, 0, NULL);
  244. #endif
  245. if (tmp_value) {
  246. xdebug_str_add(&str, tmp_value, 1);
  247. }
  248. xdebug_str_addl(&str, ")", 1, 0);
  249. xdebug_str_addl(&str, "\n", 2, 0);
  250. fprintf(context->trace_file, "%s", str.d);
  251. fflush(context->trace_file);
  252. xdfree(str.d);
  253. }
  254. }
  255. #endif
  256. void xdebug_trace_textual_assignment(void *ctxt, function_stack_entry *fse, char *full_varname, zval *retval, char *op, char *filename, int lineno TSRMLS_DC)
  257. {
  258. xdebug_trace_textual_context *context = (xdebug_trace_textual_context*) ctxt;
  259. unsigned int j = 0;
  260. xdebug_str str = XDEBUG_STR_INITIALIZER;
  261. char *tmp_value;
  262. xdebug_str_addl(&str, " ", 20, 0);
  263. if (XG(show_mem_delta)) {
  264. xdebug_str_addl(&str, " ", 8, 0);
  265. }
  266. for (j = 0; j <= fse->level; j++) {
  267. xdebug_str_addl(&str, " ", 2, 0);
  268. }
  269. xdebug_str_addl(&str, " => ", 6, 0);
  270. xdebug_str_add(&str, full_varname, 0);
  271. if (op[0] != '\0' ) { /* pre/post inc/dec ops are special */
  272. xdebug_str_add(&str, xdebug_sprintf(" %s ", op), 1);
  273. tmp_value = xdebug_get_zval_value(retval, 0, NULL);
  274. if (tmp_value) {
  275. xdebug_str_add(&str, tmp_value, 1);
  276. } else {
  277. xdebug_str_addl(&str, "NULL", 4, 0);
  278. }
  279. }
  280. xdebug_str_add(&str, xdebug_sprintf(" %s:%d\n", filename, lineno), 1);
  281. fprintf(context->trace_file, "%s", str.d);
  282. fflush(context->trace_file);
  283. xdfree(str.d);
  284. }
  285. xdebug_trace_handler_t xdebug_trace_handler_textual =
  286. {
  287. xdebug_trace_textual_init,
  288. xdebug_trace_textual_deinit,
  289. xdebug_trace_textual_write_header,
  290. xdebug_trace_textual_write_footer,
  291. xdebug_trace_textual_get_filename,
  292. xdebug_trace_textual_function_entry,
  293. NULL /*xdebug_trace_textual_function_exit */,
  294. xdebug_trace_textual_function_return_value,
  295. #if PHP_VERSION_ID >= 50500
  296. xdebug_trace_textual_generator_return_value,
  297. #endif
  298. xdebug_trace_textual_assignment
  299. };