Decompiler, disassembler: fix catch for different PHP version; fetch hack is not necessary for PHP5.4+; update for ?: operator
git-svn-id: svn://svn.lighttpd.net/xcache/trunk@1306 c26eb9a1-5813-0410-bd6c-c2e55f420ca73.1
parent
fea60080b7
commit
b6c66205a7
|
@ -566,6 +566,7 @@ class Decompiler
|
|||
XC_ASSIGN => "=",
|
||||
XC_ASSIGN_REF => "= &",
|
||||
XC_JMP_SET => "?:",
|
||||
XC_JMP_SET_VAR => "?:",
|
||||
XC_JMPZ_EX => "&&",
|
||||
XC_JMPNZ_EX => "||",
|
||||
);
|
||||
|
@ -595,6 +596,7 @@ class Decompiler
|
|||
// }}}
|
||||
function stripNamespace($name) // {{{
|
||||
{
|
||||
$name = str($name);
|
||||
$len = strlen($this->namespace) + 1;
|
||||
if (substr($name, 0, $len) == $this->namespace . '\\') {
|
||||
return substr($name, $len);
|
||||
|
@ -663,6 +665,9 @@ class Decompiler
|
|||
case XC_IS_VAR:
|
||||
case XC_IS_TMP_VAR:
|
||||
$T = &$EX['Ts'];
|
||||
if (!isset($T[$op['var']])) {
|
||||
printBacktrace();
|
||||
}
|
||||
$ret = $T[$op['var']];
|
||||
if ($free && empty($this->keepTs)) {
|
||||
unset($T[$op['var']]);
|
||||
|
@ -833,12 +838,12 @@ class Decompiler
|
|||
return false;
|
||||
}
|
||||
// }}}
|
||||
// {{{ ?: excluding JMP_SET
|
||||
// {{{ ?: excluding JMP_SET/JMP_SET_VAR
|
||||
if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts'])
|
||||
&& $range[1] >= $range[0] + 3
|
||||
&& $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN
|
||||
&& ($opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN || $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN_VAR)
|
||||
&& $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $range[1] + 1
|
||||
&& $lastOp['opcode'] == XC_QM_ASSIGN
|
||||
&& ($lastOp['opcode'] == XC_QM_ASSIGN || $lastOp['opcode'] == XC_QM_ASSIGN_VAR)
|
||||
) {
|
||||
$trueRange = array($range[0] + 1, $firstOp['jmpouts'][0] - 2);
|
||||
$falseRange = array($firstOp['jmpouts'][0], $range[1]);
|
||||
|
@ -1013,9 +1018,9 @@ class Decompiler
|
|||
$this->dasmBasicBlock($EX, array($catchFirst, $catchOpLine));
|
||||
$catchOp = &$opcodes[$catchOpLine];
|
||||
echo $indent, 'catch ('
|
||||
, isset($catchOp['op1']['constant']) ? $catchOp['op1']['constant'] : str($this->getOpVal($catchOp['op1'], $EX))
|
||||
, $this->stripNamespace(isset($catchOp['op1']['constant']) ? $catchOp['op1']['constant'] : str($this->getOpVal($catchOp['op1'], $EX)))
|
||||
, ' '
|
||||
, str($this->getOpVal($catchOp['op2'], $EX))
|
||||
, isset($catchOp['op2']['constant']) ? '$' . $catchOp['op2']['constant'] : str($this->getOpVal($catchOp['op2'], $EX))
|
||||
, ") {", PHP_EOL;
|
||||
unset($catchOp);
|
||||
|
||||
|
@ -1314,6 +1319,7 @@ class Decompiler
|
|||
case XC_JMPZ_EX:
|
||||
case XC_JMPNZ_EX:
|
||||
// case XC_JMP_SET:
|
||||
// case XC_JMP_SET_VAR:
|
||||
// case XC_FE_RESET:
|
||||
case XC_FE_FETCH:
|
||||
// case XC_JMP_NO_CTOR:
|
||||
|
@ -1474,7 +1480,7 @@ class Decompiler
|
|||
array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope']));
|
||||
$EX['object'] = (int) $res['var'];
|
||||
$EX['called_scope'] = null;
|
||||
$EX['fbc'] = 'new ' . unquoteName($this->getOpVal($op1, $EX), $EX);
|
||||
$EX['fbc'] = 'new ' . $this->stripNamespace($this->getOpVal($op1, $EX));
|
||||
break;
|
||||
// }}}
|
||||
case XC_THROW: // {{{
|
||||
|
@ -1489,7 +1495,7 @@ class Decompiler
|
|||
break;
|
||||
// }}}
|
||||
case XC_INSTANCEOF: // {{{
|
||||
$resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . str($this->getOpVal($op2, $EX));
|
||||
$resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . $this->stripNamespace($this->getOpVal($op2, $EX));
|
||||
break;
|
||||
// }}}
|
||||
case XC_FETCH_CLASS: // {{{
|
||||
|
@ -1536,27 +1542,37 @@ class Decompiler
|
|||
case XC_FETCH_FUNC_ARG:
|
||||
case XC_FETCH_UNSET:
|
||||
case XC_FETCH_IS:
|
||||
case XC_UNSET_VAR:
|
||||
$rvalue = $this->getOpVal($op1, $EX);
|
||||
$fetchtype = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type'];
|
||||
if ($fetchtype == ZEND_FETCH_STATIC_MEMBER) {
|
||||
$rvalue = $this->stripNamespace($op2['constant']) . '::$' . unquoteName($rvalue, $EX);
|
||||
$fetchType = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type'];
|
||||
$name = isset($op1['constant']) ? $op1['constant'] : unquoteName($this->getOpVal($op1, $EX), $EX);
|
||||
if ($fetchType == ZEND_FETCH_STATIC_MEMBER) {
|
||||
$class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX);
|
||||
$rvalue = $this->stripNamespace($class) . '::$' . $name;
|
||||
}
|
||||
else if ($opc != XC_UNSET_VAR) {
|
||||
$name = unquoteName($rvalue, $EX);
|
||||
else {
|
||||
$rvalue = $this->getOpVal($op1, $EX);
|
||||
$globalname = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($rvalue) . "]";
|
||||
$rvalue = new Decompiler_Fetch($rvalue, $fetchtype, $globalname);
|
||||
$rvalue = new Decompiler_Fetch($rvalue, $fetchType, $globalname);
|
||||
}
|
||||
|
||||
if ($opc == XC_UNSET_VAR) {
|
||||
$op['php'] = "unset(" . str($rvalue, $EX) . ")";
|
||||
$lastphpop = &$op;
|
||||
}
|
||||
else if ($res['op_type'] != XC_IS_UNUSED) {
|
||||
if ($res['op_type'] != XC_IS_UNUSED) {
|
||||
$resvar = $rvalue;
|
||||
}
|
||||
break;
|
||||
// }}}
|
||||
case XC_UNSET_VAR: // {{{
|
||||
$fetchType = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type'];
|
||||
if ($fetchType == ZEND_FETCH_STATIC_MEMBER) {
|
||||
$class = isset($op2['constant']) ? $op2['constant'] /* PHP5.3- */ : $this->getOpVal($op2, $EX);
|
||||
$rvalue = $this->stripNamespace($class) . '::$' . $op1['constant'];
|
||||
}
|
||||
else {
|
||||
$rvalue = $this->getOpVal($op1, $EX);
|
||||
}
|
||||
|
||||
$op['php'] = "unset(" . str($rvalue, $EX) . ")";
|
||||
$lastphpop = &$op;
|
||||
break;
|
||||
// }}}
|
||||
// {{{ case FETCH_DIM_*
|
||||
case XC_FETCH_DIM_TMP_VAR:
|
||||
case XC_FETCH_DIM_R:
|
||||
|
@ -1737,7 +1753,8 @@ class Decompiler
|
|||
}
|
||||
$fetchtype = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type'];
|
||||
if ($fetchtype == ZEND_FETCH_STATIC_MEMBER) {
|
||||
$rvalue = $this->stripNamespace($op2['constant']) . '::' . unquoteName($rvalue, $EX);
|
||||
$class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX);
|
||||
$rvalue = $this->stripNamespace($class) . '::' . unquoteName($rvalue, $EX);
|
||||
}
|
||||
}
|
||||
else if ($opc == XC_ISSET_ISEMPTY) {
|
||||
|
@ -2049,9 +2066,6 @@ class Decompiler
|
|||
// }}}
|
||||
case XC_JMP_NO_CTOR:
|
||||
break;
|
||||
case XC_JMP_SET: // ?:
|
||||
$resvar = new Decompiler_Binop($this, $this->getOpVal($op1, $EX), XC_JMP_SET, null);
|
||||
break;
|
||||
case XC_JMPZ_EX: // and
|
||||
case XC_JMPNZ_EX: // or
|
||||
$resvar = $this->getOpVal($op1, $EX);
|
||||
|
@ -2468,7 +2482,7 @@ class Decompiler
|
|||
}
|
||||
echo $isInterface ? 'interface ' : 'class ', $this->stripNamespace($class['name']);
|
||||
if ($class['parent']) {
|
||||
echo ' extends ', $class['parent'];
|
||||
echo ' extends ', $this->stripNamespace($class['parent']);
|
||||
}
|
||||
/* TODO */
|
||||
if (!empty($class['interfaces'])) {
|
||||
|
@ -2856,6 +2870,7 @@ foreach (array (
|
|||
'XC_ISSET_ISEMPTY' => -1,
|
||||
'XC_JMP_NO_CTOR' => -1,
|
||||
'XC_JMP_SET' => -1,
|
||||
'XC_JMP_SET_VAR' => -1,
|
||||
'XC_QM_ASSIGN_VAR' => -1,
|
||||
'XC_UNSET_DIM_OBJ' => -1,
|
||||
) as $k => $v) {
|
||||
|
|
|
@ -36,24 +36,49 @@ abstract class ClassName
|
|||
{
|
||||
echo CONST_VALUE;
|
||||
echo ClassName::CONST_VALUE;
|
||||
unset(ClassName::$classProp1);
|
||||
empty(ClassName::$classProp);
|
||||
isset(ClassName::$classProp);
|
||||
unset(ClassName::$classProp);
|
||||
ClassName::$classProp = 1;
|
||||
echo ClassName::$classProp;
|
||||
empty($obj->objProp);
|
||||
isset($obj->objProp);
|
||||
unset($obj->objProp);
|
||||
$obj->objProp = 1;
|
||||
echo $obj->objProp;
|
||||
empty($this->thisProp);
|
||||
isset($this->thisProp);
|
||||
unset($this->thisProp);
|
||||
$this->thisProp = 1;
|
||||
echo $this->thisProp;
|
||||
unset($array['index']->valueProp);
|
||||
unset($obj->array['index']);
|
||||
unset($this->array['index']);
|
||||
isset($GLOBALS['a']);
|
||||
empty($GLOBALS['a']);
|
||||
unset($GLOBALS['a']);
|
||||
isset(ClassName::$a);
|
||||
empty(ClassName::$a);
|
||||
unset(ClassName::$a);
|
||||
echo $GLOBALS['a'];
|
||||
$obj->objProp = 1;
|
||||
$this->thisProp = 1;
|
||||
$array['index']->valueProp = 1;
|
||||
empty($_GET['get']);
|
||||
isset($_GET['get']);
|
||||
unset($_GET['get']);
|
||||
$_GET['get'] = 1;
|
||||
echo $_GET['get'];
|
||||
isset($GLOBALS['global']);
|
||||
empty($GLOBALS['global']);
|
||||
unset($GLOBALS['global']);
|
||||
$GLOBALS['global'] = 1;
|
||||
echo $GLOBALS['global'];
|
||||
empty($array['index']);
|
||||
isset($array['index']);
|
||||
unset($array['index']);
|
||||
$array['index'] = 1;
|
||||
$array[1] = 1;
|
||||
echo $array['index'];
|
||||
empty($array['index']->indexProp);
|
||||
isset($array['index']->indexProp);
|
||||
unset($array['index']->indexProp);
|
||||
$array['index']->indexProp = 1;
|
||||
echo $array['index']->indexProp;
|
||||
empty($GLOBALS['var']->indexProp);
|
||||
isset($GLOBALS['var']->indexProp);
|
||||
unset($GLOBALS['var']->indexProp);
|
||||
$GLOBALS['var']->indexProp = 1;
|
||||
echo $GLOBALS['var']->indexProp;
|
||||
}
|
||||
|
||||
/** doc */
|
||||
|
@ -437,6 +462,7 @@ $obj::__construct();
|
|||
$a = $b ?: $d;
|
||||
$a = ($b ?: $d) + $c;
|
||||
$a = f1() ?: f2();
|
||||
$a = C::f1() ?: C::f2();
|
||||
$a = ($b ? $c : $d);
|
||||
$a = ($b ? $c : $d) + $c;
|
||||
$a = (f1() ? f3() : f2());
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
/* {{{ opcode_spec */
|
||||
#define OPSPEC(ext, op1, op2, res) { OPSPEC_##ext, OPSPEC_##op1, OPSPEC_##op2, OPSPEC_##res },
|
||||
#define OPSPEC_VAR_2 OPSPEC_STD
|
||||
#ifdef ZEND_ENGINE_2_4
|
||||
#undef OPSPEC_FETCH
|
||||
#define OPSPEC_FETCH OPSPEC_STD
|
||||
#endif
|
||||
#include "xc_opcode_spec_def.h"
|
||||
|
||||
zend_uchar xc_get_opcode_spec_count()
|
||||
|
|
|
@ -79,11 +79,7 @@ static const xc_opcode_spec_t xc_opcode_spec[] = {
|
|||
OPSPEC( UNUSED, STD, INCLUDE, VAR) /* 73 INCLUDE_OR_EVAL */
|
||||
#ifdef ZEND_ENGINE_2_1
|
||||
/* php 5.1 and up */
|
||||
# ifdef ZEND_ENGINE_2_4
|
||||
OPSPEC( UNUSED, STD, STD, UNUSED) /* 74 UNSET_VAR */
|
||||
# else
|
||||
OPSPEC( UNUSED, STD, FETCH, UNUSED) /* 74 UNSET_VAR */
|
||||
# endif
|
||||
OPSPEC( STD, STD, STD, UNUSED) /* 75 UNSET_DIM */
|
||||
OPSPEC( STD, STD, STD, UNUSED) /* 76 UNSET_OBJ */
|
||||
OPSPEC( BIT, STD, OPLINE, VAR) /* 77 FE_RESET */
|
||||
|
@ -153,11 +149,7 @@ static const xc_opcode_spec_t xc_opcode_spec[] = {
|
|||
#else
|
||||
OPSPEC( UNUSED, UCLASS, STD, UNUSED) /* 113 INIT_STATIC_METHOD_CALL */
|
||||
#endif
|
||||
#ifdef ZEND_ENGINE_2_4
|
||||
OPSPEC( ISSET, STD, STD, TMP) /* 114 ISSET_ISEMPTY_VAR */
|
||||
#else
|
||||
OPSPEC( ISSET, STD, FETCH, TMP) /* 114 ISSET_ISEMPTY_VAR */
|
||||
#endif
|
||||
OPSPEC( ISSET, STD, STD, TMP) /* 115 ISSET_ISEMPTY_DIM_OBJ */
|
||||
|
||||
OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 116 IMPORT_FUNCTION */
|
||||
|
|
Loading…
Reference in New Issue