Changeset 800 for trunk/Decompiler.class.php
- Timestamp:
- 04/27/2011 04:45:42 AM (2 years ago)
- Files:
-
- 1 modified
-
trunk/Decompiler.class.php (modified) (27 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Decompiler.class.php
r799 r800 555 555 } 556 556 // }}} 557 function outputPhp(&$EX, $ opline, $last, $indent) // {{{557 function outputPhp(&$EX, $range, $indent) // {{{ 558 558 { 559 559 $needBlankline = isset($EX['lastBlock']); 560 560 $origindent = $indent; 561 561 $curticks = 0; 562 for ($i = $ opline; $i <= $last; $i ++) {562 for ($i = $range[0]; $i <= $range[1]; $i ++) { 563 563 $op = $EX['opcodes'][$i]; 564 564 if (isset($op['gofrom'])) { … … 699 699 } 700 700 // }}} 701 function decompileBasicBlock(&$EX, $ first, $last, $indent) // {{{702 { 703 $this->dasmBasicBlock($EX, $ first, $last);704 // $this->dumpRange($EX, $ first, $last, $indent);705 $this->outputPhp($EX, $ first, $last, $indent);701 function decompileBasicBlock(&$EX, $range, $indent) // {{{ 702 { 703 $this->dasmBasicBlock($EX, $range); 704 // $this->dumpRange($EX, $range, $indent); 705 $this->outputPhp($EX, $range, $indent); 706 706 } 707 707 // }}} … … 732 732 } 733 733 // }}} 734 function decompileComplexBlock(&$EX, $ first, $last, $indent) // {{{734 function decompileComplexBlock(&$EX, $range, $indent) // {{{ 735 735 { 736 736 $T = &$EX['Ts']; 737 737 $opcodes = &$EX['opcodes']; 738 738 739 $firstOp = &$opcodes[$ first];740 $lastOp = &$opcodes[$ last];739 $firstOp = &$opcodes[$range[0]]; 740 $lastOp = &$opcodes[$range[1]]; 741 741 742 742 // {{{ ?: excludign JMP_SET 743 743 if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts']) 744 && $ last >= $first+ 3744 && $range[1] >= $range[0] + 3 745 745 && $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN 746 && $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $ last+ 1746 && $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $range[1] + 1 747 747 && $lastOp['opcode'] == XC_QM_ASSIGN 748 748 ) { 749 $trueFirst = $first + 1; 750 $trueLast = $firstOp['jmpouts'][0] - 2; 751 $falseFirst = $firstOp['jmpouts'][0]; 752 $falseLast = $last; 753 $this->removeJmpInfo($EX, $first); 749 $trueRange = array($range[0] + 1, $firstOp['jmpouts'][0] - 2); 750 $falseRange = array($firstOp['jmpouts'][0], $range[1]); 751 $this->removeJmpInfo($EX, $range[0]); 754 752 755 753 $condition = $this->getOpVal($firstOp['op1'], $EX); 756 $this->recognizeAndDecompileClosedBlocks($EX, $true First, $trueLast, $indent . INDENT);757 $trueValue = $this->getOpVal($opcodes[$true Last]['op1'], $EX, false, true);758 $this->recognizeAndDecompileClosedBlocks($EX, $false First, $falseLast, $indent . INDENT);759 $falseValue = $this->getOpVal($opcodes[$false Last]['op1'], $EX, false, true);760 $T[$opcodes[$true Last]['result']['var']] = new Decompiler_TriOp($condition, $trueValue, $falseValue);754 $this->recognizeAndDecompileClosedBlocks($EX, $trueRange, $indent . INDENT); 755 $trueValue = $this->getOpVal($opcodes[$trueRange[1]]['op1'], $EX, false, true); 756 $this->recognizeAndDecompileClosedBlocks($EX, $falseRange, $indent . INDENT); 757 $falseValue = $this->getOpVal($opcodes[$falseRange[1]]['op1'], $EX, false, true); 758 $T[$opcodes[$trueRange[1]]['result']['var']] = new Decompiler_TriOp($condition, $trueValue, $falseValue); 761 759 return false; 762 760 } … … 767 765 $catchFirst = $firstOp['jmpins'][0]; 768 766 769 $tryFirst = $first; 770 $tryLast = $catchFirst - 1; 767 $tryRange = array($range[0], $catchFirst - 1); 771 768 772 769 // search for XC_CATCH 773 770 $this->removeJmpInfo($EX, $catchFirst); 774 for ($i = $catchFirst; $i <= $ last; ) {771 for ($i = $catchFirst; $i <= $range[1]; ) { 775 772 if ($opcodes[$i]['opcode'] == XC_CATCH) { 776 773 $catchOpLine = $i; … … 792 789 } 793 790 794 if ($opcodes[$try Last]['opcode'] == XC_JMP) {795 --$try Last;791 if ($opcodes[$tryRange[1]]['opcode'] == XC_JMP) { 792 --$tryRange[1]; 796 793 } 797 794 798 795 $this->beginComplexBlock($EX); 799 796 echo $indent, "try {", PHP_EOL; 800 $this->recognizeAndDecompileClosedBlocks($EX, $try First, $tryLast, $indent . INDENT);797 $this->recognizeAndDecompileClosedBlocks($EX, $tryRange, $indent . INDENT); 801 798 echo $indent, '}', PHP_EOL; 802 799 foreach ($catchBlocks as $catchFirst => $catchInfo) { 803 800 list($catchOpLine, $catchBodyLast) = $catchInfo; 804 801 $catchBodyFirst = $catchOpLine + 1; 805 $this->recognizeAndDecompileClosedBlocks($EX, $catchFirst, $catchOpLine, $indent);802 $this->recognizeAndDecompileClosedBlocks($EX, array($catchFirst, $catchOpLine), $indent); 806 803 $catchOp = &$opcodes[$catchOpLine]; 807 804 echo $indent, 'catch (', str($this->getOpVal($catchOp['op1'], $EX)), ' ', str($this->getOpVal($catchOp['op2'], $EX)), ") {", PHP_EOL; … … 809 806 810 807 $EX['lastBlock'] = null; 811 $this->recognizeAndDecompileClosedBlocks($EX, $catchBodyFirst, $catchBodyLast, $indent . INDENT);808 $this->recognizeAndDecompileClosedBlocks($EX, array($catchBodyFirst, $catchBodyLast), $indent . INDENT); 812 809 echo $indent, '}', PHP_EOL; 813 810 } … … 835 832 $caseDefault = null; 836 833 $caseOp = null; 837 for ($i = $ first; $i <= $last; ) {834 for ($i = $range[0]; $i <= $range[1]; ) { 838 835 $op = $opcodes[$i]; 839 836 if ($op['opcode'] == XC_CASE) { … … 907 904 } 908 905 909 $this->recognizeAndDecompileClosedBlocks($EX, $caseFirst, $caseLast, $indent . INDENT);906 $this->recognizeAndDecompileClosedBlocks($EX, array($caseFirst, $caseLast), $indent . INDENT); 910 907 $caseIsOut = true; 911 908 } … … 918 915 // {{{ do/while 919 916 if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmpouts']) 920 && $lastOp['jmpouts'][0] == $ first) {921 $this->removeJmpInfo($EX, $ last);917 && $lastOp['jmpouts'][0] == $range[0]) { 918 $this->removeJmpInfo($EX, $range[1]); 922 919 $this->beginComplexBlock($EX); 923 920 924 921 echo $indent, "do {", PHP_EOL; 925 $this->recognizeAndDecompileClosedBlocks($EX, $ first, $last, $indent . INDENT);922 $this->recognizeAndDecompileClosedBlocks($EX, $range, $indent . INDENT); 926 923 echo $indent, "} while (", str($this->getOpVal($lastOp['op1'], $EX)), ');', PHP_EOL; 927 924 … … 934 931 $firstJmp = null; 935 932 $firstJmpOp = null; 936 for ($i = $ first; $i <= $last; ++$i) {933 for ($i = $range[0]; $i <= $range[1]; ++$i) { 937 934 if (!empty($opcodes[$i]['jmpouts'])) { 938 935 $firstJmp = $i; … … 946 943 if (isset($firstJmpOp) 947 944 && $firstJmpOp['opcode'] == XC_JMPZ 948 && $firstJmpOp['jmpouts'][0] > $ last945 && $firstJmpOp['jmpouts'][0] > $range[1] 949 946 && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts']) 950 && $lastOp['jmpouts'][0] == $ first) {947 && $lastOp['jmpouts'][0] == $range[0]) { 951 948 $this->removeJmpInfo($EX, $firstJmp); 952 $this->removeJmpInfo($EX, $ last);949 $this->removeJmpInfo($EX, $range[1]); 953 950 $this->beginComplexBlock($EX); 954 951 955 952 ob_start(); 956 $this->recognizeAndDecompileClosedBlocks($EX, $ first, $last, $indent . INDENT);953 $this->recognizeAndDecompileClosedBlocks($EX, $range, $indent . INDENT); 957 954 $body = ob_get_clean(); 958 955 … … 968 965 if (isset($firstJmpOp) 969 966 && $firstJmpOp['opcode'] == XC_FE_FETCH 970 && $firstJmpOp['jmpouts'][0] > $ last967 && $firstJmpOp['jmpouts'][0] > $range[1] 971 968 && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts']) 972 969 && $lastOp['jmpouts'][0] == $firstJmp) { 973 970 $this->removeJmpInfo($EX, $firstJmp); 974 $this->removeJmpInfo($EX, $ last);971 $this->removeJmpInfo($EX, $range[1]); 975 972 $this->beginComplexBlock($EX); 976 973 977 974 ob_start(); 978 $this->recognizeAndDecompileClosedBlocks($EX, $ first, $last, $indent . INDENT);975 $this->recognizeAndDecompileClosedBlocks($EX, $range, $indent . INDENT); 979 976 $body = ob_get_clean(); 980 977 … … 993 990 // }}} 994 991 995 $this->decompileBasicBlock($EX, $ first, $last, $indent);992 $this->decompileBasicBlock($EX, $range, $indent); 996 993 } 997 994 // }}} 998 function recognizeAndDecompileClosedBlocks(&$EX, $ first, $last, $indent) // {{{ decompile in a tree way995 function recognizeAndDecompileClosedBlocks(&$EX, $range, $indent) // {{{ decompile in a tree way 999 996 { 1000 997 $opcodes = &$EX['opcodes']; 1001 998 1002 $starti = $ first;1003 for ($i = $starti; $i <= $ last; ) {999 $starti = $range[0]; 1000 for ($i = $starti; $i <= $range[1]; ) { 1004 1001 if (!empty($opcodes[$i]['jmpins']) || !empty($opcodes[$i]['jmpouts'])) { 1005 1002 $blockFirst = $i; … … 1011 1008 // care about jumping from blocks behind, not before 1012 1009 foreach ($op['jmpins'] as $oplineNumber) { 1013 if ($oplineNumber <= $ last&& $blockLast < $oplineNumber) {1010 if ($oplineNumber <= $range[1] && $blockLast < $oplineNumber) { 1014 1011 $blockLast = $oplineNumber; 1015 1012 } … … 1021 1018 ++$j; 1022 1019 } while ($j <= $blockLast); 1023 if (!assert('$blockLast <= $ last')) {1024 var_dump($blockLast, $ last);1020 if (!assert('$blockLast <= $range[1]')) { 1021 var_dump($blockLast, $range[1]); 1025 1022 } 1026 1023 1027 1024 if ($blockLast >= $blockFirst) { 1028 1025 if ($blockFirst > $starti) { 1029 $this->decompileBasicBlock($EX, $starti, $blockFirst - 1, $indent);1030 } 1031 if ($this->decompileComplexBlock($EX, $blockFirst, $blockLast, $indent) === false) {1026 $this->decompileBasicBlock($EX, array($starti, $blockFirst - 1), $indent); 1027 } 1028 if ($this->decompileComplexBlock($EX, array($blockFirst, $blockLast), $indent) === false) { 1032 1029 if ($EX['lastBlock'] == 'complex') { 1033 1030 echo PHP_EOL; … … 1046 1043 } 1047 1044 } 1048 if ($starti <= $ last) {1049 $this->decompileBasicBlock($EX, $starti, $last, $indent);1045 if ($starti <= $range[1]) { 1046 $this->decompileBasicBlock($EX, array($starti, $range[1]), $indent); 1050 1047 } 1051 1048 } … … 1161 1158 $EX['op_array'] = &$op_array; 1162 1159 $EX['opcodes'] = &$opcodes; 1160 $EX['range'] = array(0, count($opcodes) - 1); 1163 1161 // func call 1164 1162 $EX['object'] = null; … … 1167 1165 $EX['argstack'] = array(); 1168 1166 $EX['arg_types_stack'] = array(); 1169 $EX['last'] = count($opcodes) - 1;1170 1167 $EX['silence'] = 0; 1171 1168 $EX['recvs'] = array(); … … 1173 1170 $EX['lastBlock'] = null; 1174 1171 1175 $first = 0;1176 $last = count($opcodes) - 1;1177 1178 1172 /* dump whole array 1179 1173 $this->keepTs = true; 1180 $this->dasmBasicBlock($EX, $ first, $last);1181 for ($i = $ first; $i <= $last; ++$i) {1174 $this->dasmBasicBlock($EX, $range); 1175 for ($i = $range[0]; $i <= $range[1]; ++$i) { 1182 1176 echo $i, "\t", $this->dumpop($opcodes[$i], $EX); 1183 1177 } 1184 1178 // */ 1185 1179 // decompile in a tree way 1186 $this->recognizeAndDecompileClosedBlocks($EX, $ first, $last, $EX['indent']);1180 $this->recognizeAndDecompileClosedBlocks($EX, $EX['range'], $EX['indent']); 1187 1181 return $EX; 1188 1182 } 1189 1183 // }}} 1190 function outputCode(&$EX, $ opline, $last, $indent, $loop = false) // {{{1191 { 1192 $op = &$EX['opcodes'][$ opline];1193 $next = $EX['nextbbs'][$ opline];1184 function outputCode(&$EX, $range, $indent, $loop = false) // {{{ 1185 { 1186 $op = &$EX['opcodes'][$range[0]]; 1187 $next = $EX['nextbbs'][$range[0]]; 1194 1188 1195 1189 $end = $next - 1; 1196 if ($end > $ last) {1197 $end = $ last;1190 if ($end > $range[1]) { 1191 $end = $range[1]; 1198 1192 } 1199 1193 … … 1204 1198 // echo ";;;\n"; 1205 1199 } 1206 $this->dasmBasicBlock($EX, $opline, $end);1207 $this->outputPhp($EX, $opline, $end, $indent);1200 $this->dasmBasicBlock($EX, array($opline, $end)); 1201 $this->outputPhp($EX, array($opline, $end), $indent); 1208 1202 // jmpout op 1209 1203 $op = &$EX['opcodes'][$end]; … … 1214 1208 1215 1209 if (isset($EX['opcodes'][$next])) { 1216 if (isset($ last) && $next > $last) {1210 if (isset($range[1]) && $next > $range[1]) { 1217 1211 $next = null; 1218 1212 } … … 1232 1226 $cond = $op['cond']; 1233 1227 echo "{$indent}if ($cond) {\n"; 1234 $this->outputCode($EX, $next, $ last, INDENT . $indent);1228 $this->outputCode($EX, $next, $range[1], INDENT . $indent); 1235 1229 echo "$indent}\n"; 1236 $this->outputCode($EX, $target, $ last, $indent);1230 $this->outputCode($EX, $target, $range[1], $indent); 1237 1231 return; 1238 1232 } … … 1284 1278 $EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')'; 1285 1279 } 1286 #$this->outputCode($EX, $next, $ last, $indent);1280 #$this->outputCode($EX, $next, $range[1], $indent); 1287 1281 #return; 1288 1282 } … … 1299 1293 } 1300 1294 1295 $nextRange = array($next, $range[1]); 1301 1296 if ($loop) { 1302 return array($next, $last);1303 } 1304 $this->outputCode($EX, $next , $last, $indent);1297 return $nextRange; 1298 } 1299 $this->outputCode($EX, $nextRange, $indent); 1305 1300 } 1306 1301 // }}} 1307 function dasmBasicBlock(&$EX, $ opline, $last) // {{{1302 function dasmBasicBlock(&$EX, $range) // {{{ 1308 1303 { 1309 1304 $T = &$EX['Ts']; … … 1311 1306 $lastphpop = null; 1312 1307 1313 for ($i = $ opline; $i <= $last; $i ++) {1308 for ($i = $range[0]; $i <= $range[1]; $i ++) { 1314 1309 // {{{ prepair 1315 1310 $op = &$opcodes[$i]; … … 1802 1797 1803 1798 for (;;) { 1804 if ($i + 1 <= $ last1799 if ($i + 1 <= $range[1] 1805 1800 && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE 1806 1801 && $opcodes[$i + 1]['op1']['var'] == $res['var']) { 1807 1802 // continue 1808 1803 } 1809 else if ($i + 2 <= $ last1804 else if ($i + 2 <= $range[1] 1810 1805 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE 1811 1806 && $opcodes[$i + 2]['op1']['var'] == $res['var'] … … 2230 2225 } 2231 2226 // }}} 2232 function dumpRange(&$EX, $ first, $last, $indent = '') // {{{2233 { 2234 for ($i = $ first; $i <= $last; ++$i) {2227 function dumpRange(&$EX, $range, $indent = '') // {{{ 2228 { 2229 for ($i = $range[0]; $i <= $range[1]; ++$i) { 2235 2230 echo $indent, $i, "\t"; $this->dumpop($EX['opcodes'][$i], $EX); 2236 2231 }

