00001 package ca.mcgill.sable.soot.coffi;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 import ca.mcgill.sable.soot.jimple.*;
00113 import ca.mcgill.sable.util.*;
00114 import ca.mcgill.sable.soot.baf.*;
00115 import ca.mcgill.sable.soot.*;
00116
00117 public class Util
00118 {
00119 static Map classNameToAbbreviation;
00120
00121 static SootClassManager classManager;
00122
00123 static int nextEasyNameIndex;
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 static String getAbbreviationOfClassName(String className)
00166 {
00167 StringBuffer buffer = new StringBuffer(new Character(className.charAt(0)).toString());
00168 int periodIndex = 0;
00169
00170 for(;;)
00171 {
00172 periodIndex = className.indexOf('.', periodIndex + 1);
00173
00174 if(periodIndex == -1)
00175 break;
00176
00177 buffer.append(Character.toLowerCase(className.charAt(periodIndex + 1)));
00178 }
00179
00180 return buffer.toString();
00181 }
00182 static Local
00183 getLocalCreatingIfNecessary(JimpleBody listBody, String name, Type type)
00184 {
00185 if(listBody.declaresLocal(name))
00186 {
00187 return listBody.getLocal(name);
00188 }
00189 else {
00190 Local l = Jimple.v().newLocal(name, type);
00191 listBody.addLocal(l);
00192
00193 return l;
00194 }
00195 }
00196 static Local getLocalForIndex(JimpleBody listBody, int index)
00197 {
00198 String name = "l" + index;
00199
00200 if(listBody.declaresLocal(name))
00201 return listBody.getLocal(name);
00202 else {
00203 Local l = Jimple.v().newLocal(name,
00204 UnknownType.v());
00205
00206 listBody.addLocal(l);
00207
00208 return l;
00209 }
00210 }
00211 static Local getLocalForStackOp(JimpleBody listBody, TypeStack typeStack,
00212 int index)
00213 {
00214 if(typeStack.get(index).equals(Double2ndHalfType.v()) ||
00215 typeStack.get(index).equals(Long2ndHalfType.v()))
00216 {
00217 index--;
00218 }
00219
00220 return getLocalCreatingIfNecessary(listBody, "op" + index, UnknownType.v());
00221 }
00222 static String getNextEasyName()
00223 {
00224 final String[] easyNames =
00225 {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
00226 "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
00227
00228 int justifiedIndex = nextEasyNameIndex++;
00229
00230 if(justifiedIndex >= easyNames.length)
00231 return "local" + (justifiedIndex - easyNames.length);
00232 else
00233 return easyNames[justifiedIndex];
00234 }
00235 static String getNormalizedClassName(String className)
00236 {
00237 className = className.replace('/', '.');
00238
00239 if(className.endsWith(";"))
00240 className = className.substring(0, className.length() - 1);
00241
00242
00243 {
00244 int numDimensions = 0;
00245
00246 while(className.startsWith("["))
00247 {
00248 numDimensions++;
00249 className = className.substring(1, className.length());
00250 className = className + "[]";
00251 }
00252
00253 if(numDimensions != 0)
00254 {
00255 if(!className.startsWith("L"))
00256 throw new RuntimeException("For some reason an array reference does not start with L");
00257
00258 className = className.substring(1, className.length());
00259 }
00260 }
00261
00262
00263 return className;
00264 }
00265 static Type jimpleReturnTypeOfMethodDescriptor(SootClassManager cm,
00266 String descriptor)
00267 {
00268 Type[] types = jimpleTypesOfFieldOrMethodDescriptor(cm, descriptor);
00269
00270 return types[types.length - 1];
00271 }
00272 static Type jimpleTypeOfFieldDescriptor(SootClassManager cm,
00273 String descriptor)
00274 {
00275 boolean isArray = false;
00276 int numDimensions = 0;
00277 Type baseType;
00278
00279
00280 while(descriptor.startsWith("["))
00281 {
00282 isArray = true;
00283 numDimensions++;
00284 descriptor = descriptor.substring(1);
00285 }
00286
00287
00288 if(descriptor.equals("B"))
00289 baseType = ByteType.v();
00290 else if(descriptor.equals("C"))
00291 baseType = CharType.v();
00292 else if(descriptor.equals("D"))
00293 baseType = DoubleType.v();
00294 else if(descriptor.equals("F"))
00295 baseType = FloatType.v();
00296 else if(descriptor.equals("I"))
00297 baseType = IntType.v();
00298 else if(descriptor.equals("J"))
00299 baseType = LongType.v();
00300 else if(descriptor.startsWith("L"))
00301 {
00302 if(!descriptor.endsWith(";"))
00303 throw new RuntimeException("Class reference does not end with ;");
00304
00305 String className = descriptor.substring(1, descriptor.length() - 1);
00306
00307 baseType = RefType.v(className.replace('/', '.'));
00308 }
00309 else if(descriptor.equals("S"))
00310 baseType = ShortType.v();
00311 else if(descriptor.equals("Z"))
00312 baseType = BooleanType.v();
00313 else
00314 throw new RuntimeException("Unknown field type: " + descriptor);
00315
00316
00317 if(isArray)
00318 return ArrayType.v((BaseType) baseType, numDimensions);
00319 else
00320 return baseType;
00321 }
00322 static Type[] jimpleTypesOfFieldOrMethodDescriptor(SootClassManager cm,
00323 String descriptor)
00324 {
00325 java.util.Vector types = new java.util.Vector();
00326
00327 while(descriptor.length() != 0)
00328 {
00329 boolean isArray = false;
00330 int numDimensions = 0;
00331 Type baseType;
00332
00333
00334 if(descriptor.startsWith("(") || descriptor.startsWith(")"))
00335 {
00336 descriptor = descriptor.substring(1);
00337 continue;
00338 }
00339
00340
00341 while(descriptor.startsWith("["))
00342 {
00343 isArray = true;
00344 numDimensions++;
00345 descriptor = descriptor.substring(1);
00346 }
00347
00348
00349 if(descriptor.startsWith("B"))
00350 {
00351 baseType = ByteType.v();
00352 descriptor = descriptor.substring(1);
00353 }
00354 else if(descriptor.startsWith("C"))
00355 {
00356 baseType = CharType.v();
00357 descriptor = descriptor.substring(1);
00358 }
00359 else if(descriptor.startsWith("D"))
00360 {
00361 baseType = DoubleType.v();
00362 descriptor = descriptor.substring(1);
00363 }
00364 else if(descriptor.startsWith("F"))
00365 {
00366 baseType = FloatType.v();
00367 descriptor = descriptor.substring(1);
00368 }
00369 else if(descriptor.startsWith("I"))
00370 {
00371 baseType = IntType.v();
00372 descriptor = descriptor.substring(1);
00373 }
00374 else if(descriptor.startsWith("J"))
00375 {
00376 baseType = LongType.v();
00377 descriptor = descriptor.substring(1);
00378 }
00379 else if(descriptor.startsWith("L"))
00380 {
00381 int index = descriptor.indexOf(';');
00382
00383 if(index == -1)
00384 throw new RuntimeException("Class reference has no ending ;");
00385
00386 String className = descriptor.substring(1, index);
00387
00388 baseType = RefType.v(className.replace('/', '.'));
00389
00390 descriptor = descriptor.substring(index + 1);
00391 }
00392 else if(descriptor.startsWith("S"))
00393 {
00394 baseType = ShortType.v();
00395 descriptor = descriptor.substring(1);
00396 }
00397 else if(descriptor.startsWith("Z"))
00398 {
00399 baseType = BooleanType.v();
00400 descriptor = descriptor.substring(1);
00401 }
00402 else if(descriptor.startsWith("V"))
00403 {
00404 baseType = VoidType.v();
00405 descriptor = descriptor.substring(1);
00406 }
00407 else
00408 throw new RuntimeException("Unknown field type!");
00409
00410 Type t;
00411
00412
00413 if(isArray)
00414 t = ArrayType.v((BaseType) baseType, numDimensions);
00415 else
00416 t = baseType;
00417
00418 types.addElement(t);
00419 }
00420
00421
00422 {
00423 Type[] typesArray = new Type[types.size()];
00424
00425 types.copyInto(typesArray);
00426
00427 return typesArray;
00428 }
00429 }
00430 static void resetEasyNames()
00431 {
00432 nextEasyNameIndex = 0;
00433 }
00434 public static void resolveClass(SootClass bclass)
00435 {
00436 if(ca.mcgill.sable.soot.jimple.Main.isVerbose)
00437 System.out.println("Resolving " + bclass.getName() + "...");
00438
00439 SootClassManager cm = bclass.getManager();
00440
00441 ClassFile coffiClass = new ClassFile(bclass.getName());
00442
00443
00444 {
00445 boolean success = coffiClass.loadClassFile();
00446
00447 if(!success)
00448 throw new RuntimeException("Couldn't load class file.");
00449
00450 CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.this_class];
00451
00452 String name = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
00453 name = name.replace('/', '.');
00454
00455 bclass.setName(name);
00456
00457
00458 }
00459
00460
00461 bclass.setModifiers(coffiClass.access_flags & (~0x0020));
00462
00463
00464
00465 {
00466 if(coffiClass.super_class != 0)
00467 {
00468
00469
00470 CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.
00471 super_class];
00472
00473 String superName = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
00474 superName = superName.replace('/', '.');
00475
00476 bclass.setSuperClass(cm.getClass(superName));
00477 }
00478 }
00479
00480
00481 {
00482 for(int i = 0; i < coffiClass.interfaces_count; i++)
00483 {
00484 CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.
00485 interfaces[i]];
00486
00487 String interfaceName =
00488 ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
00489
00490 interfaceName = interfaceName.replace('/', '.');
00491
00492 SootClass interfaceClass = cm.getClass(interfaceName);
00493 bclass.addInterface(interfaceClass);
00494 }
00495 }
00496
00497
00498 for(int i = 0; i < coffiClass.fields_count; i++)
00499 {
00500 field_info fieldInfo = coffiClass.fields[i];
00501
00502 String fieldName = ((CONSTANT_Utf8_info)
00503 (coffiClass.constant_pool[fieldInfo.name_index])).convert();
00504
00505 String fieldDescriptor = ((CONSTANT_Utf8_info)
00506 (coffiClass.constant_pool[fieldInfo.descriptor_index])).convert();
00507
00508 int modifiers = fieldInfo.access_flags;
00509 Type fieldType = jimpleTypeOfFieldDescriptor(cm, fieldDescriptor);
00510
00511 if(bclass.declaresField(fieldName, fieldType))
00512 {
00513 SootField field = bclass.getField(fieldName, fieldType);
00514
00515 field.setType(fieldType);
00516 field.setModifiers(modifiers);
00517 }
00518 else {
00519 bclass.addField(new SootField(fieldName,
00520 fieldType, modifiers));
00521 }
00522 }
00523
00524
00525 for(int i = 0; i < coffiClass.methods_count; i++)
00526 {
00527 method_info methodInfo = coffiClass.methods[i];
00528
00529 String methodName = ((CONSTANT_Utf8_info)
00530 (coffiClass.constant_pool[methodInfo.name_index])).convert();
00531
00532 String methodDescriptor = ((CONSTANT_Utf8_info)
00533 (coffiClass.constant_pool[methodInfo.descriptor_index])).convert();
00534
00535 List parameterTypes;
00536 Type returnType;
00537
00538
00539 {
00540 Type[] types = jimpleTypesOfFieldOrMethodDescriptor(cm,
00541 methodDescriptor);
00542
00543 parameterTypes = new ArrayList();
00544
00545 for(int j = 0; j < types.length - 1; j++)
00546 parameterTypes.add(types[j]);
00547
00548 returnType = types[types.length - 1];
00549 }
00550
00551 int modifiers = methodInfo.access_flags;
00552
00553 SootMethod method;
00554
00555 if(bclass.declaresMethod(methodName, parameterTypes, returnType))
00556 {
00557 method = bclass.getMethod(methodName, parameterTypes, returnType);
00558 method.setParameterTypes(parameterTypes);
00559 method.setReturnType(returnType);
00560 method.setModifiers(modifiers);
00561 }
00562 else {
00563 method = new SootMethod(methodName,
00564 parameterTypes, returnType, modifiers);
00565 bclass.addMethod(method);
00566 }
00567
00568 methodInfo.jmethod = method;
00569
00570
00571 {
00572 for(int j = 0; j < methodInfo.attributes_count; j++)
00573 if(methodInfo.attributes[j] instanceof Exception_attribute)
00574 {
00575 Exception_attribute exceptions = (Exception_attribute) methodInfo.attributes[j];
00576
00577 for(int k = 0; k < exceptions.number_of_exceptions; k++)
00578 {
00579 CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.
00580 constant_pool[exceptions.exception_index_table[k]];
00581
00582 String exceptionName = ((CONSTANT_Utf8_info)
00583 (coffiClass.constant_pool[c.name_index])).convert();
00584
00585 exceptionName = exceptionName.replace('/', '.');
00586
00587 method.addException(cm.getClass(exceptionName));
00588 }
00589 }
00590 }
00591 }
00592
00593
00594 for(int i = 0; i < coffiClass.methods_count; i++)
00595 {
00596 method_info methodInfo = coffiClass.methods[i];
00597 methodInfo.jmethod.setSource(coffiClass, methodInfo);
00598 }
00599 }
00600 static void setActiveClassManager(SootClassManager manager)
00601 {
00602 classManager = manager;
00603 }
00604 static void setClassNameToAbbreviation(Map map)
00605 {
00606 classNameToAbbreviation = map;
00607 }
00608 }