Hey:

On Sat, Jan 2, 2016 at 7:59 PM, Derick Rethans <der...@php.net> wrote:

> On Thu, 31 Dec 2015, Nikita Popov wrote:
>
> > On Thu, Dec 31, 2015 at 1:09 AM, Derick Rethans <der...@php.net> wrote:
> >
> > > On Thu, 31 Dec 2015, Nikita Popov wrote:
> > >
> > > > For PHP 7 only: FAST_CALL always jumps to op1. op2 is not a jmp
> > > > addr, it's a try_catch_array offset. For FAST_RET there are no
> > > > jump addresses encoded in the opline. It will either jump back to
> > > > one past the invoking FAST_CALL (of which there may be multiple),
> > > > or (if finally is executed due to an uncaught exception) it will
> > > > jump back to the next applicable catch or finally or leave the
> > > > function.
> > >
> > > Hmm, that's more complicated than I thought. How would I fix that
> > > code? (PR welcome :D )
> >
> > I don't know what you need this for, but maybe you can use the same
> > "good enough" approximation we use for our internal control flow
> > analysis, namely simply say that FAST_CALL either jumps to op1 or to
> > the next instruction, while FAST_RET is treated as a terminator
> > instruction (like RETURN). This does not accurately model control
> > flow, but it may be sufficient for your purposes.
>
> I need to analyse every possible branch, and path through the code in
> order to do dead code analysis (for which I think your simplified
> option works), but also for path coverage, for which I don't think your
> algorithm works. Xinchen alluded on IRC:
>
> 15:21 <@laruence> Derick, it used for calling "finally block"
> 15:22 <@laruence> it has the entry opline of finally block  as opline->op1
> 15:22 <@laruence> and in the end of finally block ,there always be a
>                   ZEND_FAST_RET opline, which will return to proper address
>                   after finally block codes is executed
>
> To me that indicates that the FAST_RET can jump back to any location
> where FAST_CALL was *called* from (+1)?
>
> In any case, I think my current code does what you describe, except for
> FAST_RET, as that does not act like a RETURN - is there any reason why
> my approach wouldn't work?
>
> Some more observations and questions:
>
> FAST_CALL:
> *jmp1 = XDEBUG_ZNODE_JMP_LINE(opcode.op1, position, base_address);
>
> - But what do do for *jmp2 - if extended_value is set?

if extended_value is set(FROM_FINALLY) that means this finally block is
inside another finally block

I am not sure what *jmp2 means here? ZEND_FAST_CALL always jmp to one
place. but  in case FROM_FINALLY it has outer FAST_CALL's opline in op2 .


> - I can't come up with PHP code that sets extended_value though. Can you?
>
try  {
} finally {
   try  {
   } finally /* this fast_call will set with FROM_FINALLY*/
   {}
}

>
> FAST_RET:
> *jmp1 = position + 1;
>
> - But you indicate that that really should be *jmp1 = XDEBUG_JMP_EXIT?
>
> - Or, it should jump back to something else?
> - But how do I know to which possible opline(s) it is going to jump back
> to?

- Is there a list of these somewhere?

I am afarid there is not, let me try to summary it(I will try to make it
clean, but mine poor english :<):

ZEND_FAST_CALL opcode is used for set a proper return address for
ZEND_FAST_RET.

there are two ways can entry a finally block, ZEND_FAST_CALL and
ZEND_HANDLE_EXCEPTION:

1) ZEND_FAST_CALL:  it set the return address to it's self (it will always
follow by a JMP, which will JMP to end of finall block).
2) ZEND_HANDLE_EXCEPTION, if there is catch block then jmp to it(in the end
of the catch block there will be a JMP to finally block), if no catch block
is matched and there is a finally block, then set fast_call_var->u2.lineno
== -1, and stash the EG(exception) into Z_OBJ_P(fast_call_var), then jmp to
the finally block.

for FAST_RET:
   in fast_ret, if fast_call_var->u2.lineno != -1, then it means a jmp
address, simply jmp to it.

   if  fast_call->u2.lineno == -1, then there must be a un-handle
exception(stored in Z_OBJ_P(fast_call_var)),  so:

   if RET_TO_FINALLY(see blow), means there is another finally block needs
to be run, jmp to the  ZEND_FAST_CALL opline of that finally block, in
which opline handle, if opline->extended_value
== ZEND_FAST_CALL_FROM_FINALLY(see below) and obviously current
Z_OBJ_P(fast_call_var) is set, then goes into the finally block behavior
like the way ZEND_HANDLE_EXCEPTION did, which is set the
fast_call->u2.lineno to -1, and jmp into the finally block.

  otherwise, restore the exception,  then goes like a new  exception is
throw(jmp to a CATCH block or leave current function which will result
ZEND_HANDLE_EXCEPTION again).



- I can't come up with PHP code that sets extended_value here either.
>
try  {
   try {
   } finally {

   } /* this fast_ret will set to RET_TO_CATCH */

}  catch () {
}

try  {
   try {
   } finally {

   } /* this fast_ret will set to RET_TO_FINALLY */

}  finally {
}

thanks

>   Can you?


thanks

>
> cheers,
> Derick
>



-- 
Xinchen Hui
@Laruence
http://www.laruence.com/

Reply via email to