KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > dava > DavaBody


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2003 Jerome Miecznikowski
3  * Copyright (C) 2004-2006 Nomair A. Naeem
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */

20
21 package soot.dava;
22
23 import java.util.HashMap JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.LinkedList JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Set JavaDoc;
30
31 import soot.Body;
32 import soot.G;
33 import soot.IntType;
34 import soot.Local;
35 import soot.PatchingChain;
36 import soot.PhaseOptions;
37 import soot.RefType;
38 import soot.SootFieldRef;
39 import soot.SootMethod;
40 import soot.SootMethodRef;
41 import soot.Trap;
42 import soot.Type;
43 import soot.Unit;
44 import soot.UnitBox;
45 import soot.Value;
46 import soot.ValueBox;
47 import soot.dava.internal.AST.ASTMethodNode;
48 import soot.dava.internal.AST.ASTNode;
49 import soot.dava.internal.SET.SETNode;
50 import soot.dava.internal.SET.SETTopNode;
51 import soot.dava.internal.asg.AugmentedStmt;
52 import soot.dava.internal.asg.AugmentedStmtGraph;
53 import soot.dava.internal.javaRep.DCmpExpr;
54 import soot.dava.internal.javaRep.DCmpgExpr;
55 import soot.dava.internal.javaRep.DCmplExpr;
56 import soot.dava.internal.javaRep.DInstanceFieldRef;
57 import soot.dava.internal.javaRep.DIntConstant;
58 import soot.dava.internal.javaRep.DInterfaceInvokeExpr;
59 import soot.dava.internal.javaRep.DLengthExpr;
60 import soot.dava.internal.javaRep.DNegExpr;
61 import soot.dava.internal.javaRep.DNewArrayExpr;
62 import soot.dava.internal.javaRep.DNewInvokeExpr;
63 import soot.dava.internal.javaRep.DNewMultiArrayExpr;
64 import soot.dava.internal.javaRep.DSpecialInvokeExpr;
65 import soot.dava.internal.javaRep.DStaticFieldRef;
66 import soot.dava.internal.javaRep.DStaticInvokeExpr;
67 import soot.dava.internal.javaRep.DThisRef;
68 import soot.dava.internal.javaRep.DVirtualInvokeExpr;
69 import soot.dava.toolkits.base.AST.UselessTryRemover;
70 import soot.dava.toolkits.base.AST.transformations.ASTCleaner;
71 import soot.dava.toolkits.base.AST.transformations.ASTCleanerTwo;
72 import soot.dava.toolkits.base.AST.transformations.AndAggregator;
73 import soot.dava.toolkits.base.AST.transformations.BooleanConditionSimplification;
74 import soot.dava.toolkits.base.AST.transformations.DeInliningFinalFields;
75 import soot.dava.toolkits.base.AST.transformations.DecrementIncrementStmtCreation;
76 import soot.dava.toolkits.base.AST.transformations.FinalFieldDefinition;
77 import soot.dava.toolkits.base.AST.transformations.ForLoopCreator;
78 import soot.dava.toolkits.base.AST.transformations.LocalVariableCleaner;
79 import soot.dava.toolkits.base.AST.transformations.LoopStrengthener;
80 import soot.dava.toolkits.base.AST.transformations.OrAggregatorFour;
81 import soot.dava.toolkits.base.AST.transformations.OrAggregatorOne;
82 import soot.dava.toolkits.base.AST.transformations.OrAggregatorTwo;
83 import soot.dava.toolkits.base.AST.transformations.PushLabeledBlockIn;
84 import soot.dava.toolkits.base.AST.transformations.SuperFirstStmtHandler;
85 import soot.dava.toolkits.base.AST.transformations.VoidReturnRemover;
86 import soot.dava.toolkits.base.AST.traversals.ClosestAbruptTargetFinder;
87 import soot.dava.toolkits.base.AST.traversals.CopyPropagation;
88 import soot.dava.toolkits.base.finders.AbruptEdgeFinder;
89 import soot.dava.toolkits.base.finders.CycleFinder;
90 import soot.dava.toolkits.base.finders.ExceptionFinder;
91 import soot.dava.toolkits.base.finders.IfFinder;
92 import soot.dava.toolkits.base.finders.LabeledBlockFinder;
93 import soot.dava.toolkits.base.finders.SequenceFinder;
94 import soot.dava.toolkits.base.finders.SwitchFinder;
95 import soot.dava.toolkits.base.finders.SynchronizedBlockFinder;
96 import soot.dava.toolkits.base.misc.MonitorConverter;
97 import soot.dava.toolkits.base.misc.ThrowNullConverter;
98 import soot.dava.toolkits.base.renamer.Renamer;
99 import soot.dava.toolkits.base.renamer.infoGatheringAnalysis;
100 import soot.grimp.GrimpBody;
101 import soot.grimp.NewInvokeExpr;
102 import soot.jimple.ArrayRef;
103 import soot.jimple.BinopExpr;
104 import soot.jimple.CastExpr;
105 import soot.jimple.CaughtExceptionRef;
106 import soot.jimple.CmpExpr;
107 import soot.jimple.CmpgExpr;
108 import soot.jimple.CmplExpr;
109 import soot.jimple.ConditionExpr;
110 import soot.jimple.Constant;
111 import soot.jimple.DefinitionStmt;
112 import soot.jimple.Expr;
113 import soot.jimple.IdentityStmt;
114 import soot.jimple.IfStmt;
115 import soot.jimple.InstanceFieldRef;
116 import soot.jimple.InstanceInvokeExpr;
117 import soot.jimple.InstanceOfExpr;
118 import soot.jimple.IntConstant;
119 import soot.jimple.InterfaceInvokeExpr;
120 import soot.jimple.InvokeExpr;
121 import soot.jimple.InvokeStmt;
122 import soot.jimple.LengthExpr;
123 import soot.jimple.LookupSwitchStmt;
124 import soot.jimple.MonitorStmt;
125 import soot.jimple.NegExpr;
126 import soot.jimple.NewArrayExpr;
127 import soot.jimple.NewExpr;
128 import soot.jimple.NewMultiArrayExpr;
129 import soot.jimple.ParameterRef;
130 import soot.jimple.Ref;
131 import soot.jimple.ReturnStmt;
132 import soot.jimple.SpecialInvokeExpr;
133 import soot.jimple.StaticFieldRef;
134 import soot.jimple.StaticInvokeExpr;
135 import soot.jimple.Stmt;
136 import soot.jimple.TableSwitchStmt;
137 import soot.jimple.ThisRef;
138 import soot.jimple.ThrowStmt;
139 import soot.jimple.UnopExpr;
140 import soot.jimple.VirtualInvokeExpr;
141 import soot.jimple.internal.JGotoStmt;
142 import soot.jimple.internal.JimpleLocal;
143 import soot.toolkits.graph.BriefUnitGraph;
144 import soot.toolkits.graph.TrapUnitGraph;
145 import soot.util.IterableSet;
146
147
148 /*
149  * CHANGE LOG: Nomair - January 2006: Moved the AST Analyses to a separate method
150  * These are now invoked as a very last staged (just before generating decompiled
151  * output. Invoked by PackManager
152  *
153  * Nomair - 7th Feb, 2006: Starting work on a naming mechanism
154  * Nomair - 13th Feb 2006: Added db phase options
155  *
156  * renamer: on /off DEFAULT:TRUE
157  * deobfuscate: DEFAULT: FALSE, dead code eliminateion, class/field renaming, constant field elimination
158  * force-recompilability: DEFAULT TRUE, super, final
159  */

160
161 /*
162  * TODO: Nomair- February 7th. Refactor the call
163  * AST.perform_Analysis( UselessTryRemover.v());
164  * use the new AnalysisAdapter routines to write this analysis. Then delete these
165  * obselete and rather clumsy way of writing analyses
166  *
167  * TODO: Nomair 14th Feb 2006, Use the Dava options renamer, deobfuscate, force-recompilability
168  * Specially the deobfuscate option with the boolean constant propagation analysis
169  *
170  */

171
172 public class DavaBody extends Body {
173
174     public final boolean DEBUG = false;
175     private Map JavaDoc pMap;
176
177     private HashSet JavaDoc consumedConditions, thisLocals;
178
179     private IterableSet synchronizedBlockFacts, exceptionFacts, monitorFacts,
180             packagesUsed;
181
182     private Local controlLocal;
183
184     private InstanceInvokeExpr constructorExpr; //holds constructorUnit.getInvokeExpr
185

186     private Unit constructorUnit; //holds a stmt (this.init<>)
187

188     private List JavaDoc caughtrefs;
189
190     /**
191      * Construct an empty DavaBody
192      */

193
194     DavaBody(SootMethod m) {
195         super(m);
196
197         pMap = new HashMap JavaDoc();
198         consumedConditions = new HashSet JavaDoc();
199         thisLocals = new HashSet JavaDoc();
200         synchronizedBlockFacts = new IterableSet();
201         exceptionFacts = new IterableSet();
202         monitorFacts = new IterableSet();
203         packagesUsed = new IterableSet();
204         caughtrefs = new LinkedList JavaDoc();
205
206         controlLocal = null;
207         constructorExpr = null;
208     }
209
210     public Unit get_ConstructorUnit() {
211         return constructorUnit;
212     }
213
214     public List JavaDoc get_CaughtRefs() {
215         return caughtrefs;
216     }
217
218     public InstanceInvokeExpr get_ConstructorExpr() {
219         return constructorExpr;
220     }
221
222     public void set_ConstructorExpr(InstanceInvokeExpr expr) {
223         constructorExpr = expr;
224     }
225
226     public void set_ConstructorUnit(Unit s) {
227         constructorUnit = s;
228     }
229
230     public Map JavaDoc get_ParamMap() {
231         return pMap;
232     }
233
234     public void set_ParamMap(Map JavaDoc map) {
235         pMap = map;
236     }
237
238     public HashSet JavaDoc get_ThisLocals() {
239         return thisLocals;
240     }
241
242     public Local get_ControlLocal() {
243         if (controlLocal == null) {
244             controlLocal = new JimpleLocal("controlLocal", IntType.v());
245             getLocals().add(controlLocal);
246         }
247
248         return controlLocal;
249     }
250
251     public Set JavaDoc get_ConsumedConditions() {
252         return consumedConditions;
253     }
254
255     public void consume_Condition(AugmentedStmt as) {
256         consumedConditions.add(as);
257     }
258
259     public Object JavaDoc clone() {
260         Body b = Dava.v().newBody(getMethod());
261         b.importBodyContentsFrom(this);
262         return b;
263     }
264
265     public IterableSet get_SynchronizedBlockFacts() {
266         return synchronizedBlockFacts;
267     }
268
269     public IterableSet get_ExceptionFacts() {
270         return exceptionFacts;
271     }
272
273     public IterableSet get_MonitorFacts() {
274         return monitorFacts;
275     }
276
277     public IterableSet get_PackagesUsed() {
278         return packagesUsed;
279     }
280
281     /**
282      * Constructs a DavaBody from the given Body.
283      */

284
285     DavaBody(Body body) {
286         this(body.getMethod());
287         debug("DavaBody","creating DavaBody for"+body.getMethod().toString());
288         Dava.v().log("\nstart method " + body.getMethod().toString());
289
290         // copy and "convert" the grimp representation
291
copy_Body(body);
292
293         // prime the analysis
294
AugmentedStmtGraph asg = new AugmentedStmtGraph(
295                 new BriefUnitGraph(this), new TrapUnitGraph(this));
296         //System.out.println(asg.toString());
297

298         ExceptionFinder.v().preprocess(this, asg);
299         SETNode SET = new SETTopNode(asg.get_ChainView());
300
301         while (true) {
302             try {
303                 CycleFinder.v().find(this, asg, SET);
304                 IfFinder.v().find(this, asg, SET);
305                 SwitchFinder.v().find(this, asg, SET);
306                 SynchronizedBlockFinder.v().find(this, asg, SET);
307                 ExceptionFinder.v().find(this, asg, SET);
308                 SequenceFinder.v().find(this, asg, SET);
309                 LabeledBlockFinder.v().find(this, asg, SET);
310                 AbruptEdgeFinder.v().find(this, asg, SET);
311             } catch (RetriggerAnalysisException rae) {
312                 SET = new SETTopNode(asg.get_ChainView());
313                 consumedConditions = new HashSet JavaDoc();
314                 continue;
315             }
316             break;
317         }
318
319         MonitorConverter.v().convert(this);
320         ThrowNullConverter.v().convert(this);
321
322         ASTNode AST = SET.emit_AST();
323
324         // get rid of the grimp representation, put in the new AST
325
getTraps().clear();
326         getUnits().clear();
327         getUnits().addLast(AST);
328
329         // perform transformations on the AST
330
/*
331          * Nomair This should be refactored to use the new AnalysisAdapter classes
332          */

333         do {
334             G.v().ASTAnalysis_modified = false;
335
336             AST.perform_Analysis(UselessTryRemover.v());
337
338         } while (G.v().ASTAnalysis_modified);
339
340         /*
341          Nomair A Naeem 10-MARCH-2005
342
343          IT IS ESSENTIAL TO CALL THIS METHOD
344          This method initializes the locals of the current method being processed
345          Failure to invoke this method here will result in no locals being printed out
346          */

347         if (AST instanceof ASTMethodNode) {
348             ((ASTMethodNode) AST).storeLocals(this);
349
350             /*
351              * January 12th, 2006
352              * Deal with the super() problem before continuing
353              */

354             Map JavaDoc options = PhaseOptions.v().getPhaseOptions("db.force-recompile");
355             boolean force = PhaseOptions.getBoolean(options, "enabled");
356             //System.out.println("force is "+force);
357
if(force){
358                 AST.apply(new SuperFirstStmtHandler((ASTMethodNode) AST));
359             }
360
361             debug("DavaBody","PreInit booleans is" + G.v().SootMethodAddedByDava);
362
363         }
364         Dava.v().log("end method " + body.getMethod().toString());
365     }
366
367     /*
368      * Method is invoked by the packmanager just before it is actually about to generate
369      * decompiled code. Works as a separate stage from the DavaBody() constructor.
370      * All AST transformations should be implemented from within this method.
371      */

372     public void analyzeAST() {
373         ASTNode AST = (ASTNode) this.getUnits().getFirst();
374         debug("analyzeAST","Applying AST analyzes for method"+this.getMethod().toString());
375
376         /*
377          * Nomair A. Naeem
378          * tranformations on the AST
379          * Any AST Transformations added should be added to the applyASTAnalyses method
380          * unless we are want to delay the analysis till for example THE LAST THING DONE
381          */

382         applyASTAnalyses(AST);
383
384         /*
385          * Nomair A. Naeem
386          * apply structural flow analyses now
387          *
388          */

389         applyStructuralAnalyses(AST);
390
391         /*
392          * Renamer
393          *
394          */

395         Map JavaDoc options = PhaseOptions.v().getPhaseOptions("db.renamer");
396         boolean renamer = PhaseOptions.getBoolean(options, "enabled");
397         //System.out.println("renaming is"+renamer);
398
if(renamer){
399             //System.out.println("\nRenaming...");
400
applyRenamerAnalyses(AST);
401         }
402         
403         
404
405         /*
406          In the end check
407          1, if there are labels which can be safely removed
408          2, int temp; temp=0 to be converted to int temp=0;
409          */

410         //AST.apply(new ExtraLabelNamesRemover());
411

412         //System.out.println("\nEND analyzing method"+this.getMethod().toString());
413
}
414
415     private void applyASTAnalyses(ASTNode AST) {
416         debug("applyASTAnalyses","initial one time analyses started");
417         /*
418          Nomair A. Naeem
419          Transformations on the AST
420          */

421         //The BooleanConditionSimplification changes flag==false to just flag
422

423
424         AST.apply(new BooleanConditionSimplification());
425
426         AST.apply(new VoidReturnRemover(this));
427
428         AST.apply(new DecrementIncrementStmtCreation());
429
430         AST.apply(new DeInliningFinalFields());
431
432         debug("applyASTAnalyses","initial one time analyses completed");
433         
434          
435          
436         boolean flag = true;
437         int times = 0;
438
439         G.v().ASTTransformations_modified = false;
440         G.v().ASTIfElseFlipped = false;
441         
442         int countFlipping=0;
443         
444         if (flag) {
445             // perform transformations on the AST
446
do {
447                 debug("applyASTAnalyses","ITERATION");
448                 G.v().ASTTransformations_modified = false;
449                 times++;
450
451
452                 AST.apply(new AndAggregator());
453                 debug("applyASTAnalyses","after AndAggregator"+G.v().ASTTransformations_modified);
454                 /*
455                  The OrAggregatorOne internally calls UselessLabelFinder which sets the label to null
456                  Always apply a UselessLabeledBlockRemover in the end to remove such labeled blocks
457                  */

458
459                 AST.apply(new OrAggregatorOne());
460                 debug("applyASTAnalyses","after OraggregatorOne"+G.v().ASTTransformations_modified);
461
462                 /*
463                  Note OrAggregatorTwo should always be followed by an emptyElseRemover
464                  since orAggregatorTwo can create empty else bodies and the ASTIfElseNode
465                  can be replaced by ASTIfNodes
466                  OrAggregator has two patterns see the class for them
467                  */

468
469                 AST.apply(new OrAggregatorTwo());
470                 debug("applyASTAnalyses","after OraggregatorTwo"+G.v().ASTTransformations_modified);
471                 debug("applyASTAnalyses","after OraggregatorTwo ifElseFlipped is"+G.v().ASTIfElseFlipped);
472                 
473                 AST.apply(new OrAggregatorFour());
474                 debug("applyASTAnalyses","after OraggregatorFour"+G.v().ASTTransformations_modified);
475
476                 /*
477                  * ASTCleaner currently does the following tasks:
478                  * 1, Remove empty Labeled Blocks UselessLabeledBlockRemover
479                  * 2, convert ASTIfElseNodes with empty else bodies to ASTIfNodes
480                  * 3, Apply OrAggregatorThree
481                  */

482                 AST.apply(new ASTCleaner());
483                 debug("applyASTAnalyses","after ASTCleaner"+G.v().ASTTransformations_modified);
484
485                 /*
486                  * PushLabeledBlockIn should not be called unless we are sure
487                  * that all labeledblocks have non null labels.
488                  * A good way of ensuring this is to run the ASTCleaner directly
489                  * before calling this
490                  */

491                 AST.apply(new PushLabeledBlockIn());
492                 debug("applyASTAnalyses","after PushLabeledBlockIn"+G.v().ASTTransformations_modified);
493                 
494                 
495                 AST.apply(new LoopStrengthener());
496                 debug("applyASTAnalyses","after LoopStrengthener"+G.v().ASTTransformations_modified);
497
498                 /*
499                  * Pattern two carried out in OrAggregatorTwo restricts some patterns in for loop creation.
500                  * Pattern two was implemented to give loopStrengthening a better chance
501                  * SEE IfElseBreaker
502                  */

503                 AST.apply(new ASTCleanerTwo());
504                 debug("applyASTAnalyses","after ASTCleanerTwo"+G.v().ASTTransformations_modified);
505
506                 
507                 AST.apply(new ForLoopCreator());
508                 debug("applyASTAnalyses","after ForLoopCreator"+G.v().ASTTransformations_modified);
509
510                 /*
511                  * if we matched some useful pattern we reserve the
512                  * right to flip conditions again
513                  */

514                 if(G.v().ASTTransformations_modified){
515                     G.v().ASTIfElseFlipped=false;
516                     countFlipping=0;
517                     debug("applyASTanalyses","Transformation modified was true hence will reiterate. set flipped to false");
518                 }
519                 else{
520                     //check if only the ifelse was flipped
521
if(G.v().ASTIfElseFlipped ){
522                         debug("","ifelseflipped and transformations NOT modified");
523                         //we couldnt transform but we did flip
524
if(countFlipping==0){
525                             debug("","ifelseflipped and transformations NOT modified count is 0");
526                             //let this go on just once more in the hope of some other pattern being matched
527
G.v().ASTIfElseFlipped=false;
528                             countFlipping++;
529                             G.v().ASTTransformations_modified=true;
530                         }
531                         else{
532                             debug("","ifelseflipped and transformations NOT modified count is not 0 TERMINATE");
533                         }
534                     }
535                 }//if ASTTransformations was not modified
536

537             } while (G.v().ASTTransformations_modified);
538             //System.out.println("The AST trasnformations has run"+times);
539
}
540
541         /*
542          * ClosestAbruptTargetFinder should be reinitialized everytime there is a change to the AST
543          * This is utilized internally by the DavaFlowSet implementation to handle Abrupt Implicit Stmts
544          */

545         AST.apply(ClosestAbruptTargetFinder.v());
546         debug("applyASTAnalyses","after ClosestAbruptTargetFinder"+G.v().ASTTransformations_modified);
547
548         //29th Jan 2006
549
//make sure when recompiling there is no variable might not be initialized error
550

551         Map JavaDoc options = PhaseOptions.v().getPhaseOptions("db.force-recompile");
552         boolean force = PhaseOptions.getBoolean(options, "enabled");
553         //System.out.println("Force is"+force);
554

555         if(force){
556             new FinalFieldDefinition((ASTMethodNode) AST);
557         }
558
559
560     }
561
562     private void applyStructuralAnalyses(ASTNode AST) {
563         //TESTING REACHING DEFS
564
//ReachingDefs defs = new ReachingDefs(AST);
565
//AST.apply(new tester(true,defs));
566

567         //TESTING REACHING COPIES
568
//ReachingCopies copies = new ReachingCopies(AST);
569
//AST.apply(new tester(true,copies));
570

571         //TESTING ASTUSESANDDEFS
572
//AST.apply(new ASTUsesAndDefs(AST));
573

574         /*
575          * Structural flow analyses.....
576          */

577
578         CopyPropagation prop = new CopyPropagation(AST);
579         AST.apply(prop);
580
581         //copy propagation should be followed by LocalVariableCleaner to get max effect
582
AST.apply(new LocalVariableCleaner(AST));
583
584     }
585
586     
587     private void applyRenamerAnalyses(ASTNode AST){
588         
589         infoGatheringAnalysis info = new infoGatheringAnalysis(this);
590         AST.apply(info);
591
592         Renamer renamer = new Renamer(info.getHeuristicSet(),(ASTMethodNode)AST);
593         renamer.rename();
594     }
595
596         
597     /*
598      * Copy and patch a GrimpBody so that it can be used to output Java.
599      */

600
601     private void copy_Body(Body body) {
602         if (!(body instanceof GrimpBody))
603             throw new RuntimeException JavaDoc(
604                     "You can only create a DavaBody from a GrimpBody!");
605
606         GrimpBody grimpBody = (GrimpBody) body;
607
608         /*
609          * Import body contents from Grimp.
610          */

611
612         {
613             HashMap JavaDoc bindings = new HashMap JavaDoc();
614             HashMap JavaDoc reverse_binding = new HashMap JavaDoc();
615
616             Iterator JavaDoc it = grimpBody.getUnits().iterator();
617
618             // Clone units in body's statement list
619
while (it.hasNext()) {
620                 Unit original = (Unit) it.next();
621                 Unit copy = (Unit) original.clone();
622
623                 // Add cloned unit to our unitChain.
624
getUnits().addLast(copy);
625
626                 // Build old <-> new map to be able to patch up references to other units
627
// within the cloned units. (these are still refering to the original
628
// unit objects).
629
bindings.put(original, copy);
630                 reverse_binding.put(copy, original);
631             }
632
633             // patch up the switch statments
634
it = getUnits().iterator();
635             while (it.hasNext()) {
636                 Unit u = (Unit) it.next();
637                 Stmt s = (Stmt) u;
638
639                 if (s instanceof TableSwitchStmt) {
640                     TableSwitchStmt ts = (TableSwitchStmt) s;
641
642                     TableSwitchStmt original_switch = (TableSwitchStmt) reverse_binding
643                             .get(u);
644                     ts.setDefaultTarget((Unit) bindings.get(original_switch
645                             .getDefaultTarget()));
646
647                     LinkedList JavaDoc new_target_list = new LinkedList JavaDoc();
648
649                     int target_count = ts.getHighIndex() - ts.getLowIndex() + 1;
650                     for (int i = 0; i < target_count; i++)
651                         new_target_list.add((Unit) bindings.get(original_switch
652                                 .getTarget(i)));
653                     ts.setTargets(new_target_list);
654
655                 }
656                 if (s instanceof LookupSwitchStmt) {
657                     LookupSwitchStmt ls = (LookupSwitchStmt) s;
658
659                     LookupSwitchStmt original_switch = (LookupSwitchStmt) reverse_binding
660                             .get(u);
661                     ls.setDefaultTarget((Unit) bindings.get(original_switch
662                             .getDefaultTarget()));
663
664                     Unit[] new_target_list = new Unit[original_switch
665                             .getTargetCount()];
666                     for (int i = 0; i < original_switch.getTargetCount(); i++)
667                         new_target_list[i] = (Unit) (bindings
668                                 .get(original_switch.getTarget(i)));
669                     ls.setTargets(new_target_list);
670
671                     ls.setLookupValues(original_switch.getLookupValues());
672                 }
673             }
674
675             // Clone locals.
676
it = grimpBody.getLocals().iterator();
677             while (it.hasNext()) {
678                 Local original = (Local) it.next();
679
680                 Value copy = Dava.v().newLocal(original.getName(),
681                         original.getType());
682
683                 getLocals().addLast(copy);
684
685                 // Build old <-> new mapping.
686
bindings.put(original, copy);
687             }
688
689             // Patch up references within units using our (old <-> new) map.
690
it = getAllUnitBoxes().iterator();
691             while (it.hasNext()) {
692                 UnitBox box = (UnitBox) it.next();
693                 Unit newObject, oldObject = box.getUnit();
694
695                 // if we have a reference to an old object, replace it
696
// it's clone.
697
if ((newObject = (Unit) bindings.get(oldObject)) != null)
698                     box.setUnit(newObject);
699             }
700
701             // backpatch all local variables.
702
it = getUseAndDefBoxes().iterator();
703             while (it.hasNext()) {
704                 ValueBox vb = (ValueBox) it.next();
705                 if (vb.getValue() instanceof Local)
706                     vb.setValue((Value) bindings.get(vb.getValue()));
707             }
708
709             // clone the traps
710
Iterator JavaDoc trit = grimpBody.getTraps().iterator();
711             while (trit.hasNext()) {
712
713                 Trap originalTrap = (Trap) trit.next();
714                 Trap cloneTrap = (Trap) originalTrap.clone();
715
716                 Unit handlerUnit = (Unit) bindings.get(originalTrap
717                         .getHandlerUnit());
718
719                 cloneTrap.setHandlerUnit(handlerUnit);
720                 cloneTrap.setBeginUnit((Unit) bindings.get(originalTrap
721                         .getBeginUnit()));
722                 cloneTrap.setEndUnit((Unit) bindings.get(originalTrap
723                         .getEndUnit()));
724
725                 getTraps().add(cloneTrap);
726             }
727         }
728
729         /*
730          * Add one level of indirection to "if", "switch", and exceptional control flow.
731          * This allows for easy handling of breaks, continues and exceptional loops.
732          */

733         {
734             PatchingChain units = getUnits();
735
736             Iterator JavaDoc it = units.snapshotIterator();
737             while (it.hasNext()) {
738                 Unit u = (Unit) it.next();
739                 Stmt s = (Stmt) u;
740
741                 if (s instanceof IfStmt) {
742                     IfStmt ifs = (IfStmt) s;
743
744                     JGotoStmt jgs = new JGotoStmt((Unit) units.getSuccOf(u));
745                     units.insertAfter(jgs, u);
746
747                     JGotoStmt jumper = new JGotoStmt((Unit) ifs.getTarget());
748                     units.insertAfter(jumper, jgs);
749                     ifs.setTarget((Unit) jumper);
750                 }
751
752                 else if (s instanceof TableSwitchStmt) {
753                     TableSwitchStmt tss = (TableSwitchStmt) s;
754
755                     int targetCount = tss.getHighIndex() - tss.getLowIndex()
756                             + 1;
757                     for (int i = 0; i < targetCount; i++) {
758                         JGotoStmt jgs = new JGotoStmt((Unit) tss.getTarget(i));
759                         units.insertAfter(jgs, tss);
760                         tss.setTarget(i, (Unit) jgs);
761                     }
762
763                     JGotoStmt jgs = new JGotoStmt((Unit) tss.getDefaultTarget());
764                     units.insertAfter(jgs, tss);
765                     tss.setDefaultTarget((Unit) jgs);
766                 }
767
768                 else if (s instanceof LookupSwitchStmt) {
769                     LookupSwitchStmt lss = (LookupSwitchStmt) s;
770
771                     for (int i = 0; i < lss.getTargetCount(); i++) {
772                         JGotoStmt jgs = new JGotoStmt((Unit) lss.getTarget(i));
773                         units.insertAfter(jgs, lss);
774                         lss.setTarget(i, (Unit) jgs);
775                     }
776
777                     JGotoStmt jgs = new JGotoStmt((Unit) lss.getDefaultTarget());
778                     units.insertAfter(jgs, lss);
779                     lss.setDefaultTarget((Unit) jgs);
780                 }
781             }
782
783             it = getTraps().iterator();
784             while (it.hasNext()) {
785                 Trap t = (Trap) it.next();
786
787                 JGotoStmt jgs = new JGotoStmt((Unit) t.getHandlerUnit());
788                 units.addLast(jgs);
789                 t.setHandlerUnit((Unit) jgs);
790             }
791         }
792
793         /*
794          * Fix up the grimp representations of statements so they can be compiled as java.
795          */

796
797         {
798             Iterator JavaDoc it = getLocals().iterator();
799             while (it.hasNext()) {
800                 Type t = ((Local) it.next()).getType();
801
802                 if (t instanceof RefType) {
803                     RefType rt = (RefType) t;
804
805                     addPackage(rt.getSootClass().getJavaPackageName());
806                 }
807             }
808
809             it = getUnits().iterator();
810             while (it.hasNext()) {
811                 Unit u = (Unit) it.next();
812                 Stmt s = (Stmt) u;
813
814                 if (s instanceof IfStmt)
815                     javafy(((IfStmt) s).getConditionBox());
816
817                 else if (s instanceof ThrowStmt)
818                     javafy(((ThrowStmt) s).getOpBox());
819
820                 else if (s instanceof TableSwitchStmt)
821                     javafy(((TableSwitchStmt) s).getKeyBox());
822
823                 else if (s instanceof LookupSwitchStmt)
824                     javafy(((LookupSwitchStmt) s).getKeyBox());
825
826                 else if (s instanceof MonitorStmt)
827                     javafy(((MonitorStmt) s).getOpBox());
828
829                 else if (s instanceof DefinitionStmt) {
830                     DefinitionStmt ds = (DefinitionStmt) s;
831
832                     javafy(ds.getRightOpBox());
833                     javafy(ds.getLeftOpBox());
834
835                     if (ds.getRightOp() instanceof IntConstant)
836                         ds.getRightOpBox().setValue(
837                                 DIntConstant.v(
838                                         ((IntConstant) ds.getRightOp()).value,
839                                         ds.getLeftOp().getType()));
840                 }
841
842                 else if (s instanceof ReturnStmt) {
843                     ReturnStmt rs = (ReturnStmt) s;
844
845                     if (rs.getOp() instanceof IntConstant)
846                         rs.getOpBox().setValue(
847                                 DIntConstant.v(
848                                         ((IntConstant) rs.getOp()).value, body
849                                                 .getMethod().getReturnType()));
850                     else
851                         javafy(rs.getOpBox());
852                 }
853
854                 else if (s instanceof InvokeStmt)
855                     javafy(((InvokeStmt) s).getInvokeExprBox());
856             }
857         }
858
859         /*
860          * Convert references to "this" and parameters.
861          */

862
863         {
864             Iterator JavaDoc ucit = getUnits().iterator();
865             while (ucit.hasNext()) {
866                 Stmt s = (Stmt) ucit.next();
867
868                 if (s instanceof IdentityStmt) {
869                     IdentityStmt ids = (IdentityStmt) s;
870                     Value ids_rightOp = ids.getRightOp();
871                     Value ids_leftOp = ids.getLeftOp();
872
873                     if ((ids_leftOp instanceof Local)
874                             && (ids_rightOp instanceof ThisRef)) {
875                         Local thisLocal = (Local) ids_leftOp;
876
877                         thisLocals.add(thisLocal);
878                         thisLocal.setName("this");
879                     }
880                 }
881
882                 if (s instanceof DefinitionStmt) {
883                     DefinitionStmt ds = (DefinitionStmt) s;
884                     Value rightOp = ds.getRightOp();
885
886                     if (rightOp instanceof ParameterRef)
887                         pMap.put(new Integer JavaDoc(((ParameterRef) rightOp)
888                                 .getIndex()), ds.getLeftOp());
889
890                     if (rightOp instanceof CaughtExceptionRef)
891                         caughtrefs.add(ds.getLeftOp());
892                 }
893             }
894         }
895
896         /*
897          * Fix up the calls to other constructors. Note, this is seriously underbuilt.
898          */

899
900         {
901             Iterator JavaDoc ucit = getUnits().iterator();
902             while (ucit.hasNext()) {
903                 Stmt s = (Stmt) ucit.next();
904
905                 if (s instanceof InvokeStmt) {
906
907                     InvokeStmt ivs = (InvokeStmt) s;
908                     Value ie = ivs.getInvokeExpr();
909
910                     if (ie instanceof InstanceInvokeExpr) {
911
912                         InstanceInvokeExpr iie = (InstanceInvokeExpr) ie;
913                         Value base = iie.getBase();
914
915                         if ((base instanceof Local)
916                                 && (((Local) base).getName().equals("this"))) {
917                             SootMethodRef m = iie.getMethodRef();
918                             String JavaDoc name = m.name();
919
920                             if ((name.equals(SootMethod.constructorName))
921                                     || (name
922                                             .equals(SootMethod.staticInitializerName))) {
923
924                                 if (constructorUnit != null)
925                                     throw new RuntimeException JavaDoc(
926                                             "More than one candidate for constructor found.");
927
928                                 constructorExpr = iie;
929                                 constructorUnit = (Unit) s;
930                             }
931                         }
932                     }
933                 }
934             }
935         }
936     }
937
938     /*
939      * The following set of routines takes care of converting the syntax of single grimp
940      * statements to java.
941      */

942
943     private void javafy(ValueBox vb) {
944         Value v = vb.getValue();
945
946         if (v instanceof Expr)
947             javafy_expr(vb);
948         else if (v instanceof Ref)
949             javafy_ref(vb);
950         else if (v instanceof Local)
951             javafy_local(vb);
952         else if (v instanceof Constant)
953             javafy_constant(vb);
954     }
955
956     private void javafy_expr(ValueBox vb) {
957         Expr e = (Expr) vb.getValue();
958
959         if (e instanceof BinopExpr)
960             javafy_binop_expr(vb);
961         else if (e instanceof UnopExpr)
962             javafy_unop_expr(vb);
963         else if (e instanceof CastExpr)
964             javafy_cast_expr(vb);
965         else if (e instanceof NewArrayExpr)
966             javafy_newarray_expr(vb);
967         else if (e instanceof NewMultiArrayExpr)
968             javafy_newmultiarray_expr(vb);
969         else if (e instanceof InstanceOfExpr)
970             javafy_instanceof_expr(vb);
971         else if (e instanceof InvokeExpr)
972             javafy_invoke_expr(vb);
973         else if (e instanceof NewExpr)
974             javafy_new_expr(vb);
975     }
976
977     private void javafy_ref(ValueBox vb) {
978         Ref r = (Ref) vb.getValue();
979
980         if (r instanceof StaticFieldRef) {
981             SootFieldRef fieldRef = ((StaticFieldRef) r).getFieldRef();
982             addPackage(fieldRef.declaringClass().getJavaPackageName());
983             vb.setValue(new DStaticFieldRef(fieldRef, getMethod()
984                     .getDeclaringClass().getName()));
985         } else if (r instanceof ArrayRef) {
986             ArrayRef ar = (ArrayRef) r;
987
988             javafy(ar.getBaseBox());
989             javafy(ar.getIndexBox());
990         }
991
992         else if (r instanceof InstanceFieldRef) {
993             InstanceFieldRef ifr = (InstanceFieldRef) r;
994
995             javafy(ifr.getBaseBox());
996
997             vb.setValue(new DInstanceFieldRef(ifr.getBase(), ifr.getFieldRef(),
998                     thisLocals));
999         }
1000
1001        else if (r instanceof ThisRef) {
1002            ThisRef tr = (ThisRef) r;
1003
1004            vb.setValue(new DThisRef((RefType) tr.getType()));
1005        }
1006    }
1007
1008    private void javafy_local(ValueBox vb) {
1009    }
1010
1011    private void javafy_constant(ValueBox vb) {
1012    }
1013
1014    private void javafy_binop_expr(ValueBox vb) {
1015        BinopExpr boe = (BinopExpr) vb.getValue();
1016
1017        ValueBox leftOpBox = boe.getOp1Box(), rightOpBox = boe.getOp2Box();
1018        Value leftOp = leftOpBox.getValue(), rightOp = rightOpBox.getValue();
1019
1020        if (rightOp instanceof IntConstant) {
1021            if ((leftOp instanceof IntConstant) == false) {
1022                javafy(leftOpBox);
1023                leftOp = leftOpBox.getValue();
1024
1025                if (boe instanceof ConditionExpr)
1026                    rightOpBox.setValue(DIntConstant.v(
1027                            ((IntConstant) rightOp).value, leftOp.getType()));
1028                else
1029                    rightOpBox.setValue(DIntConstant.v(
1030                            ((IntConstant) rightOp).value, null));
1031            }
1032        } else if (leftOp instanceof IntConstant) {
1033            javafy(rightOpBox);
1034            rightOp = rightOpBox.getValue();
1035
1036            if (boe instanceof ConditionExpr)
1037                leftOpBox.setValue(DIntConstant.v(((IntConstant) leftOp).value,
1038                        rightOp.getType()));
1039            else
1040                leftOpBox.setValue(DIntConstant.v(((IntConstant) leftOp).value,
1041                        null));
1042        } else {
1043            javafy(rightOpBox);
1044            rightOp = rightOpBox.getValue();
1045
1046            javafy(leftOpBox);
1047            leftOp = leftOpBox.getValue();
1048        }
1049
1050        if (boe instanceof CmpExpr)
1051            vb.setValue(new DCmpExpr(leftOp, rightOp));
1052
1053        else if (boe instanceof CmplExpr)
1054            vb.setValue(new DCmplExpr(leftOp, rightOp));
1055
1056        else if (boe instanceof CmpgExpr)
1057            vb.setValue(new DCmpgExpr(leftOp, rightOp));
1058    }
1059
1060    private void javafy_unop_expr(ValueBox vb) {
1061        UnopExpr uoe = (UnopExpr) vb.getValue();
1062
1063        javafy(uoe.getOpBox());
1064
1065        if (uoe instanceof LengthExpr)
1066            vb.setValue(new DLengthExpr(((LengthExpr) uoe).getOp()));
1067        else if (uoe instanceof NegExpr)
1068            vb.setValue(new DNegExpr(((NegExpr) uoe).getOp()));
1069    }
1070
1071    private void javafy_cast_expr(ValueBox vb) {
1072        CastExpr ce = (CastExpr) vb.getValue();
1073
1074        javafy(ce.getOpBox());
1075    }
1076
1077    private void javafy_newarray_expr(ValueBox vb) {
1078        NewArrayExpr nae = (NewArrayExpr) vb.getValue();
1079
1080        javafy(nae.getSizeBox());
1081        vb.setValue(new DNewArrayExpr(nae.getBaseType(), nae.getSize()));
1082    }
1083
1084    private void javafy_newmultiarray_expr(ValueBox vb) {
1085        NewMultiArrayExpr nmae = (NewMultiArrayExpr) vb.getValue();
1086
1087        for (int i = 0; i < nmae.getSizeCount(); i++)
1088            javafy(nmae.getSizeBox(i));
1089
1090        vb
1091                .setValue(new DNewMultiArrayExpr(nmae.getBaseType(), nmae
1092                        .getSizes()));
1093    }
1094
1095    private void javafy_instanceof_expr(ValueBox vb) {
1096        InstanceOfExpr ioe = (InstanceOfExpr) vb.getValue();
1097
1098        javafy(ioe.getOpBox());
1099    }
1100
1101    private void javafy_invoke_expr(ValueBox vb) {
1102        InvokeExpr ie = (InvokeExpr) vb.getValue();
1103
1104        addPackage(ie.getMethodRef().declaringClass().getJavaPackageName());
1105
1106        for (int i = 0; i < ie.getArgCount(); i++) {
1107            Value arg = ie.getArg(i);
1108
1109            if (arg instanceof IntConstant)
1110                ie.getArgBox(i).setValue(
1111                        DIntConstant.v(((IntConstant) arg).value, ie
1112                                .getMethodRef().parameterType(i)));
1113
1114            else
1115                javafy(ie.getArgBox(i));
1116        }
1117
1118        if (ie instanceof InstanceInvokeExpr) {
1119            javafy(((InstanceInvokeExpr) ie).getBaseBox());
1120
1121            if (ie instanceof VirtualInvokeExpr) {
1122                VirtualInvokeExpr vie = (VirtualInvokeExpr) ie;
1123
1124                vb.setValue(new DVirtualInvokeExpr(vie.getBase(), vie
1125                        .getMethodRef(), vie.getArgs(), thisLocals));
1126            }
1127
1128            else if (ie instanceof SpecialInvokeExpr) {
1129                SpecialInvokeExpr sie = (SpecialInvokeExpr) ie;
1130
1131                vb.setValue(new DSpecialInvokeExpr(sie.getBase(), sie
1132                        .getMethodRef(), sie.getArgs()));
1133            }
1134
1135            else if (ie instanceof InterfaceInvokeExpr) {
1136                InterfaceInvokeExpr iie = (InterfaceInvokeExpr) ie;
1137
1138                vb.setValue(new DInterfaceInvokeExpr(iie.getBase(), iie
1139                        .getMethodRef(), iie.getArgs()));
1140            }
1141
1142            else
1143                throw new RuntimeException JavaDoc("InstanceInvokeExpr " + ie
1144                        + " not javafied correctly");
1145        }
1146
1147        else if (ie instanceof StaticInvokeExpr) {
1148            StaticInvokeExpr sie = (StaticInvokeExpr) ie;
1149
1150            if (sie instanceof NewInvokeExpr) {
1151                NewInvokeExpr nie = (NewInvokeExpr) sie;
1152
1153                RefType rt = nie.getBaseType();
1154                addPackage(rt.getSootClass().getJavaPackageName());
1155
1156                vb.setValue(new DNewInvokeExpr((RefType) nie.getType(), nie
1157                        .getMethodRef(), nie.getArgs()));
1158            }
1159
1160            else {
1161                SootMethodRef methodRef = sie.getMethodRef();
1162                addPackage(methodRef.declaringClass().getJavaPackageName());
1163                vb.setValue(new DStaticInvokeExpr(methodRef, sie.getArgs()));
1164            }
1165        }
1166
1167        else
1168            throw new RuntimeException JavaDoc("InvokeExpr " + ie
1169                    + " not javafied correctly");
1170    }
1171
1172    private void javafy_new_expr(ValueBox vb) {
1173        NewExpr ne = (NewExpr) vb.getValue();
1174
1175        addPackage(ne.getBaseType().getSootClass().getJavaPackageName());
1176    }
1177
1178    public void addPackage(String JavaDoc newPackage) {
1179        if (newPackage.equals(""))
1180            return;
1181
1182        if (packagesUsed.contains(newPackage) == false){
1183            packagesUsed.add(newPackage);
1184            if(DEBUG)
1185                System.out.println("PACKAGE ADDED"+newPackage);
1186        }
1187    }
1188
1189    public void debug(String JavaDoc methodName, String JavaDoc debug){
1190        if(DEBUG)
1191            System.out.println(methodName+ " DEBUG: "+debug);
1192    }
1193
1194}
1195
Popular Tags