Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

Util.java

00001 package ca.mcgill.sable.soot.coffi;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Jimple, a 3-address code Java(TM) bytecode representation.        *
00005  * Copyright (C) 1997, 1998 Raja Vallee-Rai (kor@sable.mcgill.ca)    *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project of the Sable Research Group,      *
00009  * School of Computer Science, McGill University, Canada             *
00010  * (http://www.sable.mcgill.ca/).  It is understood that any         *
00011  * modification not identified as such is not covered by the         *
00012  * preceding statement.                                              *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this library; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other Sable Research Group projects, please      *
00033  * visit the web site: http://www.sable.mcgill.ca/                   *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 
00036 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00037  * Coffi, a bytecode parser for the Java(TM) language.               *
00038  * Copyright (C) 1996, 1997 Clark Verbrugge (clump@sable.mcgill.ca). *
00039  * All rights reserved.                                              *
00040  *                                                                   *
00041  * This work was done as a project of the Sable Research Group,      *
00042  * School of Computer Science, McGill University, Canada             *
00043  * (http://www.sable.mcgill.ca/).  It is understood that any         *
00044  * modification not identified as such is not covered by the         *
00045  * preceding statement.                                              *
00046  *                                                                   *
00047  * This work is free software; you can redistribute it and/or        *
00048  * modify it under the terms of the GNU Library General Public       *
00049  * License as published by the Free Software Foundation; either      *
00050  * version 2 of the License, or (at your option) any later version.  *
00051  *                                                                   *
00052  * This work is distributed in the hope that it will be useful,      *
00053  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00054  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00055  * Library General Public License for more details.                  *
00056  *                                                                   *
00057  * You should have received a copy of the GNU Library General Public *
00058  * License along with this library; if not, write to the             *
00059  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00060  * Boston, MA  02111-1307, USA.                                      *
00061  *                                                                   *
00062  * Java is a trademark of Sun Microsystems, Inc.                     *
00063  *                                                                   *
00064  * To submit a bug report, send a comment, or get the latest news on *
00065  * this project and other Sable Research Group projects, please      *
00066  * visit the web site: http://www.sable.mcgill.ca/                   *
00067  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00068 
00069 /*
00070  Reference Version
00071  -----------------
00072  This is the latest official version on which this file is based.
00073  The reference version is: $CoffiVersion: 1.1 $
00074                            $SootVersion: 1.beta.4 $
00075 
00076  Change History
00077  --------------
00078  A) Notes:
00079 
00080  Please use the following template.  Most recent changes should
00081  appear at the top of the list.
00082 
00083  - Modified on [date (March 1, 1900)] by [name]. [(*) if appropriate]
00084    [description of modification].
00085 
00086  Any Modification flagged with "(*)" was done as a project of the
00087  Sable Research Group, School of Computer Science,
00088  McGill University, Canada (http://www.sable.mcgill.ca/).
00089 
00090  You should add your copyright, using the following template, at
00091  the top of this file, along with other copyrights.
00092 
00093  *                                                                   *
00094  * Modifications by [name] are                                       *
00095  * Copyright (C) [year(s)] [your name (or company)].  All rights     *
00096  * reserved.                                                         *
00097  *                                                                   *
00098 
00099  B) Changes:
00100 
00101  - Modified on March 2, 1999 by Patrick Lam (plam@sable.mcgill.ca)
00102    Fixed interface modifiers bug.
00103        
00104  - Modified on November 2, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00105    Repackaged all source files and performed extensive modifications.
00106    First initial release of Soot.
00107 
00108  - Modified on 15-Jun-1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00109    First internal release (Version 0.1).
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     static void setLocalType(Local local, List locals,
00127         int localIndex, Type type)
00128     {
00129         if(local.getType().equals(UnknownType.v()) ||
00130             local.getType().equals(type))
00131         {
00132             local.setType(type);
00133 
00134             if(local.getType().equals(DoubleType.v()) ||
00135                 local.getType().equals(LongType.v()))
00136             {
00137                 // This means the next local becomes voided, since these types occupy two
00138                 // words.
00139 
00140                 Local secondHalf = (Local) locals.get(localIndex + 1);
00141 
00142                 secondHalf.setType(VoidType.v());
00143             }
00144 
00145             return;
00146         }
00147 
00148         if(type.equals(IntType.v()))
00149         {
00150             if(local.getType().equals(BooleanType.v()) ||
00151                local.getType().equals(CharType.v()) ||
00152                local.getType().equals(ShortType.v()) ||
00153                local.getType().equals(ByteType.v()))
00154             {
00155                 // Even though it's not the same, it's ok, because booleans, chars, shorts, and
00156                 // bytes are all sort of treated like integers by the JVM.
00157                 return;
00158             }
00159 
00160         }
00161 
00162         throw new RuntimeException("required and actual types do not match: " + type.toString() +
00163                 " with " + local.getType().toString());
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         // Handle array case
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         // Handle array case
00280             while(descriptor.startsWith("["))
00281             {
00282                 isArray = true;
00283                 numDimensions++;
00284                 descriptor = descriptor.substring(1);
00285             }
00286 
00287         // Determine base type
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         // Return type
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             // Skip parenthesis
00334                 if(descriptor.startsWith("(") || descriptor.startsWith(")"))
00335                 {
00336                     descriptor = descriptor.substring(1);
00337                     continue;
00338                 }
00339 
00340             // Handle array case
00341                 while(descriptor.startsWith("["))
00342                 {
00343                     isArray = true;
00344                     numDimensions++;
00345                     descriptor = descriptor.substring(1);
00346                 }
00347 
00348             // Determine base type
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             // Determine type
00413                 if(isArray)
00414                     t = ArrayType.v((BaseType) baseType, numDimensions);
00415                 else
00416                     t = baseType;
00417 
00418             types.addElement(t);
00419         }
00420 
00421         // Generate array containing types
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         // Load up class file, and retrieve bclass from class manager.
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                 // replace this classes name with its fully qualified version.
00457 
00458         }
00459   
00460           // Set modifier
00461             bclass.setModifiers(coffiClass.access_flags & (~0x0020));
00462                 // don't want the ACC_SUPER flag, it is always supposed to be set anyways
00463 
00464         // Set superclass
00465         {
00466             if(coffiClass.super_class != 0)
00467             {
00468                 // This object is not java.lang.Object, so must have a super class
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         // Add interfaces to the bclass
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         // Add every field to the bclass
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         // Add every method to the bclass
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                 // Generate parameterTypes & returnType
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                 // add exceptions to method
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         // Set coffi source of method
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 }

Generated at Thu Feb 7 06:59:01 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001