KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > dava > toolkits > base > AST > interProcedural > RedundantFieldUseEliminator


1 package soot.dava.toolkits.base.AST.interProcedural;
2
3 import java.util.ArrayList JavaDoc;
4 import java.util.HashMap JavaDoc;
5 import java.util.Iterator JavaDoc;
6
7 import soot.BooleanType;
8 import soot.ByteType;
9 import soot.CharType;
10 import soot.DoubleType;
11 import soot.FloatType;
12 import soot.IntType;
13 import soot.LongType;
14 import soot.PrimType;
15 import soot.ShortType;
16 import soot.SootClass;
17 import soot.SootField;
18 import soot.SootMethod;
19 import soot.Type;
20
21 import soot.Value;
22 import soot.dava.DavaBody;
23 import soot.dava.DecompilationException;
24
25 import soot.dava.internal.AST.ASTNode;
26 import soot.dava.internal.javaRep.DIntConstant;
27 import soot.dava.toolkits.base.AST.traversals.AllDefinitionsFinder;
28 import soot.grimp.internal.GAssignStmt;
29 import soot.jimple.DefinitionStmt;
30 import soot.jimple.DoubleConstant;
31 import soot.jimple.FieldRef;
32 import soot.jimple.FloatConstant;
33 import soot.jimple.LongConstant;
34
35 import soot.tagkit.DoubleConstantValueTag;
36 import soot.tagkit.FloatConstantValueTag;
37 import soot.tagkit.IntegerConstantValueTag;
38 import soot.tagkit.LongConstantValueTag;
39 import soot.tagkit.StringConstantValueTag;
40 import soot.util.Chain;
41
42 /*
43  * Deemed important because of obfuscation techniques which add crazy
44  * control flow under some condition which is never executed because
45  * it uses some field which is always false!!
46  *
47  * Goal:
48  * Prove that a field is never assigned a value or that if it is assigned a value
49  * we can statically tell this value
50  *
51  * Use this information to do constant field propagation
52  * i.e. wherever we have the use of a field use the constant value (ideally the default value)
53  *
54  * Use that information to remove un-necessary conditions etc
55  *
56  */

57 public class RedundantFieldUseEliminator {
58     public final boolean DEBUG = true;
59     
60     String JavaDoc combiner = "$p$g";
61     
62     HashMap JavaDoc fieldToValues = new HashMap JavaDoc();
63
64     Chain appClasses;
65     
66     public RedundantFieldUseEliminator(Chain classes){
67         appClasses = classes;
68     }
69     
70     
71     public void applyAnalysis(){
72     
73         /*
74          * Compute method summaries for each method in the application
75          */

76         debug("RedundantFielduseEliminator -- applyAnalyses","computing Method Summaries");
77         computeFieldToValuesAssignedList();
78         valuesForPrimTypeFields();
79         
80     }
81     
82     /*
83      * This method first gives default values to all the fields in all the classes
84      * We only care about fields which have primitive types
85      */

86     public void valuesForPrimTypeFields(){
87         
88         HashMap JavaDoc primTypeFieldValueToUse = new HashMap JavaDoc();
89         
90         //go through all the classes
91
Iterator JavaDoc classIt = appClasses.iterator();
92         while(classIt.hasNext()){
93             SootClass s = (SootClass) classIt.next();
94             debug("\nvaluesforPrimTypeFields","Processing class "+s.getName());
95
96             
97             String JavaDoc declaringClass = s.getName();
98             Iterator JavaDoc fieldIt = s.getFields().iterator();
99             while(fieldIt.hasNext()){
100                 SootField f = (SootField)fieldIt.next();
101                 
102                 String JavaDoc fieldName = f.getName();
103                 
104                 Type fieldType = f.getType();
105                 if(! (fieldType instanceof PrimType ) )
106                     continue;
107                 
108                 String JavaDoc combined = declaringClass + combiner + fieldName;
109                 
110                 Object JavaDoc value=null;
111                 
112                 //check for constant value tags
113
if(fieldType instanceof DoubleType && f.hasTag("DoubleConstantValueTag")){
114                     double val = ((DoubleConstantValueTag)f.getTag("DoubleConstantValueTag")).getDoubleValue();
115                     value = new Double JavaDoc(val);
116                 }
117                 else if (fieldType instanceof FloatType && f.hasTag("FloatConstantValueTag")){
118                     float val = ((FloatConstantValueTag)f.getTag("FloatConstantValueTag")).getFloatValue();
119                     value = new Float JavaDoc(val);
120                 }
121                 else if (fieldType instanceof LongType && f.hasTag("LongConstantValueTag")){
122                     long val = ((LongConstantValueTag)f.getTag("LongConstantValueTag")).getLongValue();
123                     value = new Long JavaDoc(val);
124                 }
125                 else if (fieldType instanceof CharType && f.hasTag("IntegerConstantValueTag")){
126                     int val = ((IntegerConstantValueTag)f.getTag("IntegerConstantValueTag")).getIntValue();
127                     value = new Integer JavaDoc(val);
128                 }
129                 else if (fieldType instanceof BooleanType && f.hasTag("IntegerConstantValueTag")){
130                     int val = ((IntegerConstantValueTag)f.getTag("IntegerConstantValueTag")).getIntValue();
131                     if (val ==0)
132                         value = new Boolean JavaDoc(false);
133                     else
134                         value = new Boolean JavaDoc(true);
135                 }
136                 else if ( (fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType) &&
137                       f.hasTag("IntegerConstantValueTag")){
138                     int val = ((IntegerConstantValueTag)f.getTag("IntegerConstantValueTag")).getIntValue();
139                     value = new Integer JavaDoc(val);
140                 }
141
142                 
143                 //if there was a constant value tag we have its value now
144
if(value != null){
145                     debug("TAGGED value found for tag"+combined);
146                     primTypeFieldValueToUse.put(combined,value);
147                 }
148                 else{
149                     //still havent gotten a value
150

151                     //see if the field was never assigned in which case it gets default values
152
Object JavaDoc temp = fieldToValues.get(combined);
153                     if(temp == null){
154                         //no value list found is good
155

156                         //add default value to primTypeFieldValueToUse hashmap
157

158                         if(fieldType instanceof DoubleType )
159                             value = new Double JavaDoc(0);
160                         else if (fieldType instanceof FloatType )
161                             value = new Float JavaDoc(0);
162                         else if (fieldType instanceof LongType )
163                             value = new Long JavaDoc(0);
164                         else if (fieldType instanceof BooleanType)
165                                 value = new Boolean JavaDoc(false);
166                         else if ( (fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType) || fieldType instanceof CharType){
167                             value = new Integer JavaDoc(0);
168                         }
169                         else
170                             throw new DecompilationException("Unknown primitive type...please report to developer");
171
172                         primTypeFieldValueToUse.put(combined,value);
173                         debug("DEFAULT value found for tag"+combined);
174                     }
175                     else{
176                         //there was some value assigned!!!!!!!!!
177
debug("CHECKING USER ASSIGNED VALUES FOR"+combined);
178                         
179                     }
180                 }
181                 
182     
183     
184     
185     
186     
187     
188     
189     
190                 //check if this is assigned some value in any of the methods
191

192                 //if both isnt happening then we know it gets default automatically.....put this in some sort of VALUE TO USE FOR THIS FIELD LIST
193

194                 
195                 //if either of the above is true then check that the value in the methods and tags is always the same (0 or true or something like that)
196

197                 //if you can decide then ...........put this in some sort of VALUE TO USE FOR THIS FIELD LIST
198

199                 
200                 
201                 
202                 
203                 
204                 
205             }
206         }
207     }
208     
209     /*
210      * Go through all the methods in the application and make a mapping of className+methodName ---> values assigned
211      * There can obviously be more than one value assigned to each field
212      */

213     public void computeFieldToValuesAssignedList(){
214         //go through all the classes
215
Iterator JavaDoc classIt = appClasses.iterator();
216         while(classIt.hasNext()){
217             SootClass s = (SootClass) classIt.next();
218             debug("\ncomputeMethodSummaries","Processing class "+s.getName());
219             
220             //go though all the methods
221
Iterator JavaDoc methodIt = s.methodIterator();
222             while (methodIt.hasNext()) {
223                 SootMethod m = (SootMethod) methodIt.next();
224                 DavaBody body = (DavaBody)m.getActiveBody();
225                 ASTNode AST = (ASTNode) body.getUnits().getFirst();
226                 
227                 //find all definitions in the program
228
AllDefinitionsFinder defFinder = new AllDefinitionsFinder();
229                 AST.apply(defFinder);
230                 Iterator JavaDoc allDefIt = defFinder.getAllDefs().iterator();
231                 
232                 //go through each definition
233
while(allDefIt.hasNext()){
234                     DefinitionStmt stmt = (DefinitionStmt)allDefIt.next();
235                     //debug("DefinitionStmt")
236
Value left = stmt.getLeftOp();
237                     
238                     /*
239                      * Only care if we have fieldRef on the left
240                      */

241                     if(! (left instanceof FieldRef) ){
242                         continue;
243                     }
244                     
245                     //we know definition is to a field
246
debug("computeMethodSummaries method: "+m.getName(),"Field ref is: "+left);
247                     // Information we want to store is class of field and name of field and the right op
248

249                     FieldRef ref = (FieldRef)left;
250                     SootField field = ref.getField();
251                     
252                     
253                     /*
254                      * Only care about fields with primtype
255                      */

256                     if(!( field.getType() instanceof PrimType))
257                         continue;
258                     
259                     
260                     
261                     String JavaDoc fieldName = field.getName();
262                     String JavaDoc declaringClass = field.getDeclaringClass().getName();
263                     
264                     debug("\tField Name: "+ fieldName);
265                     debug("\tField DeclaringClass: "+ declaringClass);
266                         
267                     //get the valueList for this class+field combo
268
String JavaDoc combined = declaringClass + combiner + fieldName;
269                     Object JavaDoc temp = fieldToValues.get(combined);
270
271                     ArrayList JavaDoc valueList;
272                     if(temp == null){
273                         //no value of this field was yet assigned
274
valueList = new ArrayList JavaDoc();
275                         fieldToValues.put(combined,valueList);
276                     }
277                     else{
278                         valueList = (ArrayList JavaDoc)temp;
279                     }
280                         
281                     valueList.add(stmt.getRightOp());
282                 }//going through all the definitions
283
}//going through methods of class s
284
}//going through classes
285
}
286     
287     
288     
289     public void debug(String JavaDoc methodName, String JavaDoc debug){
290         if(DEBUG)
291             System.out.println(methodName+ " DEBUG: "+debug);
292     }
293
294     
295     public void debug(String JavaDoc debug){
296         if(DEBUG)
297             System.out.println("DEBUG: "+debug);
298     }
299
300 }
301
Popular Tags