php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
phpdbg_bp.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Felipe Pena <felipe@php.net> |
14 | Authors: Joe Watkins <joe.watkins@live.co.uk> |
15 | Authors: Bob Weinand <bwoebi@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#include "zend.h"
20#include "zend_hash.h"
21#include "phpdbg.h"
22#include "phpdbg_bp.h"
23#include "phpdbg_utils.h"
24#include "zend_globals.h"
26
28
29/* {{{ private api functions */
30static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array*);
31static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function*);
32static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array*);
33static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_ptr_t);
34static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opcode(uint8_t);
35static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execute_data *execute_data); /* }}} */
36
37/*
38* Note:
39* A break point must always set the correct id and type
40* A set breakpoint function must always map new points
41*/
42static inline void _phpdbg_break_mapping(int id, HashTable *table) /* {{{ */
43{
44 zend_hash_index_update_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, table);
45}
46/* }}} */
47
48#define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table)
49#define PHPDBG_BREAK_UNMAPPING(id) \
50 zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (id))
51
52#define PHPDBG_BREAK_INIT(b, t) do {\
53 memset(&b, 0, sizeof(b)); \
54 b.id = PHPDBG_G(bp_count)++; \
55 b.type = t; \
56 b.disabled = 0;\
57 b.hits = 0; \
58} while(0)
59
60static void phpdbg_file_breaks_dtor(zval *data) /* {{{ */
61{
63
64 efree((char*)bp->filename);
65 efree(bp);
66} /* }}} */
67
68static void phpdbg_class_breaks_dtor(zval *data) /* {{{ */
69{
71
72 efree((char*)bp->class_name);
73 efree((char*)bp->func_name);
74 efree(bp);
75} /* }}} */
76
77static void phpdbg_opline_class_breaks_dtor(zval *data) /* {{{ */
78{
81} /* }}} */
82
83static void phpdbg_opline_breaks_dtor(zval *data) /* {{{ */
84{
86
87 if (bp->class_name) {
88 efree((char*)bp->class_name);
89 }
90 if (bp->func_name) {
91 efree((char*)bp->func_name);
92 }
93 efree(bp);
94} /* }}} */
95
97{
98 HashTable *table;
99
101 phpdbg_breakbase_t *brake;
102
103 ZEND_HASH_FOREACH_PTR(table, brake) {
104 brake->hits = 0;
107} /* }}} */
108
110{
111 char *string;
113 fputs(string, handle);
114}
115/* }}} */
116
118{
119 HashTable *table;
120 zend_ulong id = 0L;
121
122 *str = "";
123
124 if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) {
125 phpdbg_notice("Exporting %d breakpoints", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]));
126
127 /* this only looks like magic, it isn't */
129 phpdbg_breakbase_t *brake;
130
131 ZEND_HASH_FOREACH_PTR(table, brake) {
132 if (brake->id == id) {
133 char *new_str = NULL;
134
135 switch (brake->type) {
136 case PHPDBG_BREAK_FILE: {
137 zend_string *filename = php_addcslashes_str(((phpdbg_breakfile_t*)brake)->filename, strlen(((phpdbg_breakfile_t*)brake)->filename), "\\\"\n", 3);
138 phpdbg_asprintf(&new_str,
139 "%sbreak \"%s\":"ZEND_ULONG_FMT"\n", *str,
140 ZSTR_VAL(filename),
141 ((phpdbg_breakfile_t*)brake)->line);
142 zend_string_release(filename);
143 } break;
144
145 case PHPDBG_BREAK_SYM: {
146 phpdbg_asprintf(&new_str,
147 "%sbreak %s\n", *str,
148 ((phpdbg_breaksymbol_t*)brake)->symbol);
149 } break;
150
151 case PHPDBG_BREAK_METHOD: {
152 phpdbg_asprintf(&new_str,
153 "%sbreak %s::%s\n", *str,
154 ((phpdbg_breakmethod_t*)brake)->class_name,
156 } break;
157
159 phpdbg_asprintf(&new_str,
160 "%sbreak %s::%s#"ZEND_ULONG_FMT"\n", *str,
161 ((phpdbg_breakopline_t*)brake)->class_name,
163 ((phpdbg_breakopline_t*)brake)->opline_num);
164 } break;
165
167 phpdbg_asprintf(&new_str,
168 "%sbreak %s#"ZEND_ULONG_FMT"\n", *str,
170 ((phpdbg_breakopline_t*)brake)->opline_num);
171 } break;
172
174 zend_string *filename = php_addcslashes_str(((phpdbg_breakopline_t*)brake)->class_name, strlen(((phpdbg_breakopline_t*)brake)->class_name), "\\\"\n", 3);
175 phpdbg_asprintf(&new_str,
176 "%sbreak \"%s\":#"ZEND_ULONG_FMT"\n", *str,
177 ZSTR_VAL(filename),
178 ((phpdbg_breakopline_t*)brake)->opline_num);
179 zend_string_release(filename);
180 } break;
181
182 case PHPDBG_BREAK_OPCODE: {
183 phpdbg_asprintf(&new_str,
184 "%sbreak %s\n", *str,
185 ((phpdbg_breakop_t*)brake)->name);
186 } break;
187
188 case PHPDBG_BREAK_COND: {
189 phpdbg_breakcond_t *conditional = (phpdbg_breakcond_t*) brake;
190
191 if (conditional->paramed) {
192 switch (conditional->param.type) {
194 phpdbg_asprintf(&new_str,
195 "%sbreak at %s#"ZEND_ULONG_FMT" if %s\n",
196 *str, conditional->param.str, conditional->param.num, conditional->code);
197 break;
198
200 phpdbg_asprintf(&new_str,
201 "%sbreak at %s::%s#"ZEND_ULONG_FMT" if %s\n",
202 *str, conditional->param.method.class, conditional->param.method.name, conditional->param.num, conditional->code);
203 break;
204
205 case ADDR_PARAM:
206 phpdbg_asprintf(&new_str,
207 "%sbreak at 0X"ZEND_ULONG_FMT" if %s\n",
208 *str, conditional->param.addr, conditional->code);
209 break;
210
211 case STR_PARAM:
212 phpdbg_asprintf(&new_str,
213 "%sbreak at %s if %s\n", *str, conditional->param.str, conditional->code);
214 break;
215
216 case METHOD_PARAM:
217 phpdbg_asprintf(&new_str,
218 "%sbreak at %s::%s if %s\n", *str,
219 conditional->param.method.class, conditional->param.method.name,
220 conditional->code);
221 break;
222
223 case FILE_PARAM: {
224 zend_string *filename = php_addcslashes_str(conditional->param.file.name, strlen(conditional->param.file.name), "\\\"\n", 3);
225 phpdbg_asprintf(&new_str,
226 "%sbreak at \"%s\":"ZEND_ULONG_FMT" if %s\n", *str,
227 ZSTR_VAL(filename), conditional->param.file.line,
228 conditional->code);
229 zend_string_release(filename);
230 } break;
231
232 default: { /* do nothing */ } break;
233 }
234 } else {
235 phpdbg_asprintf(&new_str, "%sbreak if %s\n", str, conditional->code);
236 }
237 } break;
238
239 default: continue;
240 }
241
242 if ((*str)[0]) {
243 free(*str);
244 }
245 *str = new_str;
246 }
249 }
250
251 if ((*str) && !(*str)[0]) {
252 *str = NULL;
253 }
254} /* }}} */
255
256PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, size_t path_len, zend_ulong line_num) /* {{{ */
257{
259 char realpath[MAXPATHLEN];
260 const char *original_path = path;
261 bool pending = 0;
262 zend_string *path_str;
263
264 HashTable *broken, *file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE];
265 phpdbg_breakfile_t new_break;
266
267 if (!path_len) {
268 if (VCWD_REALPATH(path, realpath)) {
269 path = realpath;
270 }
271 }
272 path_len = strlen(path);
273
274 phpdbg_debug("file path: %s, resolved path: %s, was compiled: %d\n", original_path, path, zend_hash_str_exists(&PHPDBG_G(file_sources), path, path_len));
275
276 if (!zend_hash_str_exists(&PHPDBG_G(file_sources), path, path_len)) {
277 if (php_stream_stat_path(path, &ssb) == FAILURE) {
278 if (original_path[0] == '/') {
279 phpdbg_error("Cannot stat %s, it does not exist", original_path);
280 return;
281 }
282
283 file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING];
284 path = original_path;
285 path_len = strlen(path);
286 pending = 1;
287 } else if (!(ssb.sb.st_mode & (S_IFREG|S_IFLNK))) {
288 phpdbg_error("Cannot set breakpoint in %s, it is not a regular file", path);
289 return;
290 } else {
291 phpdbg_debug("File exists, but not compiled\n");
292 }
293 }
294
295 path_str = zend_string_init(path, path_len, 0);
296
297 if (!(broken = zend_hash_find_ptr(file_breaks, path_str))) {
298 HashTable breaks;
299 zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0);
300
301 broken = zend_hash_add_mem(file_breaks, path_str, &breaks, sizeof(HashTable));
302 }
303
304 if (!zend_hash_index_exists(broken, line_num)) {
306 new_break.filename = estrndup(path, path_len);
307 new_break.line = line_num;
308
309 zend_hash_index_update_mem(broken, line_num, &new_break, sizeof(phpdbg_breakfile_t));
310
311 PHPDBG_BREAK_MAPPING(new_break.id, broken);
312
313 if (pending) {
316 HashTable *fileht;
317
318 phpdbg_debug("Compare against loaded %s\n", ZSTR_VAL(file));
319
320 if (!(pending = ((fileht = phpdbg_resolve_pending_file_break_ex(ZSTR_VAL(file), ZSTR_LEN(file), path_str, broken)) == NULL))) {
321 new_break = *(phpdbg_breakfile_t *) zend_hash_index_find_ptr(fileht, line_num);
322 break;
323 }
325 }
326
327 if (pending) {
329
330 phpdbg_notice("Pending breakpoint #%d added at %s:"ZEND_ULONG_FMT"", new_break.id, new_break.filename, new_break.line);
331 } else {
333
334 phpdbg_notice("Breakpoint #%d added at %s:"ZEND_ULONG_FMT"", new_break.id, new_break.filename, new_break.line);
335 }
336 } else {
337 phpdbg_error("Breakpoint at %s:"ZEND_ULONG_FMT" exists", path, line_num);
338 }
339
340 zend_string_release(path_str);
341} /* }}} */
342
343PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uint32_t filelen, zend_string *cur, HashTable *fileht) /* {{{ */
344{
345 phpdbg_debug("file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d\n", file, filelen, ZSTR_VAL(cur), ZSTR_LEN(cur), filelen > ZSTR_LEN(cur) ? file[filelen - ZSTR_LEN(cur) - 1] : '?', filelen > ZSTR_LEN(cur) ? memcmp(file + filelen - ZSTR_LEN(cur), ZSTR_VAL(cur), ZSTR_LEN(cur)) : 0);
346
347#ifdef _WIN32
348# define WIN32_PATH_CHECK file[filelen - ZSTR_LEN(cur) - 1] == '\\'
349#else
350# define WIN32_PATH_CHECK 0
351#endif
352
353 if (((ZSTR_LEN(cur) < filelen && (file[filelen - ZSTR_LEN(cur) - 1] == '/' || WIN32_PATH_CHECK)) || filelen == ZSTR_LEN(cur)) && !memcmp(file + filelen - ZSTR_LEN(cur), ZSTR_VAL(cur), ZSTR_LEN(cur))) {
354 phpdbg_breakfile_t *brake, new_brake;
355 HashTable *master;
356
358
359 if (!(master = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen))) {
360 HashTable new_ht;
361 zend_hash_init(&new_ht, 8, NULL, phpdbg_file_breaks_dtor, 0);
362 master = zend_hash_str_add_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen, &new_ht, sizeof(HashTable));
363 }
364
365 ZEND_HASH_FOREACH_PTR(fileht, brake) {
366 new_brake = *brake;
367 new_brake.filename = estrndup(file, filelen);
368 PHPDBG_BREAK_UNMAPPING(brake->id);
369
370 if (zend_hash_index_add_mem(master, brake->line, &new_brake, sizeof(phpdbg_breakfile_t))) {
371 PHPDBG_BREAK_MAPPING(brake->id, master);
372 }
374
376
377 if (!zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING])) {
379 }
380
381 phpdbg_debug("compiled file: %s, cur bp file: %s\n", file, ZSTR_VAL(cur));
382
383 return master;
384 }
385
386 return NULL;
387} /* }}} */
388
390{
391 HashTable *fileht;
392 uint32_t filelen = strlen(file);
393 zend_string *cur;
394
395 phpdbg_debug("was compiled: %s\n", file);
396
398 phpdbg_debug("check bp: %s\n", ZSTR_VAL(cur));
399
400 phpdbg_resolve_pending_file_break_ex(file, filelen, cur, fileht);
402} /* }}} */
403
404PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len) /* {{{ */
405{
406 char *lcname;
407
408 if (*name == '\\') {
409 name++;
410 name_len--;
411 }
412
413 lcname = zend_str_tolower_dup(name, name_len);
414
415 if (!zend_hash_str_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], name, name_len)) {
416 phpdbg_breaksymbol_t new_break;
417
419
421 new_break.symbol = estrndup(name, name_len);
422
423 zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], lcname, name_len, &new_break, sizeof(phpdbg_breaksymbol_t));
424
425 phpdbg_notice("Breakpoint #%d added at %s", new_break.id, new_break.symbol);
426
428 } else {
429 phpdbg_error("Breakpoint exists at %s", name);
430 }
431
432 efree(lcname);
433} /* }}} */
434
435PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char *func_name) /* {{{ */
436{
437 HashTable class_breaks, *class_table;
438 size_t class_len = strlen(class_name);
439 size_t func_len = strlen(func_name);
440 char *func_lcname, *class_lcname;
441
442 if (*class_name == '\\') {
443 class_name++;
444 class_len--;
445 }
446
447 func_lcname = zend_str_tolower_dup(func_name, func_len);
448 class_lcname = zend_str_tolower_dup(class_name, class_len);
449
450 if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname, class_len))) {
451 zend_hash_init(&class_breaks, 8, NULL, phpdbg_class_breaks_dtor, 0);
452 class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname, class_len, &class_breaks, sizeof(HashTable));
453 }
454
455 if (!zend_hash_str_exists(class_table, func_lcname, func_len)) {
456 phpdbg_breakmethod_t new_break;
457
459
461 new_break.class_name = estrndup(class_name, class_len);
462 new_break.class_len = class_len;
463 new_break.func_name = estrndup(func_name, func_len);
464 new_break.func_len = func_len;
465
466 zend_hash_str_update_mem(class_table, func_lcname, func_len, &new_break, sizeof(phpdbg_breakmethod_t));
467
468 phpdbg_notice("Breakpoint #%d added at %s::%s", new_break.id, class_name, func_name);
469
470 PHPDBG_BREAK_MAPPING(new_break.id, class_table);
471 } else {
472 phpdbg_error("Breakpoint exists at %s::%s", class_name, func_name);
473 }
474
475 efree(func_lcname);
476 efree(class_lcname);
477} /* }}} */
478
480{
481 if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline)) {
482 phpdbg_breakline_t new_break;
483
485
487 new_break.name = NULL;
488 new_break.opline = opline;
489 new_break.base = NULL;
490
491 zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline, &new_break, sizeof(phpdbg_breakline_t));
492
493 phpdbg_notice("Breakpoint #%d added at #"ZEND_ULONG_FMT, new_break.id, new_break.opline);
495 } else {
496 phpdbg_error("Breakpoint exists at #"ZEND_ULONG_FMT, opline);
497 }
498} /* }}} */
499
501{
502 phpdbg_breakline_t opline_break;
503 if (op_array->last <= brake->opline_num) {
504 if (brake->class_name == NULL) {
505 phpdbg_error("There are only %d oplines in function %s (breaking at opline "ZEND_ULONG_FMT" impossible)", op_array->last, brake->func_name, brake->opline_num);
506 } else if (brake->func_name == NULL) {
507 phpdbg_error("There are only %d oplines in file %s (breaking at opline "ZEND_ULONG_FMT" impossible)", op_array->last, brake->class_name, brake->opline_num);
508 } else {
509 phpdbg_error("There are only %d oplines in method %s::%s (breaking at opline "ZEND_ULONG_FMT" impossible)", op_array->last, brake->class_name, brake->func_name, brake->opline_num);
510 }
511
512 return FAILURE;
513 }
514
515 opline_break.disabled = 0;
516 opline_break.hits = 0;
517 opline_break.id = brake->id;
518 opline_break.opline = brake->opline = (zend_ulong)(op_array->opcodes + brake->opline_num);
519 opline_break.name = NULL;
520 opline_break.base = brake;
521 if (op_array->scope) {
522 opline_break.type = PHPDBG_BREAK_METHOD_OPLINE;
523 } else if (op_array->function_name) {
524 opline_break.type = PHPDBG_BREAK_FUNCTION_OPLINE;
525 } else {
526 opline_break.type = PHPDBG_BREAK_FILE_OPLINE;
527 }
528
530
531 zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline_break.opline, &opline_break, sizeof(phpdbg_breakline_t));
532
533 return SUCCESS;
534} /* }}} */
535
537{
539 HashTable *oplines_table;
541
542 if (op_array->scope != NULL && !(func_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], op_array->scope->name))) {
543 return;
544 }
545
546 if (op_array->function_name == NULL) {
547 if (!(oplines_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], op_array->filename))) {
548 return;
549 }
550 } else if (!op_array->function_name || !(oplines_table = zend_hash_find_ptr(func_table, op_array->function_name))) {
551 return;
552 }
553
554 ZEND_HASH_MAP_FOREACH_PTR(oplines_table, brake) {
555 if (phpdbg_resolve_op_array_break(brake, op_array) == SUCCESS) {
556 phpdbg_breakline_t *opline_break;
557
558 zend_hash_internal_pointer_end(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]);
560
561 phpdbg_notice("Breakpoint #%d resolved at %s%s%s#"ZEND_ULONG_FMT" (opline #"ZEND_ULONG_FMT")",
562 opline_break->id,
563 brake->class_name ? brake->class_name : "",
564 brake->class_name && brake->func_name ? "::" : "",
565 brake->func_name ? brake->func_name : "",
566 brake->opline_num,
567 opline_break->opline);
568 }
570} /* }}} */
571
573{
574 HashTable *func_table = EG(function_table);
576
577 if (new_break->func_name == NULL) {
578 if (EG(current_execute_data) == NULL) {
579 if (PHPDBG_G(ops) != NULL && !memcmp(PHPDBG_G(ops)->filename, new_break->class_name, new_break->class_len)) {
581 return SUCCESS;
582 } else {
583 return 2;
584 }
585 }
586 return FAILURE;
587 } else {
588 zend_execute_data *execute_data = EG(current_execute_data);
589 do {
590 if (ZEND_USER_CODE(execute_data->func->common.type)) {
591 zend_op_array *op_array = &execute_data->func->op_array;
592 if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) {
593 if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) {
594 return SUCCESS;
595 } else {
596 return 2;
597 }
598 }
599 }
600 } while ((execute_data = execute_data->prev_execute_data) != NULL);
601 return FAILURE;
602 }
603 }
604
605 if (new_break->class_name != NULL) {
607 if (!(ce = zend_hash_str_find_ptr(EG(class_table), zend_str_tolower_dup(new_break->class_name, new_break->class_len), new_break->class_len))) {
608 return FAILURE;
609 }
610 func_table = &ce->function_table;
611 }
612
613 if (!(func = zend_hash_str_find_ptr(func_table, zend_str_tolower_dup(new_break->func_name, new_break->func_len), new_break->func_len))) {
614 if (new_break->class_name != NULL && new_break->func_name != NULL) {
615 phpdbg_error("Method %s doesn't exist in class %s", new_break->func_name, new_break->class_name);
616 return 2;
617 }
618 return FAILURE;
619 }
620
621 if (func->type != ZEND_USER_FUNCTION) {
622 if (new_break->class_name == NULL) {
623 phpdbg_error("%s is not a user defined function, no oplines exist", new_break->func_name);
624 } else {
625 phpdbg_error("%s::%s is not a user defined method, no oplines exist", new_break->class_name, new_break->func_name);
626 }
627 return 2;
628 }
629
630 if (phpdbg_resolve_op_array_break(new_break, &func->op_array) == FAILURE) {
631 return 2;
632 }
633
634 return SUCCESS;
635} /* }}} */
636
637/* TODO ... method/function oplines need to be normalized (leading backslash, lowercase) and file oplines need to be resolved properly */
638
639PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline) /* {{{ */
640{
641 phpdbg_breakopline_t new_break;
642 HashTable class_breaks, *class_table;
643 HashTable method_breaks, *method_table;
644
646 new_break.func_len = strlen(method);
647 new_break.func_name = estrndup(method, new_break.func_len);
648 new_break.class_len = strlen(class);
649 new_break.class_name = estrndup(class, new_break.class_len);
650 new_break.opline_num = opline;
651 new_break.opline = 0;
652
653 switch (phpdbg_resolve_opline_break(&new_break)) {
654 case FAILURE:
655 phpdbg_notice("Pending breakpoint #%d at %s::%s#"ZEND_ULONG_FMT, new_break.id, new_break.class_name, new_break.func_name, opline);
656 break;
657
658 case SUCCESS:
659 phpdbg_notice("Breakpoint #%d added at %s::%s#"ZEND_ULONG_FMT, new_break.id, new_break.class_name, new_break.func_name, opline);
660 break;
661
662 case 2:
663 return;
664 }
665
666 if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len))) {
667 zend_hash_init(&class_breaks, 8, NULL, phpdbg_opline_class_breaks_dtor, 0);
668 class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len, &class_breaks, sizeof(HashTable));
669 }
670
671 if (!(method_table = zend_hash_str_find_ptr(class_table, new_break.func_name, new_break.func_len))) {
672 zend_hash_init(&method_breaks, 8, NULL, phpdbg_opline_breaks_dtor, 0);
673 method_table = zend_hash_str_update_mem(class_table, new_break.func_name, new_break.func_len, &method_breaks, sizeof(HashTable));
674 }
675
676 if (zend_hash_index_exists(method_table, opline)) {
677 phpdbg_error("Breakpoint already exists for %s::%s#"ZEND_ULONG_FMT, new_break.class_name, new_break.func_name, opline);
678 efree((char*)new_break.func_name);
679 efree((char*)new_break.class_name);
681 return;
682 }
683
685
686 PHPDBG_BREAK_MAPPING(new_break.id, method_table);
687
688 zend_hash_index_update_mem(method_table, opline, &new_break, sizeof(phpdbg_breakopline_t));
689}
690/* }}} */
691
693{
694 phpdbg_breakopline_t new_break;
695 HashTable func_breaks, *func_table;
696
698 new_break.func_len = strlen(function);
699 new_break.func_name = estrndup(function, new_break.func_len);
700 new_break.class_len = 0;
701 new_break.class_name = NULL;
702 new_break.opline_num = opline;
703 new_break.opline = 0;
704
705 switch (phpdbg_resolve_opline_break(&new_break)) {
706 case FAILURE:
707 phpdbg_notice("Pending breakpoint #%d at %s#"ZEND_ULONG_FMT, new_break.id, new_break.func_name, opline);
708 break;
709
710 case SUCCESS:
711 phpdbg_notice("Breakpoint #%d added at %s#"ZEND_ULONG_FMT, new_break.id, new_break.func_name, opline);
712 break;
713
714 case 2:
715 return;
716 }
717
718 if (!(func_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len))) {
719 zend_hash_init(&func_breaks, 8, NULL, phpdbg_opline_breaks_dtor, 0);
720 func_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len, &func_breaks, sizeof(HashTable));
721 }
722
723 if (zend_hash_index_exists(func_table, opline)) {
724 phpdbg_error("Breakpoint already exists for %s#"ZEND_ULONG_FMT, new_break.func_name, opline);
725 efree((char*)new_break.func_name);
727 return;
728 }
729
730 PHPDBG_BREAK_MAPPING(new_break.id, func_table);
731
733
734 zend_hash_index_update_mem(func_table, opline, &new_break, sizeof(phpdbg_breakopline_t));
735}
736/* }}} */
737
739{
740 phpdbg_breakopline_t new_break;
741 HashTable file_breaks, *file_table;
742
744 new_break.func_len = 0;
745 new_break.func_name = NULL;
746 new_break.class_len = strlen(file);
747 new_break.class_name = estrndup(file, new_break.class_len);
748 new_break.opline_num = opline;
749 new_break.opline = 0;
750
751 switch (phpdbg_resolve_opline_break(&new_break)) {
752 case FAILURE:
753 phpdbg_notice("Pending breakpoint #%d at %s:"ZEND_ULONG_FMT, new_break.id, new_break.class_name, opline);
754 break;
755
756 case SUCCESS:
757 phpdbg_notice("Breakpoint #%d added at %s:"ZEND_ULONG_FMT, new_break.id, new_break.class_name, opline);
758 break;
759
760 case 2:
761 return;
762 }
763
764 if (!(file_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len))) {
765 zend_hash_init(&file_breaks, 8, NULL, phpdbg_opline_breaks_dtor, 0);
766 file_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len, &file_breaks, sizeof(HashTable));
767 }
768
769 if (zend_hash_index_exists(file_table, opline)) {
770 phpdbg_error("Breakpoint already exists for %s:"ZEND_ULONG_FMT, new_break.class_name, opline);
771 efree((char*)new_break.class_name);
773 return;
774 }
775
776 PHPDBG_BREAK_MAPPING(new_break.id, file_table);
777
779
780 zend_hash_index_update_mem(file_table, opline, &new_break, sizeof(phpdbg_breakopline_t));
781}
782/* }}} */
783
784PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len) /* {{{ */
785{
786 phpdbg_breakop_t new_break;
787 zend_ulong hash = zend_hash_func(name, name_len);
788
789 if (zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash)) {
790 phpdbg_error("Breakpoint exists for %s", name);
791 return;
792 }
793
795 new_break.hash = hash;
796 new_break.name = estrndup(name, name_len);
797
798 zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash, &new_break, sizeof(phpdbg_breakop_t));
799
801
802 phpdbg_notice("Breakpoint #%d added at %s", new_break.id, name);
804} /* }}} */
805
807{
808 if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline)) {
809 phpdbg_breakline_t new_break;
810
812
814 new_break.opline = (zend_ulong) opline;
815 new_break.base = NULL;
816
817 zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline, &new_break, sizeof(phpdbg_breakline_t));
818
819 phpdbg_notice("Breakpoint #%d added at #"ZEND_ULONG_FMT, new_break.id, new_break.opline);
821 } else {
822 phpdbg_error("Breakpoint exists for opline #"ZEND_ULONG_FMT, (zend_ulong) opline);
823 }
824} /* }}} */
825
826static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, const phpdbg_param_t *param, const char *expr, size_t expr_len, zend_ulong hash) /* {{{ */
827{
828 phpdbg_breakcond_t new_break;
829 uint32_t cops = CG(compiler_options);
830 zend_string *bp_code;
831
832 if (param) {
833 switch (param->type) {
834 case STR_PARAM:
836 case METHOD_PARAM:
838 case FILE_PARAM:
839 case ADDR_PARAM:
840 /* do nothing */
841 break;
842
843 default:
844 phpdbg_error("Invalid parameter type for conditional breakpoint");
845 return;
846 }
847 }
848
850 new_break.hash = hash;
851
852 if (param) {
853 new_break.paramed = 1;
855 param, &new_break.param);
856 if (new_break.param.type == FILE_PARAM ||
857 new_break.param.type == NUMERIC_FILE_PARAM) {
858 char realpath[MAXPATHLEN];
859
860 if (VCWD_REALPATH(new_break.param.file.name, realpath)) {
861 efree(new_break.param.file.name);
862
863 new_break.param.file.name = estrdup(realpath);
864 } else {
865 phpdbg_error("Invalid file for conditional break %s", new_break.param.file.name);
866 phpdbg_clear_param(&new_break.param);
867 return;
868 }
869 }
870 } else {
871 new_break.paramed = 0;
872 }
873
874 cops = CG(compiler_options);
875
876 CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
877
878 new_break.code = estrndup(expr, expr_len);
879 new_break.code_len = expr_len;
880
881 bp_code = zend_string_concat3(
882 "return ", sizeof("return ")-1, expr, expr_len, ";", sizeof(";")-1);
883 new_break.ops = zend_compile_string(bp_code, "Conditional Breakpoint Code", ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
884 zend_string_release(bp_code);
885
886 if (new_break.ops) {
887 brake = zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], hash, &new_break, sizeof(phpdbg_breakcond_t));
888
889 phpdbg_notice("Conditional breakpoint #%d added %s/%p", brake->id, brake->code, brake->ops);
890
893 } else {
894 phpdbg_error("Failed to compile code for expression %s", expr);
895 efree((char*)new_break.code);
897 }
898
899 CG(compiler_options) = cops;
900} /* }}} */
901
902PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_len) /* {{{ */
903{
904 zend_ulong expr_hash = zend_hash_func(expr, expr_len);
905 phpdbg_breakcond_t new_break;
906
907 if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], expr_hash)) {
908 phpdbg_create_conditional_break(
909 &new_break, NULL, expr, expr_len, expr_hash);
910 } else {
911 phpdbg_error("Conditional break %s exists", expr);
912 }
913} /* }}} */
914
916{
917 phpdbg_breakcond_t new_break;
918 phpdbg_param_t *condition;
919 zend_ulong hash = 0L;
920
921 if (param->next) {
922 condition = param->next;
923 hash = zend_hash_func(condition->str, condition->len);
924
925 if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], hash)) {
926 phpdbg_create_conditional_break(&new_break, param, condition->str, condition->len, hash);
927 } else {
928 phpdbg_notice("Conditional break %s exists at the specified location", condition->str);
929 }
930 }
931
932} /* }}} */
933
934static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_array) /* {{{ */
935{
936 HashTable *breaks;
937 phpdbg_breakbase_t *brake;
938
939#if 0
940 phpdbg_debug("Op at: %.*s %d\n", ZSTR_LEN(op_array->filename), ZSTR_VAL(op_array->filename), (*EG(opline_ptr))->lineno);
941#endif
942
943 /* NOTE: realpath resolution should have happened at compile time - no reason to do it here again */
944 if (!(breaks = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename))) {
945 return NULL;
946 }
947
948 if (EG(current_execute_data) && (brake = zend_hash_index_find_ptr(breaks, EG(current_execute_data)->opline->lineno))) {
949 return brake;
950 }
951
952 return NULL;
953} /* }}} */
954
955static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function *fbc) /* {{{ */
956{
958
959 if (fbc->type != ZEND_USER_FUNCTION) {
960 return NULL;
961 }
962
963 ops = (zend_op_array *) fbc;
964
965 if (ops->scope) {
966 /* find method breaks here */
967 return phpdbg_find_breakpoint_method(ops);
968 }
969
970 if (ops->function_name) {
971 phpdbg_breakbase_t *brake;
972 zend_string *fname = zend_string_tolower(ops->function_name);
973
974 brake = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname);
975
976 zend_string_release(fname);
977 return brake;
978 } else {
979 return zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], ZEND_STRL("main"));
980 }
981} /* }}} */
982
983static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array *ops) /* {{{ */
984{
985 HashTable *class_table;
986 phpdbg_breakbase_t *brake = NULL;
987 zend_string *class_lcname = zend_string_tolower(ops->scope->name);
988
989 if ((class_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname))) {
990 zend_string *lcname = zend_string_tolower(ops->function_name);
991
992 brake = zend_hash_find_ptr(class_table, lcname);
993
994 zend_string_release(lcname);
995 }
996
997 zend_string_release(class_lcname);
998 return brake;
999} /* }}} */
1000
1001static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_ptr_t opline) /* {{{ */
1002{
1003 phpdbg_breakline_t *brake;
1004
1005 if ((brake = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline)) && brake->base) {
1006 return (phpdbg_breakbase_t *)brake->base;
1007 }
1008
1009 return (phpdbg_breakbase_t *) brake;
1010} /* }}} */
1011
1012static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opcode(uint8_t opcode) /* {{{ */
1013{
1014 const char *opname = zend_get_opcode_name(opcode);
1015
1016 if (!opname) {
1017 return NULL;
1018 }
1019
1020 return zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], zend_hash_func(opname, strlen(opname)));
1021} /* }}} */
1022
1023static inline bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend_execute_data *execute_data) /* {{{ */
1024{
1026
1027 switch (param->type) {
1029 case STR_PARAM: {
1030 /* function breakpoint */
1031
1032 if (function->type != ZEND_USER_FUNCTION) {
1033 return 0;
1034 }
1035
1036 {
1037 const char *str = NULL;
1038 size_t len = 0L;
1040 str = ops->function_name ? ZSTR_VAL(ops->function_name) : "main";
1041 len = ops->function_name ? ZSTR_LEN(ops->function_name) : strlen(str);
1042
1043 if (len == param->len && memcmp(param->str, str, len) == SUCCESS) {
1044 return param->type == STR_PARAM || execute_data->opline - ops->opcodes == param->num;
1045 }
1046 }
1047 } break;
1048
1049 case FILE_PARAM: {
1050 if (param->file.line == zend_get_executed_lineno()) {
1051 const char *str = zend_get_executed_filename();
1052 size_t lengths[2] = {strlen(param->file.name), strlen(str)};
1053
1054 if (lengths[0] == lengths[1]) {
1055 return (memcmp(
1056 param->file.name, str, lengths[0]) == SUCCESS);
1057 }
1058 }
1059 } break;
1060
1062 case METHOD_PARAM: {
1063 if (function->type != ZEND_USER_FUNCTION) {
1064 return 0;
1065 }
1066
1067 {
1069
1070 if (ops->scope) {
1071 size_t lengths[2] = { strlen(param->method.class), ZSTR_LEN(ops->scope->name) };
1072 if (lengths[0] == lengths[1] && memcmp(param->method.class, ops->scope->name, lengths[0]) == SUCCESS) {
1073 lengths[0] = strlen(param->method.name);
1074 lengths[1] = ZSTR_LEN(ops->function_name);
1075
1076 if (lengths[0] == lengths[1] && memcmp(param->method.name, ops->function_name, lengths[0]) == SUCCESS) {
1077 return param->type == METHOD_PARAM || (execute_data->opline - ops->opcodes) == param->num;
1078 }
1079 }
1080 }
1081 }
1082 } break;
1083
1084 case ADDR_PARAM: {
1085 return ((zend_ulong)(phpdbg_opline_ptr_t)execute_data->opline == param->addr);
1086 } break;
1087
1088 default: {
1089 /* do nothing */
1090 } break;
1091 }
1092 return 0;
1093} /* }}} */
1094
1095static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execute_data *execute_data) /* {{{ */
1096{
1098 int breakpoint = FAILURE;
1099
1101 zval retval;
1102 const zend_op *orig_opline = EG(current_execute_data)->opline;
1103 zend_function *orig_func = EG(current_execute_data)->func;
1104 zval *orig_retval = EG(current_execute_data)->return_value;
1105
1106 if (((phpdbg_breakbase_t*)bp)->disabled) {
1107 continue;
1108 }
1109
1110 if (bp->paramed) {
1111 if (!phpdbg_find_breakpoint_param(&bp->param, execute_data)) {
1112 continue;
1113 }
1114 }
1115
1116 EG(no_extensions) = 1;
1117
1119
1120 zend_try {
1122 zend_execute(bp->ops, &retval);
1123 if (zend_is_true(&retval)) {
1124 breakpoint = SUCCESS;
1125 }
1126 } zend_end_try();
1127
1128 EG(no_extensions) = 1;
1129 EG(current_execute_data)->opline = orig_opline;
1130 EG(current_execute_data)->func = orig_func;
1131 EG(current_execute_data)->return_value = orig_retval;
1133
1134 if (breakpoint == SUCCESS) {
1135 break;
1136 }
1138
1139 return (breakpoint == SUCCESS) ? ((phpdbg_breakbase_t *) bp) : NULL;
1140} /* }}} */
1141
1143{
1144 phpdbg_breakbase_t *base = NULL;
1145
1147 return NULL;
1148 }
1149
1150 /* conditions cannot be executed by eval()'d code */
1151 if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL) &&
1153 (base = phpdbg_find_conditional_breakpoint(execute_data))) {
1154 goto result;
1155 }
1156
1157 if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP) && (base = phpdbg_find_breakpoint_file(&execute_data->func->op_array))) {
1158 goto result;
1159 }
1160
1162 zend_op_array *op_array = &execute_data->func->op_array;
1163 /* check we are at the beginning of the stack, but after argument RECV */
1164 if (execute_data->opline == op_array->opcodes + op_array->num_args + !!(op_array->fn_flags & ZEND_ACC_VARIADIC)) {
1165 if ((base = phpdbg_find_breakpoint_symbol(execute_data->func))) {
1166 goto result;
1167 }
1168 }
1169 }
1170
1171 if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP) && (base = phpdbg_find_breakpoint_opline((phpdbg_opline_ptr_t) execute_data->opline))) {
1172 goto result;
1173 }
1174
1175 if ((PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) && (base = phpdbg_find_breakpoint_opcode(execute_data->opline->opcode))) {
1176 goto result;
1177 }
1178
1179 return NULL;
1180
1181result:
1182 /* we return nothing for disable breakpoints */
1183 if (base->disabled) {
1184 return NULL;
1185 }
1186
1187 return base;
1188} /* }}} */
1189
1191{
1192 HashTable *table;
1193 phpdbg_breakbase_t *brake;
1194 zend_string *strkey;
1195 zend_ulong numkey;
1196
1197 if ((brake = phpdbg_find_breakbase_ex(num, &table, &numkey, &strkey))) {
1198 int type = brake->type;
1199 char *name = NULL;
1200 size_t name_len = 0L;
1201
1202 switch (type) {
1203 case PHPDBG_BREAK_FILE:
1205 if (zend_hash_num_elements(table) == 1) {
1206 name = estrdup(brake->name);
1207 name_len = strlen(name);
1208 if (zend_hash_num_elements(&PHPDBG_G(bp)[type]) == 1) {
1209 PHPDBG_G(flags) &= ~(1<<(brake->type+1));
1210 }
1211 }
1212 break;
1213
1214 default: {
1215 if (zend_hash_num_elements(table) == 1) {
1216 PHPDBG_G(flags) &= ~(1<<(brake->type+1));
1217 }
1218 }
1219 }
1220
1221 switch (type) {
1225 if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]) == 1) {
1227 }
1229 }
1230
1231 if (strkey) {
1232 zend_hash_del(table, strkey);
1233 } else {
1234 zend_hash_index_del(table, numkey);
1235 }
1236
1237 switch (type) {
1238 case PHPDBG_BREAK_FILE:
1240 if (name) {
1241 zend_hash_str_del(&PHPDBG_G(bp)[type], name, name_len);
1242 efree(name);
1243 }
1244 break;
1245 }
1246
1247 phpdbg_notice("Deleted breakpoint #"ZEND_ULONG_FMT, num);
1249 } else {
1250 phpdbg_error("Failed to find breakpoint #"ZEND_ULONG_FMT, num);
1251 }
1252} /* }}} */
1253
1272
1273PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t *brake, bool output) /* {{{ */
1274{
1275 brake->hits++;
1276
1277 if (output) {
1279 }
1280} /* }}} */
1281
1283{
1284 if (!brake)
1285 goto unknown;
1286
1287 switch (brake->type) {
1288 case PHPDBG_BREAK_FILE: {
1289 phpdbg_notice("Breakpoint #%d at %s:"ZEND_ULONG_FMT", hits: "ZEND_ULONG_FMT"",
1290 ((phpdbg_breakfile_t*)brake)->id,
1291 ((phpdbg_breakfile_t*)brake)->filename,
1292 ((phpdbg_breakfile_t*)brake)->line,
1293 ((phpdbg_breakfile_t*)brake)->hits);
1294 } break;
1295
1296 case PHPDBG_BREAK_SYM: {
1297 phpdbg_notice("Breakpoint #%d in %s() at %s:%u, hits: "ZEND_ULONG_FMT"",
1298 ((phpdbg_breaksymbol_t*)brake)->id,
1299 ((phpdbg_breaksymbol_t*)brake)->symbol,
1302 ((phpdbg_breakfile_t*)brake)->hits);
1303 } break;
1304
1305 case PHPDBG_BREAK_OPLINE: {
1306 phpdbg_notice("Breakpoint #%d in #"ZEND_ULONG_FMT" at %s:%u, hits: "ZEND_ULONG_FMT"",
1307 ((phpdbg_breakline_t*)brake)->id,
1308 ((phpdbg_breakline_t*)brake)->opline,
1311 ((phpdbg_breakline_t*)brake)->hits);
1312 } break;
1313
1315 phpdbg_notice("Breakpoint #%d in %s::%s()#"ZEND_ULONG_FMT" at %s:%u, hits: "ZEND_ULONG_FMT"",
1316 ((phpdbg_breakopline_t*)brake)->id,
1317 ((phpdbg_breakopline_t*)brake)->class_name,
1319 ((phpdbg_breakopline_t*)brake)->opline_num,
1322 ((phpdbg_breakopline_t*)brake)->hits);
1323 } break;
1324
1326 phpdbg_notice("Breakpoint #%d in %s()#"ZEND_ULONG_FMT" at %s:%u, hits: "ZEND_ULONG_FMT"",
1327 ((phpdbg_breakopline_t*)brake)->id,
1329 ((phpdbg_breakopline_t*)brake)->opline_num,
1332 ((phpdbg_breakopline_t*)brake)->hits);
1333 } break;
1334
1336 phpdbg_notice("Breakpoint #%d in #"ZEND_ULONG_FMT" at %s:%u, hits: "ZEND_ULONG_FMT"",
1337 ((phpdbg_breakopline_t*)brake)->id,
1338 ((phpdbg_breakopline_t*)brake)->opline_num,
1341 ((phpdbg_breakopline_t*)brake)->hits);
1342 } break;
1343
1344 case PHPDBG_BREAK_OPCODE: {
1345 phpdbg_notice("Breakpoint #%d in %s at %s:%u, hits: "ZEND_ULONG_FMT"",
1346 ((phpdbg_breakop_t*)brake)->id,
1347 ((phpdbg_breakop_t*)brake)->name,
1350 ((phpdbg_breakop_t*)brake)->hits);
1351 } break;
1352
1353 case PHPDBG_BREAK_METHOD: {
1354 phpdbg_notice("Breakpoint #%d in %s::%s() at %s:%u, hits: "ZEND_ULONG_FMT"",
1355 ((phpdbg_breakmethod_t*)brake)->id,
1356 ((phpdbg_breakmethod_t*)brake)->class_name,
1360 ((phpdbg_breakmethod_t*)brake)->hits);
1361 } break;
1362
1363 case PHPDBG_BREAK_COND: {
1364 if (((phpdbg_breakcond_t*)brake)->paramed) {
1365 char *param;
1366 phpdbg_notice("Conditional breakpoint #%d: at %s if %s at %s:%u, hits: "ZEND_ULONG_FMT"",
1367 ((phpdbg_breakcond_t*)brake)->id,
1368 phpdbg_param_tostring(&((phpdbg_breakcond_t*)brake)->param, &param),
1369 ((phpdbg_breakcond_t*)brake)->code,
1372 ((phpdbg_breakcond_t*)brake)->hits);
1373 if (param)
1374 free(param);
1375 } else {
1376 phpdbg_notice("Conditional breakpoint #%d: on %s == true at %s:%u, hits: "ZEND_ULONG_FMT"",
1377 ((phpdbg_breakcond_t*)brake)->id,
1378 ((phpdbg_breakcond_t*)brake)->code,
1381 ((phpdbg_breakcond_t*)brake)->hits);
1382 }
1383
1384 } break;
1385
1386 default: {
1387unknown:
1388 phpdbg_notice("Unknown breakpoint at %s:%u",
1391 }
1392 }
1393} /* }}} */
1394
1396{
1398
1399 if (brake) {
1400 brake->disabled = 0;
1401 }
1402} /* }}} */
1403
1405{
1407
1408 if (brake) {
1409 brake->disabled = 1;
1410 }
1411} /* }}} */
1412
1414{
1416} /* }}} */
1417
1420} /* }}} */
1421
1423{
1424 HashTable *table;
1425 zend_string *strkey;
1426 zend_ulong numkey;
1427
1428 return phpdbg_find_breakbase_ex(id, &table, &numkey, &strkey);
1429} /* }}} */
1430
1432{
1433 if ((*table = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id))) {
1434 phpdbg_breakbase_t *brake;
1435
1436 ZEND_HASH_FOREACH_KEY_PTR(*table, *numkey, *strkey, brake) {
1437 if (brake->id == id) {
1438 return brake;
1439 }
1441 }
1442
1443 return NULL;
1444} /* }}} */
1445
1447{
1448 switch (type) {
1450 phpdbg_breaksymbol_t *brake;
1451
1452 phpdbg_out(SEPARATE "\n");
1453 phpdbg_out("Function Breakpoints:\n");
1455 phpdbg_writeln("#%d\t\t%s%s",
1456 brake->id, brake->symbol,
1457 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1459 } break;
1460
1462 HashTable *class_table;
1463
1464 phpdbg_out(SEPARATE "\n");
1465 phpdbg_out("Method Breakpoints:\n");
1467 phpdbg_breakmethod_t *brake;
1468
1469 ZEND_HASH_MAP_FOREACH_PTR(class_table, brake) {
1470 phpdbg_writeln("#%d\t\t%s::%s%s",
1471 brake->id, brake->class_name, brake->func_name,
1472 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1475 } break;
1476
1478 HashTable *points;
1479
1480 phpdbg_out(SEPARATE "\n");
1481 phpdbg_out("File Breakpoints:\n");
1483 phpdbg_breakfile_t *brake;
1484
1485 ZEND_HASH_MAP_FOREACH_PTR(points, brake) {
1486 phpdbg_writeln("#%d\t\t%s:"ZEND_ULONG_FMT"%s",
1487 brake->id, brake->filename, brake->line,
1488 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1492 HashTable *points;
1493
1494 phpdbg_out(SEPARATE "\n");
1495 phpdbg_out("Pending File Breakpoints:\n");
1497 phpdbg_breakfile_t *brake;
1498
1499 ZEND_HASH_MAP_FOREACH_PTR(points, brake) {
1500 phpdbg_writeln("#%d\t\t%s:"ZEND_ULONG_FMT"%s",
1501 brake->id, brake->filename, brake->line,
1502 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1505 } break;
1506
1508 phpdbg_breakline_t *brake;
1509
1510 phpdbg_out(SEPARATE "\n");
1511 phpdbg_out("Opline Breakpoints:\n");
1513 const char *type;
1514 switch (brake->type) {
1516 type = "method";
1517 goto print_opline;
1519 type = "function";
1520 goto print_opline;
1522 type = "method";
1523
1524 print_opline: {
1525 if (brake->type == PHPDBG_BREAK_METHOD_OPLINE) {
1526 type = "method";
1527 } else if (brake->type == PHPDBG_BREAK_FUNCTION_OPLINE) {
1528 type = "function";
1529 } else if (brake->type == PHPDBG_BREAK_FILE_OPLINE) {
1530 type = "file";
1531 }
1532
1533 phpdbg_writeln("#%d\t\t#"ZEND_ULONG_FMT"\t\t(%s breakpoint)%s",
1534 brake->id, brake->opline, type,
1535 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1536 } break;
1537
1538 default:
1539 phpdbg_writeln("#%d\t\t#"ZEND_ULONG_FMT"%s",
1540 brake->id, brake->opline,
1541 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1542 break;
1543 }
1545 } break;
1546
1548 HashTable *class_table, *method_table;
1549
1550 phpdbg_out(SEPARATE "\n");
1551 phpdbg_out("Method opline Breakpoints:\n");
1553 ZEND_HASH_MAP_FOREACH_PTR(class_table, method_table) {
1554 phpdbg_breakopline_t *brake;
1555
1556 ZEND_HASH_MAP_FOREACH_PTR(method_table, brake) {
1557 phpdbg_writeln("#%d\t\t%s::%s opline "ZEND_ULONG_FMT"%s",
1558 brake->id, brake->class_name, brake->func_name, brake->opline_num,
1559 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1563 } break;
1564
1566 HashTable *function_table;
1567
1568 phpdbg_out(SEPARATE "\n");
1569 phpdbg_out("Function opline Breakpoints:\n");
1571 phpdbg_breakopline_t *brake;
1572
1573 ZEND_HASH_MAP_FOREACH_PTR(function_table, brake) {
1574 phpdbg_writeln("#%d\t\t%s opline "ZEND_ULONG_FMT"%s",
1575 brake->id, brake->func_name, brake->opline_num,
1576 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1579 } break;
1580
1582 HashTable *file_table;
1583
1584 phpdbg_out(SEPARATE "\n");
1585 phpdbg_out("File opline Breakpoints:\n");
1587 phpdbg_breakopline_t *brake;
1588
1589 ZEND_HASH_MAP_FOREACH_PTR(file_table, brake) {
1590 phpdbg_writeln("#%d\t\t%s opline "ZEND_ULONG_FMT"%s",
1591 brake->id, brake->class_name, brake->opline_num,
1592 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1595 } break;
1596
1598 phpdbg_breakcond_t *brake;
1599
1600 phpdbg_out(SEPARATE "\n");
1601 phpdbg_out("Conditional Breakpoints:\n");
1603 if (brake->paramed) {
1604 switch (brake->param.type) {
1605 case STR_PARAM:
1606 phpdbg_writeln("#%d\t\tat %s if %s%s",
1607 brake->id, brake->param.str, brake->code,
1608 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1609 break;
1610
1612 phpdbg_writeln("#%d\t\tat %s#"ZEND_ULONG_FMT" if %s%s",
1613 brake->id, brake->param.str, brake->param.num, brake->code,
1614 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1615 break;
1616
1617 case METHOD_PARAM:
1618 phpdbg_writeln("#%d\t\tat %s::%s if %s%s",
1619 brake->id, brake->param.method.class, brake->param.method.name, brake->code,
1620 ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : "");
1621 break;
1622
1624 phpdbg_writeln("#%d\t\tat %s::%s#"ZEND_ULONG_FMT" if %s%s",
1625 brake->id, brake->param.method.class, brake->param.method.name, brake->param.num, brake->code,
1626 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1627 break;
1628
1629 case FILE_PARAM:
1630 phpdbg_writeln("#%d\t\tat %s:"ZEND_ULONG_FMT" if %s%s",
1631 brake->id, brake->param.file.name, brake->param.file.line, brake->code,
1632 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1633 break;
1634
1635 case ADDR_PARAM:
1636 phpdbg_writeln("#%d\t\tat #"ZEND_ULONG_FMT" if %s%s",
1637 brake->id, brake->param.addr, brake->code,
1638 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1639 break;
1640
1641 default:
1642 phpdbg_error("Invalid parameter type for conditional breakpoint");
1643 return;
1644 }
1645 } else {
1646 phpdbg_writeln("#%d\t\tif %s%s",
1647 brake->id, brake->code,
1648 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1649 }
1651 } break;
1652
1654 phpdbg_breakop_t *brake;
1655
1656 phpdbg_out(SEPARATE "\n");
1657 phpdbg_out("Opcode Breakpoints:\n");
1659 phpdbg_writeln("#%d\t\t%s%s",
1660 brake->id, brake->name,
1661 ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : "");
1663 } break;
1664 }
1665} /* }}} */
size_t len
Definition apprentice.c:174
file(string $filename, int $flags=0, $context=null)
fputs($stream, string $data, ?int $length=null)
realpath(string $path)
Definition test.php:8
zend_ffi_type * type
Definition ffi.c:3812
DL_HANDLE handle
Definition ffi.c:3028
const php_stream_filter_ops * ops
Definition filters.c:1899
#define NULL
Definition gdcache.h:45
hash(string $algo, string $data, bool $binary=false, array $options=[])
Definition hash.stub.php:12
#define SUCCESS
Definition hash_sha3.c:261
int line
Definition php_ffi.h:54
#define php_stream_stat_path(path, ssb)
struct _php_stream_statbuf php_stream_statbuf
PHPAPI zend_string * php_addcslashes_str(const char *str, size_t len, const char *what, size_t what_len)
Definition string.c:3794
HashTable bp[PHPDBG_BREAK_TABLES]
Definition phpdbg.h:231
#define PHPDBG_HAS_SYM_BP
Definition phpdbg.h:128
#define PHPDBG_HAS_OPLINE_BP
Definition phpdbg.h:129
#define PHPDBG_G(v)
Definition phpdbg.h:102
#define PHPDBG_API
Definition phpdbg.h:27
#define PHPDBG_HAS_FUNCTION_OPLINE_BP
Definition phpdbg.h:133
#define PHPDBG_HAS_FILE_OPLINE_BP
Definition phpdbg.h:135
#define PHPDBG_HAS_METHOD_BP
Definition phpdbg.h:130
#define PHPDBG_BP_MASK
Definition phpdbg.h:170
#define PHPDBG_IN_EVAL
Definition phpdbg.h:142
#define PHPDBG_HAS_COND_BP
Definition phpdbg.h:131
HashTable file_sources
Definition phpdbg.h:275
#define PHPDBG_HAS_METHOD_OPLINE_BP
Definition phpdbg.h:134
#define PHPDBG_IN_COND_BP
Definition phpdbg.h:141
#define PHPDBG_HAS_PENDING_FILE_BP
Definition phpdbg.h:127
#define PHPDBG_IS_BP_ENABLED
Definition phpdbg.h:162
int bp_count
Definition phpdbg.h:267
#define PHPDBG_HAS_OPCODE_BP
Definition phpdbg.h:132
#define PHPDBG_HAS_FILE_BP
Definition phpdbg.h:126
#define PHPDBG_BREAK_INIT(b, t)
Definition phpdbg_bp.c:52
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakpoint(zend_execute_data *execute_data)
Definition phpdbg_bp.c:1142
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase_ex(zend_ulong id, HashTable **table, zend_ulong *numkey, zend_string **strkey)
Definition phpdbg_bp.c:1431
PHPDBG_API void phpdbg_set_breakpoint_at(const phpdbg_param_t *param)
Definition phpdbg_bp.c:915
PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline)
Definition phpdbg_bp.c:692
PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array)
Definition phpdbg_bp.c:536
PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline)
Definition phpdbg_bp.c:479
#define PHPDBG_BREAK_UNMAPPING(id)
Definition phpdbg_bp.c:49
PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type)
Definition phpdbg_bp.c:1446
PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num)
Definition phpdbg_bp.c:1190
PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break)
Definition phpdbg_bp.c:572
PHPDBG_API void phpdbg_clear_breakpoints(void)
Definition phpdbg_bp.c:1254
PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t *brake, bool output)
Definition phpdbg_bp.c:1273
PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len)
Definition phpdbg_bp.c:784
#define WIN32_PATH_CHECK
PHPDBG_API void phpdbg_disable_breakpoints(void)
Definition phpdbg_bp.c:1418
PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, size_t path_len, zend_ulong line_num)
Definition phpdbg_bp.c:256
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle)
Definition phpdbg_bp.c:109
PHPDBG_API void phpdbg_reset_breakpoints(void)
Definition phpdbg_bp.c:96
PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t *brake)
Definition phpdbg_bp.c:1282
PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file)
Definition phpdbg_bp.c:389
PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline)
Definition phpdbg_bp.c:639
PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_len)
Definition phpdbg_bp.c:902
PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline)
Definition phpdbg_bp.c:806
PHPDBG_API void phpdbg_disable_breakpoint(zend_ulong id)
Definition phpdbg_bp.c:1404
PHPDBG_API void phpdbg_enable_breakpoint(zend_ulong id)
Definition phpdbg_bp.c:1395
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakbase(zend_ulong id)
Definition phpdbg_bp.c:1422
PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str)
Definition phpdbg_bp.c:117
PHPDBG_API void phpdbg_enable_breakpoints(void)
Definition phpdbg_bp.c:1413
PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len)
Definition phpdbg_bp.c:404
PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline)
Definition phpdbg_bp.c:738
PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_op_array *op_array)
Definition phpdbg_bp.c:500
#define PHPDBG_BREAK_MAPPING(id, table)
Definition phpdbg_bp.c:48
PHPDBG_API HashTable * phpdbg_resolve_pending_file_break_ex(const char *file, uint32_t filelen, zend_string *cur, HashTable *fileht)
Definition phpdbg_bp.c:343
PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char *func_name)
Definition phpdbg_bp.c:435
#define PHPDBG_BREAK_FUNCTION_OPLINE
Definition phpdbg_bp.h:30
#define PHPDBG_BREAK_COND
Definition phpdbg_bp.h:28
#define PHPDBG_BREAK_FILE_OPLINE
Definition phpdbg_bp.h:32
#define PHPDBG_BREAK_OPLINE
Definition phpdbg_bp.h:26
#define PHPDBG_BREAK_SYM
Definition phpdbg_bp.h:25
#define PHPDBG_BREAK_FILE_PENDING
Definition phpdbg_bp.h:24
struct _phpdbg_breakopline_t phpdbg_breakopline_t
#define PHPDBG_BREAK_METHOD
Definition phpdbg_bp.h:27
#define PHPDBG_BREAK_OPCODE
Definition phpdbg_bp.h:29
#define PHPDBG_BREAK_METHOD_OPLINE
Definition phpdbg_bp.h:31
struct _phpdbg_breakmethod_t phpdbg_breakmethod_t
struct _phpdbg_breakop_t phpdbg_breakop_t
#define PHPDBG_BREAK_MAP
Definition phpdbg_bp.h:33
struct _phpdbg_breakline_t phpdbg_breakline_t
struct _zend_op * phpdbg_opline_ptr_t
Definition phpdbg_bp.h:37
#define PHPDBG_BREAK_FILE
Definition phpdbg_bp.h:23
struct _phpdbg_breakbase_t phpdbg_breakbase_t
struct _phpdbg_breakcond_t phpdbg_breakcond_t
struct _phpdbg_breakfile_t phpdbg_breakfile_t
struct _phpdbg_breaksymbol_t phpdbg_breaksymbol_t
PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t *src, phpdbg_param_t *dest)
Definition phpdbg_cmd.c:138
PHPDBG_API char * phpdbg_param_tostring(const phpdbg_param_t *param, char **pointer)
Definition phpdbg_cmd.c:96
PHPDBG_API void phpdbg_clear_param(phpdbg_param_t *param)
Definition phpdbg_cmd.c:75
struct _phpdbg_param phpdbg_param_t
Definition phpdbg_cmd.h:51
@ NUMERIC_FILE_PARAM
Definition phpdbg_cmd.h:36
@ ADDR_PARAM
Definition phpdbg_cmd.h:34
@ NUMERIC_METHOD_PARAM
Definition phpdbg_cmd.h:41
@ STR_PARAM
Definition phpdbg_cmd.h:38
@ METHOD_PARAM
Definition phpdbg_cmd.h:37
@ FILE_PARAM
Definition phpdbg_cmd.h:35
@ NUMERIC_FUNCTION_PARAM
Definition phpdbg_cmd.h:40
zend_constant * data
#define phpdbg_error(strfmt,...)
Definition phpdbg_out.h:43
#define phpdbg_out(fmt,...)
Definition phpdbg_out.h:49
#define SEPARATE
Definition phpdbg_out.h:70
#define phpdbg_asprintf(buf,...)
Definition phpdbg_out.h:53
#define phpdbg_notice(strfmt,...)
Definition phpdbg_out.h:44
#define phpdbg_debug(strfmt,...)
Definition phpdbg_out.h:59
#define phpdbg_writeln(strfmt,...)
Definition phpdbg_out.h:45
const char * func_name
zend_string * lcname
phpdbg_param_t param
Definition phpdbg_bp.h:113
zend_op_array * ops
Definition phpdbg_bp.h:115
zend_ulong line
Definition phpdbg_bp.h:57
phpdbg_breakopline_t * base
Definition phpdbg_bp.h:95
zend_ulong opline
Definition phpdbg_bp.h:94
const char * func_name
Definition phpdbg_bp.h:73
zend_ulong hash
Definition phpdbg_bp.h:103
zend_ulong opline_num
Definition phpdbg_bp.h:85
const char * class_name
Definition phpdbg_bp.h:83
zend_ulong line
Definition phpdbg_cmd.h:58
struct _phpdbg_param::@330020305320302230147242007301032363271275050165 file
phpdbg_param_type type
Definition phpdbg_cmd.h:53
zend_ulong addr
Definition phpdbg_cmd.h:55
zend_long num
Definition phpdbg_cmd.h:54
phpdbg_param_t * next
Definition phpdbg_cmd.h:66
struct _phpdbg_param::@004226021353141374347100337026301377067143131166 method
zend_string * name
Definition zend.h:149
HashTable function_table
Definition zend.h:163
zend_string * filename
zend_class_entry * scope
uint32_t num_args
zend_op * opcodes
zend_string * function_name
uint32_t fn_flags
#define zend_try
Definition zend.h:270
#define zend_end_try()
Definition zend.h:280
#define ZEND_EXTERN_MODULE_GLOBALS(module_name)
Definition zend_API.h:270
ZEND_API zend_array * zend_rebuild_symbol_table(void)
#define estrndup(s, length)
Definition zend_alloc.h:165
#define efree(ptr)
Definition zend_alloc.h:155
#define estrdup(s)
Definition zend_alloc.h:164
struct _zval_struct zval
strlen(string $string)
execute_data func
ZEND_API zend_op_array *(* zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position)
struct _zend_op zend_op
#define ZEND_USER_CODE(type)
#define ZEND_COMPILE_DEFAULT_FOR_EVAL
#define ZEND_USER_FUNCTION
struct _zend_op_array zend_op_array
@ ZEND_COMPILE_POSITION_AFTER_OPEN_TAG
#define ZEND_ACC_VARIADIC
ZEND_API uint32_t zend_get_executed_lineno(void)
ZEND_API const char * zend_get_executed_filename(void)
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)
union _zend_function zend_function
#define CG(v)
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
Definition zend_hash.c:1869
ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
Definition zend_hash.c:1692
ZEND_API zend_result ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
Definition zend_hash.c:1534
ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:1661
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_FOREACH_NUM_KEY_PTR(ht, _h, _ptr)
Definition zend_hash.h:1215
#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1326
#define ZEND_HASH_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1118
#define ZEND_HASH_MAP_FOREACH_STR_KEY(ht, _key)
Definition zend_hash.h:1346
#define ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(ht, _key, _ptr)
Definition zend_hash.h:1433
#define zend_hash_get_current_data_ptr(ht)
Definition zend_hash.h:990
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define ZEND_HASH_FOREACH_KEY_PTR(ht, _h, _key, _ptr)
Definition zend_hash.h:1235
#define ZEND_ULONG_FMT
Definition zend_long.h:88
uint32_t zend_ulong
Definition zend_long.h:43
struct _zend_string zend_string
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length)
#define ZEND_STRL(str)
struct _zend_class_entry zend_class_entry
ZEND_API zend_ulong ZEND_FASTCALL zend_hash_func(const char *str, size_t len)
Definition zend_string.c:60
ZEND_API zend_string * zend_string_concat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_PTR_P(zval_p)
@ FAILURE
Definition zend_types.h:61
struct _zend_execute_data zend_execute_data
Definition zend_types.h:91
#define MAXPATHLEN
#define S_IFLNK
#define VCWD_REALPATH(path, real_path)
zval retval
zend_string * name
zend_function * fbc
bool result
function(EX_VAR(opline->result.var))
execute_data
ZEND_API const char *ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode)