All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.coffi.Util Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 1997 Clark Verbrugge
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * Modified by the Sable Research Group and others 1997-1999.  
 * See the 'credits' file distributed with Soot for the complete list of
 * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
 */







package soot.coffi;
import soot.jimple.*;
import java.util.*;
import java.io.*;
import soot.tagkit.*;
import soot.*;


public class Util
{
    public Util( Singletons.Global g ) {}
    public static Util v() { return G.v().soot_coffi_Util(); }


    Map classNameToAbbreviation;
    Set markedClasses;
    LinkedList classesToResolve;

    int activeOriginalIndex = -1;
    cp_info[] activeConstantPool = null;
    LocalVariableTable_attribute activeVariableTable;
    LocalVariableTypeTable_attribute activeVariableTypeTable;
    boolean useFaithfulNaming = false;
    boolean isLocalStore = false;  // global variable used 
    boolean isWideLocalStore = false;
    public void setFaithfulNaming(boolean v)
    {
        useFaithfulNaming = v;
    }    

    public void resolveFromClassFile(SootClass aClass, InputStream is, List references)
    {
        SootClass bclass = aClass;                
        String className = bclass.getName();
        ClassFile coffiClass = new ClassFile(className);
        
        // Load up class file, and retrieve bclass from class manager.
        {
            boolean success = coffiClass.loadClassFile(is);

            if(!success)
                {
                    if(!Scene.v().allowsPhantomRefs())
                        throw new RuntimeException("Could not load classfile: " + bclass.getName());
                    else {                        
                        G.v().out.println("Warning: " + className + " is a phantom class!");
                        bclass.setPhantom(true);                                                                
                        return;
                    } 
                    
                }
            
            CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.this_class];
    
            String name = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
            name = name.replace('/', '.');
                	    
            if( !name.equals( bclass.getName() ) ) {
                throw new RuntimeException( 
                        "Error: class "+name+" read in from a classfile in which "+bclass.getName()+" was expected." );
            }
        }
      
        // Set modifier
        bclass.setModifiers(coffiClass.access_flags & (~0x0020));
        // don't want the ACC_SUPER flag, it is always supposed to be set anyways
    
