001: package net.sf.jdec.blockhelpers;
002:
003: import net.sf.jdec.blocks.IFBlock;
004: import net.sf.jdec.blocks.Loop;
005: import net.sf.jdec.core.GlobalVariableStore;
006: import net.sf.jdec.core.JvmOpCodes;
007: import net.sf.jdec.core.Decompiler.DowhileHelper;
008: import net.sf.jdec.lookup.FinderFactory;
009: import net.sf.jdec.lookup.IFinder;
010: import net.sf.jdec.reflection.Behaviour;
011: import net.sf.jdec.util.ExecutionState;
012: import net.sf.jdec.util.Util;
013:
014: import java.util.ArrayList;
015: import java.util.Arrays;
016: import java.util.Iterator;
017: import java.util.List;
018:
019: /*
020: * LoopHelper.java Copyright (c) 2006,07 Swaroop Belur
021: *
022: * This program is free software; you can redistribute it and/or
023: * modify it under the terms of the GNU General Public License
024: * as published by the Free Software Foundation; either version 2
025: * of the License, or (at your option) any later version.
026:
027: * This program is distributed in the hope that it will be useful,
028: * but WITHOUT ANY WARRANTY; without even the implied warranty of
029: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
030: * GNU General Public License for more details.
031:
032: * You should have received a copy of the GNU General Public License
033: * along with this program; if not, write to the Free Software
034: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
035: *
036: */
037:
038: public class LoopHelper {
039:
040: private LoopHelper() {
041: }
042:
043: private static final LoopHelper helper = new LoopHelper();
044:
045: public static LoopHelper getInstance() {
046: return helper;
047: }
048:
049: public static boolean isPositionALoopStart(ArrayList loops,
050: int index) {
051: if (loops == null || loops.size() == 0)
052: return false;
053: for (int z = 0; z < loops.size(); z++) {
054: Loop loop = (Loop) loops.get(z);
055: int loopstart = loop.getStartIndex();
056: if (loopstart == index) {
057: return true;
058: }
059: }
060: return false;
061: }
062:
063: public static int getloopEndForStart(ArrayList list, int start) {
064: for (int i = 0; i < list.size(); i++) {
065: Loop l = (Loop) list.get(i);
066: if (l.getStartIndex() == start) {
067: return l.getEndIndex();
068: }
069: }
070: return -1;
071:
072: }
073:
074: public static int findCodeIndexFromInfiniteLoop(IFBlock ifst,
075: ArrayList LoopTable, int codeIndex) {
076: Iterator iterInfLoop = LoopTable.iterator();
077: int start = ifst.getIfStart();
078: int loopstarts[] = new int[LoopTable.size()];
079: int j = 0;
080: boolean ok = false;
081: while (iterInfLoop.hasNext()) {
082: Loop iloop = (Loop) iterInfLoop.next();
083: int lstart = iloop.getStartIndex();
084: loopstarts[j] = lstart;
085: j++;
086: ok = true;
087: /*
088: * if(iloop.getStartIndex() == codeIndex) { return
089: * iloop.getEndIndex(); }
090: */
091: }
092: if (ok) {
093: for (int z = loopstarts.length - 1; z >= 0; z--) {
094:
095: if (loopstarts[z] < start) {
096: int end = getloopEndForStart(LoopTable,
097: loopstarts[z]);
098: if (end < start)
099: return -1;
100: return end;
101: }
102:
103: }
104: }
105:
106: return -1;
107: }
108:
109: public static Object[] sortLoops(ArrayList list) {
110: Object o[] = list.toArray();
111: Arrays.sort(o);
112: return o;
113: }
114:
115: public static int getParentLoopStartForIf(Object[] sortedloops,
116: int ifbegin) {
117: int reqdStart = -1;
118: int max = -1;
119: int pos = 0;
120: int counter = sortedloops.length - 1;
121: while (counter >= 0) {
122: Object o = sortedloops[counter];
123: if (o instanceof Loop) {
124: Loop l = (Loop) o;
125: int ls = l.getStartIndex();
126: int this LoopEnd = getloopEndForStart(getContext()
127: .getBehaviourLoops(), ls);
128: if (ls < ifbegin && !(ifbegin > this LoopEnd)) {
129: reqdStart = ls;
130: break;
131: }
132:
133: }
134: counter--;
135: }
136: return reqdStart;
137:
138: }
139:
140: private static Behaviour getContext() {
141: return ExecutionState.getMethodContext();
142: }
143:
144: public static boolean isThisLoopEndAlso(ArrayList loops, int i,
145: int ifstart) {
146: for (int s = 0; s < loops.size(); s++) {
147: Loop l = (Loop) loops.get(s);
148: int lend = (l).getEndIndex();
149: if (lend == i && ifstart > l.getStartIndex())
150: return true;
151: }
152: return false;
153: }
154:
155: public static int getNextLoopStart(int start) {
156: int i = -1;
157: ArrayList loops = getContext().getBehaviourLoops();
158: for (int s = 0; s < loops.size(); s++) {
159: Loop l = (Loop) loops.get(s);
160: int next = s + 1;
161: if (next < loops.size()) {
162: Loop n = (Loop) loops.get(next);
163: if (start == l.getStartIndex()) {
164: return n.getStartIndex();
165: }
166:
167: } else
168: return i;
169: }
170:
171: return i;
172: }
173:
174: public static int getLoopStartForEnd(int s, ArrayList list) {
175: for (int k = 0; k < list.size(); k++) {
176: Loop l = (Loop) list.get(k);
177: if (l.getEndIndex() == s)
178: return l.getStartIndex();
179: }
180: return -1;
181: }
182:
183: public static boolean isIndexEndOfLoop(ArrayList list, int s) {
184: boolean ok = false;
185: for (int st = 0; st < list.size(); st++) {
186: if (((Loop) list.get(st)).getEndIndex() == s)
187: return true;
188: }
189: return ok;
190: }
191:
192: public static boolean checkForParentLoopForIF(IFBlock ifst) {
193: ArrayList loops = getContext().getBehaviourLoops();
194: if (loops != null) {
195: Object[] sortedLoops = sortLoops(loops);
196: int parentLoopStart = getParentLoopStartForIf(sortedLoops,
197: ifst.getIfStart());
198: if (parentLoopStart == -1) {
199: return false;
200: } else {
201: int by = ifst.getIfCloseFromByteCode();
202: Loop l = getParentLoopForIf(sortedLoops, ifst
203: .getIfStart());
204: if (l != null) {
205: int le = l.getEndIndex();
206: if (by > ifst.getIfStart() && by < le) {
207: return false;
208: }
209: if (by < ifst.getIfStart()
210: && by == l.getStartIndex()) {
211: return false;
212: }
213: if (by > ifst.getIfStart() && by > le) {
214: return true;
215: }
216:
217: }
218:
219: }
220: }
221: return false;
222: }
223:
224: public static Loop getParentLoopForIf(Object[] sortedloops,
225: int ifbegin) {
226: int reqdStart = -1;
227: Loop reqdl = null;
228: int max = -1;
229: int pos = 0;
230: int counter = sortedloops.length - 1;
231: while (counter >= 0) {
232: Object o = sortedloops[counter];
233: if (o instanceof Loop) {
234: Loop l = (Loop) o;
235: int ls = l.getStartIndex();
236: int this LoopEnd = getloopEndForStart(getContext()
237: .getBehaviourLoops(), ls);
238: if (ls < ifbegin && !(ifbegin > this LoopEnd)) {
239: reqdStart = ls;
240: reqdl = l;
241: break;
242: }
243:
244: }
245: counter--;
246: }
247: return reqdl;
248:
249: }
250:
251: public static boolean checkForMatchingLoopAgain(ArrayList loops,
252: int start, StringBuffer S) {
253: boolean b = false;
254: if (loops == null || loops.size() == 0)
255: return b;
256: else {
257: for (int s = 0; s < loops.size(); s++) {
258: Loop l = (Loop) loops.get(s);
259: int loopstart = l.getStartIndex();
260: if (loopstart == start) {
261: b = true;
262: S.append(l.getEndIndex());
263: return b;
264: }
265:
266: }
267: }
268: return b;
269: }
270:
271: public static int getClosestLoopEndForThisIf(int s,
272: ArrayList loops, byte[] info) {
273:
274: int end = -1;
275: if (loops == null || loops.size() == 0)
276: return end;
277: int gotos = s + 3;
278: if (info[gotos] == JvmOpCodes.GOTO
279: && getGenericFinder().isThisInstrStart(gotos)) {
280: int gotoj = getGenericFinder().getJumpAddress(gotos);
281: int starts[] = new int[loops.size()];
282: for (int z = 0; z < loops.size(); z++) {
283: starts[z] = ((Loop) loops.get(z)).getEndIndex();
284: }
285: Arrays.sort(starts);
286: int reqdloopend = -1;
287: for (int x = 0; x < starts.length; x++) {
288: int cur = starts[x];
289: if (gotoj > cur) {
290: reqdloopend = cur;
291: break;
292: }
293: }
294:
295: if (reqdloopend != -1) {
296: int lstart = getLoopStartForEnd(reqdloopend, loops);
297: if (lstart < s) {
298: return reqdloopend;
299: }
300: } else {
301: return -1;
302: }
303:
304: }
305:
306: return end;
307: }
308:
309: private static IFinder getGenericFinder() {
310: return FinderFactory.getFinder(IFinder.BASE);
311: }
312:
313: public static boolean isBeyondLoop(int ifjump, ArrayList list,
314: byte[] info) {
315: boolean b = false;
316: int temp = ifjump - 3;
317: Loop l;
318: int currentForIndex = getCurrentForIndex();
319: Loop this Loop = GlobalVariableStore.getThisLoop();
320: boolean inststart = getGenericFinder().isThisInstrStart(temp);
321: if (temp >= 0 && info[temp] == JvmOpCodes.GOTO && inststart) {
322:
323: int jmp = getGenericFinder().getJumpAddress(temp);
324: boolean end;
325: end = isIndexEndOfLoop(list, temp);
326: if (end) {
327: b = true;
328: l = getThisLoop(list, temp);
329: this Loop = l;
330: if (currentForIndex < this Loop.getStartIndex()) {
331: b = false;
332: }
333: }
334: /*
335: * if(!b) { int tmp2=jmp-3; end=isIndexEndOfLoop(list,tmp2); if(end) {
336: * b=true;
337: *
338: * l=getThisLoop(list,tmp2); thisLoop=l; } }
339: */
340:
341: }
342:
343: if (b == false) {
344: int if_start = currentForIndex;
345: for (int y = ifjump - 1; y > if_start; y--) {
346: boolean atbegin = getGenericFinder()
347: .isThisInstrStart(y);
348: if (atbegin) {
349: Loop someloop = getLoopGivenEnd(y, list);
350: if (someloop != null) {
351: int someloopstart = someloop.getStartIndex();
352: if (someloopstart < if_start) {
353: b = true;
354: l = someloop;
355: this Loop = l;
356: }
357: }
358: }
359:
360: }
361: }
362:
363: if (b == false) {
364:
365: for (int z = 0; z < list.size(); z++) {
366: Loop loop = (Loop) list.get(z);
367: int loops = loop.getStartIndex();
368: int loopend = loop.getEndIndex();
369: for (int x = loops + 1; x <= currentForIndex
370: && x < loopend; x++) {
371: boolean st = getGenericFinder().isThisInstrStart(x);
372: if (st) {
373: boolean isif = getBranchFinder()
374: .isInstructionIF(x);
375: if (isif) {
376: if (x == currentForIndex) {
377:
378: st = getGenericFinder()
379: .isThisInstrStart(loopend);
380: if (st && (loopend > loops)) {
381: boolean gotoinst = (info[loopend] == JvmOpCodes.GOTO);
382: if (gotoinst) {
383: this Loop = loop;
384: b = true;
385: }
386: }
387: }
388: }
389: }
390: }
391:
392: }
393: }
394: GlobalVariableStore.setThisLoop(this Loop);
395: return b;
396:
397: }
398:
399: public static Loop getThisLoop(ArrayList list, int s) {
400: Loop l;
401: for (int st = 0; st < list.size(); st++) {
402: Loop tmp = (Loop) list.get(st);
403: if (tmp.getEndIndex() == s)
404: return tmp;
405: }
406: return null;
407: }
408:
409: private static int getCurrentForIndex() {
410: return ExecutionState.getCurrentInstructionPosition();
411: }
412:
413: private static Loop getLoopGivenEnd(int end, ArrayList loops) {
414: for (int z = 0; z < loops.size(); z++) {
415: Loop l = (Loop) loops.get(z);
416: if (l.getEndIndex() == end)
417: return l;
418: }
419: return null;
420: }
421:
422: public static Loop isIfInADoWhile(int current, IFBlock ifst,
423: ArrayList loops) {
424:
425: Loop l = getLoopGivenEnd(current, loops);
426: byte[] info = getContext().getCode();
427: if (l != null) {
428: boolean isif = getBranchFinder().isInstructionIF(current);
429: if (isif && getGenericFinder().isThisInstrStart(current))
430: return l;
431: }
432: return null;
433: }
434:
435: public static IFinder getBranchFinder() {
436: return FinderFactory.getFinder(IFinder.BRANCH);
437: }
438:
439: public static boolean isIfFirstIfInLoopCondition(byte[] info,
440: int pos) {
441:
442: Loop loop = getParentLoopForIf(sortLoops(getContext()
443: .getBehaviourLoops()), pos);
444: if (loop != null) {
445: int start = loop.getStartIndex();
446: for (int x = start; x < info.length; x++) {
447: boolean b = getGenericFinder().isThisInstrStart(x);
448: if (b) {
449: boolean isif = getBranchFinder().isInstructionIF(x);
450: if (isif) {
451: if (x == pos) {
452: return true;
453: } else {
454: return false;
455: }
456: }
457: }
458: }
459: }
460:
461: return false;
462: }
463:
464: public static boolean addReturnAtDoWhileEnd(int current, int loopend) {
465: Loop l = getLoopGivenEnd(loopend, getContext()
466: .getBehaviourLoops());
467: int ls = l.getStartIndex();
468: return true;
469:
470: }
471:
472: public static java.lang.String closeDoWhile(int index,
473: List doWhileHelperList) {
474: int currentForIndex = getCurrentForIndex();
475: Behaviour behavior = getContext();
476: for (int z = 0; z < doWhileHelperList.size(); z++) {
477: DowhileHelper dow = (DowhileHelper) doWhileHelperList
478: .get(z);
479: if (dow.getIndex() == index) {
480: if (dow.getIsClosed() == false) {
481: dow.setClosed(true);
482: boolean addRet = addReturnAtDoWhileEnd(
483: getCurrentForIndex(), (index - 3));
484:
485: if (currentForIndex == (index - 3)) {
486: if (!dow.getLoop().wasLoopClosedInCode()) {
487: /* boolean childIfPresent = checkForAnyChildIFEndAtWhileEnd(
488: index, dow.getLoop().getStartIndex());
489: dow.getLoop().setWasLoopClosedInCode(true);
490: if (!childIfPresent)
491: behavior.appendToBuffer(Util
492: .formatDecompiledStatement("\n}\n")); // Added
493: // while
494: // decompiling
495: // BigIntger.class
496: // smallPrime
497: // Method
498: else{*/
499: dow.getLoop().setWasLoopClosedInCode(true);
500: return "\n}\n";
501: //}
502:
503: }
504: continue;
505: }
506: /*behavior.appendToBuffer(Util
507: .formatDecompiledStatement("break;\n"));
508: // Util.forceNewLine=false;
509: Util.forceTrimString = false;
510: behavior.appendToBuffer(Util.formatDecompiledStatement("\n}//1\n"));*/
511: if (!dow.getLoop().wasLoopClosedInCode()) {
512: /*boolean childIfPresent = checkForAnyChildIFEndAtWhileEnd(
513: index, dow.getLoop().getStartIndex());
514: dow.getLoop().setWasLoopClosedInCode(true);
515: if (!childIfPresent) {
516: return "\n}\n";
517: }
518: else {
519: */dow.getLoop().setWasLoopClosedInCode(true);
520: return "\n}\n";
521: //}
522: }
523:
524: }
525: }
526: }
527:
528: return "";
529: }
530:
531: public static boolean checkForAnyChildIFEndAtWhileEnd(
532: int currentForIndex, int loopStart) {
533:
534: Iterator currentIFs = getContext().getMethodIfs().iterator();
535: while (currentIFs.hasNext()) {
536:
537: IFBlock IF = (IFBlock) currentIFs.next();
538: if (IF.getIfCloseLineNumber() == currentForIndex) {
539: if (loopStart < IF.getIfStart()) {
540: return true;
541: }
542: }
543: }
544:
545: return false;
546: }
547:
548: public static Loop getLoopGivenStart(int start) {
549:
550: Iterator currentLoops = getContext().getBehaviourLoops()
551: .iterator();
552: while (currentLoops.hasNext()) {
553:
554: Loop l = (Loop) currentLoops.next();
555: if (l.getStartIndex() == start) {
556: return l;
557: }
558: }
559: return null;
560: }
561:
562: public static Loop getLoopGivenEnd(int end) {
563:
564: Iterator currentLoops = getContext().getBehaviourLoops()
565: .iterator();
566: while (currentLoops.hasNext()) {
567:
568: Loop l = (Loop) currentLoops.next();
569: if (l.getEndIndex() == end) {
570: return l;
571: }
572: }
573: return null;
574: }
575:
576: }
|