1
0
Fork 0

Decompiler: mark jmpouts for BRK/CONT, unmark after decompiled with complex block

This commit is contained in:
Xuefer 2015-06-15 14:03:48 +08:00
parent 813986f735
commit ade274ea0f
1 changed files with 48 additions and 0 deletions

View File

@ -1078,6 +1078,7 @@ class Decompiler
$this->beginComplexBlock($EX);
echo $indent, 'for (', str($initial, $EX), '; ', implode(', ', $conditionCodes), '; ', implode(', ', $nextCodes), ') ', '{', PHP_EOL;
$this->clearJmpInfo_brk_cont($bodyRange);
$this->beginScope($EX);
$this->recognizeAndDecompileClosedBlocks($bodyRange);
$this->endScope($EX);
@ -1213,6 +1214,7 @@ class Decompiler
if ($firstOp['opcode'] == XC_CASE && !empty($lastOp['jmptos'])
|| $firstOp['opcode'] == XC_JMP && !empty($firstOp['jmptos']) && $opcodes[$firstOp['jmptos'][0]]['opcode'] == XC_CASE && !empty($lastOp['jmptos'])
) {
$this->clearJmpInfo_brk_cont($range);
$cases = array();
$caseDefault = null;
$caseOp = null;
@ -1302,6 +1304,7 @@ class Decompiler
if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmptos'])
&& $lastOp['jmptos'][0] == $range[0]) {
$this->removeJmpInfo($EX, $range[1]);
$this->clearJmpInfo_brk_cont($range);
$this->beginComplexBlock($EX);
echo $indent, "do {", PHP_EOL;
@ -1368,6 +1371,7 @@ class Decompiler
&& !empty($lastJmpOp['jmptos']) && $lastJmpOp['jmptos'][0] == $firstJmpOp['line']) {
$this->removeJmpInfo($EX, $firstJmpOp['line']);
$this->removeJmpInfo($EX, $lastJmpOp['line']);
$this->clearJmpInfo_brk_cont($range);
$this->beginComplexBlock($EX);
ob_start();
@ -1459,7 +1463,31 @@ class Decompiler
switch ($op['opcode']) {
case XC_CONT:
case XC_BRK:
$jmpTo = null;
if ($op['op2']['op_type'] == XC_IS_CONST && is_int($op['op2']['constant'])) {
$nestedLevel = $op['op2']['constant'];
$arrayOffset = $op['op1']['opline_num'];
// zend_brk_cont
while ($nestedLevel-- > 0) {
if ($arrayOffset == -1) {
$jmpTo = null;
break;
}
if (!isset($op_array['brk_cont_array'][$arrayOffset])) {
fprintf(STDERR, "%d: brk/cont not found at #$i\n", __LINE__);
break;
}
$jmpTo = $op_array['brk_cont_array'][$arrayOffset];
$arrayOffset = $jmpTo['parent'];
}
}
$op['jmptos'] = array();
if (isset($jmpTo)) {
$jmpTo = $jmpTo[$op['opcode'] == XC_CONT ? 'cont' : 'brk'];
$op['jmptos'][] = $jmpTo;
$opcodes[$jmpTo]['jmpfroms'][] = $i;
}
break;
case XC_GOTO:
@ -1567,6 +1595,26 @@ class Decompiler
}
}
// }}}
function clearJmpInfo_brk_cont($range) // {{{ clear jmpfroms/jmptos for BRK/CONT relative to this range only
{
$opcodes = &$range['EX']['opcodes'];
for ($i = $range[0]; $i <= $range[1]; $i++) {
$op = &$opcodes[$i];
switch ($op['opcode']) {
case XC_CONT:
case XC_BRK:
if (!empty($op['jmptos'])) {
if ($op['jmptos'][0] == $range[0]
|| $op['jmptos'][0] == $range[1] + 1) {
$this->removeJmpInfo($range['EX'], $i);
}
}
break;
}
}
unset($op);
}
// }}}
function &dop_array($op_array, $indent = '') // {{{
{
$op_array['opcodes'] = $this->fixOpCode($op_array['opcodes'], true, $indent == '' ? 1 : null);