        // Set superclass
        {
            if(coffiClass.super_class != 0)
                {
                    // This object is not java.lang.Object, so must have a super class
                    
                    CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.super_class];
    
                    String superName = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
                    superName = superName.replace('/', '.');
    
                    references.add(superName);
                    bclass.setSuperclass(SootResolver.v().makeClassRef(superName));
                }
        }
    
        // Add interfaces to the bclass
        {
            for(int i = 0; i < coffiClass.interfaces_count; i++)
                {
                    CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.interfaces[i]];
    
                    String interfaceName =
                        ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
    
                    interfaceName = interfaceName.replace('/', '.');
    
                    references.add(interfaceName);
                    SootClass interfaceClass = SootResolver.v().makeClassRef(interfaceName);
                    bclass.addInterface(interfaceClass);
                }
        }
    
        // Add every field to the bclass
        for(int i = 0; i < coffiClass.fields_count; i++){
            
            field_info fieldInfo = coffiClass.fields[i];

            String fieldName = ((CONSTANT_Utf8_info)
                                (coffiClass.constant_pool[fieldInfo.name_index])).convert();

            String fieldDescriptor = ((CONSTANT_Utf8_info)
                                      (coffiClass.constant_pool[fieldInfo.descriptor_index])).convert();

            int modifiers = fieldInfo.access_flags;
            Type fieldType = jimpleTypeOfFieldDescriptor(fieldDescriptor);
                
            SootField field = new SootField(fieldName, fieldType, modifiers);
            bclass.addField(field);
                
            references.add(fieldType);

            // add initialization constant, if any
		    for(int j = 0; j < fieldInfo.attributes_count; j++) {
                // add constant value attributes
                if (fieldInfo.attributes[j] instanceof ConstantValue_attribute){
                    
                    ConstantValue_attribute attr = (ConstantValue_attribute) fieldInfo.attributes[j];
                    cp_info cval = coffiClass.constant_pool[attr.constantvalue_index];
                    ConstantValueTag tag;
                    switch (cval.tag) {
                    case cp_info.CONSTANT_Integer:
                    tag = new IntegerConstantValueTag((int)((CONSTANT_Integer_info)cval).bytes);
                    break;
                    case cp_info.CONSTANT_Float:
                    //tag = new FloatConstantValueTag((int)((CONSTANT_Float_info)cval).bytes);
                    tag = new FloatConstantValueTag(((CONSTANT_Float_info)cval).convert());
                    break;
                    case cp_info.CONSTANT_Long:
                      {
                    CONSTANT_Long_info lcval = (CONSTANT_Long_info)cval;
                    tag = new LongConstantValueTag((lcval.high << 32) + lcval.low);
                    break;
                      }
                    case cp_info.CONSTANT_Double:
                      {
                    CONSTANT_Double_info dcval = (CONSTANT_Double_info)cval;
                    //tag = new DoubleConstantValueTag((dcval.high << 32) + dcval.low);
                    tag = new DoubleConstantValueTag(dcval.convert());
                    break;
                      }
                    case cp_info.CONSTANT_String:
                      {
                    CONSTANT_String_info scval = (CONSTANT_String_info)cval;
                    CONSTANT_Utf8_info ucval = (CONSTANT_Utf8_info)coffiClass.constant_pool[scval.string_index];
                    tag = new StringConstantValueTag(ucval.convert());
                    break;
                      }
                    default:
                    throw new RuntimeException("unexpected ConstantValue: " + cval);
                    }
                    field.addTag(tag);
                }
                // add synthetic tag
                else if (fieldInfo.attributes[j] instanceof Synthetic_attribute){
                    field.addTag(new SyntheticTag());
                }
                // add deprecated tag
                else if (fieldInfo.attributes[j] instanceof Deprecated_attribute){
                    field.addTag(new DeprecatedTag());
                }
                // add signature tag
                else if (fieldInfo.attributes[j] instanceof Signature_attribute){
                    String generic_sig = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[((Signature_attribute)fieldInfo.attributes[j]).signature_index])).convert();
                    field.addTag(new SignatureTag(generic_sig));
                }
                else if (fieldInfo.attributes[j] instanceof RuntimeVisibleAnnotations_attribute || fieldInfo.attributes[j] instanceof RuntimeInvisibleAnnotations_attribute)
                {
                    addAnnotationVisibilityAttribute(field, fieldInfo.attributes[j], coffiClass, references);
                }
                else if (fieldInfo.attributes[j] instanceof Generic_attribute)
                {        	
                	Generic_attribute attr = (Generic_attribute) fieldInfo.attributes[j];
                    String name = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[attr.attribute_name])).convert();
        			field.addTag(new GenericAttribute(name, attr.info));
                }
		    }
        }
    
        // Add every method to the bclass
        for(int i = 0; i < coffiClass.methods_count; i++){
            
            method_info methodInfo = coffiClass.methods[i];
		
		
		    if( (coffiClass.constant_pool[methodInfo.name_index]) == null) {
		        G.v().out.println("method index: " + methodInfo.toName(coffiClass.constant_pool));
		        throw new RuntimeException("method has no name");
		    }

            String methodName = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[methodInfo.name_index])).convert();
		    String methodDescriptor = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[methodInfo.descriptor_index])).convert();
    
            List parameterTypes;
            Type returnType;
    
            // Generate parameterTypes & returnType
            {
                Type[] types = jimpleTypesOfFieldOrMethodDescriptor(methodDescriptor);
    
                parameterTypes = new ArrayList();
                for(int j = 0; j < types.length - 1; j++){
                    references.add(types[j]);
                    parameterTypes.add(types[j]);
                }
                        
                returnType = types[types.length - 1];
                references.add(returnType);
            }
    
            int modifiers = methodInfo.access_flags;

            SootMethod method;

            method = new SootMethod(methodName,
                                    parameterTypes, returnType, modifiers);
            bclass.addMethod(method);

            methodInfo.jmethod = method;

            // add exceptions to method
            {
                for(int j = 0; j < methodInfo.attributes_count; j++){
                    if(methodInfo.attributes[j] instanceof Exception_attribute){
                        Exception_attribute exceptions = (Exception_attribute) methodInfo.attributes[j];

                        for(int k = 0; k < exceptions.number_of_exceptions; k++)
{
                            CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.
                            constant_pool[exceptions.exception_index_table[k]];

                            String exceptionName = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[c.name_index])).convert();

                            exceptionName = exceptionName.replace('/', '.');

                            references.add(exceptionName);
                            method.addExceptionIfAbsent(SootResolver.v().makeClassRef(exceptionName));
                        }
                    }
                    else if (methodInfo.attributes[j] instanceof Synthetic_attribute) {
                        method.addTag(new SyntheticTag());
                    }
                    else if (methodInfo.attributes[j] instanceof Deprecated_attribute) {
                        method.addTag(new DeprecatedTag());
                    }
                    else if (methodInfo.attributes[j] instanceof Signature_attribute){
                        String generic_sig = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[((Signature_attribute)methodInfo.attributes[j]).signature_index])).convert();
                        method.addTag(new SignatureTag(generic_sig));
                    }
                    else if (methodInfo.attributes[j] instanceof RuntimeVisibleAnnotations_attribute || methodInfo.attributes[j] instanceof RuntimeInvisibleAnnotations_attribute)
                    {
                        addAnnotationVisibilityAttribute(method, methodInfo.attributes[j], coffiClass, references);
                    }
                    else if (methodInfo.attributes[j] instanceof RuntimeVisibleParameterAnnotations_attribute || methodInfo.attributes[j] instanceof RuntimeInvisibleParameterAnnotations_attribute)
                    {
                        addAnnotationVisibilityParameterAttribute(method, methodInfo.attributes[j], coffiClass, references);
                    }
                    else if (methodInfo.attributes[j] instanceof AnnotationDefault_attribute)
                    {
                        AnnotationDefault_attribute attr = (AnnotationDefault_attribute)methodInfo.attributes[j];
                        element_value [] input = new element_value[1];
                        input[0] = attr.default_value;
                        ArrayList list = createElementTags(1, coffiClass, input);
                        method.addTag(new AnnotationDefaultTag(list.get(0)));
                    }
                    else if (methodInfo.attributes[j] instanceof Generic_attribute)
                    {        	
                    	Generic_attribute attr = (Generic_attribute) methodInfo.attributes[j];
                        String name = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[attr.attribute_name])).convert();
            			method.addTag(new GenericAttribute(name, attr.info));
                    }
                }
            }
                    
                // Go through the constant pool, forcing all mentioned classes to be resolved. 
                {
                    for(int k = 0; k < coffiClass.constant_pool_count; k++) {
                        if(coffiClass.constant_pool[k] instanceof CONSTANT_Class_info)
                            {
                                CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[k];

                                String desc = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
                                String name = desc.replace('/', '.');

                                if(name.startsWith("["))
                                    references.add(jimpleTypeOfFieldDescriptor(desc));
                                else
                                    references.add(name);
                            }
                        if(coffiClass.constant_pool[k] instanceof CONSTANT_Fieldref_info
                        || coffiClass.constant_pool[k] instanceof CONSTANT_Methodref_info
                        || coffiClass.constant_pool[k] instanceof CONSTANT_InterfaceMethodref_info) {
                            Type[] types = jimpleTypesOfFieldOrMethodDescriptor(
                                cp_info.getTypeDescr(coffiClass.constant_pool,k));
                            for (Type element : types) {
                                references.add(element);
                            }
                        }

                    }
                }
            }

        // Set coffi source of method
        for(int i = 0; i < coffiClass.methods_count; i++)
            {
                method_info methodInfo = coffiClass.methods[i];
                //                methodInfo.jmethod.setSource(coffiClass, methodInfo);
                methodInfo.jmethod.setSource(new CoffiMethodSource(coffiClass, methodInfo));
            }
        
	// Set "SourceFile" attribute tag
	for(int i = 0; i < coffiClass.attributes_count; i++){
	    
		if(coffiClass.attributes[i] instanceof SourceFile_attribute){
		    
		    SourceFile_attribute attr = (SourceFile_attribute)coffiClass.attributes[i];
            String sourceFile = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[attr.sourcefile_index])).convert();

            if( sourceFile.indexOf(' ') >= 0 ) {
                G.v().out.println( "Warning: Class "+className+" has invalid SourceFile attribute (will be ignored)." );
            } else {
                bclass.addTag(new SourceFileTag( sourceFile ) );
            }
	
	    }
	    // Set "InnerClass" attribute tag
	    else if(coffiClass.attributes[i] instanceof InnerClasses_attribute){
		   
		    InnerClasses_attribute attr = (InnerClasses_attribute)coffiClass.attributes[i];
            for (int j = 0; j < attr.inner_classes_length; j++)
                {
                    inner_class_entry e = attr.inner_classes[j];
                String inner = null;
                String outer = null;
                String name = null;
                if (e.inner_class_index != 0)
                    inner = ((CONSTANT_Utf8_info)coffiClass.constant_pool[((CONSTANT_Class_info)coffiClass.constant_pool[e.inner_class_index]).name_index]).convert();
                if (e.outer_class_index != 0)
                    outer = ((CONSTANT_Utf8_info)coffiClass.constant_pool[((CONSTANT_Class_info)coffiClass.constant_pool[e.outer_class_index]).name_index]).convert();
                if (e.name_index != 0)
                    name = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[e.name_index])).convert();
                bclass.addTag(new InnerClassTag(inner, outer, name, e.access_flags));
            }
        }
        // set synthetic tags
        else if(coffiClass.attributes[i] instanceof Synthetic_attribute){
		    
		    bclass.addTag(new SyntheticTag());
        }
        // set deprectaed tags
        else if(coffiClass.attributes[i] instanceof Deprecated_attribute){
		    
		    bclass.addTag(new DeprecatedTag());
        }
        else if (coffiClass.attributes[i] instanceof Signature_attribute){
            String generic_sig = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[((Signature_attribute)coffiClass.attributes[i]).signature_index])).convert();
            bclass.addTag(new SignatureTag(generic_sig));
        }
        else if (coffiClass.attributes[i] instanceof EnclosingMethod_attribute){           
            EnclosingMethod_attribute attr = (EnclosingMethod_attribute)coffiClass.attributes[i];
            String class_name = ((CONSTANT_Utf8_info)coffiClass.constant_pool[((CONSTANT_Class_info)coffiClass.constant_pool[ attr.class_index  ]).name_index]).convert();
            CONSTANT_NameAndType_info info = (CONSTANT_NameAndType_info)coffiClass.constant_pool[attr.method_index];

            String method_name = "";
            String method_sig = "";
            
            if (info != null){
                method_name = ((CONSTANT_Utf8_info)coffiClass.constant_pool[info.name_index]).convert();
                method_sig = ((CONSTANT_Utf8_info)coffiClass.constant_pool[info.descriptor_index]).convert();
            }
            bclass.addTag(new EnclosingMethodTag(class_name, method_name, method_sig));
        }
        else if (coffiClass.attributes[i] instanceof RuntimeVisibleAnnotations_attribute || coffiClass.attributes[i] instanceof RuntimeInvisibleAnnotations_attribute)
        {
            addAnnotationVisibilityAttribute(bclass, coffiClass.attributes[i], coffiClass, references);
        }
        else if (coffiClass.attributes[i] instanceof Generic_attribute)
        {        	
        	Generic_attribute attr = (Generic_attribute) coffiClass.attributes[i];
            String name = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[attr.attribute_name])).convert();
			bclass.addTag(new GenericAttribute(name, attr.info));
        }
   
    }
    }



    Type jimpleReturnTypeOfMethodDescriptor(String descriptor)
    {
        Type[] types = jimpleTypesOfFieldOrMethodDescriptor(descriptor);

        return types[types.length - 1];
    }

    private final ArrayList conversionTypes = new ArrayList();
    
    /*
    private Map cache = new HashMap();
    public Type[] jimpleTypesOfFieldOrMethodDescriptor(String descriptor)
    {
        Type[] ret = (Type[]) cache.get(descriptor);
        if( ret != null ) return ret;
        conversionTypes.clear();

        while(descriptor.length() != 0)
        {
            boolean isArray = false;
            int numDimensions = 0;
            Type baseType;

            // Skip parenthesis
                if(descriptor.startsWith("(") || descriptor.startsWith(")"))
                {
                    descriptor = descriptor.substring(1);
                    continue;
                }

            // Handle array case
                while(descriptor.startsWith("["))
                {
                    isArray = true;
                    numDimensions++;
                    descriptor = descriptor.substring(1);
                }

            // Determine base type
                if(descriptor.startsWith("B"))
                {
                    baseType = ByteType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("C"))
                {
                    baseType = CharType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("D"))
                {
                    baseType = DoubleType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("F"))
                {
                    baseType = FloatType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("I"))
                {
                    baseType = IntType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("J"))
                {
                    baseType = LongType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("L"))
                {
                    int index = descriptor.indexOf(';');

                    if(index == -1)
                        throw new RuntimeException("Class reference has no ending ;");

                    String className = descriptor.substring(1, index);

                    baseType = RefType.v(className.replace('/', '.'));

                    descriptor = descriptor.substring(index + 1);
                }
                else if(descriptor.startsWith("S"))
                {
                    baseType = ShortType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("Z"))
                {
                    baseType = BooleanType.v();
                    descriptor = descriptor.substring(1);
                }
                else if(descriptor.startsWith("V"))
                {
                    baseType = VoidType.v();
                    descriptor = descriptor.substring(1);
                }
                else
                    throw new RuntimeException("Unknown field type!");

            Type t;

            // Determine type
                if(isArray)
                    t = ArrayType.v(baseType, numDimensions);
                else
                    t = baseType;

            conversionTypes.add(t);
        }

        ret = (Type[]) conversionTypes.toArray(new Type[0]);
        cache.put(descriptor, ret);
        return ret;
    }
*/


    private final Map cache = new HashMap();
    public Type[] jimpleTypesOfFieldOrMethodDescriptor(String descriptor)
    {
        Type[] ret = cache.get(descriptor);
        if( ret != null ) return ret;
        char[] d = descriptor.toCharArray();
        int p = 0;
        conversionTypes.clear();

outer:
        while(p= d.length )
                            throw new RuntimeException("Class reference has no ending ;");
                        String className = new String(d, p+1, index - p - 1);
                        baseType = RefType.v(className);
                        p = index+1;
                        break swtch;
                    case 'S':
                        baseType = ShortType.v();
                        p++;
                        break swtch;
                    case 'Z':
                        baseType = BooleanType.v();
                        p++;
                        break swtch;
                    case 'V':
                        baseType = VoidType.v();
                        p++;
                        break swtch;
                    default:
                        throw new RuntimeException("Unknown field type!");
                }
            }
            if( baseType == null ) continue;

            // Determine type
            Type t;
            if(isArray)
                t = ArrayType.v(baseType, numDimensions);
            else
                t = baseType;

            conversionTypes.add(t);
        }

        ret = conversionTypes.toArray(new Type[0]);
        cache.put(descriptor, ret);
        return ret;
    }

    public Type jimpleTypeOfFieldDescriptor(String descriptor)
    {
        boolean isArray = false;
        int numDimensions = 0;
        Type baseType;

        // Handle array case
            while(descriptor.startsWith("["))
            {
                isArray = true;
                numDimensions++;
                descriptor = descriptor.substring(1);
            }

        // Determine base type
            if(descriptor.equals("B"))
                baseType = ByteType.v();
            else if(descriptor.equals("C"))
                baseType = CharType.v();
            else if(descriptor.equals("D"))
                baseType = DoubleType.v();
            else if(descriptor.equals("F"))
                baseType = FloatType.v();
            else if(descriptor.equals("I"))
                baseType = IntType.v();
            else if(descriptor.equals("J"))
                baseType = LongType.v();
            else if(descriptor.equals("V"))
                baseType = VoidType.v();
            else if(descriptor.startsWith("L"))
            {
                if(!descriptor.endsWith(";"))
                    throw new RuntimeException("Class reference does not end with ;");

                String className = descriptor.substring(1, descriptor.length() - 1);

                baseType = RefType.v(className.replace('/', '.'));
            }
            else if(descriptor.equals("S"))
                baseType = ShortType.v();
            else if(descriptor.equals("Z"))
                baseType = BooleanType.v();
            else
                throw new RuntimeException("Unknown field type: " + descriptor);

        // Return type
            if(isArray)
                return ArrayType.v(baseType, numDimensions);
            else
                return baseType;
    }

    int nextEasyNameIndex;

    void resetEasyNames()
    {
        nextEasyNameIndex = 0;
    }

    String getNextEasyName()
    {
        final String[] easyNames =
            {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
             "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};

        int justifiedIndex = nextEasyNameIndex++;

        if(justifiedIndex >= easyNames.length)
            return "local" + (justifiedIndex - easyNames.length);
        else
            return easyNames[justifiedIndex];
    }

    void setClassNameToAbbreviation(Map map)
    {
        classNameToAbbreviation = map;
    }

    Local getLocalForStackOp(JimpleBody listBody, TypeStack typeStack,
        int index)
    {
        if(typeStack.get(index).equals(Double2ndHalfType.v()) ||
            typeStack.get(index).equals(Long2ndHalfType.v()))
        {
            index--;
        }

        return getLocalCreatingIfNecessary(listBody, "$stack" + index, UnknownType.v());
    }

    String getAbbreviationOfClassName(String className)
    {
        StringBuffer buffer = new StringBuffer(new Character(className.charAt(0)).toString());
        int periodIndex = 0;

        for(;;)
        {
            periodIndex = className.indexOf('.', periodIndex + 1);

            if(periodIndex == -1)
                break;

            buffer.append(Character.toLowerCase(className.charAt(periodIndex + 1)));
        }

        return buffer.toString();
    }

    String getNormalizedClassName(String className)
    {
        className = className.replace('/', '.');

        if(className.endsWith(";"))
            className = className.substring(0, className.length() - 1);

        // Handle array case
        {
            int numDimensions = 0;

            while(className.startsWith("["))
            {
                numDimensions++;
                className = className.substring(1, className.length());
                className = className + "[]";
            }

            if(numDimensions != 0)
            {
                if(!className.startsWith("L"))
                    throw new RuntimeException("For some reason an array reference does not start with L");

                className = className.substring(1, className.length());
            }
        }


        return className;
    }

    public Local getLocal(Body b, String name) 
        throws soot.jimple.NoSuchLocalException
    {
        Iterator localIt = b.getLocals().iterator();

        while(localIt.hasNext())
        {
            Local local = (Local) localIt.next();

            if(local.getName().equals(name))
                return local;
        }

        throw new soot.jimple.NoSuchLocalException();
    }


    public boolean declaresLocal(Body b, String localName)
    {
        Iterator localIt = b.getLocals().iterator();

        while(localIt.hasNext())
        {
            Local local = (Local) localIt.next();

            if(local.getName().equals(localName))
                return true;
        }

        return false;
    }

     Local
        getLocalCreatingIfNecessary(JimpleBody listBody, String name, Type type)
    {
        if(declaresLocal(listBody, name))
        {
            return getLocal(listBody, name);
        }
        else {
            Local l = Jimple.v().newLocal(name, type);
            listBody.getLocals().add(l);

            return l;
        }
    }

    Local getLocalForIndex(JimpleBody listBody, int index)
    {
        String name = null;
        String debug_type = null;
        boolean assignedName = false;
        if(useFaithfulNaming && activeVariableTable != null)
        {
            if(activeOriginalIndex != -1)
            {

	      // Feng asks: why this is necessary? it does wrong thing
	      //            for searching local variable names.
	      // It is going to be verified with plam.
                if(isLocalStore)
                    activeOriginalIndex++;
                if(isWideLocalStore)
                    activeOriginalIndex++;

                name = activeVariableTable.getLocalVariableName(activeConstantPool, index, activeOriginalIndex);
                if (activeVariableTypeTable != null){
               debug_type = activeVariableTypeTable.getLocalVariableType(activeConstantPool, index, activeOriginalIndex);
               if (debug_type != null){
               }
                }
                if(name != null) 
                    assignedName = true;
            }
        }  
        
        if(!assignedName)
            name = "l" + index;

        if(declaresLocal(listBody, name))
            return getLocal(listBody, name);
        else {
            Local l = Jimple.v().newLocal(name,
                UnknownType.v());
            l.setIndex(index); // RoboVM note: Added

            listBody.getLocals().add(l);
            /*if (debug_type != null){
                l.addTag(new DebugTypeTag(debug_type));
            } */   

            return l;
        }
    }

    /*
    void setLocalType(Local local, List locals,
        int localIndex, Type type)
    {
        if(local.getType().equals(UnknownType.v()) ||
            local.getType().equals(type))
        {
            local.setType(type);

            if(local.getType().equals(DoubleType.v()) ||
                local.getType().equals(LongType.v()))
            {
                // This means the next local becomes voided, since these types occupy two
                // words.

                Local secondHalf = (Local) locals.get(localIndex + 1);

                secondHalf.setType(VoidType.v());
            }

            return;
        }

        if(type.equals(IntType.v()))
        {
            if(local.getType().equals(BooleanType.v()) ||
               local.getType().equals(CharType.v()) ||
               local.getType().equals(ShortType.v()) ||
               local.getType().equals(ByteType.v()))
            {
                // Even though it's not the same, it's ok, because booleans, chars, shorts, and
                // bytes are all sort of treated like integers by the JVM.
                return;
            }

        }

        throw new RuntimeException("required and actual types do not match: " + type.toString() +
                " with " + local.getType().toString());
    }    */

    /** Verifies the prospective name for validity as a Jimple name.
     * In particular, first-char is alpha | _ | $, subsequent-chars 
     * are alphanum | _ | $. 
     *
     * We could use isJavaIdentifier, except that Jimple's grammar
     * doesn't support all of those, just ASCII.
     *
     * I'd put this in soot.Local, but that's an interface.
     *
     * @author Patrick Lam
     */
    boolean isValidJimpleName(String prospectiveName) {
        if(prospectiveName == null) return false;
	for (int i = 0; i < prospectiveName.length(); i++) {
	    char c = prospectiveName.charAt(i);
	    if (i == 0 && c >= '0' && c <= '9')
		return false;

	    if (!((c >= '0' && c <= '9') ||
		  (c >= 'a' && c <= 'z') ||
		  (c >= 'A' && c <= 'Z') ||
		  (c == '_' || c == '$')))
		return false;
	}
	return true;
    }

    private void addAnnotationVisibilityAttribute(Host host, attribute_info attribute, ClassFile coffiClass, List references){
        VisibilityAnnotationTag tag;
        if (attribute instanceof RuntimeVisibleAnnotations_attribute){
            tag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_VISIBLE);         
            RuntimeVisibleAnnotations_attribute attr = (RuntimeVisibleAnnotations_attribute)attribute;
            addAnnotations(attr.number_of_annotations, attr.annotations, coffiClass, tag, references);
        }
        else {
            tag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_INVISIBLE);
            RuntimeInvisibleAnnotations_attribute attr = (RuntimeInvisibleAnnotations_attribute)attribute;
            addAnnotations(attr.number_of_annotations, attr.annotations, coffiClass, tag, references);
        }
        host.addTag(tag); 
    }
    
    private void addAnnotationVisibilityParameterAttribute(Host host, attribute_info attribute, ClassFile coffiClass, List references){
        VisibilityParameterAnnotationTag tag;
        if (attribute instanceof RuntimeVisibleParameterAnnotations_attribute){
            RuntimeVisibleParameterAnnotations_attribute attr = (RuntimeVisibleParameterAnnotations_attribute)attribute;
            tag = new VisibilityParameterAnnotationTag(attr.num_parameters, AnnotationConstants.RUNTIME_VISIBLE);
            for (int i = 0; i < attr.num_parameters; i++){
                parameter_annotation pAnnot = attr.parameter_annotations[i];
                VisibilityAnnotationTag vTag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_VISIBLE);
                addAnnotations(pAnnot.num_annotations, pAnnot.annotations, coffiClass, vTag, references);
                tag.addVisibilityAnnotation(vTag);
            }
        }
        else {
            RuntimeInvisibleParameterAnnotations_attribute attr = (RuntimeInvisibleParameterAnnotations_attribute)attribute;
            tag = new VisibilityParameterAnnotationTag(attr.num_parameters, AnnotationConstants.RUNTIME_INVISIBLE);
            for (int i = 0; i < attr.num_parameters; i++){
                parameter_annotation pAnnot = attr.parameter_annotations[i];
                VisibilityAnnotationTag vTag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_INVISIBLE);
                addAnnotations(pAnnot.num_annotations, pAnnot.annotations, coffiClass, vTag, references);
                tag.addVisibilityAnnotation(vTag);
            }
        }
        host.addTag(tag); 
    }

    private void addAnnotations(int numAnnots, annotation [] annotations, ClassFile coffiClass, VisibilityAnnotationTag tag, List references){
        for (int i = 0; i < numAnnots; i++){
            annotation annot = annotations[i];
            String annotType = ((CONSTANT_Utf8_info)coffiClass.constant_pool[annot.type_index]).convert();
            String ref = annotType.substring(1, annotType.length()-1);
            ref = ref.replace('/', '.');
            references.add(ref);
            int numElems = annot.num_element_value_pairs;
            AnnotationTag annotTag = new AnnotationTag(annotType, numElems);
            annotTag.setElems(createElementTags(numElems, coffiClass, annot.element_value_pairs));
            tag.addAnnotation(annotTag);
        }
    }
    
    private ArrayList createElementTags(int count, ClassFile coffiClass, element_value [] elems){
        ArrayList list = new ArrayList();
        for (int j = 0; j < count; j++){
            element_value ev = elems[j];
            char kind = ev.tag;
            String elemName = "default";
            if (ev.name_index != 0){
                elemName = ((CONSTANT_Utf8_info)coffiClass.constant_pool[ev.name_index]).convert();
            }
            if (kind == 'B' || kind == 'C' || kind == 'I' || kind == 'S' || kind == 'Z' || kind == 'D' || kind == 'F' || kind == 'J' || kind == 's'){
                constant_element_value cev = (constant_element_value)ev;
                if (kind == 'B' || kind == 'C' || kind == 'I' || kind == 'S' || kind == 'Z'){
                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
                    int constant_val = (int)((CONSTANT_Integer_info)cval).bytes;
                    AnnotationIntElem elem = new AnnotationIntElem(constant_val, kind, elemName);
                    list.add(elem);
                }
                else if (kind == 'D'){
                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
                    double constant_val = ((CONSTANT_Double_info)cval).convert();
                    AnnotationDoubleElem elem = new AnnotationDoubleElem(constant_val, kind, elemName);
                    list.add(elem);
                
                }
                else if (kind == 'F'){
                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
                    float constant_val = ((CONSTANT_Float_info)cval).convert();
                    AnnotationFloatElem elem = new AnnotationFloatElem(constant_val, kind, elemName);
                    list.add(elem);
                
                }
                else if (kind == 'J'){
                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
                    CONSTANT_Long_info lcval = (CONSTANT_Long_info)cval;
                    long constant_val = (lcval.high << 32) + lcval.low;
                    AnnotationLongElem elem = new AnnotationLongElem(constant_val, kind, elemName);
                    list.add(elem);
                
                }
                else if (kind == 's'){
                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
                    String constant_val = ((CONSTANT_Utf8_info)cval).convert();
                    AnnotationStringElem elem = new AnnotationStringElem(constant_val, kind, elemName);
                    list.add(elem);
                }
            }
            else if (kind == 'e'){
                enum_constant_element_value ecev = (enum_constant_element_value)ev;
                cp_info type_val = coffiClass.constant_pool[ecev.type_name_index];
                String type_name = ((CONSTANT_Utf8_info)type_val).convert();
                cp_info name_val = coffiClass.constant_pool[ecev.constant_name_index];
                String constant_name = ((CONSTANT_Utf8_info)name_val).convert();
                AnnotationEnumElem elem = new AnnotationEnumElem(type_name, constant_name, kind, elemName);
                list.add(elem);
            }
            else if (kind == 'c'){
                class_element_value cev = (class_element_value)ev;
                cp_info cval = coffiClass.constant_pool[cev.class_info_index];
                CONSTANT_Utf8_info sval = (CONSTANT_Utf8_info)cval;
                String desc = sval.convert();
                
                AnnotationClassElem elem = new AnnotationClassElem(desc, kind, elemName);
                list.add(elem);
            }
            else if (kind == '['){
                array_element_value aev = (array_element_value)ev;
                int num_vals = aev.num_values;

                ArrayList elemVals = createElementTags(num_vals, coffiClass, aev.values);
                AnnotationArrayElem elem = new AnnotationArrayElem(elemVals, kind, elemName);
                list.add(elem);
            }
            else if (kind == '@'){
                annotation_element_value aev = (annotation_element_value)ev;
                annotation annot = aev.annotation_value;
                String annotType = ((CONSTANT_Utf8_info)coffiClass.constant_pool[annot.type_index]).convert();
                int numElems = annot.num_element_value_pairs;
                AnnotationTag annotTag = new AnnotationTag(annotType, numElems);
                annotTag.setElems(createElementTags(numElems, coffiClass, annot.element_value_pairs));
                
                AnnotationAnnotationElem elem = new AnnotationAnnotationElem(annotTag, kind, elemName);
                list.add(elem);
            }
        }
   
        return list;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy