Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 640 lines (550 sloc) 21.475 kB
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
1 /*
2 +----------------------------------------------------------------------+
b66d5be @derickr - Licence update. This change only renames "PHP Licence" to "Xdebug L…
authored
3 | Xdebug |
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
4 +----------------------------------------------------------------------+
05871b5 @derickr - Happy 2010!
authored
5 | Copyright (c) 2002-2010 Derick Rethans |
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
6 +----------------------------------------------------------------------+
b66d5be @derickr - Licence update. This change only renames "PHP Licence" to "Xdebug L…
authored
7 | This source file is subject to version 1.0 of the Xdebug license, |
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
8 | that is bundled with this package in the file LICENSE, and is |
9 | available at through the world-wide-web at |
b66d5be @derickr - Licence update. This change only renames "PHP Licence" to "Xdebug L…
authored
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. |
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
14 +----------------------------------------------------------------------+
637bd81 @derickr - Email update
authored
15 | Authors: Derick Rethans <derick@xdebug.org> |
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
16 +----------------------------------------------------------------------+
17 */
18
19 #include "php_xdebug.h"
e37efa4 @derickr - DBGp: remove breakpoint_disable/breakpoint_enable and add breakpoin…
authored
20 #include "xdebug_private.h"
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
21 #include "xdebug_set.h"
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
22 #include "xdebug_var.h"
23 #include "xdebug_code_coverage.h"
459e351 @derickr - Fixed TSRM issues for PHP 5.2 and PHP 5.3. (Original patch by Eliza…
authored
24 #include "xdebug_compat.h"
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
25 #include "xdebug_tracing.h"
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
26
b06b349 @derickr - Fix problems with symbols on MacOSX
authored
27 extern ZEND_DECLARE_MODULE_GLOBALS(xdebug);
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
28
29 void xdebug_coverage_line_dtor(void *data)
30 {
31 xdebug_coverage_line *line = (xdebug_coverage_line *) data;
32
33 xdfree(line);
34 }
35
36 void xdebug_coverage_file_dtor(void *data)
37 {
38 xdebug_coverage_file *file = (xdebug_coverage_file *) data;
39
40 xdebug_hash_destroy(file->lines);
41 xdfree(file->name);
42 xdfree(file);
43 }
44
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
45 #define XDEBUG_OPCODE_OVERRIDE(f) \
46 int xdebug_##f##_handler(ZEND_OPCODE_HANDLER_ARGS) \
47 { \
48 return xdebug_common_override_handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \
49 }
50
51
52 int xdebug_common_override_handler(ZEND_OPCODE_HANDLER_ARGS)
53 {
54 if (XG(do_code_coverage)) {
55 zend_op *cur_opcode;
56 int lineno;
57 char *file;
58
59 zend_op_array *op_array = execute_data->op_array;
60
61 cur_opcode = *EG(opline_ptr);
62 lineno = cur_opcode->lineno;
63
64 file = op_array->filename;
65
66 xdebug_count_line(file, lineno, 0, 0 TSRMLS_CC);
67 }
68 return ZEND_USER_OPCODE_DISPATCH;
69 }
70
71 static char *xdebug_find_var_name(zend_execute_data *execute_data TSRMLS_DC)
72 {
73 zend_op *cur_opcode, *next_opcode, *prev_opcode = NULL, *opcode_ptr;
74 zval *dimval;
75 int is_var, cv_len;
76 zend_op_array *op_array = execute_data->op_array;
77 xdebug_str name = {0, 0, NULL};
78 int gohungfound = 0, is_static = 0;
79 char *zval_value = NULL;
80 xdebug_var_export_options *options;
81
82 cur_opcode = *EG(opline_ptr);
83 next_opcode = cur_opcode + 1;
84 prev_opcode = cur_opcode - 1;
85
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
86 if (cur_opcode->XDEBUG_TYPE(op1) == IS_VAR &&
87 (next_opcode->XDEBUG_TYPE(op1) == IS_VAR || cur_opcode->XDEBUG_TYPE(op2) == IS_VAR) &&
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
88 prev_opcode->opcode == ZEND_FETCH_RW &&
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
89 prev_opcode->XDEBUG_TYPE(op1) == IS_CONST &&
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
90 #if PHP_VERSION_ID >= 50399
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
91 Z_TYPE_P(prev_opcode->op1.zv) == IS_STRING
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
92 #else
93 prev_opcode->op1.u.constant.type == IS_STRING
94 #endif
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
95 ) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
96 #if PHP_VERSION_ID >= 50399
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
97 xdebug_str_add(&name, xdebug_sprintf("$%s", Z_STRVAL_P(prev_opcode->op1.zv)), 1);
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
98 #else
99 xdebug_str_add(&name, xdebug_sprintf("$%s", prev_opcode->op1.u.constant.value.str.val), 1);
100 #endif
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
101 }
102
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
103 is_static = (prev_opcode->XDEBUG_TYPE(op1) == IS_CONST && prev_opcode->XDEBUG_EXTENDED_VALUE(op2) == ZEND_FETCH_STATIC_MEMBER);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
104 options = xdebug_var_export_options_from_ini(TSRMLS_C);
105 options->no_decoration = 1;
106
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
107 if (cur_opcode->XDEBUG_TYPE(op1) == IS_CV) {
108 xdebug_str_add(&name, xdebug_sprintf("$%s", zend_get_compiled_variable_name(op_array, cur_opcode->XDEBUG_ZNODE_ELEM(op1, var), &cv_len)), 1);
109 } else if (cur_opcode->XDEBUG_TYPE(op1) == IS_VAR && cur_opcode->opcode == ZEND_ASSIGN && prev_opcode->opcode == ZEND_FETCH_W) {
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
110 if (is_static) {
111 xdebug_str_add(&name, xdebug_sprintf("self::"), 1);
112 } else {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
113 zval_value = xdebug_get_zval_value(xdebug_get_zval(execute_data, prev_opcode->XDEBUG_TYPE(op1), &prev_opcode->op1, execute_data->Ts, &is_var), 0, options);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
114 xdebug_str_add(&name, xdebug_sprintf("$%s", zval_value), 1);
115 }
116 } else if (is_static) { // todo : see if you can change this and the previous cases around
117 xdebug_str_add(&name, xdebug_sprintf("self::"), 1 );
118 }
119 if (cur_opcode->opcode >= ZEND_ASSIGN_ADD && cur_opcode->opcode <= ZEND_ASSIGN_BW_XOR ) {
120 if (cur_opcode->extended_value == ZEND_ASSIGN_OBJ) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
121 zval_value = xdebug_get_zval_value(xdebug_get_zval(execute_data, cur_opcode->XDEBUG_TYPE(op2), &cur_opcode->op2, execute_data->Ts, &is_var), 0, options);
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
122 if (cur_opcode->XDEBUG_TYPE(op1) == IS_UNUSED) {
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
123 xdebug_str_add(&name, xdebug_sprintf("$this->%s", zval_value), 1);
124 } else {
125 xdebug_str_add(&name, xdebug_sprintf("->%s", zval_value), 1);
126 }
127 } else if (cur_opcode->extended_value == ZEND_ASSIGN_DIM) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
128 zval_value = xdebug_get_zval_value(xdebug_get_zval(execute_data, cur_opcode->XDEBUG_TYPE(op2), &cur_opcode->op2, execute_data->Ts, &is_var), 0, NULL);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
129 xdebug_str_add(&name,xdebug_sprintf("[%s]", zval_value), 1);
130 }
131 }
132 if (zval_value) {
133 xdfree(zval_value);
134 zval_value = NULL;
135 }
136
137 /* Scroll back to start of FETCHES */
138 gohungfound = 0;
139 opcode_ptr = prev_opcode;
140 while (opcode_ptr->opcode == ZEND_FETCH_DIM_W || opcode_ptr->opcode == ZEND_FETCH_OBJ_W || opcode_ptr->opcode == ZEND_FETCH_W) {
141 opcode_ptr = opcode_ptr - 1;
142 gohungfound = 1;
143 }
144 opcode_ptr = opcode_ptr + 1;
145
146 if (gohungfound) {
147 do
148 {
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
149 if (opcode_ptr->XDEBUG_TYPE(op1) == IS_UNUSED && opcode_ptr->opcode == ZEND_FETCH_OBJ_W) {
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
150 xdebug_str_add(&name, "$this", 0);
151 }
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
152 if (opcode_ptr->XDEBUG_TYPE(op1) == IS_CV) {
153 xdebug_str_add(&name, xdebug_sprintf("$%s", zend_get_compiled_variable_name(op_array, opcode_ptr->XDEBUG_ZNODE_ELEM(op1, var), &cv_len)), 1);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
154 }
155 if (opcode_ptr->opcode == ZEND_FETCH_W) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
156 zval_value = xdebug_get_zval_value(xdebug_get_zval(execute_data, opcode_ptr->XDEBUG_TYPE(op1), &opcode_ptr->op1, execute_data->Ts, &is_var), 0, options);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
157 xdebug_str_add(&name, xdebug_sprintf("%s", zval_value), 1);
158 }
159 if (opcode_ptr->opcode == ZEND_FETCH_DIM_W) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
160 zval_value = xdebug_get_zval_value(xdebug_get_zval(execute_data, opcode_ptr->XDEBUG_TYPE(op2), &opcode_ptr->op2, execute_data->Ts, &is_var), 0, NULL);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
161 xdebug_str_add(&name, xdebug_sprintf("[%s]", zval_value), 1);
162 } else if (opcode_ptr->opcode == ZEND_FETCH_OBJ_W) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
163 zval_value = xdebug_get_zval_value(xdebug_get_zval(execute_data, opcode_ptr->XDEBUG_TYPE(op2), &opcode_ptr->op2, execute_data->Ts, &is_var), 0, options);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
164 xdebug_str_add(&name, xdebug_sprintf("->%s", zval_value), 1);
165 }
166 opcode_ptr = opcode_ptr + 1;
167 if (zval_value) {
168 xdfree(zval_value);
169 zval_value = NULL;
170 }
171 } while (opcode_ptr->opcode == ZEND_FETCH_DIM_W || opcode_ptr->opcode == ZEND_FETCH_OBJ_W || opcode_ptr->opcode == ZEND_FETCH_W);
172 }
173
174 if (cur_opcode->opcode == ZEND_ASSIGN_OBJ) {
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
175 if (cur_opcode->XDEBUG_TYPE(op1) == IS_UNUSED) {
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
176 xdebug_str_add(&name, "$this", 0);
177 }
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
178 dimval = xdebug_get_zval(execute_data, cur_opcode->XDEBUG_TYPE(op2), &cur_opcode->op2, execute_data->Ts, &is_var);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
179 xdebug_str_add(&name, xdebug_sprintf("->%s", Z_STRVAL_P(dimval)), 1);
180 }
181
182 if (cur_opcode->opcode == ZEND_ASSIGN_DIM) {
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
183 if (next_opcode->opcode == ZEND_OP_DATA && cur_opcode->XDEBUG_TYPE(op2) == IS_UNUSED) {
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
184 xdebug_str_add(&name, "[]", 0);
185 } else {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
186 zval_value = xdebug_get_zval_value(xdebug_get_zval(execute_data, opcode_ptr->XDEBUG_TYPE(op2), &opcode_ptr->op2, execute_data->Ts, &is_var), 0, NULL);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
187 xdebug_str_add(&name, xdebug_sprintf("[%s]", zval_value), 1);
188 xdfree(zval_value);
189 }
190 }
191
192 xdfree(options->runtime);
193 xdfree(options);
194
195 return name.d;
196 }
197
198 static int xdebug_common_assign_dim_handler(char *op, int do_cc, ZEND_OPCODE_HANDLER_ARGS)
199 {
200 char *file;
201 zend_op_array *op_array = execute_data->op_array;
202 int lineno;
203 zend_op *cur_opcode, *next_opcode;
204 char *full_varname;
205 zval *val = NULL;
206 char *t;
207 int is_var;
208 function_stack_entry *fse;
209
210 cur_opcode = *EG(opline_ptr);
211 next_opcode = cur_opcode + 1;
212 file = op_array->filename;
213 lineno = cur_opcode->lineno;
214
215 if (do_cc && XG(do_code_coverage)) {
216 xdebug_count_line(file, lineno, 0, 0 TSRMLS_CC);
217 }
218 if (XG(do_trace) && XG(trace_file) && XG(collect_assignments)) {
219 full_varname = xdebug_find_var_name(execute_data TSRMLS_CC);
220
221 if (cur_opcode->opcode >= ZEND_PRE_INC && cur_opcode->opcode <= ZEND_POST_DEC) {
222 char *tmp_varname;
223
224 switch (cur_opcode->opcode) {
225 case ZEND_PRE_INC: tmp_varname = xdebug_sprintf("++%s", full_varname); break;
226 case ZEND_POST_INC: tmp_varname = xdebug_sprintf("%s++", full_varname); break;
227 case ZEND_PRE_DEC: tmp_varname = xdebug_sprintf("--%s", full_varname); break;
228 case ZEND_POST_DEC: tmp_varname = xdebug_sprintf("%s--", full_varname); break;
229 }
230 xdfree(full_varname);
231 full_varname = tmp_varname;
232
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
233 val = xdebug_get_zval(execute_data, cur_opcode->XDEBUG_TYPE(op1), &cur_opcode->op1, execute_data->Ts, &is_var);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
234 } else if (next_opcode->opcode == ZEND_OP_DATA) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
235 val = xdebug_get_zval(execute_data, next_opcode->XDEBUG_TYPE(op1), &next_opcode->op1, execute_data->Ts, &is_var);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
236 } else {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
237 val = xdebug_get_zval(execute_data, cur_opcode->XDEBUG_TYPE(op2), &cur_opcode->op2, execute_data->Ts, &is_var);
c6f939b @derickr - Refactor to make the xdebug.c file a lot smaller. Stack related fun…
authored
238 }
239
240 fse = XDEBUG_LLIST_VALP(XDEBUG_LLIST_TAIL(XG(stack)));
241 t = xdebug_return_trace_assignment(fse, full_varname, val, op, file, lineno TSRMLS_CC);
242 xdfree(full_varname);
243 fprintf(XG(trace_file), "%s", t);
244 fflush(XG(trace_file));
245 xdfree(t);
246 }
247 return ZEND_USER_OPCODE_DISPATCH;
248 }
249
250 #define XDEBUG_OPCODE_OVERRIDE_ASSIGN(f,o,cc) \
251 int xdebug_##f##_handler(ZEND_OPCODE_HANDLER_ARGS) \
252 { \
253 return xdebug_common_assign_dim_handler((o), (cc), ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \
254 }
255
256 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign,"=",1)
257 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_add,"+=",0)
258 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_sub,"-=",0)
259 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_mul,"*=",0)
260 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_div,"/=",0)
261 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_mod,"%=",0)
262 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_sl,"<<=",0)
263 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_sr,">>=",0)
264 XDEBUG_OPCODE_OVERRIDE_ASSIGN(pre_inc,"",0)
265 XDEBUG_OPCODE_OVERRIDE_ASSIGN(post_inc,"",0)
266 XDEBUG_OPCODE_OVERRIDE_ASSIGN(pre_dec,"",0)
267 XDEBUG_OPCODE_OVERRIDE_ASSIGN(post_dec,"",0)
268 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_concat,".=",1)
269 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_bw_or,"|=",0)
270 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_bw_and,"&=",0)
271 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_bw_xor,"^=",0)
272 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_dim,"=",1)
273 XDEBUG_OPCODE_OVERRIDE_ASSIGN(assign_obj,"=",1)
274
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
275 void xdebug_count_line(char *filename, int lineno, int executable, int deadcode TSRMLS_DC)
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
276 {
277 xdebug_coverage_file *file;
278 xdebug_coverage_line *line;
279 char *sline;
280
281 sline = xdebug_sprintf("%d", lineno);
282
283 /* Check if the file already exists in the hash */
284 if (!xdebug_hash_find(XG(code_coverage), filename, strlen(filename), (void *) &file)) {
285 /* The file does not exist, so we add it to the hash, and
286 * add a line element to the file */
287 file = xdmalloc(sizeof(xdebug_coverage_file));
288 file->name = xdstrdup(filename);
289 file->lines = xdebug_hash_alloc(128, xdebug_coverage_line_dtor);
290
291 xdebug_hash_add(XG(code_coverage), filename, strlen(filename), file);
292 }
293
294 /* Check if the line already exists in the hash */
295 if (!xdebug_hash_find(file->lines, sline, strlen(sline), (void *) &line)) {
296 line = xdmalloc(sizeof(xdebug_coverage_line));
297 line->lineno = lineno;
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
298 line->count = 0;
299 line->executable = 0;
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
300
301 xdebug_hash_add(file->lines, sline, strlen(sline), line);
302 }
303
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
304 if (executable) {
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
305 if (line->executable != 1 && deadcode) {
306 line->executable = 2;
307 } else {
308 line->executable = 1;
309 }
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
310 } else {
311 line->count++;
312 }
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
313
314 xdfree(sline);
315 }
316
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
317 static void prefill_from_opcode(char *fn, zend_op opcode, int deadcode TSRMLS_DC)
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
318 {
645cef8 @derickr - More tweaks for code coverage.
authored
319 if (
320 opcode.opcode != ZEND_NOP &&
321 opcode.opcode != ZEND_EXT_NOP &&
322 opcode.opcode != ZEND_RECV &&
95b4d91 @derickr - PHP 4.x doesn't have VERIFY_ABSTRACT_CLASS.
authored
323 opcode.opcode != ZEND_RECV_INIT
324 && opcode.opcode != ZEND_VERIFY_ABSTRACT_CLASS
a93ea9a @derickr - Overload some more opcodes
authored
325 && opcode.opcode != ZEND_OP_DATA
0e026cc @derickr - Ignore ZEND_ADD_INTERFACE, which is on a different line in PHP >= 5…
authored
326 && opcode.opcode != ZEND_ADD_INTERFACE
8057136 @derickr - Fixed bug #515: declare(ticks) statement confuses code coverage.
authored
327 && opcode.opcode != ZEND_TICKS
645cef8 @derickr - More tweaks for code coverage.
authored
328 ) {
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
329 xdebug_count_line(fn, opcode.lineno, 1, deadcode TSRMLS_CC);
83aeec7 @derickr - Suppress NOP/EXT_NOP from being marked as executable code with Code
authored
330 }
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
331 }
332
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
333 static zend_brk_cont_element* xdebug_find_brk_cont(zval *nest_levels_zval, int array_offset, zend_op_array *op_array)
334 {
335 int nest_levels;
336 zend_brk_cont_element *jmp_to;
337
338 nest_levels = nest_levels_zval->value.lval;
339
340 do {
341 jmp_to = &op_array->brk_cont_array[array_offset];
342 array_offset = jmp_to->parent;
343 } while (--nest_levels > 0);
344 return jmp_to;
345 }
346
7394eff @derickr - Fixed code coverage dead-code detection.
authored
347 static int xdebug_find_jump(zend_op_array *opa, unsigned int position, long *jmp1, long *jmp2)
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
348 {
c6751c2 @derickr - Fixed bug #334: Code Coverage Regressions.
authored
349 zend_op *base_address = &(opa->opcodes[0]);
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
350
351 zend_op opcode = opa->opcodes[position];
352 if (opcode.opcode == ZEND_JMP) {
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
353 *jmp1 = ((long) opcode.XDEBUG_ZNODE_ELEM(op1, jmp_addr) - (long) base_address) / sizeof(zend_op);
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
354 return 1;
355 } else if (
356 opcode.opcode == ZEND_JMPZ ||
357 opcode.opcode == ZEND_JMPNZ ||
358 opcode.opcode == ZEND_JMPZ_EX ||
359 opcode.opcode == ZEND_JMPNZ_EX
360 ) {
361 *jmp1 = position + 1;
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
362 *jmp2 = ((long) opcode.XDEBUG_ZNODE_ELEM(op2, jmp_addr) - (long) base_address) / sizeof(zend_op);
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
363 return 1;
364 } else if (opcode.opcode == ZEND_JMPZNZ) {
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
365 *jmp1 = opcode.XDEBUG_ZNODE_ELEM(op2, opline_num);
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
366 *jmp2 = opcode.extended_value;
367 return 1;
368 } else if (opcode.opcode == ZEND_BRK || opcode.opcode == ZEND_CONT) {
369 zend_brk_cont_element *el;
370
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
371 if (opcode.XDEBUG_TYPE(op2) == IS_CONST
372 && opcode.XDEBUG_ZNODE_ELEM(op1, jmp_addr) != (zend_op*) 0xFFFFFFFF
9ce7174 @mixedpuppy - fix xdebug builds against 4.4.
mixedpuppy authored
373 ) {
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
374 #if PHP_VERSION_ID >= 50399
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
375 el = xdebug_find_brk_cont(opcode.op2.zv, opcode.XDEBUG_ZNODE_ELEM(op1, opline_num), opa);
1ef642b @derickr - Make things compile with PHP 5.3 again.
authored
376 #else
377 el = xdebug_find_brk_cont(&opcode.op2.u.constant, opcode.op1.u.opline_num, opa);
378 #endif
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
379 *jmp1 = opcode.opcode == ZEND_BRK ? el->brk : el->cont;
380 return 1;
381 }
404fceb @derickr - The foreach loop contruct contains some jump information as well.
authored
382 } else if (opcode.opcode == ZEND_FE_RESET || opcode.opcode == ZEND_FE_FETCH) {
383 *jmp1 = position + 1;
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
384 *jmp2 = opcode.XDEBUG_ZNODE_ELEM(op2, opline_num);
404fceb @derickr - The foreach loop contruct contains some jump information as well.
authored
385 return 1;
08e5fed @derickr - Fixed bug #470: catch blocks marked as dead code unless executed.
authored
386 #if (PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3)
387 } else if (opcode.opcode == ZEND_GOTO) {
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
388 *jmp1 = ((long) opcode.XDEBUG_ZNODE_ELEM(op1, jmp_addr) - (long) base_address) / sizeof(zend_op);
08e5fed @derickr - Fixed bug #470: catch blocks marked as dead code unless executed.
authored
389 return 1;
390 #endif
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
391 }
392 return 0;
393 }
394
971289b @derickr - Fixed TSRMLS issues.
authored
395 static void xdebug_analyse_branch(zend_op_array *opa, unsigned int position, xdebug_set *set TSRMLS_DC)
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
396 {
b46dc45 @derickr - Added support for PHP 5.3 and local variables for debugging.
authored
397 long jump_pos1;
398 long jump_pos2;
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
399
400 /*(fprintf(stderr, "Branch analysis from position: %d\n", position);)*/
401 /* First we see if the branch has been visited, if so we bail out. */
402 if (xdebug_set_in(set, position)) {
403 return;
404 }
405 /* Loop over the opcodes until the end of the array, or until a jump point has been found */
406 xdebug_set_add(set, position);
407 /*(fprintf(stderr, "XDEBUG Adding %d\n", position);)*/
d8fe724 @derickr - Fixed issues with code coverage crashing on parse errors.
authored
408 while (position < opa->last) {
b46dc45 @derickr - Added support for PHP 5.3 and local variables for debugging.
authored
409 jump_pos1 = -1;
410 jump_pos2 = -1;
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
411
412 /* See if we have a jump instruction */
413 if (xdebug_find_jump(opa, position, &jump_pos1, &jump_pos2)) {
036ed7f @derickr - Remove debug information that accidently slipped in.
authored
414 /*(fprintf(stderr, "XDEBUG Jump found. Position 1 = %d", jump_pos1);)*/
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
415 if (jump_pos2 != -1) {
036ed7f @derickr - Remove debug information that accidently slipped in.
authored
416 /*(fprintf(stderr, ", Position 2 = %d\n", jump_pos2))*/;
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
417 } else {
036ed7f @derickr - Remove debug information that accidently slipped in.
authored
418 /*(fprintf(stderr, "\n"))*/;
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
419 }
3390716 @derickr - More TSRMLS issues.
authored
420 xdebug_analyse_branch(opa, jump_pos1, set TSRMLS_CC);
d8fe724 @derickr - Fixed issues with code coverage crashing on parse errors.
authored
421 if (jump_pos2 != -1 && jump_pos2 <= opa->last) {
3390716 @derickr - More TSRMLS issues.
authored
422 xdebug_analyse_branch(opa, jump_pos2, set TSRMLS_CC);
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
423 }
424 break;
425 }
c18ee1e @derickr - Ripped out support for PHP 4 and PHP 5.0.
authored
426
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
427 /* See if we have a throw instruction */
428 if (opa->opcodes[position].opcode == ZEND_THROW) {
a8c0524 @derickr - Fixed dead code analysis for THROW.
authored
429 /* fprintf(stderr, "Throw found at %d\n", position); */
08e5fed @derickr - Fixed bug #470: catch blocks marked as dead code unless executed.
authored
430 break;
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
431 }
c18ee1e @derickr - Ripped out support for PHP 4 and PHP 5.0.
authored
432
a8c0524 @derickr - Fixed dead code analysis for THROW.
authored
433 /* See if we have an exit instruction */
434 if (opa->opcodes[position].opcode == ZEND_EXIT) {
435 /* fprintf(stderr, "X* Return found\n"); */
436 break;
437 }
438 /* See if we have a return instruction */
439 if (opa->opcodes[position].opcode == ZEND_RETURN) {
440 /*(fprintf(stderr, "XDEBUG Return found\n");)*/
441 break;
442 }
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
443
444 position++;
445 /*(fprintf(stderr, "XDEBUG Adding %d\n", position);)*/
446 xdebug_set_add(set, position);
447 }
448 }
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
449
08e5fed @derickr - Fixed bug #470: catch blocks marked as dead code unless executed.
authored
450 static void xdebug_analyse_oparray(zend_op_array *opa, xdebug_set *set TSRMLS_DC)
451 {
452 unsigned int position = 0;
453
454 while (position < opa->last) {
455 if (position == 0) {
456 xdebug_analyse_branch(opa, position, set TSRMLS_CC);
457 } else if (opa->opcodes[position].opcode == ZEND_CATCH) {
458 xdebug_analyse_branch(opa, position, set TSRMLS_CC);
459 }
460 position++;
461 }
462 }
463
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
464 static void prefill_from_oparray(char *fn, zend_op_array *op_array TSRMLS_DC)
3895cb1 @derickr - Improve code coverage by eliminating unreachable code for:
authored
465 {
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
466 unsigned int i;
467 xdebug_set *set = NULL;
3895cb1 @derickr - Improve code coverage by eliminating unreachable code for:
authored
468
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
469 op_array->reserved[XG(reserved_offset)] = (void*) 1;
831e38b @derickr - Fixed oparray prefill caching for code coverage.
authored
470
3895cb1 @derickr - Improve code coverage by eliminating unreachable code for:
authored
471 /* Check for abstract methods and simply return from this function in those
472 * cases. */
e7785f9 @derickr - Fixed abstract method detection.
authored
473 #if PHP_VERSION_ID >= 50300
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
474 if (op_array->last >= 3 && op_array->opcodes[op_array->last - 3].opcode == ZEND_RAISE_ABSTRACT_ERROR)
e7785f9 @derickr - Fixed abstract method detection.
authored
475 #else
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
476 if (op_array->last >= 4 && op_array->opcodes[op_array->last - 4].opcode == ZEND_RAISE_ABSTRACT_ERROR)
e7785f9 @derickr - Fixed abstract method detection.
authored
477 #endif
3895cb1 @derickr - Improve code coverage by eliminating unreachable code for:
authored
478 {
479 return;
480 }
481
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
482 /* Run dead code analysis if requested */
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
483 if (XG(code_coverage_dead_code_analysis) && XDEBUG_PASS_TWO_DONE) {
484 set = xdebug_set_create(op_array->last);
485 xdebug_analyse_oparray(op_array, set TSRMLS_CC);
3895cb1 @derickr - Improve code coverage by eliminating unreachable code for:
authored
486 }
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
487
488 /* The normal loop then finally */
413d88b @derickr - Trunk (5.4) support (minus output catching for DBGp).
authored
489 for (i = 0; i < op_array->last; i++) {
490 zend_op opcode = op_array->opcodes[i];
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
491 prefill_from_opcode(fn, opcode, set ? !xdebug_set_in(set, i) : 0 TSRMLS_CC);
3895cb1 @derickr - Improve code coverage by eliminating unreachable code for:
authored
492 }
493
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
494 if (set) {
495 xdebug_set_free(set);
3895cb1 @derickr - Improve code coverage by eliminating unreachable code for:
authored
496 }
497 }
498
459e351 @derickr - Fixed TSRM issues for PHP 5.2 and PHP 5.3. (Original patch by Eliza…
authored
499 static int prefill_from_function_table(zend_op_array *opa XDEBUG_ZEND_HASH_APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
de8deed @derickr - Fixed bug #107: Code Coverage only detects executable code in used …
authored
500 {
501 char *new_filename;
459e351 @derickr - Fixed TSRM issues for PHP 5.2 and PHP 5.3. (Original patch by Eliza…
authored
502 #if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
047bcee @derickr - Make it compile on Windows again. (Thanks to Marcus Börger)
authored
503 TSRMLS_FETCH();
459e351 @derickr - Fixed TSRM issues for PHP 5.2 and PHP 5.3. (Original patch by Eliza…
authored
504 #endif
de8deed @derickr - Fixed bug #107: Code Coverage only detects executable code in used …
authored
505
506 new_filename = va_arg(args, char*);
507 if (opa->type == ZEND_USER_FUNCTION) {
8238638 @derickr - Fixed bug #418: compilation breaks with CodeWarrior for NetWare.
authored
508 if (opa->reserved[XG(reserved_offset)] != (void*) 1 /* && opa->filename && strcmp(opa->filename, new_filename) == 0)*/) {
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
509 prefill_from_oparray(opa->filename, opa TSRMLS_CC);
de8deed @derickr - Fixed bug #107: Code Coverage only detects executable code in used …
authored
510 }
511 }
512
513 return ZEND_HASH_APPLY_KEEP;
514 }
515
459e351 @derickr - Fixed TSRM issues for PHP 5.2 and PHP 5.3. (Original patch by Eliza…
authored
516 static int prefill_from_class_table(zend_class_entry **class_entry XDEBUG_ZEND_HASH_APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
de8deed @derickr - Fixed bug #107: Code Coverage only detects executable code in used …
authored
517 {
518 char *new_filename;
519 zend_class_entry *ce;
520
521 ce = *class_entry;
522
523 new_filename = va_arg(args, char*);
524 if (ce->type == ZEND_USER_CLASS) {
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
525 if (!(ce->ce_flags & ZEND_XDEBUG_VISITED)) {
526 ce->ce_flags |= ZEND_XDEBUG_VISITED;
459e351 @derickr - Fixed TSRM issues for PHP 5.2 and PHP 5.3. (Original patch by Eliza…
authored
527 zend_hash_apply_with_arguments(&ce->function_table XDEBUG_ZEND_HASH_APPLY_TSRMLS_CC, (apply_func_args_t) prefill_from_function_table, 1, new_filename);
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
528 }
de8deed @derickr - Fixed bug #107: Code Coverage only detects executable code in used …
authored
529 }
530
531 return ZEND_HASH_APPLY_KEEP;
532 }
533
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
534 void xdebug_prefill_code_coverage(zend_op_array *op_array TSRMLS_DC)
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
535 {
8238638 @derickr - Fixed bug #418: compilation breaks with CodeWarrior for NetWare.
authored
536 if (op_array->reserved[XG(reserved_offset)] != (void*) 1) {
9e76e80 @derickr - MF20: Improve code coverage gathering performace by 1000%.
authored
537 prefill_from_oparray(op_array->filename, op_array TSRMLS_CC);
538 }
de8deed @derickr - Fixed bug #107: Code Coverage only detects executable code in used …
authored
539
459e351 @derickr - Fixed TSRM issues for PHP 5.2 and PHP 5.3. (Original patch by Eliza…
authored
540 zend_hash_apply_with_arguments(CG(function_table) XDEBUG_ZEND_HASH_APPLY_TSRMLS_CC, (apply_func_args_t) prefill_from_function_table, 1, op_array->filename);
541 zend_hash_apply_with_arguments(CG(class_table) XDEBUG_ZEND_HASH_APPLY_TSRMLS_CC, (apply_func_args_t) prefill_from_class_table, 1, op_array->filename);
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
542 }
543
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
544 PHP_FUNCTION(xdebug_start_code_coverage)
545 {
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
546 long options = 0;
547
548 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &options) == FAILURE) {
549 return;
550 }
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
551 XG(code_coverage_unused) = (options & XDEBUG_CC_OPTION_UNUSED);
552 XG(code_coverage_dead_code_analysis) = (options & XDEBUG_CC_OPTION_DEAD_CODE);
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
553
b1efad6 @derickr - Removed profiler code, and lay foundation for new code.
authored
554 if (XG(extended_info)) {
48a99f0 @derickr - Added return values for xdebug_start_code_coverage() and
authored
555 RETVAL_BOOL(!XG(do_code_coverage));
b1efad6 @derickr - Removed profiler code, and lay foundation for new code.
authored
556 XG(do_code_coverage) = 1;
557 } else {
558 php_error(E_WARNING, "You can only use code coverage when you leave the setting of 'xdebug.extended_info' to the default '1'.");
48a99f0 @derickr - Added return values for xdebug_start_code_coverage() and
authored
559 RETVAL_BOOL(0);
b1efad6 @derickr - Removed profiler code, and lay foundation for new code.
authored
560 }
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
561 }
562
563 PHP_FUNCTION(xdebug_stop_code_coverage)
564 {
7911345 @derickr - xdebug_code_coverage_stop() will now clean up the code coverage arr…
authored
565 long cleanup = 1;
566
567 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &cleanup) == FAILURE) {
568 return;
569 }
8d6392a @derickr - Override some more opcodes as there is not always EXT_STMT when you…
authored
570 if (XG(do_code_coverage)) {
571 if (cleanup) {
572 xdebug_hash_destroy(XG(code_coverage));
573 XG(code_coverage) = xdebug_hash_alloc(32, xdebug_coverage_file_dtor);
574 }
575 XG(do_code_coverage) = 0;
48a99f0 @derickr - Added return values for xdebug_start_code_coverage() and
authored
576 RETURN_TRUE;
7911345 @derickr - xdebug_code_coverage_stop() will now clean up the code coverage arr…
authored
577 }
48a99f0 @derickr - Added return values for xdebug_start_code_coverage() and
authored
578 RETURN_FALSE;
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
579 }
580
581
582 static int xdebug_lineno_cmp(const void *a, const void *b TSRMLS_DC)
583 {
584 Bucket *f = *((Bucket **) a);
585 Bucket *s = *((Bucket **) b);
586
587 if (f->h < s->h) {
588 return -1;
589 } else if (f->h > s->h) {
590 return 1;
591 } else {
592 return 0;
593 }
594 }
595
596
597 static void add_line(void *ret, xdebug_hash_element *e)
598 {
599 xdebug_coverage_line *line = (xdebug_coverage_line*) e->ptr;
600 zval *retval = (zval*) ret;
601
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
602 if (line->executable && (line->count == 0)) {
2bca68e @derickr - Implemented dead code analysis that should give much better code co…
authored
603 add_index_long(retval, line->lineno, -line->executable);
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
604 } else {
8d6392a @derickr - Override some more opcodes as there is not always EXT_STMT when you…
authored
605 add_index_long(retval, line->lineno, 1);
df2814b @derickr - Fixed the exit handler hook to use the new "5.1" way of handling it…
authored
606 }
72bcfe1 @derickr - Added code coverage, enable with xdebug_start_code_coverage(), disa…
authored
607 }
608
609 static void add_file(void *ret, xdebug_hash_element *e)
610 {
611 xdebug_coverage_file *file = (xdebug_coverage_file*) e->ptr;
612 zval *retval = (zval*) ret;
613 zval *lines;
614 HashTable *target_hash;
615 TSRMLS_FETCH();
616
617 MAKE_STD_ZVAL(lines);
618 array_init(lines);
619
620 /* Add all the lines */
621 xdebug_hash_apply(file->lines, (void *) lines, add_line);
622
623 /* Sort on linenumber */
624 target_hash = HASH_OF(lines);
625 zend_hash_sort(target_hash, zend_qsort, xdebug_lineno_cmp, 0 TSRMLS_CC);
626
627 add_assoc_zval_ex(retval, file->name, strlen(file->name) + 1, lines);
628 }
629
630 PHP_FUNCTION(xdebug_get_code_coverage)
631 {
632 array_init(return_value);
633 xdebug_hash_apply(XG(code_coverage), (void *) return_value, add_file);
634 }
635
46c3439 @derickr - Implemented function_counter
authored
636 PHP_FUNCTION(xdebug_get_function_count)
637 {
638 RETURN_LONG(XG(function_count));
639 }
Something went wrong with that request. Please try again.