@@ -245,8 +245,7 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
245245 PHPDBG_G (prompt )[1 ] = NULL ;
246246
247247 if (PHPDBG_G (oplog )) {
248- fclose (
249- PHPDBG_G (oplog ));
248+ fclose (PHPDBG_G (oplog ));
250249 PHPDBG_G (oplog ) = NULL ;
251250 }
252251
@@ -256,6 +255,18 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
256255 PHPDBG_G (ops ) = NULL ;
257256 }
258257
258+ if (PHPDBG_G (oplog_list )) {
259+ phpdbg_oplog_list * cur = PHPDBG_G (oplog_list );
260+ do {
261+ phpdbg_oplog_list * prev = cur -> prev ;
262+ efree (cur );
263+ cur = prev ;
264+ } while (cur != NULL );
265+
266+ zend_arena_destroy (PHPDBG_G (oplog_arena ));
267+ PHPDBG_G (oplog_list ) = NULL ;
268+ }
269+
259270 return SUCCESS ;
260271} /* }}} */
261272
@@ -403,6 +414,132 @@ static PHP_FUNCTION(phpdbg_prompt)
403414 phpdbg_set_prompt (prompt );
404415} /* }}} */
405416
417+ /* {{{ proto void phpdbg_start_oplog() */
418+ static PHP_FUNCTION (phpdbg_start_oplog )
419+ {
420+ phpdbg_oplog_list * prev ;
421+
422+ if (zend_parse_parameters_none () == FAILURE ) {
423+ return ;
424+ }
425+
426+ prev = PHPDBG_G (oplog_list );
427+
428+ if (!prev ) {
429+ PHPDBG_G (oplog_arena ) = zend_arena_create (64 * 1024 );
430+
431+ PHPDBG_G (oplog_cur ) = ((phpdbg_oplog_entry * ) zend_arena_alloc (& PHPDBG_G (oplog_arena ), sizeof (phpdbg_oplog_entry ))) + 1 ;
432+ PHPDBG_G (oplog_cur )-> next = NULL ;
433+ }
434+
435+ PHPDBG_G (oplog_list ) = emalloc (sizeof (phpdbg_oplog_list ));
436+ PHPDBG_G (oplog_list )-> prev = prev ;
437+ PHPDBG_G (oplog_list )-> start = PHPDBG_G (oplog_cur );
438+ }
439+
440+ /* {{{ proto void phpdbg_end_oplog() */
441+ static PHP_FUNCTION (phpdbg_end_oplog )
442+ {
443+ phpdbg_oplog_entry * cur = PHPDBG_G (oplog_list )-> start ;
444+ phpdbg_oplog_list * prev = PHPDBG_G (oplog_list )-> prev ;
445+
446+ HashTable * options ;
447+ zval * option_buffer ;
448+ zend_bool by_function = 0 ;
449+ zend_bool by_opcode = 0 ;
450+
451+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "|H" , & options ) == FAILURE ) {
452+ return ;
453+ }
454+
455+ if (!PHPDBG_G (oplog_list )) {
456+ zend_error (E_WARNING , "Can not end an oplog without starting it" );
457+ return ;
458+ }
459+
460+ efree (PHPDBG_G (oplog_list ));
461+ PHPDBG_G (oplog_list ) = prev ;
462+
463+ if (options && (option_buffer = zend_hash_str_find (options , ZEND_STRL ("functions" )))) {
464+ by_function = zend_is_true (option_buffer );
465+ }
466+
467+ if (options && (option_buffer = zend_hash_str_find (options , ZEND_STRL ("opcodes" )))) {
468+ if (by_function ) {
469+ by_opcode = zend_is_true (option_buffer );
470+ }
471+ }
472+
473+ array_init (return_value );
474+
475+ {
476+ zend_string * last_file = NULL ;
477+ zval * file_buf ;
478+ zend_string * last_function = (void * )~(uintptr_t )0 ;
479+ zend_class_entry * last_scope = NULL ;
480+ zval * fn_buf ;
481+
482+ HashTable * insert_ht ;
483+ zend_long insert_idx ;
484+
485+ do {
486+ zend_op_array * op_array = cur -> op_array ;
487+ if (op_array -> filename != last_file ) {
488+ last_file = op_array -> filename ;
489+ file_buf = zend_hash_find (Z_ARR_P (return_value ), last_file );
490+ if (!file_buf ) {
491+ zval ht ;
492+ array_init (& ht );
493+ file_buf = zend_hash_add_new (Z_ARR_P (return_value ), last_file , & ht );
494+ }
495+ }
496+ insert_ht = Z_ARR_P (file_buf );
497+
498+ if (by_function ) {
499+ if (op_array -> function_name != last_function || op_array -> scope != last_scope ) {
500+ zend_string * fn_name ;
501+ last_function = op_array -> function_name ;
502+ last_scope = op_array -> scope ;
503+ if (last_scope == NULL ) {
504+ fn_name = zend_string_copy (last_function );
505+ } else {
506+ fn_name = strpprintf (last_function -> len + last_scope -> name -> len + 2 , "%.*s::%.*s" , last_function -> len , last_function -> val , last_scope -> name -> len , last_scope -> name -> val );
507+ }
508+ fn_buf = zend_hash_find (Z_ARR_P (return_value ), fn_name );
509+ if (!fn_buf ) {
510+ zval ht ;
511+ array_init (& ht );
512+ fn_buf = zend_hash_add_new (Z_ARR_P (return_value ), fn_name , & ht );
513+ }
514+ }
515+ insert_ht = Z_ARR_P (fn_buf );
516+ }
517+
518+ if (by_opcode ) {
519+ insert_idx = cur -> op - op_array -> opcodes ;
520+ } else {
521+ insert_idx = cur -> op -> lineno ;
522+ }
523+
524+ {
525+ zval * num = zend_hash_index_find (insert_ht , insert_idx );
526+ if (!num ) {
527+ zval zv ;
528+ ZVAL_LONG (& zv , 0 );
529+ num = zend_hash_index_add_new (insert_ht , insert_idx , & zv );
530+ }
531+ Z_LVAL_P (num )++ ;
532+ }
533+
534+ cur = cur -> next ;
535+ } while (cur != NULL );
536+ }
537+
538+ if (!prev ) {
539+ zend_arena_destroy (PHPDBG_G (oplog_arena ));
540+ }
541+ }
542+
406543ZEND_BEGIN_ARG_INFO_EX (phpdbg_break_next_arginfo , 0 , 0 , 0 )
407544ZEND_END_ARG_INFO ()
408545
@@ -436,6 +573,12 @@ ZEND_END_ARG_INFO()
436573ZEND_BEGIN_ARG_INFO_EX (phpdbg_clear_arginfo , 0 , 0 , 0 )
437574ZEND_END_ARG_INFO ()
438575
576+ ZEND_BEGIN_ARG_INFO_EX (phpdbg_start_oplog_arginfo , 0 , 0 , 0 )
577+ ZEND_END_ARG_INFO ()
578+
579+ ZEND_BEGIN_ARG_INFO_EX (phpdbg_end_oplog_arginfo , 0 , 0 , 0 )
580+ ZEND_END_ARG_INFO ()
581+
439582zend_function_entry phpdbg_user_functions [] = {
440583 PHP_FE (phpdbg_clear , phpdbg_clear_arginfo )
441584 PHP_FE (phpdbg_break_next , phpdbg_break_next_arginfo )
@@ -445,6 +588,8 @@ zend_function_entry phpdbg_user_functions[] = {
445588 PHP_FE (phpdbg_exec , phpdbg_exec_arginfo )
446589 PHP_FE (phpdbg_color , phpdbg_color_arginfo )
447590 PHP_FE (phpdbg_prompt , phpdbg_prompt_arginfo )
591+ PHP_FE (phpdbg_start_oplog , phpdbg_start_oplog_arginfo )
592+ PHP_FE (phpdbg_end_oplog , phpdbg_end_oplog_arginfo )
448593#ifdef PHP_FE_END
449594 PHP_FE_END
450595#else
0 commit comments