PageRenderTime 60ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/xdebug.c

http://github.com/derickr/xdebug
C | 1099 lines | 845 code | 184 blank | 70 comment | 128 complexity | 655f98e5f6376d863cff92a00acd2d5c MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Xdebug |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2002-2020 Derick Rethans |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 1.01 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. | https://xdebug.org/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. | derick@xdebug.org so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Derick Rethans <derick@xdebug.org> |
  16. | Ilia Alshanetsky <ilia@prohost.org> |
  17. | Harald Radi <harald.radi@nme.at> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "php.h"
  24. #include "main/php_version.h"
  25. #include "lib/compat.h"
  26. #if HAVE_XDEBUG
  27. #ifndef PHP_WIN32
  28. #include <sys/time.h>
  29. #include <unistd.h>
  30. #else
  31. #include "win32/time.h"
  32. #include <process.h>
  33. #endif
  34. #include "TSRM.h"
  35. #include "SAPI.h"
  36. #include "zend_extensions.h"
  37. #include "main/php_ini.h"
  38. #include "ext/standard/head.h"
  39. #include "ext/standard/html.h"
  40. #include "ext/standard/info.h"
  41. #include "ext/standard/php_string.h"
  42. #include "php_globals.h"
  43. #include "main/php_output.h"
  44. #include "ext/standard/php_var.h"
  45. #include "php_xdebug.h"
  46. #include "base/base.h"
  47. #include "base/filter.h"
  48. #include "base/monitor.h"
  49. #include "base/stack.h"
  50. #include "base/superglobals.h"
  51. #include "coverage/code_coverage.h"
  52. #include "gcstats/gc_stats.h"
  53. #include "lib/usefulstuff.h"
  54. #include "lib/lib.h"
  55. #include "lib/llist.h"
  56. #include "lib/mm.h"
  57. #include "lib/var_export_html.h"
  58. #include "lib/var_export_line.h"
  59. #include "lib/var_export_text.h"
  60. #include "profiler/profiler.h"
  61. #include "tracing/tracing.h"
  62. #if PHP_VERSION_ID >= 70300
  63. static int (*xdebug_orig_post_startup_cb)(void);
  64. static int xdebug_post_startup(void);
  65. #endif
  66. static int xdebug_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s);
  67. int xdebug_exit_handler(zend_execute_data *execute_data);
  68. int zend_xdebug_initialised = 0;
  69. static int (*xdebug_orig_header_handler)(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s);
  70. ZEND_BEGIN_ARG_INFO_EX(xdebug_void_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  71. ZEND_END_ARG_INFO()
  72. ZEND_BEGIN_ARG_INFO_EX(xdebug_print_function_stack_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  73. ZEND_ARG_INFO(0, message)
  74. ZEND_ARG_INFO(0, options)
  75. ZEND_END_ARG_INFO()
  76. ZEND_BEGIN_ARG_INFO_EX(xdebug_call_class_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  77. ZEND_ARG_INFO(0, depth)
  78. ZEND_END_ARG_INFO()
  79. ZEND_BEGIN_ARG_INFO_EX(xdebug_call_function_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  80. ZEND_ARG_INFO(0, depth)
  81. ZEND_END_ARG_INFO()
  82. ZEND_BEGIN_ARG_INFO_EX(xdebug_call_file_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  83. ZEND_ARG_INFO(0, depth)
  84. ZEND_END_ARG_INFO()
  85. ZEND_BEGIN_ARG_INFO_EX(xdebug_call_line_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  86. ZEND_ARG_INFO(0, depth)
  87. ZEND_END_ARG_INFO()
  88. ZEND_BEGIN_ARG_INFO_EX(xdebug_var_dump_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
  89. ZEND_ARG_INFO(0, var)
  90. ZEND_END_ARG_INFO()
  91. ZEND_BEGIN_ARG_INFO_EX(xdebug_debug_zval_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
  92. ZEND_ARG_INFO(0, var)
  93. ZEND_END_ARG_INFO()
  94. ZEND_BEGIN_ARG_INFO_EX(xdebug_debug_zval_stdout_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
  95. ZEND_ARG_INFO(0, var)
  96. ZEND_END_ARG_INFO()
  97. ZEND_BEGIN_ARG_INFO_EX(xdebug_start_trace_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  98. ZEND_ARG_INFO(0, fname)
  99. ZEND_ARG_INFO(0, options)
  100. ZEND_END_ARG_INFO()
  101. ZEND_BEGIN_ARG_INFO_EX(xdebug_get_collected_errors_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  102. ZEND_ARG_INFO(0, clear)
  103. ZEND_END_ARG_INFO()
  104. ZEND_BEGIN_ARG_INFO_EX(xdebug_start_function_monitor_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
  105. ZEND_ARG_INFO(0, functions_to_monitor)
  106. ZEND_END_ARG_INFO()
  107. ZEND_BEGIN_ARG_INFO_EX(xdebug_get_monitored_functions_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  108. ZEND_ARG_INFO(0, clear)
  109. ZEND_END_ARG_INFO()
  110. ZEND_BEGIN_ARG_INFO_EX(xdebug_start_code_coverage_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  111. ZEND_ARG_INFO(0, options)
  112. ZEND_END_ARG_INFO()
  113. ZEND_BEGIN_ARG_INFO_EX(xdebug_stop_code_coverage_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  114. ZEND_ARG_INFO(0, cleanup)
  115. ZEND_END_ARG_INFO()
  116. ZEND_BEGIN_ARG_INFO_EX(xdebug_start_gcstats_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  117. ZEND_ARG_INFO(0, fname)
  118. ZEND_END_ARG_INFO()
  119. ZEND_BEGIN_ARG_INFO_EX(xdebug_stop_gcstats_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
  120. ZEND_END_ARG_INFO()
  121. ZEND_BEGIN_ARG_INFO_EX(xdebug_set_filter_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 3)
  122. ZEND_ARG_INFO(0, filter_group)
  123. ZEND_ARG_INFO(0, filter_type)
  124. ZEND_ARG_INFO(0, array_of_filters)
  125. ZEND_END_ARG_INFO()
  126. zend_function_entry xdebug_functions[] = {
  127. PHP_FE(xdebug_get_stack_depth, xdebug_void_args)
  128. PHP_FE(xdebug_get_function_stack, xdebug_void_args)
  129. PHP_FE(xdebug_get_formatted_function_stack, xdebug_void_args)
  130. PHP_FE(xdebug_print_function_stack, xdebug_print_function_stack_args)
  131. PHP_FE(xdebug_get_declared_vars, xdebug_void_args)
  132. PHP_FE(xdebug_call_class, xdebug_call_class_args)
  133. PHP_FE(xdebug_call_function, xdebug_call_function_args)
  134. PHP_FE(xdebug_call_file, xdebug_call_file_args)
  135. PHP_FE(xdebug_call_line, xdebug_call_line_args)
  136. PHP_FE(xdebug_var_dump, xdebug_var_dump_args)
  137. PHP_FE(xdebug_debug_zval, xdebug_debug_zval_args)
  138. PHP_FE(xdebug_debug_zval_stdout, xdebug_debug_zval_stdout_args)
  139. PHP_FE(xdebug_enable, xdebug_void_args)
  140. PHP_FE(xdebug_disable, xdebug_void_args)
  141. PHP_FE(xdebug_is_enabled, xdebug_void_args)
  142. PHP_FE(xdebug_is_debugger_active, xdebug_void_args)
  143. PHP_FE(xdebug_break, xdebug_void_args)
  144. PHP_FE(xdebug_start_trace, xdebug_start_trace_args)
  145. PHP_FE(xdebug_stop_trace, xdebug_void_args)
  146. PHP_FE(xdebug_get_tracefile_name, xdebug_void_args)
  147. PHP_FE(xdebug_get_profiler_filename, xdebug_void_args)
  148. PHP_FE(xdebug_start_gcstats, xdebug_start_gcstats_args)
  149. PHP_FE(xdebug_stop_gcstats, xdebug_stop_gcstats_args)
  150. PHP_FE(xdebug_get_gcstats_filename, xdebug_void_args)
  151. PHP_FE(xdebug_get_gc_run_count, xdebug_void_args)
  152. PHP_FE(xdebug_get_gc_total_collected_roots, xdebug_void_args)
  153. PHP_FE(xdebug_memory_usage, xdebug_void_args)
  154. PHP_FE(xdebug_peak_memory_usage, xdebug_void_args)
  155. PHP_FE(xdebug_time_index, xdebug_void_args)
  156. PHP_FE(xdebug_start_error_collection, xdebug_void_args)
  157. PHP_FE(xdebug_stop_error_collection, xdebug_void_args)
  158. PHP_FE(xdebug_get_collected_errors, xdebug_get_collected_errors_args)
  159. PHP_FE(xdebug_start_function_monitor, xdebug_start_function_monitor_args)
  160. PHP_FE(xdebug_stop_function_monitor, xdebug_void_args)
  161. PHP_FE(xdebug_get_monitored_functions, xdebug_get_monitored_functions_args)
  162. PHP_FE(xdebug_start_code_coverage, xdebug_start_code_coverage_args)
  163. PHP_FE(xdebug_stop_code_coverage, xdebug_stop_code_coverage_args)
  164. PHP_FE(xdebug_get_code_coverage, xdebug_void_args)
  165. PHP_FE(xdebug_code_coverage_started, xdebug_void_args)
  166. PHP_FE(xdebug_get_function_count, xdebug_void_args)
  167. PHP_FE(xdebug_dump_superglobals, xdebug_void_args)
  168. PHP_FE(xdebug_get_headers, xdebug_void_args)
  169. PHP_FE(xdebug_set_filter, xdebug_set_filter_args)
  170. {NULL, NULL, 0, 0, 0}
  171. };
  172. zend_module_entry xdebug_module_entry = {
  173. STANDARD_MODULE_HEADER,
  174. "xdebug",
  175. xdebug_functions,
  176. PHP_MINIT(xdebug),
  177. PHP_MSHUTDOWN(xdebug),
  178. PHP_RINIT(xdebug),
  179. PHP_RSHUTDOWN(xdebug),
  180. PHP_MINFO(xdebug),
  181. XDEBUG_VERSION,
  182. NO_MODULE_GLOBALS,
  183. ZEND_MODULE_POST_ZEND_DEACTIVATE_N(xdebug),
  184. STANDARD_MODULE_PROPERTIES_EX
  185. };
  186. ZEND_DECLARE_MODULE_GLOBALS(xdebug)
  187. #if COMPILE_DL_XDEBUG
  188. ZEND_GET_MODULE(xdebug)
  189. # ifdef ZTS
  190. ZEND_TSRMLS_CACHE_DEFINE();
  191. # endif
  192. #endif
  193. static PHP_INI_MH(OnUpdateServer)
  194. {
  195. DUMP_TOK(server);
  196. }
  197. static PHP_INI_MH(OnUpdateGet)
  198. {
  199. DUMP_TOK(get);
  200. }
  201. static PHP_INI_MH(OnUpdatePost)
  202. {
  203. DUMP_TOK(post);
  204. }
  205. static PHP_INI_MH(OnUpdateCookie)
  206. {
  207. DUMP_TOK(cookie);
  208. }
  209. static PHP_INI_MH(OnUpdateFiles)
  210. {
  211. DUMP_TOK(files);
  212. }
  213. static PHP_INI_MH(OnUpdateEnv)
  214. {
  215. DUMP_TOK(env);
  216. }
  217. static PHP_INI_MH(OnUpdateRequest)
  218. {
  219. DUMP_TOK(request);
  220. }
  221. static PHP_INI_MH(OnUpdateSession)
  222. {
  223. DUMP_TOK(session);
  224. }
  225. #ifdef P_tmpdir
  226. # define XDEBUG_TEMP_DIR P_tmpdir
  227. #else
  228. # ifdef PHP_WIN32
  229. # define XDEBUG_TEMP_DIR "C:\\Windows\\Temp"
  230. # else
  231. # define XDEBUG_TEMP_DIR "/tmp"
  232. # endif
  233. #endif
  234. PHP_INI_BEGIN()
  235. /* Library settings */
  236. STD_PHP_INI_ENTRY("xdebug.output_dir", XDEBUG_TEMP_DIR, PHP_INI_ALL, OnUpdateString, settings.library.output_dir, zend_xdebug_globals, xdebug_globals)
  237. /* Debugger settings */
  238. STD_PHP_INI_BOOLEAN("xdebug.coverage_enable", "1", PHP_INI_SYSTEM, OnUpdateBool, settings.coverage.enable, zend_xdebug_globals, xdebug_globals)
  239. STD_PHP_INI_BOOLEAN("xdebug.collect_includes","1", PHP_INI_ALL, OnUpdateBool, base.settings.collect_includes, zend_xdebug_globals, xdebug_globals)
  240. STD_PHP_INI_ENTRY("xdebug.collect_params", "0", PHP_INI_ALL, OnUpdateLong, base.settings.collect_params, zend_xdebug_globals, xdebug_globals)
  241. STD_PHP_INI_BOOLEAN("xdebug.collect_return", "0", PHP_INI_ALL, OnUpdateBool, base.settings.collect_return, zend_xdebug_globals, xdebug_globals)
  242. STD_PHP_INI_BOOLEAN("xdebug.collect_vars", "0", PHP_INI_ALL, OnUpdateBool, base.settings.collect_vars, zend_xdebug_globals, xdebug_globals)
  243. STD_PHP_INI_BOOLEAN("xdebug.collect_assignments", "0", PHP_INI_ALL, OnUpdateBool, base.settings.collect_assignments, zend_xdebug_globals, xdebug_globals)
  244. STD_PHP_INI_BOOLEAN("xdebug.default_enable", "1", PHP_INI_ALL, OnUpdateBool, base.settings.default_enable, zend_xdebug_globals, xdebug_globals)
  245. STD_PHP_INI_ENTRY("xdebug.file_link_format", "", PHP_INI_ALL, OnUpdateString, base.settings.file_link_format, zend_xdebug_globals, xdebug_globals)
  246. STD_PHP_INI_ENTRY("xdebug.filename_format", "", PHP_INI_ALL, OnUpdateString, base.settings.filename_format, zend_xdebug_globals, xdebug_globals)
  247. STD_PHP_INI_BOOLEAN("xdebug.force_display_errors", "0", PHP_INI_SYSTEM, OnUpdateBool, base.settings.force_display_errors, zend_xdebug_globals, xdebug_globals)
  248. STD_PHP_INI_ENTRY("xdebug.force_error_reporting", "0", PHP_INI_SYSTEM, OnUpdateLong, base.settings.force_error_reporting, zend_xdebug_globals, xdebug_globals)
  249. STD_PHP_INI_ENTRY("xdebug.halt_level", "0", PHP_INI_ALL, OnUpdateLong, base.settings.halt_level, zend_xdebug_globals, xdebug_globals)
  250. STD_PHP_INI_ENTRY("xdebug.max_nesting_level", "256", PHP_INI_ALL, OnUpdateLong, base.settings.max_nesting_level, zend_xdebug_globals, xdebug_globals)
  251. STD_PHP_INI_ENTRY("xdebug.max_stack_frames", "-1", PHP_INI_ALL, OnUpdateLong, base.settings.max_stack_frames, zend_xdebug_globals, xdebug_globals)
  252. STD_PHP_INI_ENTRY("xdebug.overload_var_dump", "2", PHP_INI_ALL, OnUpdateLong, base.settings.overload_var_dump, zend_xdebug_globals, xdebug_globals)
  253. STD_PHP_INI_BOOLEAN("xdebug.show_error_trace", "0", PHP_INI_ALL, OnUpdateBool, base.settings.show_error_trace, zend_xdebug_globals, xdebug_globals)
  254. STD_PHP_INI_BOOLEAN("xdebug.show_exception_trace", "0", PHP_INI_ALL, OnUpdateBool, base.settings.show_ex_trace, zend_xdebug_globals, xdebug_globals)
  255. STD_PHP_INI_BOOLEAN("xdebug.show_local_vars", "0", PHP_INI_ALL, OnUpdateBool, base.settings.show_local_vars, zend_xdebug_globals, xdebug_globals)
  256. STD_PHP_INI_BOOLEAN("xdebug.show_mem_delta", "0", PHP_INI_ALL, OnUpdateBool, base.settings.show_mem_delta, zend_xdebug_globals, xdebug_globals)
  257. /* Dump superglobals settings */
  258. PHP_INI_ENTRY("xdebug.dump.COOKIE", NULL, PHP_INI_ALL, OnUpdateCookie)
  259. PHP_INI_ENTRY("xdebug.dump.ENV", NULL, PHP_INI_ALL, OnUpdateEnv)
  260. PHP_INI_ENTRY("xdebug.dump.FILES", NULL, PHP_INI_ALL, OnUpdateFiles)
  261. PHP_INI_ENTRY("xdebug.dump.GET", NULL, PHP_INI_ALL, OnUpdateGet)
  262. PHP_INI_ENTRY("xdebug.dump.POST", NULL, PHP_INI_ALL, OnUpdatePost)
  263. PHP_INI_ENTRY("xdebug.dump.REQUEST", NULL, PHP_INI_ALL, OnUpdateRequest)
  264. PHP_INI_ENTRY("xdebug.dump.SERVER", NULL, PHP_INI_ALL, OnUpdateServer)
  265. PHP_INI_ENTRY("xdebug.dump.SESSION", NULL, PHP_INI_ALL, OnUpdateSession)
  266. STD_PHP_INI_BOOLEAN("xdebug.dump_globals", "1", PHP_INI_ALL, OnUpdateBool, base.settings.dump_globals, zend_xdebug_globals, xdebug_globals)
  267. STD_PHP_INI_BOOLEAN("xdebug.dump_once", "1", PHP_INI_ALL, OnUpdateBool, base.settings.dump_once, zend_xdebug_globals, xdebug_globals)
  268. STD_PHP_INI_BOOLEAN("xdebug.dump_undefined", "0", PHP_INI_ALL, OnUpdateBool, base.settings.dump_undefined, zend_xdebug_globals, xdebug_globals)
  269. /* Profiler settings */
  270. STD_PHP_INI_BOOLEAN("xdebug.profiler_enable", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, settings.profiler.profiler_enable, zend_xdebug_globals, xdebug_globals)
  271. STD_PHP_INI_ENTRY("xdebug.profiler_output_name", "cachegrind.out.%p", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, settings.profiler.profiler_output_name, zend_xdebug_globals, xdebug_globals)
  272. STD_PHP_INI_BOOLEAN("xdebug.profiler_enable_trigger", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, settings.profiler.profiler_enable_trigger, zend_xdebug_globals, xdebug_globals)
  273. STD_PHP_INI_ENTRY("xdebug.profiler_enable_trigger_value", "", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, settings.profiler.profiler_enable_trigger_value, zend_xdebug_globals, xdebug_globals)
  274. STD_PHP_INI_BOOLEAN("xdebug.profiler_append", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, settings.profiler.profiler_append, zend_xdebug_globals, xdebug_globals)
  275. /* Remote debugger settings */
  276. STD_PHP_INI_BOOLEAN("xdebug.remote_enable", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, settings.debugger.remote_enable, zend_xdebug_globals, xdebug_globals)
  277. STD_PHP_INI_ENTRY("xdebug.remote_host", "localhost", PHP_INI_ALL, OnUpdateString, settings.debugger.remote_host, zend_xdebug_globals, xdebug_globals)
  278. PHP_INI_ENTRY("xdebug.remote_mode", "req", PHP_INI_ALL, OnUpdateDebugMode)
  279. STD_PHP_INI_ENTRY("xdebug.remote_port", "9000", PHP_INI_ALL, OnUpdateLong, settings.debugger.remote_port, zend_xdebug_globals, xdebug_globals)
  280. STD_PHP_INI_BOOLEAN("xdebug.remote_autostart","0", PHP_INI_ALL, OnUpdateBool, settings.debugger.remote_autostart, zend_xdebug_globals, xdebug_globals)
  281. STD_PHP_INI_BOOLEAN("xdebug.remote_connect_back","0", PHP_INI_ALL, OnUpdateBool, settings.debugger.remote_connect_back, zend_xdebug_globals, xdebug_globals)
  282. STD_PHP_INI_ENTRY("xdebug.remote_log", "", PHP_INI_ALL, OnUpdateString, settings.debugger.remote_log, zend_xdebug_globals, xdebug_globals)
  283. STD_PHP_INI_ENTRY("xdebug.remote_log_level", XDEBUG_LOG_DEFAULT, PHP_INI_ALL, OnUpdateLong, settings.debugger.remote_log_level, zend_xdebug_globals, xdebug_globals)
  284. STD_PHP_INI_ENTRY("xdebug.idekey", "", PHP_INI_ALL, OnUpdateString, settings.debugger.ide_key_setting, zend_xdebug_globals, xdebug_globals)
  285. STD_PHP_INI_ENTRY("xdebug.remote_cookie_expire_time", "3600", PHP_INI_ALL, OnUpdateLong, settings.debugger.remote_cookie_expire_time, zend_xdebug_globals, xdebug_globals)
  286. STD_PHP_INI_ENTRY("xdebug.remote_addr_header", "", PHP_INI_ALL, OnUpdateString, settings.debugger.remote_addr_header, zend_xdebug_globals, xdebug_globals)
  287. STD_PHP_INI_ENTRY("xdebug.remote_timeout", "200", PHP_INI_ALL, OnUpdateLong, settings.debugger.remote_connect_timeout, zend_xdebug_globals, xdebug_globals)
  288. /* Variable display settings */
  289. STD_PHP_INI_ENTRY("xdebug.var_display_max_children", "128", PHP_INI_ALL, OnUpdateLong, base.settings.display_max_children, zend_xdebug_globals, xdebug_globals)
  290. STD_PHP_INI_ENTRY("xdebug.var_display_max_data", "512", PHP_INI_ALL, OnUpdateLong, base.settings.display_max_data, zend_xdebug_globals, xdebug_globals)
  291. STD_PHP_INI_ENTRY("xdebug.var_display_max_depth", "3", PHP_INI_ALL, OnUpdateLong, base.settings.display_max_depth, zend_xdebug_globals, xdebug_globals)
  292. STD_PHP_INI_ENTRY("xdebug.cli_color", "0", PHP_INI_ALL, OnUpdateLong, base.settings.cli_color, zend_xdebug_globals, xdebug_globals)
  293. /* Scream support */
  294. STD_PHP_INI_BOOLEAN("xdebug.scream", "0", PHP_INI_ALL, OnUpdateBool, base.settings.do_scream, zend_xdebug_globals, xdebug_globals)
  295. /* GC Stats support */
  296. STD_PHP_INI_BOOLEAN("xdebug.gc_stats_enable", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, settings.gc_stats.enable, zend_xdebug_globals, xdebug_globals)
  297. STD_PHP_INI_ENTRY("xdebug.gc_stats_output_name", "gcstats.%p", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, settings.gc_stats.output_name, zend_xdebug_globals, xdebug_globals)
  298. /* Tracing settings */
  299. STD_PHP_INI_BOOLEAN("xdebug.auto_trace", "0", PHP_INI_ALL, OnUpdateBool, settings.tracing.auto_trace, zend_xdebug_globals, xdebug_globals)
  300. STD_PHP_INI_BOOLEAN("xdebug.trace_enable_trigger", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, settings.tracing.trace_enable_trigger, zend_xdebug_globals, xdebug_globals)
  301. STD_PHP_INI_ENTRY("xdebug.trace_enable_trigger_value", "", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, settings.tracing.trace_enable_trigger_value, zend_xdebug_globals, xdebug_globals)
  302. STD_PHP_INI_ENTRY("xdebug.trace_output_name", "trace.%c", PHP_INI_ALL, OnUpdateString, settings.tracing.trace_output_name, zend_xdebug_globals, xdebug_globals)
  303. STD_PHP_INI_ENTRY("xdebug.trace_format", "0", PHP_INI_ALL, OnUpdateLong, settings.tracing.trace_format, zend_xdebug_globals, xdebug_globals)
  304. STD_PHP_INI_ENTRY("xdebug.trace_options", "0", PHP_INI_ALL, OnUpdateLong, settings.tracing.trace_options, zend_xdebug_globals, xdebug_globals)
  305. PHP_INI_END()
  306. static void xdebug_init_base_globals(struct xdebug_base_info *xg)
  307. {
  308. xg->level = 0;
  309. xg->stack = NULL;
  310. xg->headers = NULL;
  311. xg->in_debug_info = 0;
  312. xg->output_is_tty = OUTPUT_NOT_CHECKED;
  313. xg->do_monitor_functions = 0;
  314. xg->headers = NULL;
  315. xg->in_at = 0; /* scream */
  316. xg->in_execution = 0;
  317. xg->in_var_serialisation = 0;
  318. xg->error_reporting_override = 0;
  319. xg->error_reporting_overridden = 0;
  320. xg->filter_type_tracing = XDEBUG_FILTER_NONE;
  321. xg->filter_type_profiler = XDEBUG_FILTER_NONE;
  322. xg->filter_type_code_coverage = XDEBUG_FILTER_NONE;
  323. xg->filters_tracing = NULL;
  324. xg->filters_code_coverage = NULL;
  325. xdebug_llist_init(&xg->server, xdebug_superglobals_dump_dtor);
  326. xdebug_llist_init(&xg->get, xdebug_superglobals_dump_dtor);
  327. xdebug_llist_init(&xg->post, xdebug_superglobals_dump_dtor);
  328. xdebug_llist_init(&xg->cookie, xdebug_superglobals_dump_dtor);
  329. xdebug_llist_init(&xg->files, xdebug_superglobals_dump_dtor);
  330. xdebug_llist_init(&xg->env, xdebug_superglobals_dump_dtor);
  331. xdebug_llist_init(&xg->request, xdebug_superglobals_dump_dtor);
  332. xdebug_llist_init(&xg->session, xdebug_superglobals_dump_dtor);
  333. }
  334. static void php_xdebug_init_globals (zend_xdebug_globals *xg)
  335. {
  336. xdebug_init_base_globals(&xg->base);
  337. xdebug_init_coverage_globals(&xg->globals.coverage);
  338. xdebug_init_debugger_globals(&xg->globals.debugger);
  339. xdebug_init_library_globals(&xg->globals.library);
  340. xdebug_init_profiler_globals(&xg->globals.profiler);
  341. xdebug_init_gc_stats_globals(&xg->globals.gc_stats);
  342. xdebug_init_tracing_globals(&xg->globals.tracing);
  343. /* Override header generation in SAPI */
  344. if (sapi_module.header_handler != xdebug_header_handler) {
  345. xdebug_orig_header_handler = sapi_module.header_handler;
  346. sapi_module.header_handler = xdebug_header_handler;
  347. }
  348. }
  349. static void xdebug_deinit_base_globals(struct xdebug_base_info *xg)
  350. {
  351. xdebug_llist_empty(&xg->server, NULL);
  352. xdebug_llist_empty(&xg->get, NULL);
  353. xdebug_llist_empty(&xg->post, NULL);
  354. xdebug_llist_empty(&xg->cookie, NULL);
  355. xdebug_llist_empty(&xg->files, NULL);
  356. xdebug_llist_empty(&xg->env, NULL);
  357. xdebug_llist_empty(&xg->request, NULL);
  358. xdebug_llist_empty(&xg->session, NULL);
  359. }
  360. static void php_xdebug_shutdown_globals (zend_xdebug_globals *xg)
  361. {
  362. xdebug_deinit_base_globals(&xg->base);
  363. }
  364. static void xdebug_env_config(void)
  365. {
  366. char *config = getenv("XDEBUG_CONFIG");
  367. xdebug_arg *parts;
  368. int i;
  369. /*
  370. XDEBUG_CONFIG format:
  371. XDEBUG_CONFIG=var=val var=val
  372. */
  373. if (!config) {
  374. return;
  375. }
  376. parts = (xdebug_arg*) xdmalloc(sizeof(xdebug_arg));
  377. xdebug_arg_init(parts);
  378. xdebug_explode(" ", config, parts, -1);
  379. for (i = 0; i < parts->c; ++i) {
  380. const char *name = NULL;
  381. char *envvar = parts->args[i];
  382. char *envval = NULL;
  383. char *eq = strchr(envvar, '=');
  384. if (!eq || !*eq) {
  385. continue;
  386. }
  387. *eq = 0;
  388. envval = eq + 1;
  389. if (!*envval) {
  390. continue;
  391. }
  392. if (strcasecmp(envvar, "remote_connect_back") == 0) {
  393. name = "xdebug.remote_connect_back";
  394. } else
  395. if (strcasecmp(envvar, "remote_enable") == 0) {
  396. name = "xdebug.remote_enable";
  397. } else
  398. if (strcasecmp(envvar, "remote_port") == 0) {
  399. name = "xdebug.remote_port";
  400. } else
  401. if (strcasecmp(envvar, "remote_host") == 0) {
  402. name = "xdebug.remote_host";
  403. } else
  404. if (strcasecmp(envvar, "remote_handler") == 0) {
  405. name = "xdebug.remote_handler";
  406. } else
  407. if (strcasecmp(envvar, "remote_mode") == 0) {
  408. name = "xdebug.remote_mode";
  409. } else
  410. if (strcasecmp(envvar, "idekey") == 0) {
  411. xdebug_debugger_reset_ide_key(envval);
  412. } else
  413. if (strcasecmp(envvar, "profiler_enable") == 0) {
  414. name = "xdebug.profiler_enable";
  415. } else
  416. if (strcasecmp(envvar, "profiler_output_dir") == 0) {
  417. name = "xdebug.profiler_output_dir";
  418. } else
  419. if (strcasecmp(envvar, "profiler_output_name") == 0) {
  420. name = "xdebug.profiler_output_name";
  421. } else
  422. if (strcasecmp(envvar, "profiler_enable_trigger") == 0) {
  423. name = "xdebug.profiler_enable_trigger";
  424. } else
  425. if (strcasecmp(envvar, "trace_enable") == 0) {
  426. name = "xdebug.trace_enable";
  427. } else
  428. if (strcasecmp(envvar, "remote_log") == 0) {
  429. name = "xdebug.remote_log";
  430. } else
  431. if (strcasecmp(envvar, "remote_log_level") == 0) {
  432. name = "xdebug.remote_log_level";
  433. } else
  434. if (strcasecmp(envvar, "remote_cookie_expire_time") == 0) {
  435. name = "xdebug.remote_cookie_expire_time";
  436. }
  437. else if (strcasecmp(envvar, "cli_color") == 0) {
  438. name = "xdebug.cli_color";
  439. }
  440. if (name) {
  441. zend_string *ini_name = zend_string_init(name, strlen(name), 0);
  442. zend_string *ini_val = zend_string_init(envval, strlen(envval), 0);
  443. zend_alter_ini_entry(ini_name, ini_val, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
  444. zend_string_release(ini_val);
  445. zend_string_release(ini_name);
  446. }
  447. }
  448. xdebug_arg_dtor(parts);
  449. }
  450. int xdebug_is_output_tty(void)
  451. {
  452. if (XG_BASE(output_is_tty) == OUTPUT_NOT_CHECKED) {
  453. #ifndef PHP_WIN32
  454. XG_BASE(output_is_tty) = isatty(STDOUT_FILENO);
  455. #else
  456. XG_BASE(output_is_tty) = getenv("ANSICON");
  457. #endif
  458. }
  459. return (XG_BASE(output_is_tty));
  460. }
  461. PHP_MINIT_FUNCTION(xdebug)
  462. {
  463. ZEND_INIT_MODULE_GLOBALS(xdebug, php_xdebug_init_globals, php_xdebug_shutdown_globals);
  464. REGISTER_INI_ENTRIES();
  465. xdebug_library_minit();
  466. xdebug_base_minit(INIT_FUNC_ARGS_PASSTHRU);
  467. xdebug_debugger_minit();
  468. xdebug_gcstats_minit();
  469. xdebug_profiler_minit();
  470. xdebug_tracing_minit(INIT_FUNC_ARGS_PASSTHRU);
  471. /* Overload the "exit" opcode */
  472. XDEBUG_SET_OPCODE_OVERRIDE_ASSIGN(exit, ZEND_EXIT);
  473. /* Coverage must be last, as it has a catch all override for opcodes */
  474. xdebug_coverage_minit(INIT_FUNC_ARGS_PASSTHRU);
  475. if (zend_xdebug_initialised == 0) {
  476. zend_error(E_WARNING, "Xdebug MUST be loaded as a Zend extension");
  477. }
  478. xdebug_filter_register_constants(INIT_FUNC_ARGS_PASSTHRU);
  479. return SUCCESS;
  480. }
  481. PHP_MSHUTDOWN_FUNCTION(xdebug)
  482. {
  483. xdebug_gcstats_mshutdown();
  484. xdebug_profiler_mshutdown();
  485. xdebug_library_mshutdown();
  486. #ifdef ZTS
  487. ts_free_id(xdebug_globals_id);
  488. #else
  489. php_xdebug_shutdown_globals(&xdebug_globals);
  490. #endif
  491. return SUCCESS;
  492. }
  493. static void xdebug_init_auto_globals(void)
  494. {
  495. zend_is_auto_global_str((char*) ZEND_STRL("_ENV"));
  496. zend_is_auto_global_str((char*) ZEND_STRL("_GET"));
  497. zend_is_auto_global_str((char*) ZEND_STRL("_POST"));
  498. zend_is_auto_global_str((char*) ZEND_STRL("_COOKIE"));
  499. zend_is_auto_global_str((char*) ZEND_STRL("_REQUEST"));
  500. zend_is_auto_global_str((char*) ZEND_STRL("_FILES"));
  501. zend_is_auto_global_str((char*) ZEND_STRL("_SERVER"));
  502. zend_is_auto_global_str((char*) ZEND_STRL("_SESSION"));
  503. }
  504. PHP_RINIT_FUNCTION(xdebug)
  505. {
  506. #if defined(ZTS) && defined(COMPILE_DL_XDEBUG)
  507. ZEND_TSRMLS_CACHE_UPDATE();
  508. #endif
  509. xdebug_coverage_rinit();
  510. xdebug_debugger_rinit();
  511. xdebug_gcstats_rinit();
  512. xdebug_profiler_rinit();
  513. xdebug_tracing_rinit();
  514. /* Get xdebug ini entries from the environment also,
  515. this can override the idekey if one is set */
  516. xdebug_env_config();
  517. xdebug_init_auto_globals();
  518. /* Only enabled extended info when it is not disabled */
  519. CG(compiler_options) = CG(compiler_options) | ZEND_COMPILE_EXTENDED_STMT;
  520. xdebug_base_rinit();
  521. return SUCCESS;
  522. }
  523. ZEND_MODULE_POST_ZEND_DEACTIVATE_D(xdebug)
  524. {
  525. xdebug_coverage_post_deactivate();
  526. xdebug_debugger_post_deactivate();
  527. xdebug_gcstats_post_deactivate();
  528. xdebug_profiler_post_deactivate();
  529. xdebug_tracing_post_deactivate();
  530. xdebug_base_post_deactivate();
  531. return SUCCESS;
  532. }
  533. PHP_RSHUTDOWN_FUNCTION(xdebug)
  534. {
  535. xdebug_base_rshutdown();
  536. return SUCCESS;
  537. }
  538. static int xdebug_info_printf(const char *fmt, ...) /* {{{ */
  539. {
  540. char *buf;
  541. size_t len, written;
  542. va_list argv;
  543. va_start(argv, fmt);
  544. len = vspprintf(&buf, 0, fmt, argv);
  545. va_end(argv);
  546. written = php_output_write(buf, len);
  547. efree(buf);
  548. return written;
  549. }
  550. /* }}} */
  551. PHP_MINFO_FUNCTION(xdebug)
  552. {
  553. php_info_print_table_start();
  554. php_info_print_table_header(2, "xdebug support", "enabled");
  555. php_info_print_table_row(2, "Version", XDEBUG_VERSION);
  556. if (!sapi_module.phpinfo_as_text) {
  557. xdebug_info_printf("<tr><td colspan='2' style='background-color: white; text-align: center'>%s</td></tr>\n", "<a style='color: #317E1E; background-color: transparent; font-weight: bold; text-decoration: underline' href='https://xdebug.org/support'>Support Xdebug on Patreon, GitHub, or as a business</a>");
  558. } else {
  559. xdebug_info_printf("Support Xdebug on Patreon, GitHub, or as a business: https://xdebug.org/support\n");
  560. }
  561. php_info_print_table_end();
  562. if (zend_xdebug_initialised == 0) {
  563. php_info_print_table_start();
  564. php_info_print_table_header(1, "XDEBUG NOT LOADED AS ZEND EXTENSION");
  565. php_info_print_table_end();
  566. }
  567. xdebug_debugger_minfo();
  568. DISPLAY_INI_ENTRIES();
  569. }
  570. static void xdebug_header_remove_with_prefix(xdebug_llist *headers, char *prefix, size_t prefix_len)
  571. {
  572. xdebug_llist_element *le;
  573. char *header;
  574. for (le = XDEBUG_LLIST_HEAD(XG_BASE(headers)); le != NULL; /* intentionally left blank*/) {
  575. header = XDEBUG_LLIST_VALP(le);
  576. if ((strlen(header) > prefix_len + 1) && (header[prefix_len] == ':') && (strncasecmp(header, prefix, prefix_len) == 0)) {
  577. xdebug_llist_element *current = le;
  578. le = XDEBUG_LLIST_NEXT(le);
  579. xdebug_llist_remove(headers, current, NULL);
  580. } else {
  581. le = XDEBUG_LLIST_NEXT(le);
  582. }
  583. }
  584. }
  585. static int xdebug_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s)
  586. {
  587. if (XG_BASE(headers)) {
  588. switch (op) {
  589. case SAPI_HEADER_ADD:
  590. xdebug_llist_insert_next(XG_BASE(headers), XDEBUG_LLIST_TAIL(XG_BASE(headers)), xdstrdup(h->header));
  591. break;
  592. case SAPI_HEADER_REPLACE: {
  593. char *colon_offset = strchr(h->header, ':');
  594. if (colon_offset) {
  595. char save = *colon_offset;
  596. *colon_offset = '\0';
  597. xdebug_header_remove_with_prefix(XG_BASE(headers), h->header, strlen(h->header));
  598. *colon_offset = save;
  599. }
  600. xdebug_llist_insert_next(XG_BASE(headers), XDEBUG_LLIST_TAIL(XG_BASE(headers)), xdstrdup(h->header));
  601. } break;
  602. case SAPI_HEADER_DELETE_ALL:
  603. xdebug_llist_empty(XG_BASE(headers), NULL);
  604. case SAPI_HEADER_DELETE:
  605. case SAPI_HEADER_SET_STATUS:
  606. break;
  607. }
  608. }
  609. if (xdebug_orig_header_handler) {
  610. return xdebug_orig_header_handler(h, op, s);
  611. }
  612. return SAPI_HEADER_ADD;
  613. }
  614. /* {{{ proto void xdebug_set_time_limit(void)
  615. Dummy function to prevent time limit from being set within the script */
  616. PHP_FUNCTION(xdebug_set_time_limit)
  617. {
  618. if (!xdebug_is_debug_connection_active()) {
  619. XG_BASE(orig_set_time_limit_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  620. }
  621. }
  622. /* }}} */
  623. /* {{{ proto int xdebug_error_reporting(void)
  624. Dummy function to return original error reporting level when 'eval' has turned it into 0 */
  625. PHP_FUNCTION(xdebug_error_reporting)
  626. {
  627. if (ZEND_NUM_ARGS() == 0 && XG_BASE(error_reporting_overridden) && xdebug_is_debug_connection_active()) {
  628. RETURN_LONG(XG_BASE(error_reporting_override));
  629. }
  630. XG_BASE(orig_error_reporting_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  631. }
  632. /* }}} */
  633. /* {{{ proto void xdebug_pcntl_exec(void)
  634. Dummy function to stop profiling when we run pcntl_exec */
  635. PHP_FUNCTION(xdebug_pcntl_exec)
  636. {
  637. /* We need to stop the profiler and trace files here */
  638. xdebug_profiler_pcntl_exec_handler();
  639. XG_BASE(orig_pcntl_exec_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  640. }
  641. /* }}} */
  642. /* {{{ proto int xdebug_pcntl_fork(void)
  643. Dummy function to set a new connection when forking a process */
  644. PHP_FUNCTION(xdebug_pcntl_fork)
  645. {
  646. XG_BASE(orig_pcntl_fork_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  647. xdebug_debugger_restart_if_pid_changed();
  648. }
  649. /* }}} */
  650. /* {{{ proto void xdebug_var_dump(mixed var [, ...] )
  651. Outputs a fancy string representation of a variable */
  652. PHP_FUNCTION(xdebug_var_dump)
  653. {
  654. zval *args;
  655. int argc;
  656. int i;
  657. xdebug_str *val;
  658. /* Ignore our new shiny function if overload_var_dump is set to 0 *and* the
  659. * function is not being called as xdebug_var_dump() (usually, that'd be
  660. * the overloaded var_dump() of course). Fixes issue 1262. */
  661. if (
  662. !XINI_BASE(overload_var_dump)
  663. && (strcmp("xdebug_var_dump", execute_data->func->common.function_name->val) != 0)
  664. ) {
  665. XG_BASE(orig_var_dump_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  666. return;
  667. }
  668. argc = ZEND_NUM_ARGS();
  669. args = safe_emalloc(argc, sizeof(zval), 0);
  670. if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) {
  671. efree(args);
  672. WRONG_PARAM_COUNT;
  673. }
  674. for (i = 0; i < argc; i++) {
  675. if (XINI_BASE(default_enable) == 0) {
  676. xdebug_php_var_dump(&args[i], 1);
  677. }
  678. else if (PG(html_errors)) {
  679. val = xdebug_get_zval_value_html(NULL, (zval*) &args[i], 0, NULL);
  680. PHPWRITE(val->d, val->l);
  681. xdebug_str_free(val);
  682. }
  683. else if ((XINI_BASE(cli_color) == 1 && xdebug_is_output_tty()) || (XINI_BASE(cli_color) == 2)) {
  684. val = xdebug_get_zval_value_ansi((zval*) &args[i], 0, NULL);
  685. PHPWRITE(val->d, val->l);
  686. xdebug_str_free(val);
  687. }
  688. else {
  689. val = xdebug_get_zval_value_text((zval*) &args[i], 0, NULL);
  690. PHPWRITE(val->d, val->l);
  691. xdebug_str_free(val);
  692. }
  693. }
  694. efree(args);
  695. }
  696. /* }}} */
  697. /* {{{ proto void xdebug_debug_zval(mixed var [, ...] )
  698. Outputs a fancy string representation of a variable */
  699. PHP_FUNCTION(xdebug_debug_zval)
  700. {
  701. zval *args;
  702. int argc;
  703. int i;
  704. xdebug_str *val;
  705. argc = ZEND_NUM_ARGS();
  706. args = safe_emalloc(argc, sizeof(zval), 0);
  707. if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) {
  708. efree(args);
  709. WRONG_PARAM_COUNT;
  710. }
  711. if (!(ZEND_CALL_INFO(EG(current_execute_data)->prev_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
  712. zend_rebuild_symbol_table();
  713. }
  714. for (i = 0; i < argc; i++) {
  715. if (Z_TYPE(args[i]) == IS_STRING) {
  716. zval debugzval;
  717. xdebug_str *tmp_name;
  718. xdebug_lib_set_active_symbol_table(EG(current_execute_data)->prev_execute_data->symbol_table);
  719. xdebug_lib_set_active_data(EG(current_execute_data)->prev_execute_data);
  720. tmp_name = xdebug_str_create(Z_STRVAL(args[i]), Z_STRLEN(args[i]));
  721. xdebug_get_php_symbol(&debugzval, tmp_name);
  722. xdebug_str_free(tmp_name);
  723. /* Reduce refcount for dumping */
  724. Z_TRY_DELREF(debugzval);
  725. php_printf("%s: ", Z_STRVAL(args[i]));
  726. if (Z_TYPE(debugzval) != IS_UNDEF) {
  727. if (PG(html_errors)) {
  728. val = xdebug_get_zval_value_html(NULL, &debugzval, 1, NULL);
  729. PHPWRITE(val->d, val->l);
  730. }
  731. else if ((XINI_BASE(cli_color) == 1 && xdebug_is_output_tty()) || (XINI_BASE(cli_color) == 2)) {
  732. val = xdebug_get_zval_value_ansi(&debugzval, 1, NULL);
  733. PHPWRITE(val->d, val->l);
  734. }
  735. else {
  736. val = xdebug_get_zval_value_line(&debugzval, 1, NULL);
  737. PHPWRITE(val->d, val->l);
  738. }
  739. xdfree(val);
  740. PHPWRITE("\n", 1);
  741. } else {
  742. PHPWRITE("no such symbol\n", 15);
  743. }
  744. /* Restore original refcount */
  745. Z_TRY_ADDREF(debugzval);
  746. zval_ptr_dtor_nogc(&debugzval);
  747. }
  748. }
  749. efree(args);
  750. }
  751. /* }}} */
  752. /* {{{ proto void xdebug_debug_zval_stdout(mixed var [, ...] )
  753. Outputs a fancy string representation of a variable */
  754. PHP_FUNCTION(xdebug_debug_zval_stdout)
  755. {
  756. zval *args;
  757. int argc;
  758. int i;
  759. argc = ZEND_NUM_ARGS();
  760. args = safe_emalloc(argc, sizeof(zval), 0);
  761. if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) {
  762. efree(args);
  763. WRONG_PARAM_COUNT;
  764. }
  765. if (!(ZEND_CALL_INFO(EG(current_execute_data)->prev_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
  766. zend_rebuild_symbol_table();
  767. }
  768. for (i = 0; i < argc; i++) {
  769. if (Z_TYPE(args[i]) == IS_STRING) {
  770. zval debugzval;
  771. xdebug_str *tmp_name;
  772. xdebug_str *val;
  773. xdebug_lib_set_active_symbol_table(EG(current_execute_data)->prev_execute_data->symbol_table);
  774. xdebug_lib_set_active_data(EG(current_execute_data)->prev_execute_data);
  775. tmp_name = xdebug_str_create(Z_STRVAL(args[i]), Z_STRLEN(args[i]));
  776. xdebug_get_php_symbol(&debugzval, tmp_name);
  777. xdebug_str_free(tmp_name);
  778. /* Reduce refcount for dumping */
  779. Z_TRY_DELREF(debugzval);
  780. printf("%s: ", Z_STRVAL(args[i]));
  781. if (Z_TYPE(debugzval) != IS_UNDEF) {
  782. val = xdebug_get_zval_value_line(&debugzval, 1, NULL);
  783. printf("%s(%zd)", val->d, val->l);
  784. xdebug_str_free(val);
  785. printf("\n");
  786. } else {
  787. printf("no such symbol\n\n");
  788. }
  789. /* Restore original refcount */
  790. Z_TRY_ADDREF(debugzval);
  791. zval_ptr_dtor_nogc(&debugzval);
  792. }
  793. }
  794. efree(args);
  795. }
  796. /* }}} */
  797. PHP_FUNCTION(xdebug_is_debugger_active)
  798. {
  799. RETURN_BOOL(xdebug_is_debug_connection_active());
  800. }
  801. PHP_FUNCTION(xdebug_start_error_collection)
  802. {
  803. if (XG_BASE(do_collect_errors) == 1) {
  804. php_error(E_NOTICE, "Error collection was already started");
  805. }
  806. XG_BASE(do_collect_errors) = 1;
  807. }
  808. PHP_FUNCTION(xdebug_stop_error_collection)
  809. {
  810. if (XG_BASE(do_collect_errors) == 0) {
  811. php_error(E_NOTICE, "Error collection was not started");
  812. }
  813. XG_BASE(do_collect_errors) = 0;
  814. }
  815. PHP_FUNCTION(xdebug_get_headers)
  816. {
  817. xdebug_llist_element *le;
  818. char *string;
  819. array_init(return_value);
  820. for (le = XDEBUG_LLIST_HEAD(XG_BASE(headers)); le != NULL; le = XDEBUG_LLIST_NEXT(le)) {
  821. string = XDEBUG_LLIST_VALP(le);
  822. add_next_index_string(return_value, string);
  823. }
  824. }
  825. PHP_FUNCTION(xdebug_memory_usage)
  826. {
  827. RETURN_LONG(zend_memory_usage(0));
  828. }
  829. PHP_FUNCTION(xdebug_peak_memory_usage)
  830. {
  831. RETURN_LONG(zend_memory_peak_usage(0));
  832. }
  833. PHP_FUNCTION(xdebug_time_index)
  834. {
  835. RETURN_DOUBLE(xdebug_get_utime() - XG_BASE(start_time));
  836. }
  837. ZEND_DLEXPORT void xdebug_statement_call(zend_execute_data *frame)
  838. {
  839. zend_op_array *op_array = &frame->func->op_array;
  840. int lineno;
  841. char *file;
  842. int file_len;
  843. if (!EG(current_execute_data)) {
  844. return;
  845. }
  846. lineno = EG(current_execute_data)->opline->lineno;
  847. file = (char*) STR_NAME_VAL(op_array->filename);
  848. file_len = STR_NAME_LEN(op_array->filename);
  849. xdebug_coverage_count_line_if_active(op_array, file, lineno);
  850. xdebug_debugger_statement_call(file, file_len, lineno);
  851. }
  852. ZEND_DLEXPORT int xdebug_zend_startup(zend_extension *extension)
  853. {
  854. /* Override header handler in SAPI */
  855. if (xdebug_orig_header_handler == NULL) {
  856. xdebug_orig_header_handler = sapi_module.header_handler;
  857. sapi_module.header_handler = xdebug_header_handler;
  858. }
  859. xdebug_debugger_zend_startup();
  860. zend_xdebug_initialised = 1;
  861. #if PHP_VERSION_ID >= 70300
  862. xdebug_orig_post_startup_cb = zend_post_startup_cb;
  863. zend_post_startup_cb = xdebug_post_startup;
  864. return zend_startup_module(&xdebug_module_entry);
  865. }
  866. static int xdebug_post_startup(void)
  867. {
  868. if (xdebug_orig_post_startup_cb) {
  869. int (*cb)(void) = xdebug_orig_post_startup_cb;
  870. xdebug_orig_post_startup_cb = NULL;
  871. if (cb() != SUCCESS) {
  872. return FAILURE;
  873. }
  874. }
  875. xdebug_base_post_startup();
  876. return SUCCESS;
  877. #else
  878. return zend_startup_module(&xdebug_module_entry);
  879. #endif
  880. }
  881. ZEND_DLEXPORT void xdebug_zend_shutdown(zend_extension *extension)
  882. {
  883. /* Restore original header handler in SAPI */
  884. sapi_module.header_handler = xdebug_orig_header_handler;
  885. xdebug_orig_header_handler = NULL;
  886. xdebug_debugger_zend_shutdown();
  887. }
  888. ZEND_DLEXPORT void xdebug_init_oparray(zend_op_array *op_array)
  889. {
  890. xdebug_coverage_init_oparray(op_array);
  891. }
  892. #ifndef ZEND_EXT_API
  893. #define ZEND_EXT_API ZEND_DLEXPORT
  894. #endif
  895. ZEND_EXT_API zend_extension_version_info extension_version_info = { ZEND_EXTENSION_API_NO, (char*) ZEND_EXTENSION_BUILD_ID };
  896. ZEND_DLEXPORT zend_extension zend_extension_entry = {
  897. (char*) XDEBUG_NAME,
  898. (char*) XDEBUG_VERSION,
  899. (char*) XDEBUG_AUTHOR,
  900. (char*) XDEBUG_URL_FAQ,
  901. (char*) XDEBUG_COPYRIGHT_SHORT,
  902. xdebug_zend_startup,
  903. xdebug_zend_shutdown,
  904. NULL, /* activate_func_t */
  905. NULL, /* deactivate_func_t */
  906. NULL, /* message_handler_func_t */
  907. NULL, /* op_array_handler_func_t */
  908. xdebug_statement_call, /* statement_handler_func_t */
  909. NULL, /* fcall_begin_handler_func_t */
  910. NULL, /* fcall_end_handler_func_t */
  911. xdebug_init_oparray, /* op_array_ctor_func_t */
  912. NULL, /* op_array_dtor_func_t */
  913. STANDARD_ZEND_EXTENSION_PROPERTIES
  914. };
  915. #endif