2323#include "php_memprof.h"
2424#include "zend_extensions.h"
2525#include "zend_exceptions.h"
26+ #include "zend_observer.h"
2627#include <stdint.h>
2728#include <sys/queue.h>
2829#include "util.h"
@@ -198,10 +199,6 @@ static void (*old_free_hook) (void *ptr, const void *caller) = NULL;
198199static void * (* old_memalign_hook ) (size_t alignment , size_t size , const void * caller ) = NULL ;
199200#endif /* HAVE_MALLOC_HOOKS */
200201
201- static void (* old_zend_execute )(zend_execute_data * execute_data );
202- static void (* old_zend_execute_internal )(zend_execute_data * execute_data_ptr , zval * return_value );
203- #define zend_execute_fn zend_execute_ex
204-
205202static void (* old_zend_error_cb )(int type , zend_string * error_filename , const uint32_t error_lineno , zend_string * message );
206203static void (* rinit_zend_error_cb )(int type , zend_string * error_filename , const uint32_t error_lineno , zend_string * message );
207204static zend_bool zend_error_cb_overridden ;
@@ -214,6 +211,7 @@ static int track_mallocs = 0;
214211
215212static frame root_frame ;
216213static frame * current_frame ;
214+ static bool current_frame_ignored ;
217215static alloc_list_head * current_alloc_list ;
218216static alloc_buckets current_alloc_buckets ;
219217
@@ -738,70 +736,77 @@ static void memprof_late_override_error_cb(void) {
738736 zend_error_cb_overridden = 1 ;
739737}
740738
741- static void memprof_zend_execute (zend_execute_data * execute_data )
742- {
739+ static void memprof_observer_fcall_begin_handler (zend_execute_data * execute_data ) {
740+ ZEND_ASSERT (MEMPROF_G (profile_flags ).enabled );
741+
743742 if (UNEXPECTED (!zend_error_cb_overridden )) {
744743 memprof_late_override_error_cb ();
745744 }
746745
746+ #ifdef MEMPROF_DEBUG_OBSERVER
747+ if (execute_data -> func -> common .function_name ) {
748+ fprintf (stderr , "fcall begin %s\n" , ZSTR_VAL (execute_data -> func -> common .function_name ));
749+ }
750+ #endif
751+ if (execute_data -> func -> type == ZEND_INTERNAL_FUNCTION ) {
752+ if (& execute_data -> func -> internal_function == & zend_pass_function ) {
753+ current_frame_ignored = true;
754+ } else if (execute_data -> func -> common .function_name ) {
755+ zend_string * name = execute_data -> func -> common .function_name ;
756+ if (ZSTR_LEN (name ) == sizeof ("call_user_func" )- 1
757+ && 0 == memcmp (name , "call_user_func" , sizeof ("call_user_func" )))
758+ {
759+ current_frame_ignored = true;
760+ } else if (ZSTR_LEN (name ) == sizeof ("call_user_func_array" )- 1
761+ && 0 == memcmp (name , "call_user_func_array" , sizeof ("call_user_func_array" )))
762+ {
763+ current_frame_ignored = true;
764+ }
765+ } else {
766+ current_frame_ignored = false;
767+ }
768+ } else {
769+ current_frame_ignored = false;
770+ }
771+
772+ if (current_frame_ignored ) {
773+ return ;
774+ }
775+
747776 WITHOUT_MALLOC_TRACKING {
748777
749778 current_frame = get_or_create_frame (execute_data , current_frame );
750779 current_frame -> calls ++ ;
751780 current_alloc_list = & current_frame -> allocs ;
752781
753782 } END_WITHOUT_MALLOC_TRACKING ;
754-
755- old_zend_execute (execute_data );
756-
757- if (MEMPROF_G (profile_flags ).enabled ) {
758- current_frame = current_frame -> prev ;
759- current_alloc_list = & current_frame -> allocs ;
760- }
761783}
762784
763- static void memprof_zend_execute_internal (zend_execute_data * execute_data_ptr , zval * return_value )
764- {
765- int ignore = 0 ;
785+ static void memprof_observer_fcall_end_handler (zend_execute_data * execute_data , zval * retval ) {
786+ ZEND_ASSERT (MEMPROF_G (profile_flags ).enabled );
766787
767- if (UNEXPECTED (!zend_error_cb_overridden )) {
768- memprof_late_override_error_cb ();
788+ #ifdef MEMPROF_DEBUG_OBSERVER
789+ if (execute_data -> func -> common .function_name ) {
790+ fprintf (stderr , "fcall end %s\n" , ZSTR_VAL (execute_data -> func -> common .function_name ));
769791 }
792+ #endif
770793
771- if (& execute_data_ptr -> func -> internal_function == & zend_pass_function ) {
772- ignore = 1 ;
773- } else if (execute_data_ptr -> func -> common .function_name ) {
774- zend_string * name = execute_data_ptr -> func -> common .function_name ;
775- if (ZSTR_LEN (name ) == sizeof ("call_user_func" )- 1
776- && 0 == memcmp (name , "call_user_func" , sizeof ("call_user_func" )))
777- {
778- ignore = 1 ;
779- } else if (ZSTR_LEN (name ) == sizeof ("call_user_func_array" )- 1
780- && 0 == memcmp (name , "call_user_func_array" , sizeof ("call_user_func_array" )))
781- {
782- ignore = 1 ;
783- }
794+ if (current_frame_ignored ) {
795+ current_frame_ignored = false;
796+ return ;
784797 }
798+ current_frame = current_frame -> prev ;
799+ current_alloc_list = & current_frame -> allocs ;
800+ }
785801
786- WITHOUT_MALLOC_TRACKING {
787-
788- if (!ignore ) {
789- current_frame = get_or_create_frame (execute_data_ptr , current_frame );
790- current_frame -> calls ++ ;
791- current_alloc_list = & current_frame -> allocs ;
792- }
793-
794- } END_WITHOUT_MALLOC_TRACKING ;
795-
796- if (!old_zend_execute_internal ) {
797- execute_internal (execute_data_ptr , return_value );
802+ static zend_observer_fcall_handlers memprof_observer_fcall_init (zend_execute_data * execute_data ) {
803+ if (MEMPROF_G (profile_flags ).enabled ) {
804+ return (zend_observer_fcall_handlers ){
805+ .begin = memprof_observer_fcall_begin_handler ,
806+ .end = memprof_observer_fcall_end_handler ,
807+ };
798808 } else {
799- old_zend_execute_internal (execute_data_ptr , return_value );
800- }
801-
802- if (!ignore && MEMPROF_G (profile_flags ).enabled ) {
803- current_frame = current_frame -> prev ;
804- current_alloc_list = & current_frame -> allocs ;
809+ return (zend_observer_fcall_handlers ){0 };
805810 }
806811}
807812
@@ -973,21 +978,13 @@ static void memprof_enable(memprof_profile_flags * pf)
973978 orig_zheap = NULL ;
974979 }
975980
976- old_zend_execute = zend_execute_fn ;
977- old_zend_execute_internal = zend_execute_internal ;
978- zend_execute_fn = memprof_zend_execute ;
979- zend_execute_internal = memprof_zend_execute_internal ;
980-
981981 track_mallocs = 1 ;
982982}
983983
984984static void memprof_disable (void )
985985{
986986 track_mallocs = 0 ;
987987
988- zend_execute_fn = old_zend_execute ;
989- zend_execute_internal = old_zend_execute_internal ;
990-
991988 if (zheap ) {
992989 zend_mm_set_heap (orig_zheap );
993990 free (zheap );
@@ -1200,6 +1197,8 @@ PHP_MINIT_FUNCTION(memprof)
12001197
12011198 REGISTER_INI_ENTRIES ();
12021199
1200+ zend_observer_fcall_register (memprof_observer_fcall_init );
1201+
12031202 entry = zend_hash_str_find_ptr (EG (ini_directives ), "memory_limit" , sizeof ("memory_limit" )- 1 );
12041203
12051204 if (entry == NULL ) {
0 commit comments