001: package net.sf.jdec.lookup;
002:
003: import net.sf.jdec.core.GlobalVariableStore;
004: import net.sf.jdec.core.JvmOpCodes;
005: import net.sf.jdec.exceptions.ApplicationException;
006: import net.sf.jdec.jvminstructions.util.InstrConstants;
007: import net.sf.jdec.reflection.Behaviour;
008: import net.sf.jdec.util.ExecutionState;
009:
010: import java.util.ArrayList;
011:
012: /*
013: * BasicFinder.java Copyright (c) 2006,07 Swaroop Belur
014: *
015: * This program is free software; you can redistribute it and/or
016: * modify it under the terms of the GNU General Public License
017: * as published by the Free Software Foundation; either version 2
018: * of the License, or (at your option) any later version.
019:
020: * This program is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024:
025: * You should have received a copy of the GNU General Public License
026: * along with this program; if not, write to the Free Software
027: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
028: *
029: */
030:
031: /**
032: * Base class for all lookup. To include all common finder methods util method
033: * implementation and all those which do not easily fall under load/store etc
034: * categories....
035: *
036: * @author swaroop belur( belurs)
037: * @since version 1.2.1
038: */
039:
040: public abstract class BasicFinder implements IFinder {
041:
042: protected Behaviour getMethod() {
043: return ExecutionState.getMethodContext();
044: }
045:
046: public boolean isThisInstrStart(int pos) {
047: ArrayList list = getMethod().getInstructionStartPositions();
048: boolean start = false;
049: boolean beyondcode = beyondCodeArrayPos(pos);
050: if (beyondcode) {
051: return false;
052: }
053: if (list == null && getMethod().getCode() != null
054: && getMethod().getCode().length > 0) {
055: throw new ApplicationException(
056: "Fatal error : Start positions not set for method : "
057: + getMethod().getBehaviourName());
058: }
059: if (list != null) {
060: for (int k = 0; k < list.size(); k++) {
061: Integer in = (Integer) list.get(k);
062: if (in != null) {
063: int i = in.intValue();
064: if (i == pos) {
065: return !start;
066: }
067: }
068: }
069: }
070: return start;
071:
072: }
073:
074: /**
075: * @param pos -
076: * position in the code array to check
077: * @return true if IADD|FADD|ISUB|FSUB
078: */
079: public boolean isCategory1AddSub(int pos) {
080:
081: byte info[] = getMethod().getCode();
082: boolean st = isThisInstrStart(pos);
083: if (st) {
084: switch (info[pos]) {
085: case JvmOpCodes.IADD:
086: case JvmOpCodes.FADD:
087: case JvmOpCodes.ISUB:
088: case JvmOpCodes.FSUB:
089: return true;
090: }
091:
092: }
093: return false;
094:
095: }
096:
097: /**
098: * @param pos -
099: * position in the code array to check
100: * @return true if LADD|DADD|LSUB|DSUB
101: */
102: public boolean isCategory2AddSub(int pos) {
103:
104: boolean st = isThisInstrStart(pos);
105: if (st) {
106: switch (getMethod().getCode()[pos]) {
107: case JvmOpCodes.LADD:
108: case JvmOpCodes.DADD:
109: case JvmOpCodes.LSUB:
110: case JvmOpCodes.DSUB:
111: return true;
112: }
113:
114: }
115: return false;
116:
117: }
118:
119: /**
120: * @param pos
121: * @return
122: */
123: protected boolean beyondCodeArrayPos(int pos) {
124: if (pos >= getMethod().getCode().length) {
125:
126: return true;
127: }
128:
129: return false;
130: }
131:
132: public boolean isInstAnyBasicPrimitiveOperation(int pos,
133: StringBuffer sb) {
134: boolean b = false;
135: boolean st = isThisInstrStart(pos);
136: if (!st) {
137: return b;
138: }
139: switch (getMethod().getCode()[pos]) {
140:
141: case JvmOpCodes.DADD:
142: sb.append(2);
143: b = true;
144: break;
145: case JvmOpCodes.DDIV:
146: b = true;
147: sb.append(2);
148: break;
149: case JvmOpCodes.DMUL:
150: b = true;
151: sb.append(2);
152: break;
153: case JvmOpCodes.DNEG:
154: b = true;
155: sb.append(1);
156: break;
157: case JvmOpCodes.DREM:
158: b = true;
159: sb.append(2);
160: break;
161: case JvmOpCodes.DSUB:
162: b = true;
163: sb.append(2);
164: break;
165:
166: case JvmOpCodes.FADD:
167: b = true;
168: sb.append(2);
169: break;
170: case JvmOpCodes.FDIV:
171: b = true;
172: sb.append(2);
173: break;
174: case JvmOpCodes.FMUL:
175: b = true;
176: sb.append(2);
177: break;
178: case JvmOpCodes.FNEG:
179: b = true;
180: sb.append(1);
181: break;
182: case JvmOpCodes.FREM:
183: b = true;
184: sb.append(2);
185: break;
186: case JvmOpCodes.IADD:
187: b = true;
188: sb.append(2);
189: break;
190: case JvmOpCodes.IAND:
191: b = true;
192: break;
193: case JvmOpCodes.IDIV:
194: b = true;
195: sb.append(2);
196: break;
197: case JvmOpCodes.IMUL:
198: b = true;
199: sb.append(2);
200: break;
201: case JvmOpCodes.INEG:
202: b = true;
203: sb.append(1);
204: break;
205: case JvmOpCodes.IOR:
206: b = true;
207: sb.append(2);
208: break;
209: case JvmOpCodes.IREM:
210: b = true;
211: sb.append(2);
212: break;
213: case JvmOpCodes.ISHL:
214: b = true;
215: sb.append(2);
216: break;
217: case JvmOpCodes.ISHR:
218: b = true;
219: sb.append(2);
220: break;
221: case JvmOpCodes.ISUB:
222: b = true;
223: sb.append(2);
224: break;
225: case JvmOpCodes.IUSHR:
226: b = true;
227: sb.append(2);
228: break;
229: case JvmOpCodes.IXOR:
230: b = true;
231: sb.append(2);
232: break;
233: case JvmOpCodes.LADD:
234: b = true;
235: sb.append(2);
236: break;
237:
238: case JvmOpCodes.LAND:
239: b = true;
240: sb.append(2);
241: break;
242: case JvmOpCodes.LDIV:
243: b = true;
244: sb.append(2);
245: break;
246: case JvmOpCodes.LMUL:
247: b = true;
248: sb.append(2);
249: break;
250: case JvmOpCodes.LNEG:
251: b = true;
252: sb.append(1);
253: break;
254: case JvmOpCodes.LOR:
255: b = true;
256: sb.append(2);
257: break;
258: case JvmOpCodes.LREM:
259: b = true;
260: sb.append(2);
261: break;
262: case JvmOpCodes.LSHL:
263: b = true;
264: sb.append(2);
265: break;
266: case JvmOpCodes.LSHR:
267: b = true;
268: sb.append(2);
269: break;
270: case JvmOpCodes.LSUB:
271: b = true;
272: sb.append(2);
273: break;
274: case JvmOpCodes.LUSHR:
275: b = true;
276: sb.append(2);
277: break;
278: case JvmOpCodes.LXOR:
279: b = true;
280: sb.append(2);
281: break;
282:
283: }
284:
285: return b;
286: }
287:
288: public boolean isInstAnyCMPInst(int pos) {
289:
290: if (isThisInstrStart(pos)) {
291: switch (getMethod().getCode()[pos]) {
292: case JvmOpCodes.DCMPG:
293: case JvmOpCodes.DCMPL:
294: case JvmOpCodes.FCMPG:
295: case JvmOpCodes.FCMPL:
296: case JvmOpCodes.LCMP:
297: return true;
298: }
299: }
300: return false;
301: }
302:
303: public int isInstAnyConstInst(int pos) {
304: if (isThisInstrStart(pos)) {
305: switch (getMethod().getCode()[pos]) {
306: case JvmOpCodes.ICONST_0:
307: case JvmOpCodes.ICONST_1:
308: case JvmOpCodes.ICONST_2:
309: case JvmOpCodes.ICONST_3:
310: case JvmOpCodes.ICONST_M1:
311: case JvmOpCodes.ICONST_4:
312: case JvmOpCodes.ICONST_5:
313: case JvmOpCodes.LCONST_0:
314: case JvmOpCodes.LCONST_1:
315: case JvmOpCodes.DCONST_0:
316: case JvmOpCodes.DCONST_1:
317: case JvmOpCodes.FCONST_0:
318: case JvmOpCodes.FCONST_1:
319: case JvmOpCodes.FCONST_2:
320: return pos;
321: default:
322: return -1;
323: }
324: }
325:
326: return -1;
327:
328: }
329:
330: public int isInstdConstInst(int pos) {
331: if (isThisInstrStart(pos)) {
332: switch (getMethod().getCode()[pos]) {
333: case JvmOpCodes.DCONST_0:
334: case JvmOpCodes.DCONST_1:
335: return pos;
336: }
337: }
338: return -1;
339: }
340:
341: public int isInstDloadInst(int pos, StringBuffer buffer) {
342: if (isThisInstrStart(pos)) {
343:
344: switch (getMethod().getCode()[(pos)]) {
345: case JvmOpCodes.DLOAD_0:
346: buffer.append(0);
347: return pos;
348:
349: case JvmOpCodes.DLOAD_1:
350:
351: buffer.append(1);
352: return pos;
353:
354: case JvmOpCodes.DLOAD_2:
355:
356: buffer.append(2);
357: return pos;
358:
359: case JvmOpCodes.DLOAD_3:
360:
361: buffer.append(3);
362: return pos;
363:
364: case JvmOpCodes.DLOAD:
365: buffer.append(getMethod().getCode()[pos + 1]);
366: return pos;
367:
368: }
369: }
370: int temp = pos - 1;
371: if (isThisInstrStart(temp)
372: && getMethod().getCode()[temp] == JvmOpCodes.DLOAD) {
373: buffer.append(getMethod().getCode()[pos]);
374: return temp;
375:
376: }
377:
378: return -1;
379:
380: }
381:
382: public boolean isInstDup(int pos) {
383: if (isThisInstrStart(pos)
384: && (getMethod().getCode()[pos] == JvmOpCodes.DUP || getMethod()
385: .getCode()[pos] == JvmOpCodes.DUP2)) {
386: return true;
387: } else {
388: return false;
389: }
390: }
391:
392: public boolean isPrevInstDup(int cur) {
393:
394: byte[] info = getMethod().getCode();
395:
396: if (isThisInstrStart(cur - 1)
397: && (info[cur - 1] == JvmOpCodes.DUP || info[cur - 1] == JvmOpCodes.DUP2))
398: return true;
399: else
400: return false;
401:
402: }
403:
404: public int getOffset(int counter) {
405:
406: byte[] info = getMethod().getCode();
407: int b1 = info[++counter];
408: int b2 = info[++counter];
409: int z;
410: if (b1 < 0)
411: b1 = (256 + b1);
412: if (b2 < 0)
413: b2 = (256 + b2);
414:
415: int indexInst = (((b1 << 8) | b2));
416: if (indexInst > 65535)
417: indexInst = indexInst - 65536;
418: if (indexInst < 0)
419: indexInst = 256 + indexInst;
420: return indexInst;
421: }
422:
423: public int getJumpAddress(int counter) {
424:
425: byte[] info = getMethod().getCode();
426: int b1 = info[++counter];
427: int b2 = info[++counter];
428: int z;
429: if (b1 < 0)
430: b1 = (256 + b1);
431: if (b2 < 0)
432: b2 = (256 + b2);
433:
434: int indexInst = ((((b1 << 8) | b2)) + (counter - 2));
435: if (indexInst > 65535)
436: indexInst = indexInst - 65536;
437: if (indexInst < 0)
438: indexInst = 256 + indexInst;
439: return indexInst;
440: }
441:
442: public boolean isInstructionAnyDUP(int pos) {
443: boolean start = isThisInstrStart(pos);
444: if (!start) {
445: return false;
446: }
447: switch (getMethod().getCode()[pos]) {
448: case JvmOpCodes.DUP:
449: case JvmOpCodes.DUP2:
450: case JvmOpCodes.DUP_X1:
451: case JvmOpCodes.DUP_X2:
452: case JvmOpCodes.DUP2_X1:
453: case JvmOpCodes.DUP2_X2:
454: return true;
455:
456: }
457: return false;
458: }
459:
460: public int isInstFConstInst(int k)
461:
462: {
463: if (isThisInstrStart(k)) {
464: switch (getMethod().getCode()[k]) {
465: case JvmOpCodes.FCONST_0:
466: case JvmOpCodes.FCONST_1:
467: case JvmOpCodes.FCONST_2:
468: return k;
469: }
470: }
471: return -1;
472: }
473:
474: public int isInstFloadInst(int pos, StringBuffer buffer)
475:
476: {
477: if (isThisInstrStart(pos)) {
478: switch (getMethod().getCode()[(pos)]) {
479: case JvmOpCodes.FLOAD_0:
480: buffer.append(0);
481: return pos;
482:
483: case JvmOpCodes.FLOAD_1:
484:
485: buffer.append(1);
486: return pos;
487:
488: case JvmOpCodes.FLOAD_2:
489:
490: buffer.append(2);
491: return pos;
492:
493: case JvmOpCodes.FLOAD_3:
494:
495: buffer.append(3);
496: return pos;
497:
498: case JvmOpCodes.FLOAD:
499:
500: buffer.append(getMethod().getCode()[(pos + 1)]);
501: return pos;
502:
503: }
504: }
505:
506: int temp = pos - 1;
507: if (isThisInstrStart(temp)
508: && getMethod().getCode()[temp] == JvmOpCodes.FLOAD) {
509: buffer.append(getMethod().getCode()[pos]);
510: return temp;
511:
512: }
513:
514: return -1;
515:
516: }
517:
518: public int isInstIConstInst(int pos) {
519: if (isThisInstrStart(pos)) {
520: switch (getMethod().getCode()[pos]) {
521: case JvmOpCodes.ICONST_0:
522: case JvmOpCodes.ICONST_1:
523: case JvmOpCodes.ICONST_2:
524: case JvmOpCodes.ICONST_3:
525: case JvmOpCodes.ICONST_M1:
526: case JvmOpCodes.ICONST_4:
527: case JvmOpCodes.ICONST_5:
528: return pos;
529:
530: }
531: }
532: return -1;
533: }
534:
535: public int isInstLConstInst(int pos) {
536: if (isThisInstrStart(pos)) {
537: switch (getMethod().getCode()[pos]) {
538: case JvmOpCodes.LCONST_0:
539: case JvmOpCodes.LCONST_1:
540: return pos;
541: }
542: }
543: return -1;
544:
545: }
546:
547: public boolean isNextInstIINC(int pos, int index,
548: java.lang.String type) {
549: int next;
550: if (type.equals(InstrConstants.COMPLEX)) {
551: next = pos + 2;
552: } else {
553: next = pos + 1;
554: }
555: if (isThisInstrStart(next)) {
556:
557: if (getMethod().getCode()[next] == JvmOpCodes.IINC) {
558: int j = getMethod().getCode()[next + 1];
559: if (index == j) {
560: return true;
561: }
562: }
563:
564: }
565:
566: return false;
567:
568: }
569:
570: public boolean isPrevInstIINC(int current, int index) {
571: int prev = current - 3;
572: byte[] info = getMethod().getCode();
573: if (isThisInstrStart(prev)) {
574:
575: if (info[prev] == JvmOpCodes.IINC) {
576: int j = info[prev + 1];
577: if (index == j) {
578: return true;
579: }
580: }
581:
582: }
583:
584: return false;
585:
586: }
587:
588: public boolean isPreviousInst(int current, int lookfor) {
589:
590: for (int s = current - 1; s >= 0; s--) {
591: boolean ok = isThisInstrStart(s);
592: if (ok) {
593: if (s == lookfor) {
594: return true;
595: }
596: return false;
597: }
598: }
599:
600: return false;
601: }
602:
603: public boolean isNextInstructionAnyInvoke(int pos, StringBuffer sb) {
604:
605: if (!isThisInstrStart(pos))
606: return false;
607:
608: int instr = getMethod().getCode()[pos];
609: boolean ok = isNextInstructionInvokeInterface(instr);
610: if (ok) {
611: sb.append(InstrConstants.INVOKE_INTERFACE);
612: return ok;
613: }
614: ok = isNextInstructionInvokeSpecial(instr);
615: if (ok) {
616: sb.append(InstrConstants.INVOKE_SPECIAL);
617: return ok;
618: }
619: ok = isNextInstructionInvokeStatic(instr);
620: if (ok)
621: return ok;
622: ok = isNextInstructionInvokeVirtual(instr);
623: if (ok)
624: return ok;
625: return false;
626: }
627:
628: /**
629: * WARNING : NO CHECK FOR START OF INSTRUCTION !!!
630: *
631: * @param nextInst
632: * @return
633: */
634: public boolean isNextInstructionInvokeInterface(int nextInst) {
635:
636: if (nextInst == JvmOpCodes.INVOKEINTERFACE)
637: return true;
638: else
639: return false;
640: }
641:
642: /**
643: * WARNING : NO CHECK FOR START OF INSTRUCTION !!!
644: *
645: * @param nextInst
646: * @return
647: */
648: public boolean isNextInstructionInvokeSpecial(int nextInst) {
649:
650: if (nextInst == JvmOpCodes.INVOKESPECIAL)
651: return true;
652: else
653: return false;
654: }
655:
656: /**
657: * WARNING : NO CHECK FOR START OF INSTRUCTION !!!
658: *
659: * @param nextInst
660: * @return
661: */
662:
663: public boolean isNextInstructionInvokeStatic(int nextInst) {
664:
665: if (nextInst == JvmOpCodes.INVOKESTATIC)
666: return true;
667: else
668: return false;
669: }
670:
671: /**
672: * WARNING : NO CHECK FOR START OF INSTRUCTION !!!
673: *
674: * @param nextInst
675: * @return
676: */
677:
678: public boolean isNextInstructionInvokeVirtual(int nextInst) {
679:
680: if (nextInst == JvmOpCodes.INVOKEVIRTUAL)
681: return true;
682: else
683: return false;
684: }
685:
686: public boolean isNextInstructionConversionInst(int i) {
687: if (!isThisInstrStart(i))
688: return false;
689: switch (getMethod().getCode()[i]) {
690:
691: case JvmOpCodes.D2L:
692: case JvmOpCodes.D2I:
693: case JvmOpCodes.D2F:
694: case JvmOpCodes.I2B:
695: case JvmOpCodes.I2C:
696: case JvmOpCodes.I2D:
697: case JvmOpCodes.I2F:
698: case JvmOpCodes.I2L:
699: case JvmOpCodes.I2S:
700: case JvmOpCodes.L2D:
701: case JvmOpCodes.L2F:
702: case JvmOpCodes.L2I:
703: case JvmOpCodes.F2D:
704:
705: case JvmOpCodes.F2I:
706: case JvmOpCodes.F2L:
707: return true;
708: default:
709: return false;
710:
711: }
712:
713: }
714:
715: public int isNextInstructionConversionInst(int pos,
716: StringBuffer value) {
717: if (!isThisInstrStart(pos))
718: return -1;
719:
720: switch (getMethod().getCode()[pos]) {
721:
722: case JvmOpCodes.D2L:
723: value.append("long");
724:
725: break;
726: case JvmOpCodes.D2I:
727: value.append("int");
728:
729: break;
730: case JvmOpCodes.D2F:
731: value.append("float");
732:
733: break;
734: case JvmOpCodes.I2B:
735: value.append("byte");
736:
737: break;
738: case JvmOpCodes.I2C:
739: value.append("char");
740:
741: break;
742: case JvmOpCodes.I2D:
743: value.append("double");
744:
745: break;
746: case JvmOpCodes.I2F:
747: value.append("float");
748:
749: break;
750: case JvmOpCodes.I2L:
751: value.append("long");
752:
753: break;
754: case JvmOpCodes.I2S:
755: value.append("short");
756:
757: break;
758: case JvmOpCodes.L2D:
759: value.append("double");
760:
761: break;
762: case JvmOpCodes.L2F:
763: value.append("float");
764:
765: break;
766: case JvmOpCodes.L2I:
767: value.append("int");
768:
769: break;
770: case JvmOpCodes.F2D:
771: value.append("double");
772:
773: break;
774:
775: case JvmOpCodes.F2I:
776: value.append("int");
777:
778: break;
779: case JvmOpCodes.F2L:
780: value.append("long");
781:
782: break;
783:
784: default:
785: return -1;
786:
787: }
788:
789: return pos;
790:
791: }
792:
793: public boolean isNextInstructionPop(int pos) {
794: boolean flag = false;
795:
796: if (!isThisInstrStart(pos)) {
797: return flag;
798: }
799:
800: switch (getMethod().getCode()[pos]) {
801: case JvmOpCodes.POP:
802: case JvmOpCodes.POP2:
803: return true;
804: default:
805: return false;
806:
807: }
808: }
809:
810: public boolean newfound() {
811: if ((GlobalVariableStore.getNewfoundstack()).size() > 0)
812: return true;
813: return false;
814: }
815:
816: /**
817: * No ternary support yet in jdec
818: *
819: * @param i
820: * @return
821: */
822: public boolean isTernaryEnd(int i) {
823: return false;
824: }
825:
826: public int getPrevStartOfInst(int current) {
827: int start = current - 1;
828: while (start >= 0) {
829: boolean s = isThisInstrStart(start);
830: if (s)
831: return start;
832: start--;
833: }
834: return start;
835: }
836:
837: /* public boolean isInstPrimitiveArrayStore(int inst) {
838: switch (inst) {
839: case JvmOpCodes.IASTORE:
840: case JvmOpCodes.BASTORE:
841: case JvmOpCodes.SASTORE:
842: case JvmOpCodes.FASTORE:
843: case JvmOpCodes.LASTORE:
844: case JvmOpCodes.DASTORE:
845: return true;
846: }
847: return false;
848: }*/
849:
850: public boolean checkForSomeSpecificInstructions(byte[] code, int i)
851:
852: {
853: int inst = code[i];
854: switch (inst) {
855:
856: // LDC // TODO: Need to Regressoion Testing Here // uncommented bcoz of
857: // trytrest_4
858: // case JvmOpCodes.LDC2_W:
859: // case JvmOpCodes.LDC_W:
860:
861: // case JvmOpCodes.ACONST_NULL:
862: case JvmOpCodes.DUP:
863: case JvmOpCodes.DUP2:
864: // case JvmOpCodes.NEW:
865: case JvmOpCodes.CHECKCAST:
866: case JvmOpCodes.ATHROW:
867:
868: case JvmOpCodes.ANEWARRAY:
869: case JvmOpCodes.NEWARRAY:
870: case JvmOpCodes.MULTIANEWARRAY:
871:
872: case JvmOpCodes.LOOKUPSWITCH:
873: case JvmOpCodes.TABLESWITCH:
874: return true;
875:
876: }
877: /*
878: * if(inst==JvmOpCodes.LDC &&
879: * (isThisInstrStart(behaviour.getInstructionStartPositions(),(i-3)) &&
880: * code[(i-3)]!=JvmOpCodes.INVOKESPECIAL)) { return true; }
881: */
882: if (inst == JvmOpCodes.LDC) {
883: return false;
884: }
885: return false;
886:
887: }
888: }
|