merge decompiler updates from trunk
git-svn-id: svn://svn.lighttpd.net/xcache/branches/1.3@739 c26eb9a1-5813-0410-bd6c-c2e55f420ca71.3
parent
0e0c9f1589
commit
3a7d26c290
|
@ -8,39 +8,33 @@ function color($str, $color = 33)
|
|||
return "\x1B[{$color}m$str\x1B[0m";
|
||||
}
|
||||
|
||||
function str($src, $indent = '') // {{{
|
||||
function str($code, $indent = '') // {{{
|
||||
{
|
||||
if (is_object($code)) {
|
||||
if (get_class($code) != 'Decompiler_Code') {
|
||||
$code = toCode($code, $indent);
|
||||
}
|
||||
return $code->__toString();
|
||||
}
|
||||
|
||||
return (string) $code;
|
||||
}
|
||||
// }}}
|
||||
function toCode($src, $indent = '') // {{{
|
||||
{
|
||||
if (is_array($indent)) {
|
||||
$indent = $indent['indent'];
|
||||
}
|
||||
|
||||
/*
|
||||
$e = xcache_get_special_value($src);
|
||||
if (isset($e)) {
|
||||
if (is_array($e)) {
|
||||
$src = $e;
|
||||
}
|
||||
else {
|
||||
return $e;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (is_array($src)) {
|
||||
exit('array str');
|
||||
$src = new Decompiler_Array($src, $indent);
|
||||
return $src->__toString();
|
||||
}
|
||||
|
||||
if (is_object($src)) {
|
||||
if (!method_exists($src, '__toString')) {
|
||||
if (!method_exists($src, 'toCode')) {
|
||||
var_dump($src);
|
||||
exit('no __toString');
|
||||
exit('no toCode');
|
||||
}
|
||||
return $src->__toString();
|
||||
return new Decompiler_Code($src->toCode($indent));
|
||||
}
|
||||
|
||||
return $src;
|
||||
return new Decompiler_Code($src);
|
||||
}
|
||||
// }}}
|
||||
function value($value) // {{{
|
||||
|
@ -54,11 +48,11 @@ function value($value) // {{{
|
|||
}
|
||||
}
|
||||
|
||||
if ($value instanceof Decompiler_Object) {
|
||||
if (is_a($value, 'Decompiler_Object')) {
|
||||
// use as is
|
||||
}
|
||||
else if (is_array($value)) {
|
||||
$value = new Decompiler_Array($value);
|
||||
$value = new Decompiler_ConstArray($value);
|
||||
}
|
||||
else {
|
||||
$value = new Decompiler_Value($value);
|
||||
|
@ -79,7 +73,7 @@ class Decompiler_Value extends Decompiler_Object // {{{
|
|||
$this->value = $value;
|
||||
}
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
return var_export($this->value, true);
|
||||
}
|
||||
|
@ -94,6 +88,11 @@ class Decompiler_Code extends Decompiler_Object // {{{
|
|||
$this->src = $src;
|
||||
}
|
||||
|
||||
function toCode($indent)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
function __toString()
|
||||
{
|
||||
return $this->src;
|
||||
|
@ -106,6 +105,7 @@ class Decompiler_Binop extends Decompiler_Code // {{{
|
|||
var $op1;
|
||||
var $op2;
|
||||
var $parent;
|
||||
var $indent;
|
||||
|
||||
function Decompiler_Binop($parent, $op1, $opc, $op2)
|
||||
{
|
||||
|
@ -115,17 +115,17 @@ class Decompiler_Binop extends Decompiler_Code // {{{
|
|||
$this->op2 = $op2;
|
||||
}
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
$op1 = str($this->op1);
|
||||
$op1 = toCode($this->op1, $indent);
|
||||
if (is_a($this->op1, 'Decompiler_Binop') && $this->op1->opc != $this->opc) {
|
||||
$op1 = "($op1)";
|
||||
}
|
||||
$opstr = $this->parent->binops[$this->opc];
|
||||
if ($op1 == '0' && $this->opc == XC_SUB) {
|
||||
return $opstr . str($this->op2);
|
||||
return $opstr . toCode($this->op2, $indent);
|
||||
}
|
||||
return $op1 . ' ' . $opstr . ' ' . str($this->op2);
|
||||
return $op1 . ' ' . $opstr . ' ' . toCode($this->op2, $indent);
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
@ -141,7 +141,7 @@ class Decompiler_Fetch extends Decompiler_Code // {{{
|
|||
$this->globalsrc = $globalsrc;
|
||||
}
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
switch ($this->fetchType) {
|
||||
case ZEND_FETCH_LOCAL:
|
||||
|
@ -167,9 +167,9 @@ class Decompiler_Box // {{{
|
|||
$this->obj = &$obj;
|
||||
}
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
return $this->obj->__toString();
|
||||
return $this->obj->toCode($indent);
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
@ -179,16 +179,16 @@ class Decompiler_Dim extends Decompiler_Value // {{{
|
|||
var $isLast = false;
|
||||
var $assign = null;
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
if (is_a($this->value, 'Decompiler_ListBox')) {
|
||||
$exp = str($this->value->obj->src);
|
||||
$exp = toCode($this->value->obj->src, $indent);
|
||||
}
|
||||
else {
|
||||
$exp = str($this->value);
|
||||
$exp = toCode($this->value, $indent);
|
||||
}
|
||||
foreach ($this->offsets as $dim) {
|
||||
$exp .= '[' . str($dim) . ']';
|
||||
$exp .= '[' . toCode($dim, $indent) . ']';
|
||||
}
|
||||
return $exp;
|
||||
}
|
||||
|
@ -204,16 +204,16 @@ class Decompiler_List extends Decompiler_Code // {{{
|
|||
var $dims = array();
|
||||
var $everLocked = false;
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
if (count($this->dims) == 1 && !$this->everLocked) {
|
||||
$dim = $this->dims[0];
|
||||
unset($dim->value);
|
||||
$dim->value = $this->src;
|
||||
if (!isset($dim->assign)) {
|
||||
return str($dim);
|
||||
return toCode($dim, $indent);
|
||||
}
|
||||
return str($this->dims[0]->assign) . ' = ' . str($dim);
|
||||
return toCode($this->dims[0]->assign, $indent) . ' = ' . toCode($dim, $indent);
|
||||
}
|
||||
/* flatten dims */
|
||||
$assigns = array();
|
||||
|
@ -222,9 +222,9 @@ class Decompiler_List extends Decompiler_Code // {{{
|
|||
foreach ($dim->offsets as $offset) {
|
||||
$assign = &$assign[$offset];
|
||||
}
|
||||
$assign = str($dim->assign);
|
||||
$assign = toCode($dim->assign, $indent);
|
||||
}
|
||||
return $this->toList($assigns) . ' = ' . str($this->src);
|
||||
return $this->toList($assigns) . ' = ' . toCode($this->src, $indent);
|
||||
}
|
||||
|
||||
function toList($assigns)
|
||||
|
@ -259,40 +259,55 @@ class Decompiler_ListBox extends Decompiler_Box // {{{
|
|||
// }}}
|
||||
class Decompiler_Array extends Decompiler_Value // {{{
|
||||
{
|
||||
var $indent = '';
|
||||
|
||||
function Decompiler_Array($value = array(), $indent = '')
|
||||
// emenets
|
||||
function Decompiler_Array()
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->indent = $indent;
|
||||
$this->value = array();
|
||||
}
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
$subindent = $indent . INDENT;
|
||||
|
||||
$elementsCode = array();
|
||||
$index = 0;
|
||||
foreach ($this->value as $element) {
|
||||
list($key, $value) = $element;
|
||||
if (!isset($key)) {
|
||||
$key = $index++;
|
||||
}
|
||||
$elementsCode[] = array(str($key, $subindent), str($value, $subindent), $key, $value);
|
||||
}
|
||||
|
||||
$exp = "array(";
|
||||
$indent = $this->indent . INDENT;
|
||||
$assoclen = 0;
|
||||
$indent = $indent . INDENT;
|
||||
$assocWidth = 0;
|
||||
$multiline = 0;
|
||||
$i = 0;
|
||||
foreach ($this->value as $k => $v) {
|
||||
if ($i !== $k) {
|
||||
$len = strlen($k);
|
||||
if ($assoclen < $len) {
|
||||
$assoclen = $len;
|
||||
foreach ($elementsCode as $element) {
|
||||
list($keyCode, $valueCode) = $element;
|
||||
if ((string) $i !== $keyCode) {
|
||||
$assocWidth = 1;
|
||||
break;
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
foreach ($elementsCode as $element) {
|
||||
list($keyCode, $valueCode, $key, $value) = $element;
|
||||
if ($assocWidth) {
|
||||
$len = strlen($keyCode);
|
||||
if ($assocWidth < $len) {
|
||||
$assocWidth = $len;
|
||||
}
|
||||
}
|
||||
if (is_array($v)) {
|
||||
if (is_array($value) || is_a($value, 'Decompiler_Array')) {
|
||||
$multiline ++;
|
||||
}
|
||||
++ $i;
|
||||
}
|
||||
if ($assoclen) {
|
||||
$assoclen += 2;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$subindent = $indent . INDENT;
|
||||
foreach ($this->value as $k => $v) {
|
||||
foreach ($elementsCode as $element) {
|
||||
list($keyCode, $value) = $element;
|
||||
if ($multiline) {
|
||||
if ($i) {
|
||||
$exp .= ",";
|
||||
|
@ -306,20 +321,21 @@ class Decompiler_Array extends Decompiler_Value // {{{
|
|||
}
|
||||
}
|
||||
|
||||
$k = var_export($k, true);
|
||||
if ($multiline) {
|
||||
$exp .= sprintf("%{$assoclen}s => ", $k);
|
||||
}
|
||||
else if ($assoclen) {
|
||||
$exp .= $k . ' => ';
|
||||
if ($assocWidth) {
|
||||
if ($multiline) {
|
||||
$exp .= sprintf("%-{$assocWidth}s => ", $keyCode);
|
||||
}
|
||||
else {
|
||||
$exp .= $keyCode . ' => ';
|
||||
}
|
||||
}
|
||||
|
||||
$exp .= str(value($v), $subindent);
|
||||
$exp .= $value;
|
||||
|
||||
$i ++;
|
||||
}
|
||||
if ($multiline) {
|
||||
$exp .= "$indent);";
|
||||
$exp .= "\n$indent)";
|
||||
}
|
||||
else {
|
||||
$exp .= ")";
|
||||
|
@ -328,11 +344,23 @@ class Decompiler_Array extends Decompiler_Value // {{{
|
|||
}
|
||||
}
|
||||
// }}}
|
||||
class Decompiler_ConstArray extends Decompiler_Array // {{{
|
||||
{
|
||||
function Decompiler_ConstArray($array)
|
||||
{
|
||||
$elements = array();
|
||||
foreach ($array as $key => $value) {
|
||||
$elements[] = array(value($key), value($value));
|
||||
}
|
||||
$this->value = $elements;
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
class Decompiler_ForeachBox extends Decompiler_Box // {{{
|
||||
{
|
||||
var $iskey;
|
||||
|
||||
function __toString()
|
||||
function toCode($indent)
|
||||
{
|
||||
return 'foreach (' . '';
|
||||
}
|
||||
|
@ -416,7 +444,7 @@ class Decompiler
|
|||
}
|
||||
$curticks = $toticks;
|
||||
}
|
||||
echo $indent, str($op['php']), ";\n";
|
||||
echo $indent, toCode($op['php'], $indent), ";\n";
|
||||
}
|
||||
}
|
||||
if ($curticks) {
|
||||
|
@ -428,14 +456,14 @@ class Decompiler
|
|||
{
|
||||
switch ($op['op_type']) {
|
||||
case XC_IS_CONST:
|
||||
return str(value($op['constant']));
|
||||
return toCode(value($op['constant']), $EX);
|
||||
|
||||
case XC_IS_VAR:
|
||||
case XC_IS_TMP_VAR:
|
||||
$T = &$EX['Ts'];
|
||||
$ret = $T[$op['var']];
|
||||
if ($tostr) {
|
||||
$ret = str($ret, $EX);
|
||||
$ret = toCode($ret, $EX);
|
||||
}
|
||||
if ($free) {
|
||||
unset($T[$op['var']]);
|
||||
|
@ -465,14 +493,8 @@ class Decompiler
|
|||
return $ret;
|
||||
}
|
||||
// }}}
|
||||
function &dop_array($op_array, $indent = '') // {{{
|
||||
function &fixOpcode($opcodes, $removeTailing = false, $defaultReturnValue = null) // {{{
|
||||
{
|
||||
$opcodes = &$op_array['opcodes'];
|
||||
$last = count($opcodes) - 1;
|
||||
if ($opcodes[$last]['opcode'] == XC_HANDLE_EXCEPTION) {
|
||||
unset($opcodes[$last]);
|
||||
}
|
||||
$EX['indent'] = '';
|
||||
for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
|
||||
if (function_exists('xcache_get_fixed_opcode')) {
|
||||
$opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
|
||||
|
@ -504,6 +526,29 @@ class Decompiler
|
|||
$opcodes[$i] = $op;
|
||||
}
|
||||
}
|
||||
|
||||
if ($removeTailing) {
|
||||
$last = count($opcodes) - 1;
|
||||
if ($opcodes[$last]['opcode'] == XC_HANDLE_EXCEPTION) {
|
||||
unset($opcodes[$last]);
|
||||
--$last;
|
||||
}
|
||||
if ($opcodes[$last]['opcode'] == XC_RETURN) {
|
||||
$op1 = $opcodes[$last]['op1'];
|
||||
if ($op1['op_type'] == XC_IS_CONST && array_key_exists('constant', $op1) && $op1['constant'] === $defaultReturnValue) {
|
||||
unset($opcodes[$last]);
|
||||
--$last;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $opcodes;
|
||||
}
|
||||
// }}}
|
||||
function &dop_array($op_array, $indent = '') // {{{
|
||||
{
|
||||
$op_array['opcodes'] = $this->fixOpcode($op_array['opcodes'], true, $indent == '' ? 1 : null);
|
||||
$opcodes = &$op_array['opcodes'];
|
||||
$EX['indent'] = '';
|
||||
// {{{ build jmp array
|
||||
for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
|
||||
$op = &$opcodes[$i];
|
||||
|
@ -632,11 +677,11 @@ class Decompiler
|
|||
$this->outputCode($EX, $opline, $end /* - 1 skip last jmp */, $indent . INDENT);
|
||||
$body = ob_get_clean();
|
||||
|
||||
$as = str($op['fe_as']);
|
||||
$as = toCode($op['fe_as'], $EX);
|
||||
if (isset($op['fe_key'])) {
|
||||
$as = str($op['fe_key']) . ' => ' . $as;
|
||||
$as = toCode($op['fe_key'], $EX) . ' => ' . $as;
|
||||
}
|
||||
echo "{$indent}foreach (" . str($op['fe_src']) . " as $as) {\n";
|
||||
echo "{$indent}foreach (" . toCode($op['fe_src'], $EX) . " as $as) {\n";
|
||||
echo $body;
|
||||
echo "{$indent}}";
|
||||
// $this->outputCode($EX, $next, $last, $indent);
|
||||
|
@ -756,7 +801,7 @@ class Decompiler
|
|||
// $this->dumpop($op, $EX); //var_dump($op);
|
||||
|
||||
$resvar = null;
|
||||
if (isset($res['EA.type']) && ($res['EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
|
||||
if ((ZEND_ENGINE_2_4 ? ($res['op_type'] & EXT_TYPE_UNUSED) : ($res['EA.type'] & EXT_TYPE_UNUSED)) || $res['op_type'] == XC_IS_UNUSED) {
|
||||
$istmpres = false;
|
||||
}
|
||||
else {
|
||||
|
@ -790,14 +835,14 @@ class Decompiler
|
|||
$EX['object'] = (int) $res['var'];
|
||||
$EX['called_scope'] = null;
|
||||
$EX['fbc'] = 'new ' . $this->unquoteName($this->getOpVal($op1, $EX));
|
||||
if (PHP_VERSION < 5) {
|
||||
if (!ZEND_ENGINE_2) {
|
||||
$resvar = '$new object$';
|
||||
}
|
||||
break;
|
||||
// }}}
|
||||
case XC_FETCH_CLASS: // {{{
|
||||
if ($op2['op_type'] == XC_IS_UNUSED) {
|
||||
switch ($ext) {
|
||||
switch (($ext & (defined('ZEND_FETCH_CLASS_MASK') ? ZEND_FETCH_CLASS_MASK : 0xFF))) {
|
||||
case ZEND_FETCH_CLASS_SELF:
|
||||
$class = 'self';
|
||||
break;
|
||||
|
@ -842,7 +887,12 @@ class Decompiler
|
|||
case XC_FETCH_IS:
|
||||
case XC_UNSET_VAR:
|
||||
$rvalue = $this->getOpVal($op1, $EX);
|
||||
$fetchtype = $op2[PHP_VERSION < 5 ? 'fetch_type' : 'EA.type'];
|
||||
if (defined('ZEND_FETCH_TYPE_MASK')) {
|
||||
$fetchtype = ($ext & ZEND_FETCH_TYPE_MASK);
|
||||
}
|
||||
else {
|
||||
$fetchtype = $op2[!ZEND_ENGINE_2 ? 'fetch_type' : 'EA.type'];
|
||||
}
|
||||
switch ($fetchtype) {
|
||||
case ZEND_FETCH_STATIC_MEMBER:
|
||||
$class = $this->getOpVal($op2, $EX);
|
||||
|
@ -855,7 +905,7 @@ class Decompiler
|
|||
break;
|
||||
}
|
||||
if ($opc == XC_UNSET_VAR) {
|
||||
$op['php'] = "unset(" . str($rvalue) . ")";
|
||||
$op['php'] = "unset(" . toCode($rvalue, $EX) . ")";
|
||||
$lastphpop = &$op;
|
||||
}
|
||||
else if ($res['op_type'] != XC_IS_UNUSED) {
|
||||
|
@ -916,10 +966,10 @@ class Decompiler
|
|||
$lvalue = $rvalue;
|
||||
++ $i;
|
||||
$rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
|
||||
$resvar = str($lvalue) . ' = ' . $rvalue;
|
||||
$resvar = toCode($lvalue, $EX) . ' = ' . $rvalue;
|
||||
}
|
||||
else if ($opc == XC_UNSET_DIM) {
|
||||
$op['php'] = "unset(" . str($rvalue) . ")";
|
||||
$op['php'] = "unset(" . toCode($rvalue, $EX) . ")";
|
||||
$lastphpop = &$op;
|
||||
}
|
||||
else if ($res['op_type'] != XC_IS_UNUSED) {
|
||||
|
@ -940,22 +990,23 @@ class Decompiler
|
|||
$dim = &$rvalue->obj;
|
||||
$dim->assign = $lvalue;
|
||||
if ($dim->isLast) {
|
||||
$resvar = str($dim->value);
|
||||
$resvar = toCode($dim->value, $EX);
|
||||
}
|
||||
unset($dim);
|
||||
break;
|
||||
}
|
||||
$resvar = "$lvalue = " . str($rvalue, $EX);
|
||||
$resvar = "$lvalue = " . toCode($rvalue, $EX);
|
||||
break;
|
||||
// }}}
|
||||
case XC_ASSIGN_REF: // {{{
|
||||
$lvalue = $this->getOpVal($op1, $EX);
|
||||
$rvalue = $this->getOpVal($op2, $EX, false);
|
||||
if (is_a($rvalue, 'Decompiler_Fetch')) {
|
||||
$src = str($rvalue->src);
|
||||
$src = toCode($rvalue->src, $EX);
|
||||
if (substr($src, 1, -1) == substr($lvalue, 1)) {
|
||||
switch ($rvalue->fetchType) {
|
||||
case ZEND_FETCH_GLOBAL:
|
||||
case ZEND_FETCH_GLOBAL_LOCK:
|
||||
$resvar = 'global ' . $lvalue;
|
||||
break 2;
|
||||
case ZEND_FETCH_STATIC:
|
||||
|
@ -965,14 +1016,16 @@ class Decompiler
|
|||
if (isset($statics[$name])) {
|
||||
$var = $statics[$name];
|
||||
$resvar .= ' = ';
|
||||
$resvar .= str(value($var), $EX);
|
||||
$resvar .= toCode(value($var), $EX);
|
||||
}
|
||||
unset($statics);
|
||||
break 2;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
$rvalue = str($rvalue);
|
||||
// TODO: PHP_6 global
|
||||
$rvalue = toCode($rvalue, $EX);
|
||||
$resvar = "$lvalue = &$rvalue";
|
||||
break;
|
||||
// }}}
|
||||
|
@ -1017,7 +1070,7 @@ class Decompiler
|
|||
$rvalue = '$' . substr($rvalue, 1, -1);
|
||||
}
|
||||
else {
|
||||
$rvalue = "${" . $rvalue . "}";
|
||||
$rvalue = '${' . $rvalue . '}';
|
||||
}
|
||||
if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
|
||||
$class = $this->getOpVal($op2, $EX);
|
||||
|
@ -1043,7 +1096,7 @@ class Decompiler
|
|||
}
|
||||
}
|
||||
|
||||
switch ((PHP_VERSION < 5 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) {
|
||||
switch ((!ZEND_ENGINE_2 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) {
|
||||
case ZEND_ISSET:
|
||||
$rvalue = "isset($rvalue)";
|
||||
break;
|
||||
|
@ -1185,10 +1238,10 @@ class Decompiler
|
|||
$op2val = $this->getOpVal($op2, $EX);
|
||||
switch ($opc) {
|
||||
case XC_ADD_CHAR:
|
||||
$op2val = str(chr($op2val), $EX);
|
||||
$op2val = toCode(chr($op2val), $EX);
|
||||
break;
|
||||
case XC_ADD_STRING:
|
||||
$op2val = str($op2val, $EX);
|
||||
$op2val = toCode($op2val, $EX);
|
||||
break;
|
||||
case XC_ADD_VAR:
|
||||
break;
|
||||
|
@ -1225,12 +1278,12 @@ class Decompiler
|
|||
$rvalue = $this->getOpVal($op1, $EX, false, true);
|
||||
|
||||
if ($opc == XC_ADD_ARRAY_ELEMENT) {
|
||||
$offset = $this->getOpVal($op2, $EX);
|
||||
if (isset($offset)) {
|
||||
$T[$res['var']]->value[$offset] = $rvalue;
|
||||
$assoc = $this->getOpVal($op2, $EX);
|
||||
if (isset($assoc)) {
|
||||
$T[$res['var']]->value[] = array($assoc, $rvalue);
|
||||
}
|
||||
else {
|
||||
$T[$res['var']]->value[] = $rvalue;
|
||||
$T[$res['var']]->value[] = array(null, $rvalue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1241,12 +1294,12 @@ class Decompiler
|
|||
}
|
||||
}
|
||||
|
||||
$offset = $this->getOpVal($op2, $EX);
|
||||
if (isset($offset)) {
|
||||
$resvar->value[$offset] = $rvalue;
|
||||
$assoc = $this->getOpVal($op2, $EX);
|
||||
if (isset($assoc)) {
|
||||
$resvar->value[] = array($assoc, $rvalue);
|
||||
}
|
||||
else {
|
||||
$resvar->value[] = $rvalue;
|
||||
$resvar->value[] = array(null, $rvalue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1328,10 +1381,10 @@ class Decompiler
|
|||
if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX || $opc == XC_JMPZ) {
|
||||
$targetop = &$EX['opcodes'][$op2['opline_num']];
|
||||
if ($opc == XC_JMPNZ_EX) {
|
||||
$targetop['cond_true'][] = str($rvalue);
|
||||
$targetop['cond_true'][] = toCode($rvalue, $EX);
|
||||
}
|
||||
else {
|
||||
$targetop['cond_false'][] = str($rvalue);
|
||||
$targetop['cond_false'][] = toCode($rvalue, $EX);
|
||||
}
|
||||
unset($targetop);
|
||||
}
|
||||
|
@ -1359,7 +1412,7 @@ class Decompiler
|
|||
else {
|
||||
$default = null;
|
||||
}
|
||||
$EX['recvs'][$offset] = array($lvalue, $default);
|
||||
$EX['recvs'][str($offset)] = array($lvalue, $default);
|
||||
break;
|
||||
case XC_POST_DEC:
|
||||
case XC_POST_INC:
|
||||
|
@ -1399,7 +1452,7 @@ class Decompiler
|
|||
// }}}
|
||||
case XC_END_SILENCE: // {{{
|
||||
$EX['silence'] --;
|
||||
$lastresvar = '@' . str($lastresvar);
|
||||
$lastresvar = '@' . toCode($lastresvar, $EX);
|
||||
break;
|
||||
// }}}
|
||||
case XC_CONT: // {{{
|
||||
|
@ -1469,7 +1522,7 @@ class Decompiler
|
|||
for ($i = 0; $i < $n; $i ++) {
|
||||
$a = array_pop($EX['argstack']);
|
||||
if (is_array($a)) {
|
||||
array_unshift($args, str($a, $EX));
|
||||
array_unshift($args, toCode($a, $EX));
|
||||
}
|
||||
else {
|
||||
array_unshift($args, $a);
|
||||
|
@ -1510,6 +1563,8 @@ class Decompiler
|
|||
|
||||
default:
|
||||
if ($kk == 'res') {
|
||||
var_dump($op);
|
||||
exit;
|
||||
assert(0);
|
||||
}
|
||||
else {
|
||||
|
@ -1524,7 +1579,6 @@ class Decompiler
|
|||
// }}}
|
||||
function dargs(&$EX, $indent) // {{{
|
||||
{
|
||||
$EX['indent'] = $indent;
|
||||
$op_array = &$EX['op_array'];
|
||||
|
||||
if (isset($op_array['num_args'])) {
|
||||
|
@ -1543,17 +1597,18 @@ class Decompiler
|
|||
if ($i) {
|
||||
echo ', ';
|
||||
}
|
||||
$arg = $EX['recvs'][$i + 1];
|
||||
if (isset($op_array['arg_info'])) {
|
||||
$ai = $op_array['arg_info'][$i];
|
||||
if (!empty($ai['class_name'])) {
|
||||
echo $ai['class_name'], ' ';
|
||||
if ($ai['allow_null']) {
|
||||
if (!ZEND_ENGINE_2_2 && $ai['allow_null']) {
|
||||
echo 'or NULL ';
|
||||
}
|
||||
}
|
||||
else if (!empty($ai['array_type_hint'])) {
|
||||
echo 'array ';
|
||||
if ($ai['allow_null']) {
|
||||
if (!ZEND_ENGINE_2_2 && $ai['allow_null']) {
|
||||
echo 'or NULL ';
|
||||
}
|
||||
}
|
||||
|
@ -1582,11 +1637,10 @@ class Decompiler
|
|||
assert(0);
|
||||
}
|
||||
}
|
||||
$arg = $EX['recvs'][$i + 1];
|
||||
echo str($arg[0]);
|
||||
if (isset($arg[1])) {
|
||||
echo ' = ', str($arg[1]);
|
||||
}
|
||||
echo toCode($arg[0], $indent);
|
||||
}
|
||||
if (isset($arg[1])) {
|
||||
echo ' = ', toCode($arg[1], $indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1662,17 +1716,18 @@ class Decompiler
|
|||
foreach ($class[$type] as $name => $v) {
|
||||
echo $newindent;
|
||||
echo $prefix, $name, ' = ';
|
||||
echo str(value($v), $EX);
|
||||
echo toCode(value($v), $newindent);
|
||||
echo ";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
// {{{ properties
|
||||
if (!empty($class['default_properties']) || !empty($class['default_static_members'])) {
|
||||
$member_variables = isset($class['properties_info']) ? $class['properties_info'] : ($class['default_static_members'] + $class['default_properties']);
|
||||
if ($member_variables) {
|
||||
echo "\n";
|
||||
$infos = !empty($class['properties_info']) ? $class['properties_info'] : null;
|
||||
foreach (!empty($class['properties_info']) ? $class['properties_info'] : ($class['default_static_members'] + $class['default_properties']) as $name => $dummy) {
|
||||
foreach ($member_variables as $name => $dummy) {
|
||||
$info = (isset($infos) && isset($infos[$name])) ? $infos[$name] : null;
|
||||
if (isset($info)) {
|
||||
if (!empty($info['doc_comment'])) {
|
||||
|
@ -1698,7 +1753,7 @@ class Decompiler
|
|||
}
|
||||
|
||||
$mangled = false;
|
||||
if (PHP_VERSION < 5) {
|
||||
if (!ZEND_ENGINE_2) {
|
||||
echo 'var ';
|
||||
}
|
||||
else if (!isset($info)) {
|
||||
|
@ -1725,12 +1780,17 @@ class Decompiler
|
|||
|
||||
echo '$', $name;
|
||||
|
||||
$key = isset($info) ? $info['name'] . ($mangled ? "\000" : "") : $name;
|
||||
if (isset($info['offset'])) {
|
||||
$value = $class[$static ? 'default_static_members_table' : 'default_properties_table'][$info['offset']];
|
||||
}
|
||||
else {
|
||||
$key = isset($info) ? $info['name'] . ($mangled ? "\000" : "") : $name;
|
||||
|
||||
$value = $class[$static ? 'default_static_members' : 'default_properties'][$key];
|
||||
$value = $class[$static ? 'default_static_members' : 'default_properties'][$key];
|
||||
}
|
||||
if (isset($value)) {
|
||||
echo ' = ';
|
||||
echo str(value($value));
|
||||
echo toCode(value($value), $newindent);
|
||||
}
|
||||
echo ";\n";
|
||||
}
|
||||
|
@ -1855,11 +1915,29 @@ define('ZEND_ACC_ALLOW_STATIC', 0x10000);
|
|||
|
||||
define('ZEND_ACC_SHADOW', 0x2000);
|
||||
|
||||
define('ZEND_FETCH_GLOBAL', 0);
|
||||
define('ZEND_FETCH_LOCAL', 1);
|
||||
define('ZEND_FETCH_STATIC', 2);
|
||||
define('ZEND_FETCH_STATIC_MEMBER', 3);
|
||||
define('ZEND_FETCH_GLOBAL_LOCK', 4);
|
||||
define('ZEND_ENGINE_2_4', PHP_VERSION >= "5.3.99");
|
||||
define('ZEND_ENGINE_2_3', ZEND_ENGINE_2_4 || PHP_VERSION >= "5.3.");
|
||||
define('ZEND_ENGINE_2_2', ZEND_ENGINE_2_3 || PHP_VERSION >= "5.2.");
|
||||
define('ZEND_ENGINE_2_1', ZEND_ENGINE_2_2 || PHP_VERSION >= "5.1.");
|
||||
define('ZEND_ENGINE_2', ZEND_ENGINE_2_1 || PHP_VERSION >= "5.0.");
|
||||
|
||||
if (ZEND_ENGINE_2_4) {
|
||||
define('ZEND_FETCH_GLOBAL', 0x00000000);
|
||||
define('ZEND_FETCH_LOCAL', 0x10000000);
|
||||
define('ZEND_FETCH_STATIC', 0x20000000);
|
||||
define('ZEND_FETCH_STATIC_MEMBER', 0x30000000);
|
||||
define('ZEND_FETCH_GLOBAL_LOCK', 0x40000000);
|
||||
define('ZEND_FETCH_LEXICAL', 0x50000000);
|
||||
|
||||
define('ZEND_FETCH_TYPE_MASK', 0x70000000);
|
||||
}
|
||||
else {
|
||||
define('ZEND_FETCH_GLOBAL', 0);
|
||||
define('ZEND_FETCH_LOCAL', 1);
|
||||
define('ZEND_FETCH_STATIC', 2);
|
||||
define('ZEND_FETCH_STATIC_MEMBER', 3);
|
||||
define('ZEND_FETCH_GLOBAL_LOCK', 4);
|
||||
}
|
||||
|
||||
define('ZEND_FETCH_CLASS_DEFAULT', 0);
|
||||
define('ZEND_FETCH_CLASS_SELF', 1);
|
||||
|
@ -1869,6 +1947,12 @@ define('ZEND_FETCH_CLASS_GLOBAL', 4);
|
|||
define('ZEND_FETCH_CLASS_AUTO', 5);
|
||||
define('ZEND_FETCH_CLASS_INTERFACE', 6);
|
||||
define('ZEND_FETCH_CLASS_STATIC', 7);
|
||||
if (ZEND_ENGINE_2_4) {
|
||||
define('ZEND_FETCH_CLASS_TRAIT', 14);
|
||||
}
|
||||
if (ZEND_ENGINE_2_3) {
|
||||
define('ZEND_FETCH_CLASS_MASK', 0xF);
|
||||
}
|
||||
|
||||
define('ZEND_EVAL', (1<<0));
|
||||
define('ZEND_INCLUDE', (1<<1));
|
||||
|
@ -1878,7 +1962,12 @@ define('ZEND_REQUIRE_ONCE', (1<<4));
|
|||
|
||||
define('ZEND_ISSET', (1<<0));
|
||||
define('ZEND_ISEMPTY', (1<<1));
|
||||
define('EXT_TYPE_UNUSED', (1<<0));
|
||||
if (ZEND_ENGINE_2_4) {
|
||||
define('EXT_TYPE_UNUSED', (1<<5));
|
||||
}
|
||||
else {
|
||||
define('EXT_TYPE_UNUSED', (1<<0));
|
||||
}
|
||||
|
||||
define('ZEND_FETCH_STANDARD', 0);
|
||||
define('ZEND_FETCH_ADD_LOCK', 1);
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
class ClassName
|
||||
{
|
||||
/** doc */
|
||||
static public $static = array(
|
||||
array('array'),
|
||||
'str'
|
||||
);
|
||||
/** doc */
|
||||
static public $public_static = array(2, 'str');
|
||||
/** doc */
|
||||
static private $private_static = array(2, 'str');
|
||||
/** doc */
|
||||
static protected $protected_static = array(2, 'str');
|
||||
/** doc */
|
||||
public $property = array(
|
||||
array('array'),
|
||||
'str'
|
||||
);
|
||||
/** doc */
|
||||
public $public_property = array(2, 'str');
|
||||
/** doc */
|
||||
private $private_property = array(2, 'str');
|
||||
/** doc */
|
||||
protected $protected_property = array(2, 'str');
|
||||
|
||||
/** doc */
|
||||
public function __construct($a, $b)
|
||||
{
|
||||
}
|
||||
|
||||
/** doc */
|
||||
public function method(array $a = NULL, $b = NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/** doc */
|
||||
public function publicMethod(ClassName $a = NULL, $b = 2)
|
||||
{
|
||||
}
|
||||
|
||||
/** doc */
|
||||
protected function protectedMethod(ClassName $a, $b = array(
|
||||
array('array')
|
||||
))
|
||||
{
|
||||
$runtimeArray = array('1');
|
||||
$runtimeArray2 = array(
|
||||
'1',
|
||||
array()
|
||||
);
|
||||
$runtimeArray3 = array(
|
||||
'a' => '1',
|
||||
2 => array()
|
||||
);
|
||||
return 'protected';
|
||||
}
|
||||
|
||||
/** doc */
|
||||
private function privateMethod(ClassName $a, $b = NULL)
|
||||
{
|
||||
return 'private';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
20
phpdop.phpr
20
phpdop.phpr
|
@ -2,6 +2,7 @@
|
|||
<?php
|
||||
|
||||
$srcdir = dirname(__FILE__);
|
||||
require_once("$srcdir/Decompiler.class.php");
|
||||
if (file_exists("$srcdir/phpdc.debug.php")) {
|
||||
include("$srcdir/phpdc.debug.php");
|
||||
}
|
||||
|
@ -10,31 +11,33 @@ function get_op($op)
|
|||
{
|
||||
switch ($op['op_type']) {
|
||||
case 1: // CONST
|
||||
return var_export($op['u.constant'], true);
|
||||
return var_export($op['constant'], true);
|
||||
|
||||
case 2: // IS_TMP_VAR
|
||||
return 't@' . $op['u.var'];
|
||||
return 't@' . $op['var'];
|
||||
|
||||
case 4:
|
||||
return 'v$' . $op['u.var'];
|
||||
return 'v$' . $op['var'];
|
||||
|
||||
case 8: // UNUSED
|
||||
if (isset($op['u.opline_num'])) {
|
||||
return 'l#' . $op['u.opline_num'];
|
||||
if (isset($op['opline_num'])) {
|
||||
return 'l#' . $op['opline_num'];
|
||||
}
|
||||
else {
|
||||
return '-';
|
||||
}
|
||||
|
||||
default:
|
||||
return $op['op_type'] . $op['u.var'];
|
||||
return $op['op_type'] . $op['var'];
|
||||
}
|
||||
}
|
||||
|
||||
function dump_opcodes($op_array, $indent = '')
|
||||
function dump_opcodes($opcodes, $indent = '')
|
||||
{
|
||||
global $decompiler;
|
||||
|
||||
$types = array('result' => 5, 'op1' => 20, 'op2' => 20);
|
||||
foreach ($op_array as $line => $op) {
|
||||
foreach ($decompiler->fixOpcode($opcodes) as $line => $op) {
|
||||
echo $indent;
|
||||
echo sprintf("%3d ", $op['lineno']);
|
||||
echo sprintf("%3x ", $line);
|
||||
|
@ -90,6 +93,7 @@ function dump_class($name, $class, $indent = '')
|
|||
if (!isset($argv[1])) {
|
||||
die("Usage: $argv[0] <file>\n");
|
||||
}
|
||||
$decompiler = new Decompiler();
|
||||
$pk = xcache_dasm_file($argv[1]);
|
||||
$op_array = $funcs = $classes = null;
|
||||
if (isset($pk['op_array'])) {
|
||||
|
|
|
@ -135,7 +135,7 @@ IFASSERT(`
|
|||
#undef C_RELAYLINE
|
||||
#define C_RELAYLINE , __LINE__
|
||||
')
|
||||
static inline void xc_calc_string_n(xc_processor_t *processor, zend_uchar type, const zstr str, long size IFASSERT(`, int relayline')) {
|
||||
static inline void xc_calc_string_n(xc_processor_t *processor, zend_uchar type, const zstr const str, long size IFASSERT(`, int relayline')) {
|
||||
pushdef(`__LINE__', `relayline')
|
||||
int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size);
|
||||
long dummy = 1;
|
||||
|
@ -157,7 +157,7 @@ static inline void xc_calc_string_n(xc_processor_t *processor, zend_uchar type,
|
|||
/* }}} */
|
||||
/* {{{ xc_store_string_n */
|
||||
REDEF(`KIND', `store')
|
||||
static inline zstr xc_store_string_n(xc_processor_t *processor, zend_uchar type, const zstr str, long size IFASSERT(`, int relayline')) {
|
||||
static inline zstr xc_store_string_n(xc_processor_t *processor, zend_uchar type, const zstr const str, long size IFASSERT(`, int relayline')) {
|
||||
pushdef(`__LINE__', `relayline')
|
||||
int realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size);
|
||||
zstr ret, *pret;
|
||||
|
|
|
@ -324,10 +324,10 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{
|
|||
|
||||
#ifdef ZEND_ENGINE_2_4
|
||||
DISPATCH(int, default_properties_count)
|
||||
STRUCT_ARRAY(default_properties_count, zval, default_properties_table)
|
||||
STRUCT_ARRAY(default_properties_count, zval_ptr, default_properties_table)
|
||||
DISPATCH(int, default_static_members_count)
|
||||
STRUCT_ARRAY(default_static_members_count, zval, default_static_members_table)
|
||||
IFCOPY(`dst->static_members_table = &dst->default_static_members_table;')
|
||||
STRUCT_ARRAY(default_static_members_count, zval_ptr, default_static_members_table)
|
||||
IFCOPY(`dst->static_members_table = dst->default_static_members_table;')
|
||||
DONE(static_members_table)
|
||||
#else
|
||||
IFCOPY(`dst->builtin_functions = src->builtin_functions;')
|
||||
|
|
Loading…
Reference in New Issue