intercepting function calls

php.internals

Unnamed Person

21 years ago
Is it possible to intercept a function call (user space or built-in) in the Zend Engine and execute user space code before/after the function call? =====

Sara Golemon

21 years ago
> Is it possible to intercept a function call (user > space or built-in) in the Zend Engine and execute user > space code before/after the function call? >
Yes, you can do this by way of a Zend extension (not a PHP extension mind you). The parts of Zend/zend_extensions.h you'll want to pay attention to are: typedef void (*fcall_begin_handler_func_t)(zend_op_array *op_array); typedef void (*fcall_end_handler_func_t)(zend_op_array *op_array); struct _zend_extension { ... fcall_begin_handler_func_t fcall_begin_handler; fcall_end_handler_func_t fcall_end_handler; ... }; -Sara

George Schlossnagle

21 years ago
On Feb 9, 2005, at 10:57 AM, Sara Golemon wrote:
>> Is it possible to intercept a function call (user >> space or built-in) in the Zend Engine and execute user >> space code before/after the function call? >> > Yes, you can do this by way of a Zend extension (not a PHP extension > mind > you). > > The parts of Zend/zend_extensions.h you'll want to pay attention to > are:
You can also do this by directly wrapping zend_execute. This is the preferred method if you're writing a profiler or such. George

Unnamed Person

21 years ago
--- George Schlossnagle <george@omniti.com> wrote:
> > On Feb 9, 2005, at 10:57 AM, Sara Golemon wrote: > > >> Is it possible to intercept a function call (user > >> space or built-in) in the Zend Engine and execute > user > >> space code before/after the function call? > >> > > Yes, you can do this by way of a Zend extension > (not a PHP extension > > mind > > you). > > > > The parts of Zend/zend_extensions.h you'll want to > pay attention to > > are: > > You can also do this by directly wrapping > zend_execute. This is the > preferred method if you're writing a profiler or > such. > > George
Thanks, to both of you. I'm mostly just curious, but I may actually create an extension to provide user space ability to intercept function/method calls and execute code before / after them. I made a comment about the Aspect Oriented PHP article on /. back in January that it'd be better to implement that type of call interception within PHP itself, not using some kind of preprocessor. The damn idea's been stuck in my brain ever since. So, just to be clear... Will using call_user_function() either from the hooks or a zend_execute() wrapper cause any problems in the zend engine? - Gabriel =====

Derick Rethans

21 years ago
On Wed, 9 Feb 2005 sumoraigabe-php@yahoo.com wrote:
> I made a comment about the Aspect Oriented PHP article > on /. back in January that it'd be better to implement > that type of call interception within PHP itself, not > using some kind of preprocessor. The damn idea's been > stuck in my brain ever since. > > So, just to be clear... Will using > call_user_function() either from the hooks or a > zend_execute() wrapper cause any problems in the zend > engine?
Should work fine - I use that in Xdebug in some way. regards, Derick
-- Derick Rethans http://derickrethans.nl | http://ez.no | http://xdebug.org

Sebastian Bergmann

21 years ago
Sara Golemon wrote:
> typedef void (*fcall_begin_handler_func_t)(zend_op_array *op_array); > typedef void (*fcall_end_handler_func_t)(zend_op_array *op_array); > > struct _zend_extension { > ... > fcall_begin_handler_func_t fcall_begin_handler; > fcall_end_handler_func_t fcall_end_handler; > ... > };
What about patching __call() so that it is always called?
-- Sebastian Bergmann http://www.sebastian-bergmann.de/ GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

Sara Golemon

21 years ago
>> typedef void (*fcall_begin_handler_func_t)(zend_op_array *op_array); >> typedef void (*fcall_end_handler_func_t)(zend_op_array *op_array); >> >> struct _zend_extension { >> ... >> fcall_begin_handler_func_t fcall_begin_handler; >> fcall_end_handler_func_t fcall_end_handler; >> ... >> }; > > What about patching __call() so that it is always called? >
I hesitate to solve a problem via engine patch if it's at all possible to do within an extension. I havn't entirely mapped it out, but it certainly looks like some magic methods could be hooked out using a zend_extension: function __pre($funcname, &$args) {} and function __post($funcname, &$args, &$retval) for procedural calls and matching object methods for class calls. No time to look deeper myself, but curious to see what others come up with. -Sara

Andi Gutmans

21 years ago
At 11:01 AM 2/9/2005 -0500, George Schlossnagle wrote:
>On Feb 9, 2005, at 10:57 AM, Sara Golemon wrote: > >>>Is it possible to intercept a function call (user >>>space or built-in) in the Zend Engine and execute user >>>space code before/after the function call? >>Yes, you can do this by way of a Zend extension (not a PHP extension mind >>you). >> >>The parts of Zend/zend_extensions.h you'll want to pay attention to are: > >You can also do this by directly wrapping zend_execute. This is the >preferred method if you're writing a profiler or such.
Yeah. Actually I thought we already nuked the old way. Is anyone using it? Andi

Derick Rethans

21 years ago
On Thu, 10 Feb 2005, Andi Gutmans wrote:
> At 11:01 AM 2/9/2005 -0500, George Schlossnagle wrote: > > >On Feb 9, 2005, at 10:57 AM, Sara Golemon wrote: > > > >>>Is it possible to intercept a function call (user > >>>space or built-in) in the Zend Engine and execute user > >>>space code before/after the function call? > >>Yes, you can do this by way of a Zend extension (not a PHP extension mind > >>you). > >> > >>The parts of Zend/zend_extensions.h you'll want to pay attention to are: > > > >You can also do this by directly wrapping zend_execute. This is the > >preferred method if you're writing a profiler or such. > > Yeah. Actually I thought we already nuked the old way. > Is anyone using it?
I'm using: ZEND_DLEXPORT zend_extension zend_extension_entry = { XDEBUG_NAME, XDEBUG_VERSION, XDEBUG_AUTHOR, XDEBUG_URL, "Copyright (c) 2002, 2003, 2004", xdebug_zend_startup, xdebug_zend_shutdown, NULL, /* activate_func_t */ NULL, /* deactivate_func_t */ NULL, /* message_handler_func_t */ NULL, /* op_array_handler_func_t */ xdebug_statement_call, /* statement_handler_func_t */ NULL, /* fcall_begin_handler_func_t */ NULL, /* fcall_end_handler_func_t */ NULL, /* op_array_ctor_func_t */ NULL, /* op_array_dtor_func_t */ STANDARD_ZEND_EXTENSION_PROPERTIES }; I really need the statement call callback for single stepping through code. regards, Derick
-- Derick Rethans http://derickrethans.nl | http://ez.no | http://xdebug.org

George Schlossnagle

21 years ago
On Feb 11, 2005, at 3:09 AM, Derick Rethans wrote:
> ; > > I really need the statement call callback for single stepping through > code.
Seconded. I use something similar. The statement call is really useful. The fcall_(begin|end) hooks I never use though. George

Andi Gutmans

21 years ago
OK you got a point. It doesn't really hurt to keep it so I'll leave it all in. I can think of cases where using those opcodes might be easier to use at runtime than overloading zend_execute. Andi At 09:09 AM 2/11/2005 +0100, Derick Rethans wrote: