Beispiel #1
0
  private static StructureType getInstanceType0(
      SootClass clazz, int subClassAlignment, int[] superSize) {
    List<Type> types = new ArrayList<Type>();
    List<SootField> fields = getInstanceFields(clazz);
    int superAlignment = 1;
    if (!fields.isEmpty()) {
      // Pad the super type so that the first field is aligned properly
      SootField field = fields.get(0);
      superAlignment = getFieldAlignment(field);
    }
    if (clazz.hasSuperclass()) {
      types.add(getInstanceType0(clazz.getSuperclass(), superAlignment, superSize));
    }
    int offset = superSize[0];
    for (SootField field : fields) {
      int falign = getFieldAlignment(field);
      int padding = (offset & (falign - 1)) != 0 ? (falign - (offset & (falign - 1))) : 0;
      types.add(padType(getType(field.getType()), padding));
      offset += padding + getFieldSize(field);
    }

    int padding =
        (offset & (subClassAlignment - 1)) != 0
            ? (subClassAlignment - (offset & (subClassAlignment - 1)))
            : 0;
    for (int i = 0; i < padding; i++) {
      types.add(I8);
      offset++;
    }

    superSize[0] = offset;

    return new StructureType(types.toArray(new Type[types.size()]));
  }
  public void transform() {
    if (clazz.isPhantom()) return;

    // build ancestor
    // List<SootClass> ancestors = Scene.v().getActiveHierarchy().getSuperclassesOf(clazz);
    List<SootClass> ancestors = new LinkedList<SootClass>();

    // fill in ancestor list without using Soot.Hierarchy
    SootClass curAncestor = clazz;
    while (curAncestor.hasSuperclass()) {
      ancestors.add(curAncestor.getSuperclass());
      curAncestor = curAncestor.getSuperclass();
    }

    for (SootClass ancestor : ancestors) {
      if (ancestor.isPhantom()) continue;

      cloneReachableNonHiddenAncestorMethods(ancestor);
    }

    // modify ancestors fields
    for (SootClass ancestor : ancestors) {
      if (ancestor.isPhantom()) continue;

      SootUtils.makeFieldsVisible(ancestor);
    }

    cloneHiddenAncestorMethodsAndFixInvokeSpecial();
  }
  /**
   * Resolve the concrete target of a special invoke using our modified semantics for special invoke
   * expression.
   */
  private SootMethod resolveSpecialInvokeTarget(SpecialInvokeExpr si) {
    SootMethod target = null;

    try {
      target = SootUtils.resolve(si.getMethodRef());
    } catch (CannotFindMethodException e) {
      logger.error("Cannot find concrete method target for special invoke: {}", si);
      return null;
    }

    String targetSubSig = target.getSubSignature();

    SootClass current = target.getDeclaringClass();

    while (true) {
      if (current.declaresMethod(targetSubSig)) {
        return current.getMethod(targetSubSig);
      }

      // not a match in current, try superclass on next loop
      if (current.hasSuperclass()) current = current.getSuperclass();
      else {
        logger.error("Cannot find concrete method target for special invoke: {}", si);
        droidsafe.main.Main.exit(1);
        return null;
      }
    }
  }
Beispiel #4
0
 public static boolean isSubclass(SootClass sc, String className) {
   SootClass clazz = sc;
   while (clazz.hasSuperclass()) {
     clazz = clazz.getSuperclass();
     if (className.equals(clazz.getName())) {
       return true;
     }
   }
   return false;
 }
  public static boolean isAssignable(SootClass taintType, SootClass declaredType) {
    if (taintType.equals(declaredType)) return true;

    if (taintType.hasSuperclass() && isAssignable(taintType.getSuperclass(), declaredType)) {
      return true;
    }
    for (SootClass interf : taintType.getInterfaces()) {
      if (isAssignable(interf, declaredType)) return true;
    }
    return false;
  }
Beispiel #6
0
 public ResolvedEntry resolve(SootClass clazz) {
   while (clazz != null) {
     for (SootMethod m : clazz.getMethods()) {
       if (m.getName().equals(name) && desc.equals(Types.getDescriptor(m))) {
         return new ResolvedEntry(this, m);
       }
     }
     clazz = clazz.hasSuperclass() ? clazz.getSuperclass() : null;
   }
   return null;
 }
  public ReverseClassHierarchy(Map<String, OpenCLClass> classes) {
    m_Hierarchy = new ArrayList<TreeNode>();
    m_Classes = classes;

    addClass("java.lang.String");

    Set<String> key_set = classes.keySet();
    Set<String> visited = new HashSet<String>();
    for (String key : key_set) {
      OpenCLClass ocl_class = classes.get(key);
      SootClass soot_class = Scene.v().getSootClass(ocl_class.getJavaName());
      if (soot_class.hasSuperclass() == false) continue;
      SootClass parent = soot_class.getSuperclass();
      if (parent.getName().equals("java.lang.Object")) {
        TreeNode tree = new TreeNode(soot_class, ocl_class);
        m_Hierarchy.add(tree);
        visited.add(key);
      }
    }

    boolean modified;
    do {
      modified = false;

      key_set = classes.keySet();
      for (String key : key_set) {
        if (visited.contains(key)) continue;
        OpenCLClass ocl_class = classes.get(key);
        SootClass soot_class = Scene.v().getSootClass(ocl_class.getJavaName());
        if (soot_class.hasSuperclass() == false) continue;
        SootClass parent = soot_class.getSuperclass();
        TreeNode node = getNode(parent);
        if (node == null) continue;
        node.addChild(soot_class, ocl_class);
        modified = true;
        visited.add(key);
      }

    } while (modified);
  }
Beispiel #8
0
  public static HashSet<SootMethod> getAllImplementations(SootMethod method) {
    Chain appClasses = Scene.v().getApplicationClasses();
    HashSet<SootClass> implementingClasses = new HashSet<SootClass>(1);
    HashSet<SootMethod> overridingMethods = new HashSet<SootMethod>(1);

    SootClass t = method.getDeclaringClass();
    if (
    /*t.isAbstract() || */ t.isPhantom() || t.isPhantomClass()) {
      boolean b1 = t.isAbstract();
      boolean be = t.isPhantom();
      boolean b3 = t.isPhantomClass();

      try {
        throw new Exception("Need to implement for Plantom Classes");
      } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
    if (t.isAbstract()) {
      for (Object object : appClasses) {
        SootClass clazz = (SootClass) object;
        SootClass superClass = clazz.getSuperclass();
        {
          if (superClass.getName().equals(t.toString())) {
            implementingClasses.add(clazz);
            SootMethod m2 =
                clazz.getMethod(
                    method.getName(), method.getParameterTypes(), method.getReturnType());
            overridingMethods.add(m2);
          }
        }
      }
    }
    if (t.isInterface()) {
      for (Object object : appClasses) {
        SootClass clazz = (SootClass) object;
        Chain<SootClass> interfaces = clazz.getInterfaces();
        for (SootClass sootClass : interfaces) {
          if (sootClass.getName().equals(t.toString())) {
            implementingClasses.add(clazz);
            SootMethod m2 =
                clazz.getMethod(
                    method.getName(), method.getParameterTypes(), method.getReturnType());
            overridingMethods.add(m2);
          }
        }
      }
    }
    return overridingMethods;
  }
Beispiel #9
0
  /** For instance invokes */
  public static ArrayList<SootMethod> resolveAppCall(Type tgtType, SootMethodRef methodRef) {
    final NumberedString mSubsignature = methodRef.getSubSignature();
    if (tgtType instanceof RefType) {
      // find first class upwards in hierarchy, starting from cls, that implements method (i.e.,
      // *concrete* method)
      SootClass cls = ((RefType) tgtType).getSootClass();
      while (!cls.declaresMethod(mSubsignature))
        cls =
            cls
                .getSuperclass(); // if method not in this class, it HAS to be in a superclass, so a
                                  // superclass must exist

      if (!cls.hasTag(ClassTag.TAG_NAME)) return null; // not an app method

      // finally, store resolved app method
      SootMethod m = cls.getMethod(mSubsignature);
      assert m.hasTag(MethodTag.TAG_NAME);

      ArrayList<SootMethod> methods = new ArrayList<SootMethod>();
      methods.add(m); // just one element, directly resolved
      return methods;
    }

    if (tgtType instanceof AnySubType) {
      // return set of all app subtypes that implement referenced method
      SootClass baseCls = ((AnySubType) tgtType).getBase().getSootClass();
      List subClasses =
          baseCls.isInterface()
              ? Scene.v().getActiveHierarchy().getImplementersOf(baseCls)
              : Scene.v().getActiveHierarchy().getSubclassesOf(baseCls);
      ArrayList<SootMethod> methods = new ArrayList<SootMethod>();
      for (Object oSubCls : subClasses) {
        SootClass subCls = (SootClass) oSubCls;
        if (subCls.hasTag(ClassTag.TAG_NAME)) {
          try {
            SootMethod m = subCls.getMethod(mSubsignature);
            assert m.hasTag(MethodTag.TAG_NAME);
            if (!m.isAbstract()) methods.add(m);
          } catch (RuntimeException e) {
          }
        }
      }

      return methods;
    }

    assert tgtType instanceof ArrayType; // only other case observed so far
    return new ArrayList(); // no array class/method is in app
  }
Beispiel #10
0
 public VTable get(SootClass clazz) {
   if (clazz.isInterface()) {
     throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName());
   }
   VTable vtable = cache.get(clazz.getName());
   if (vtable != null) {
     return vtable;
   }
   VTable parent = null;
   if (clazz.hasSuperclass()) {
     parent = get(clazz.getSuperclass());
   }
   vtable = new VTable(clazz, parent);
   cache.put(clazz.getName(), vtable);
   return vtable;
 }
Beispiel #11
0
  /**
   * Finds in class hierarchy and returns all app and lib concrete methods possibly referenced by
   * method ref. Method is assumed to be virtual (not special or static). Returns true if there are
   * library methods among targets found.
   */
  public static boolean getConcreteCallTargets(
      InvokeExpr instInvExpr, /*OUT*/
      Set<SootMethod> appTargets, /*OUT*/
      Set<SootMethod> libTargets) {
    // get class of method ref; we start searching from this class
    SootMethodRef mref = instInvExpr.getMethodRef();
    SootClass cls = mref.declaringClass(); // starting class
    final NumberedString subsignature = mref.getSubSignature(); // signature to search for

    // CASE 1: object is of declared class type or inherited from some superclass
    //         find first superclass, starting from current cls, that declares method; there HAS to
    // be such a class
    // note that if cls is interface, superclass if java.lang.Object
    // note that we don't check if there is indeed an interface declaring the method; we assume this
    // is the case if no superclass declares it
    while (!cls.declaresMethod(subsignature) && cls.hasSuperclass())
      cls = cls.getSuperclass(); // never an interface
    // now, method might not be in superclass, or might be abstract; in that case, it's not a target
    SootMethod m;
    if (cls.declaresMethod(subsignature)) {
      m = cls.getMethod(subsignature);
      if (!m.isAbstract()) {
        if (cls.hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method
        else libTargets.add(m); // add lib method
      }
    }

    // (only for virtual/interface calls)
    // CASE 2: object's actual type is a subclass; any subclass declaring the method is a possible
    // target
    //         we have to check all superclasses of implementers, because starting cls might be
    // interface
    if (instInvExpr instanceof VirtualInvokeExpr || instInvExpr instanceof InterfaceInvokeExpr) {
      cls = mref.declaringClass(); // start again from declaring class
      List<SootClass> allSubclasses = getAllSubtypes(cls);
      for (SootClass subCls : allSubclasses) {
        m = getMethodInClassOrSuperclass(subCls, subsignature);
        if (m != null && !m.isAbstract()) {
          if (m.getDeclaringClass().hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method
          else libTargets.add(m); // add lib method
        }
      }
    }

    return !libTargets.isEmpty();
  }
  // TODO: Consider implementing a cached version
  private static Set<SootMethod> getInitialDeclaration(SootMethod method, SootClass candidate) {
    Set<SootMethod> result = Sets.newHashSet();

    if (candidate.hasSuperclass()) {
      result.addAll(getInitialDeclaration(method, candidate.getSuperclass()));
    }
    for (SootClass intface : candidate.getInterfaces()) {
      result.addAll(getInitialDeclaration(method, intface));
    }

    if (result.isEmpty()) {
      for (SootMethod candidateMethod : candidate.getMethods()) {
        if (compatible(candidateMethod, method)) {
          result.add(candidateMethod);
          break;
        }
      }
    }
    return result;
  }
  // finds the most restrictive form of exception that is also a superclass of exception_class
  SootClass GetMostRestrictiveFormOfException(
      List<TwoValuePair<Trap, Set<SootClass>>> tvps, SootClass exception_class) {
    List<TwoValuePair<SootClass, Integer>> superclass_counters =
        new ArrayList<TwoValuePair<SootClass, Integer>>();
    for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {
      SootClass super_exception_class = exception_class;
      int i = 0;
      while (super_exception_class != null) {

        if (tvp.v.getException() == super_exception_class) {
          superclass_counters.add(
              new TwoValuePair<SootClass, Integer>(tvp.v.getException(), new Integer(i)));
        }

        i++;
        try {
          super_exception_class = super_exception_class.getSuperclass();
        } catch (
            RuntimeException
                e) { // unfortunately soot doesn't have a specific exception class for "no
          // superclass for java.lang.Object" exception
          super_exception_class = null;
        }
      }
    }

    assert superclass_counters.size() != 0;

    TwoValuePair<SootClass, Integer> most_restrictive_form = superclass_counters.get(0);
    for (TwoValuePair<SootClass, Integer> tvp : superclass_counters) {
      if (tvp.w < most_restrictive_form.w) {
        most_restrictive_form = tvp;
      }
    }

    return most_restrictive_form.v;
  }
Beispiel #14
0
 public static boolean isEnum(SootClass sc) {
   return sc.hasSuperclass() && sc.getSuperclass().getName().equals("java.lang.Enum");
 }
Beispiel #15
0
  private StructureConstant createClassInfoStruct() {
    int flags = 0;

    if (Modifier.isPublic(sootClass.getModifiers())) {
      flags |= CI_PUBLIC;
    }
    if (Modifier.isFinal(sootClass.getModifiers())) {
      flags |= CI_FINAL;
    }
    if (Modifier.isInterface(sootClass.getModifiers())) {
      flags |= CI_INTERFACE;
    }
    if (Modifier.isAbstract(sootClass.getModifiers())) {
      flags |= CI_ABSTRACT;
    }
    if ((sootClass.getModifiers() & 0x1000) > 0) {
      flags |= CI_SYNTHETIC;
    }
    if (Modifier.isAnnotation(sootClass.getModifiers())) {
      flags |= CI_ANNOTATION;
    }
    if (Modifier.isEnum(sootClass.getModifiers())) {
      flags |= CI_ENUM;
    }
    if (attributesEncoder.classHasAttributes()) {
      flags |= CI_ATTRIBUTES;
    }
    if (hasFinalizer(sootClass)) {
      flags |= CI_FINALIZABLE;
    }

    // Create the ClassInfoHeader structure.
    StructureConstantBuilder header = new StructureConstantBuilder();
    header.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct
    header.add(new IntegerConstant(flags));
    header.add(getString(getInternalName(sootClass)));
    if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) {
      SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v());
      header.add(new FunctionRef(mangleMethod(method), getFunctionType(method)));
    } else {
      header.add(new NullConstant(I8_PTR));
    }
    header.add(sizeof(classType));
    header.add(sizeof(instanceType));
    if (!instanceFields.isEmpty()) {
      header.add(offsetof(instanceType, 1, 1));
    } else {
      header.add(sizeof(instanceType));
    }
    header.add(new IntegerConstant((short) countReferences(classFields)));
    header.add(new IntegerConstant((short) countReferences(instanceFields)));

    PackedStructureConstantBuilder body = new PackedStructureConstantBuilder();
    body.add(new IntegerConstant((short) sootClass.getInterfaceCount()));
    body.add(new IntegerConstant((short) sootClass.getFieldCount()));
    body.add(new IntegerConstant((short) sootClass.getMethodCount()));

    if (!sootClass.isInterface()) {
      body.add(
          getStringOrNull(
              sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null));
    }

    if (attributesEncoder.classHasAttributes()) {
      body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR));
    }

    for (SootClass s : sootClass.getInterfaces()) {
      body.add(getString(getInternalName(s)));
    }

    for (SootField f : sootClass.getFields()) {
      flags = 0;
      soot.Type t = f.getType();
      if (t instanceof PrimType) {
        if (t.equals(BooleanType.v())) {
          flags |= DESC_Z;
        } else if (t.equals(ByteType.v())) {
          flags |= DESC_B;
        } else if (t.equals(ShortType.v())) {
          flags |= DESC_S;
        } else if (t.equals(CharType.v())) {
          flags |= DESC_C;
        } else if (t.equals(IntType.v())) {
          flags |= DESC_I;
        } else if (t.equals(LongType.v())) {
          flags |= DESC_J;
        } else if (t.equals(FloatType.v())) {
          flags |= DESC_F;
        } else if (t.equals(DoubleType.v())) {
          flags |= DESC_D;
        }
        flags <<= 12;
      }
      if (Modifier.isPublic(f.getModifiers())) {
        flags |= FI_PUBLIC;
      } else if (Modifier.isPrivate(f.getModifiers())) {
        flags |= FI_PRIVATE;
      } else if (Modifier.isProtected(f.getModifiers())) {
        flags |= FI_PROTECTED;
      }
      if (Modifier.isStatic(f.getModifiers())) {
        flags |= FI_STATIC;
      }
      if (Modifier.isFinal(f.getModifiers())) {
        flags |= FI_FINAL;
      }
      if (Modifier.isVolatile(f.getModifiers())) {
        flags |= FI_VOLATILE;
      }
      if (Modifier.isTransient(f.getModifiers())) {
        flags |= FI_TRANSIENT;
      }
      if ((f.getModifiers() & 0x1000) > 0) {
        flags |= FI_SYNTHETIC;
      }
      if (Modifier.isEnum(f.getModifiers())) {
        flags |= FI_ENUM;
      }
      if (attributesEncoder.fieldHasAttributes(f)) {
        flags |= FI_ATTRIBUTES;
      }
      body.add(new IntegerConstant((short) flags));
      body.add(getString(f.getName()));
      if (!(t instanceof PrimType)) {
        body.add(getString(getDescriptor(f)));
      }
      if (f.isStatic()) {
        int index = classFields.indexOf(f);
        body.add(offsetof(classType, 1, index, 1));
      } else {
        int index = instanceFields.indexOf(f);
        body.add(offsetof(instanceType, 1, 1 + index, 1));
      }
      if (attributesEncoder.fieldHasAttributes(f)) {
        body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR));
      }
    }

    for (SootMethod m : sootClass.getMethods()) {
      soot.Type t = m.getReturnType();
      flags = 0;
      if (Modifier.isPublic(m.getModifiers())) {
        flags |= MI_PUBLIC;
      } else if (Modifier.isPrivate(m.getModifiers())) {
        flags |= MI_PRIVATE;
      } else if (Modifier.isProtected(m.getModifiers())) {
        flags |= MI_PROTECTED;
      }
      if (Modifier.isStatic(m.getModifiers())) {
        flags |= MI_STATIC;
      }
      if (Modifier.isFinal(m.getModifiers())) {
        flags |= MI_FINAL;
      }
      if (Modifier.isSynchronized(m.getModifiers())) {
        flags |= MI_SYNCHRONIZED;
      }
      if ((m.getModifiers() & 0x0040) > 0) {
        flags |= MI_BRIDGE;
      }
      if ((m.getModifiers() & 0x0080) > 0) {
        flags |= MI_VARARGS;
      }
      if (Modifier.isNative(m.getModifiers())) {
        if (!isStruct(sootClass) && !isStructMember(m)) {
          flags |= MI_NATIVE;
        }
      }
      if (Modifier.isAbstract(m.getModifiers())) {
        flags |= MI_ABSTRACT;
      }
      if (Modifier.isStrictFP(m.getModifiers())) {
        flags |= MI_STRICT;
      }
      if ((m.getModifiers() & 0x1000) > 0) {
        flags |= MI_SYNTHETIC;
      }
      if (attributesEncoder.methodHasAttributes(m)) {
        flags |= MI_ATTRIBUTES;
      }
      if (isBridge(m)) {
        flags |= MI_BRO_BRIDGE;
      }
      if (isCallback(m)) {
        flags |= MI_BRO_CALLBACK;
      }
      if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) {
        flags |= MI_COMPACT_DESC;
      }
      body.add(new IntegerConstant((short) flags));

      body.add(getString(m.getName()));

      if ((flags & MI_COMPACT_DESC) > 0) {
        int desc = 0;
        if (t.equals(BooleanType.v())) {
          desc = DESC_Z;
        } else if (t.equals(ByteType.v())) {
          desc = DESC_B;
        } else if (t.equals(ShortType.v())) {
          desc = DESC_S;
        } else if (t.equals(CharType.v())) {
          desc = DESC_C;
        } else if (t.equals(IntType.v())) {
          desc = DESC_I;
        } else if (t.equals(LongType.v())) {
          desc = DESC_J;
        } else if (t.equals(FloatType.v())) {
          desc = DESC_F;
        } else if (t.equals(DoubleType.v())) {
          desc = DESC_D;
        } else if (t.equals(VoidType.v())) {
          desc = DESC_V;
        }
        body.add(new IntegerConstant((byte) desc));
      } else {
        body.add(getString(getDescriptor(m)));
      }
      if (attributesEncoder.methodHasAttributes(m)) {
        body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR));
      }
      if (!m.isAbstract()) {
        body.add(new ConstantBitcast(new FunctionRef(mangleMethod(m), getFunctionType(m)), I8_PTR));
        body.add(
            new IntegerConstant(
                DUMMY_METHOD_SIZE)); // Size of function. This value will be modified later by
                                     // patching the .s file.
        if (m.isSynchronized()) {
          body.add(
              new ConstantBitcast(
                  new FunctionRef(mangleMethod(m) + "_synchronized", getFunctionType(m)), I8_PTR));
        }
      }
      if (isBridge(m)) {
        body.add(new GlobalRef(BridgeMethodCompiler.getTargetFnPtrName(m), I8_PTR));
      }
      if (isCallback(m)) {
        body.add(
            new ConstantBitcast(
                new FunctionRef(mangleMethod(m) + "_callback", getCallbackFunctionType(m)),
                I8_PTR));
      }
    }

    // Return the struct {header, body}. To be compatible with the C code in classinfo.c
    // it is important that the header is padded the same as in C so that the body starts
    // after sizeof(ClassInfoHeader) bytes.
    return new StructureConstantBuilder().add(header.build()).add(body.build()).build();
  }
Beispiel #16
0
  private StructureConstant createClassInfoErrorStruct() {
    /*
     * Check that clazz can be loaded, i.e. that the superclass
     * and interfaces of the class exist and are accessible to the
     * class. Also check that any exception the class uses in catch
     * clauses exist and is accessible to the class. If the class
     * cannot be loaded we override the ClassInfoHeader struct
     * produced by the ClassCompiler for the class with one which
     * tells the code in bc.c to throw an appropriate exception
     * whenever clazz is accessed.
     */

    int errorType = ClassCompiler.CI_ERROR_TYPE_NONE;
    String errorMessage = null;
    if (!sootClass.isInterface() && sootClass.hasSuperclass()) {
      // Check superclass
      SootClass superclazz = sootClass.getSuperclass();
      if (superclazz.isPhantom()) {
        errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND;
        errorMessage = superclazz.getName();
      } else if (!checkClassAccessible(superclazz, sootClass)) {
        errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS;
        errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, superclazz, sootClass);
      } else if (superclazz.isInterface()) {
        errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE;
        errorMessage =
            String.format("class %s has interface %s as super class", sootClass, superclazz);
      }
      // No need to check for ClassCircularityError. Soot doesn't handle
      // such problems so the compilation will fail earlier.
    }

    if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) {
      // Check interfaces
      for (SootClass interfaze : sootClass.getInterfaces()) {
        if (interfaze.isPhantom()) {
          errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND;
          errorMessage = interfaze.getName();
          break;
        } else if (!checkClassAccessible(interfaze, sootClass)) {
          errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS;
          errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, interfaze, sootClass);
          break;
        } else if (!interfaze.isInterface()) {
          errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE;
          errorMessage =
              String.format(
                  "class %s tries to implement class %s as interface", sootClass, interfaze);
          break;
        }
      }
    }

    if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) {
      // Check exceptions used in catch clauses. I cannot find any info in
      // the VM spec specifying that this has to be done when the class is loaded.
      // However, this is how it's done in other VMs so we do it too.
      for (String exName : catches) {
        Clazz ex = config.getClazzes().load(exName);
        if (ex == null || ex.getSootClass().isPhantom()) {
          errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND;
          errorMessage = exName;
          break;
        } else if (!checkClassAccessible(ex.getSootClass(), sootClass)) {
          errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS;
          errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, ex, sootClass);
          break;
        }
      }
    }

    if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) {
      return null;
    }

    // Create a ClassInfoError struct
    StructureConstantBuilder error = new StructureConstantBuilder();
    error.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct
    error.add(new IntegerConstant(ClassCompiler.CI_ERROR));
    error.add(getString(getInternalName(sootClass)));
    error.add(new IntegerConstant(errorType));
    error.add(getString(errorMessage));
    return error.build();
  }
Beispiel #17
0
  private void compile(Clazz clazz, OutputStream out) throws IOException {
    sootClass = clazz.getSootClass();
    mb = new ModuleBuilder();
    trampolines = new HashSet<Trampoline>();
    catches = new HashSet<String>();
    classFields = getClassFields(sootClass);
    instanceFields = getInstanceFields(sootClass);
    classType = getClassType(sootClass);
    instanceType = getInstanceType(sootClass);

    attributesEncoder.encode(mb, sootClass);

    // Add a <clinit> method if the class has ConstantValueTags but no <clinit>.
    // This has to be done before createInfoStruct() is called otherwise the
    // ClassInfoHeader->initializer value will become NULL and constant static fields
    // will never be initialized.
    if (!sootClass.declaresMethodByName("<clinit>") && hasConstantValueTags(classFields)) {
      SootMethod clinit =
          new SootMethod("<clinit>", Collections.EMPTY_LIST, VoidType.v(), Modifier.STATIC);
      JimpleBody body = Jimple.v().newBody(clinit);
      clinit.setActiveBody(body);
      body.getUnits().add(new JReturnVoidStmt());
      this.sootClass.addMethod(clinit);
    }

    if (isStruct(sootClass)) {
      if (!Modifier.isFinal(sootClass.getModifiers())) {
        throw new IllegalArgumentException("Struct class must be final");
      }
      SootMethod _sizeOf =
          new SootMethod("_sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PROTECTED);
      sootClass.addMethod(_sizeOf);
      SootMethod sizeOf =
          new SootMethod(
              "sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PUBLIC | Modifier.STATIC);
      sootClass.addMethod(sizeOf);
    }

    mb.addInclude(
        getClass()
            .getClassLoader()
            .getResource(
                String.format("header-%s-%s.ll", config.getOs().getFamily(), config.getArch())));
    mb.addInclude(getClass().getClassLoader().getResource("header.ll"));

    mb.addFunction(createInstanceof());
    mb.addFunction(createCheckcast());
    mb.addFunction(createLdcClass());
    mb.addFunction(createLdcClassWrapper());
    Function allocator = createAllocator();
    mb.addFunction(allocator);
    mb.addFunction(createClassInitWrapperFunction(allocator.ref()));

    for (SootField f : sootClass.getFields()) {
      Function getter = createFieldGetter(f);
      Function setter = createFieldSetter(f);
      mb.addFunction(getter);
      mb.addFunction(setter);
      if (f.isStatic() && !f.isPrivate()) {
        mb.addFunction(createClassInitWrapperFunction(getter.ref()));
        if (!f.isFinal()) {
          mb.addFunction(createClassInitWrapperFunction(setter.ref()));
        }
      }
    }

    for (SootMethod method : sootClass.getMethods()) {
      String name = method.getName();
      if (isBridge(method)) {
        bridgeMethod(method);
      } else if (isStruct(sootClass)
          && ("_sizeOf".equals(name) || "sizeOf".equals(name) || isStructMember(method))) {
        structMember(method);
      } else if (method.isNative()) {
        nativeMethod(method);
      } else if (!method.isAbstract()) {
        method(method);
      }
      if (!name.equals("<clinit>")
          && !name.equals("<init>")
          && !method.isPrivate()
          && !method.isStatic()
          && !Modifier.isFinal(method.getModifiers())
          && !Modifier.isFinal(sootClass.getModifiers())) {

        createLookupFunction(method);
      }
      if (method.isStatic()) {
        String fnName = mangleMethod(method);
        if (method.isSynchronized()) {
          fnName += "_synchronized";
        }
        FunctionRef fn = new FunctionRef(fnName, getFunctionType(method));
        mb.addFunction(createClassInitWrapperFunction(fn));
      }
    }

    Set<String> trampolineDependencies = new HashSet<String>();
    for (Trampoline trampoline : trampolines) {
      trampolineResolver.compile(mb, trampoline);
      trampolineDependencies.addAll(trampolineResolver.getDependencies());
    }

    Global classInfoStruct = null;
    StructureConstant classInfoErrorStruct = createClassInfoErrorStruct();
    if (classInfoErrorStruct != null) {
      // The class cannot be loaded at runtime. Replace the ClassInfo struct
      // with a ClassInfoError struct with details of why.
      classInfoStruct = new Global(mangleClass(sootClass) + "_info_struct", classInfoErrorStruct);
    } else {
      classInfoStruct =
          new Global(mangleClass(sootClass) + "_info_struct", createClassInfoStruct());
    }
    mb.addGlobal(classInfoStruct);

    Function infoFn = FunctionBuilder.infoStruct(sootClass);
    infoFn.add(new Ret(new ConstantBitcast(classInfoStruct.ref(), I8_PTR_PTR)));
    mb.addFunction(infoFn);

    out.write(mb.build().toString().getBytes("UTF-8"));

    clazz.clearDependencies();
    clazz.addDependency(
        "java/lang/Object"); // Make sure no class or interface has zero dependencies
    if (sootClass.hasSuperclass() && !sootClass.isInterface()) {
      clazz.addDependency(getInternalName(sootClass.getSuperclass()));
    }
    for (SootClass iface : sootClass.getInterfaces()) {
      clazz.addDependency(getInternalName(iface));
    }
    for (SootField f : sootClass.getFields()) {
      addDependencyIfNeeded(clazz, f.getType());
    }
    for (SootMethod m : sootClass.getMethods()) {
      addDependencyIfNeeded(clazz, m.getReturnType());
      @SuppressWarnings("unchecked")
      List<soot.Type> paramTypes = (List<soot.Type>) m.getParameterTypes();
      for (soot.Type type : paramTypes) {
        addDependencyIfNeeded(clazz, type);
      }
    }
    clazz.addDependencies(attributesEncoder.getDependencies());
    clazz.addDependencies(trampolineDependencies);
    clazz.addDependencies(catches);

    for (Trampoline t : trampolines) {
      if (!(t instanceof LdcString)) {
        String desc = t.getTarget();
        if (desc.charAt(0) == 'L' || desc.charAt(0) == '[') {
          // Target is a descriptor
          addDependencyIfNeeded(clazz, desc);
        } else {
          clazz.addDependency(t.getTarget());
        }
      }
      if (t instanceof FieldAccessor) {
        addDependencyIfNeeded(clazz, ((FieldAccessor) t).getFieldDesc());
      } else if (t instanceof Invoke) {
        String methodDesc = ((Invoke) t).getMethodDesc();
        addDependencyIfNeeded(clazz, getReturnTypeDescriptor(methodDesc));
        for (String desc : getParameterDescriptors(methodDesc)) {
          addDependencyIfNeeded(clazz, desc);
        }
      }
    }
    clazz.saveDependencies();
  }
  public boolean DoAnalysis(boolean verbose) {
    Stack<List<Set<SootClass>>> current_exception_sets = new Stack<List<Set<SootClass>>>();
    {
      List<Set<SootClass>> exception_sets = new ArrayList<Set<SootClass>>();
      exception_sets.add(method_exception_set);
      current_exception_sets.push(exception_sets);
    }

    PatchingChain<Unit> chain = body.getUnits();
    Unit next = chain.getFirst();

    int previous_class_count = method_exception_set.size();
    for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry :
        trap_begin_exception_sets.entrySet()) {
      for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) {
        previous_class_count += tvp.w.size();
      }
    }

    do {

      if (trap_begin_exception_sets.containsKey(next)) {
        List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_begin_exception_sets.get(next);
        List<Set<SootClass>> sets_to_add = new ArrayList<Set<SootClass>>();
        for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {
          sets_to_add.add(tvp.w);
        }
        current_exception_sets.push(sets_to_add);
      }
      if (next instanceof InvokeStmt || next instanceof AssignStmt) {
        SootMethod callee = null;

        if (next instanceof AssignStmt) {
          if (((AssignStmt) next).getRightOp() instanceof InvokeExpr) {
            callee = ((InvokeExpr) ((AssignStmt) next).getRightOp()).getMethod();
          }
        } else {
          callee = ((InvokeStmt) next).getInvokeExpr().getMethod();
        }

        if (callee != null) { // invocation only

          Collection<SootClass> exception_classes;
          if (class_map.containsKey(callee.getDeclaringClass())) {
            assert class_map.get(callee.getDeclaringClass()).method_analysis.containsKey(callee);

            exception_classes =
                class_map
                    .get(callee.getDeclaringClass())
                    .method_analysis
                    .get(callee)
                    .method_exception_set;
          } else {
            exception_classes = callee.getExceptions();
          }
          for (SootClass exception_class : exception_classes) {
            for (Set<SootClass> current_exception_set : current_exception_sets.peek()) {
              current_exception_set.add(exception_class);
            }
          }
        }

      } else if (next instanceof ThrowStmt) {

        assert chain.getPredOf(next) instanceof JInvokeStmt;
        assert ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr() instanceof SpecialInvokeExpr;
        assert ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()).getBase()
            instanceof JimpleLocal;
        assert ((JimpleLocal)
                    ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr())
                        .getBase())
                .getType()
            instanceof RefType;

        SootClass exception_class =
            ((RefType)
                    ((JimpleLocal)
                            ((SpecialInvokeExpr)
                                    ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr())
                                .getBase())
                        .getType())
                .getSootClass();

        for (Set<SootClass> current_exception_set : current_exception_sets.peek()) {
          current_exception_set.add(exception_class);
        }
      }

      if (trap_end_exception_sets.containsKey(next)) {

        List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_end_exception_sets.get(next);

        if (verbose) {
          for (Set<SootClass> current_exception_set : current_exception_sets.peek()) {
            if (current_exception_set.size() == 0) {
              for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {
                if (!tvp.v.getException().getName().equals("java.lang.RuntimeException"))
                  System.out.println(
                      "Warning: In "
                          + method.toString()
                          + ": Unncessary exception handler for catching "
                          + tvp.v.getException().getName());
              }
            }
          }
        }

        for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {

          Iterator<SootClass> i = tvp.w.iterator();
          while (i.hasNext()) {
            SootClass exception_class = i.next();

            if (tvp.v.getException()
                == exception_class) { // getting properly caught by the handler.
              i.remove();
            } else {
              SootClass super_exception_class = exception_class;
              while (super_exception_class != null) {

                if (tvp.v.getException() == super_exception_class) {
                  i.remove();
                  if (verbose
                      && super_exception_class != exception_class
                      && GetMostRestrictiveFormOfException(tvps, exception_class)
                          == tvp.v.getException()
                      && !super_exception_class.getName().equals("java.lang.RuntimeException")) {
                    System.out.println(
                        "Warning: In "
                            + method.toString()
                            + ": attempting to catch "
                            + exception_class.getName()
                            + " with "
                            + super_exception_class.getName()
                            + " Consider catching the most restrictive exception class");
                  }
                  break;
                }
                try {
                  super_exception_class = super_exception_class.getSuperclass();
                } catch (
                    RuntimeException
                        e) { // unfortunately soot doesn't have a specific exception class for "no
                  // superclass for java.lang.Object" exception
                  super_exception_class = null;
                }
              }
            }
          }
        }

        current_exception_sets.pop();

        for (Set<SootClass> current_exception_set :
            current_exception_sets
                .peek()) { // This list iteration is not necessary if we are still making the
          // assumption that there's only one unique set that contains exception
          // classes if the range for traps are the same
          for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {
            for (SootClass exception_class : tvp.w) {
              current_exception_set.add(exception_class);
            }
          }
        }
      }
      next = chain.getSuccOf(next);
    } while (next != null);

    int new_class_count = method_exception_set.size();
    for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry :
        trap_begin_exception_sets.entrySet()) {
      for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) {
        new_class_count += tvp.w.size();
      }
    }

    return new_class_count != previous_class_count;
  }
Beispiel #19
0
 /**
  * Returns method in given class or first upwards superclass, or null if not found in any class
  * (no interface checked)
  */
 private static SootMethod getMethodInClassOrSuperclass(
     SootClass cls, NumberedString subsignature) {
   if (cls.declaresMethod(subsignature)) return cls.getMethod(subsignature);
   if (cls.hasSuperclass()) return getMethodInClassOrSuperclass(cls.getSuperclass(), subsignature);
   return null;
 }
  private StructureType getStructType(SootClass clazz, boolean checkEmpty) {
    int n = 0;
    for (SootMethod method : clazz.getMethods()) {
      n = Math.max(getStructMemberOffset(method) + 1, n);
    }

    Type[] result = new Type[n + 1];

    StructureType superType = null;
    if (clazz.hasSuperclass()) {
      SootClass superclass = clazz.getSuperclass();
      if (!superclass.getName().equals("org.robovm.rt.bro.Struct")) {
        superType = getStructType(superclass, false);
      }
    }
    result[0] = superType != null ? superType : new StructureType();

    for (SootMethod method : clazz.getMethods()) {
      int offset = getStructMemberOffset(method);
      if (offset != -1) {
        if (!method.isNative() && !method.isStatic()) {
          throw new IllegalArgumentException(
              "@StructMember annotated method " + method + " must be native and not static");
        }
        Type type = null;
        if (method.getParameterCount() == 0) {
          soot.Type sootType = method.getReturnType();
          // Possibly a getter
          if (hasPointerAnnotation(method) && !sootType.equals(LongType.v())) {
            throw new IllegalArgumentException(
                "@StructMember("
                    + offset
                    + ") annotated getter "
                    + method
                    + " must be of type long when annotated with @Pointer");
          }
          if (hasMachineSizedFloatAnnotation(method)
              && !sootType.equals(DoubleType.v())
              && !sootType.equals(FloatType.v())) {
            throw new IllegalArgumentException(
                "@StructMember("
                    + offset
                    + ") annotated getter "
                    + method
                    + " must be of type float or double when annotated with @MachineSizedFloat");
          }
          if ((hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method))
              && !sootType.equals(LongType.v())) {
            throw new IllegalArgumentException(
                "@StructMember("
                    + offset
                    + ") annotated getter "
                    + method
                    + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt");
          }
          if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method)) {
            throw new IllegalArgumentException(
                "@Array annotation expected on struct member getter " + method);
          }
        } else if (method.getParameterCount() == 1) {
          soot.Type sootType = method.getParameterType(0);
          if (hasPointerAnnotation(method, 0) && !sootType.equals(LongType.v())) {
            throw new IllegalArgumentException(
                "@StructMember("
                    + offset
                    + ") annotated setter "
                    + method
                    + " must be of type long when annotated with @Pointer");
          }
          if (hasMachineSizedFloatAnnotation(method, 0)
              && !sootType.equals(DoubleType.v())
              && !sootType.equals(FloatType.v())) {
            throw new IllegalArgumentException(
                "@StructMember("
                    + offset
                    + ") annotated setter "
                    + method
                    + " must be of type float or double when annotated with @MachineSizedFloat");
          }
          if ((hasMachineSizedSIntAnnotation(method, 0) || hasMachineSizedUIntAnnotation(method))
              && !sootType.equals(LongType.v())) {
            throw new IllegalArgumentException(
                "@StructMember("
                    + offset
                    + ") annotated setter "
                    + method
                    + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt");
          }
          if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method, 0)) {
            throw new IllegalArgumentException(
                "@Array annotation expected on first parameter of struct member setter " + method);
          }
          soot.Type retType = method.getReturnType();
          // The return type of the setter must be void or this
          if (!retType.equals(VoidType.v())
              && !(retType instanceof RefType
                  && ((RefType) retType).getSootClass().equals(clazz))) {
            throw new IllegalArgumentException(
                "Setter "
                    + method
                    + " for "
                    + "@StructMember("
                    + offset
                    + ") "
                    + " must either return nothing or return a "
                    + clazz);
          }
        } else {
          throw new IllegalArgumentException(
              "@StructMember annotated method " + method + " has too many parameters");
        }

        type = getStructMemberType(method);
        int index = offset + 1;
        if (result[index] == null) {
          result[index] = type;
        } else if (type != result[index]) {
          // Two members mapped to the same offset (union). Pick
          // the type with the largest alignment and pad with bytes
          // up to the largest size.
          result[index] = mergeStructMemberTypes(config.getDataLayout(), type, result[index]);
        }
      }
    }

    for (int i = 1; i < result.length; i++) {
      if (result[i] == null) {
        throw new IllegalArgumentException("No @StructMember(" + i + ") defined in class " + clazz);
      }
    }

    if (!clazz.isAbstract() && checkEmpty && n == 0 && superType == null) {
      throw new IllegalArgumentException(
          "Struct class " + clazz + " has no @StructMember annotated methods");
    }

    return new StructureType(result);
  }
Beispiel #21
0
  public void printTo(SootClass cl, PrintWriter out) {

    // IterableSet packagesUsed = new IterableSet();
    IterableSet importList = new IterableSet();
    {
      String curPackage = cl.getJavaPackageName();

      if (!curPackage.equals("")) {
        out.println("package " + curPackage + ";");
        out.println();
      }

      if (cl.hasSuperclass()) {
        SootClass superClass = cl.getSuperclass();
        importList.add(superClass.toString());
        // packagesUsed.add(superClass.getJavaPackageName());
      }

      Iterator<SootClass> interfaceIt = cl.getInterfaces().iterator();
      while (interfaceIt.hasNext()) {
        String interfacePackage = ((SootClass) interfaceIt.next()).toString();

        if (!importList.contains(interfacePackage)) importList.add(interfacePackage);

        // if (!packagesUsed.contains(interfacePackage))
        //  packagesUsed.add(interfacePackage);
      }

      Iterator<SootMethod> methodIt = cl.methodIterator();
      while (methodIt.hasNext()) {
        SootMethod dm = (SootMethod) methodIt.next();

        if (dm.hasActiveBody()) {
          // packagesUsed = packagesUsed.union(((DavaBody) dm.getActiveBody()).get_PackagesUsed());
          importList = importList.union(((DavaBody) dm.getActiveBody()).getImportList());
        }

        Iterator<SootClass> eit = dm.getExceptions().iterator();
        while (eit.hasNext()) {
          String thrownPackage = eit.next().toString();
          if (!importList.contains(thrownPackage)) importList.add(thrownPackage);

          // if (!packagesUsed.contains(thrownPackage))
          //  packagesUsed.add(thrownPackage);
        }

        Iterator<Type> pit = dm.getParameterTypes().iterator();
        while (pit.hasNext()) {
          Type t = (Type) pit.next();

          if (t instanceof RefType) {
            String paramPackage = ((RefType) t).getSootClass().toString();

            if (!importList.contains(paramPackage)) importList.add(paramPackage);

            // if (packagesUsed.contains(paramPackage) == false)
            //  packagesUsed.add(paramPackage);
          }
        }

        Type t = dm.getReturnType();
        if (t instanceof RefType) {
          String returnPackage = ((RefType) t).getSootClass().toString();

          if (!importList.contains(returnPackage)) importList.add(returnPackage);

          // if (packagesUsed.contains(returnPackage) == false)
          //  packagesUsed.add(returnPackage);
        }
      }

      Iterator<SootField> fieldIt = cl.getFields().iterator();
      while (fieldIt.hasNext()) {
        SootField f = (SootField) fieldIt.next();

        if (f.isPhantom()) continue;

        Type t = f.getType();

        if (t instanceof RefType) {
          String fieldPackage = ((RefType) t).getSootClass().toString();

          if (!importList.contains(fieldPackage)) importList.add(fieldPackage);
        }
      }

      Iterator<String> pit = importList.iterator();
      List<String> toImport = new ArrayList<String>();
      while (pit.hasNext()) {
        /*
         * dont import any file which has currentPackage.className
         * dont import any file which starts with java.lang
         */
        String temp = (String) pit.next();
        // System.out.println("temp is "+temp);
        if (temp.indexOf("java.lang") > -1) {
          // problem is that we need to import sub packages java.lang.ref
          // for instance if the type is java.lang.ref.WeakReference
          String tempClassName = RemoveFullyQualifiedName.getClassName(temp);
          if (temp.equals("java.lang." + tempClassName)) {
            // System.out.println("temp was not printed as it belongs to java.lang");
            continue;
          }
        }

        if (curPackage.length() > 0 && temp.indexOf(curPackage) > -1) {
          // System.out.println("here  "+temp);
          continue;
        }

        if (cl.toString().equals(temp)) continue;

        // System.out.println("printing"+);
        toImport.add(temp);
      }

      /*
       * Check that we are not importing two classes with the same last name
       * If yes then remove explicit import and import the whole package
       * else output explicit import statement
       */
      Iterator it = toImport.iterator();
      while (it.hasNext()) {
        String temp = (String) it.next();
        if (RemoveFullyQualifiedName.containsMultiple(toImport.iterator(), temp, null)) {
          // there are atleast two imports with this className
          // import package add *
          if (temp.lastIndexOf('.') > -1) {
            temp = temp.substring(0, temp.lastIndexOf('.'));
            out.println("import " + temp + ".*;");
          } else throw new DecompilationException("Cant find the DOT . for fullyqualified name");
        } else {
          if (temp.lastIndexOf('.') == -1) {
            // dot not found this is a class belonging to this package so dont add
          } else out.println("import " + temp + ";");
        }
      }
      boolean addNewLine = false;
      addNewLine = true;

      // out.println("import " + temp + ";");

      if (addNewLine) out.println();

      /*if (!packagesUsed.isEmpty())
          out.println();

      packagesUsed.add("java.lang");
      packagesUsed.add(curPackage);
      */
      Dava.v().set_CurrentPackageContext(importList);
      // Dava.v().set_CurrentPackageContext(packagesUsed);
      Dava.v().set_CurrentPackage(curPackage);
    }

    // Print class name + modifiers
    {
      String classPrefix = "";

      classPrefix = classPrefix + " " + Modifier.toString(cl.getModifiers());
      classPrefix = classPrefix.trim();

      if (!cl.isInterface()) {
        classPrefix = classPrefix + " class";
        classPrefix = classPrefix.trim();
      }

      out.print(classPrefix + " " + cl.getShortJavaStyleName());
    }

    // Print extension
    if (cl.hasSuperclass() && !(cl.getSuperclass().getName().equals("java.lang.Object"))) {

      String superClassName = cl.getSuperclass().getName();

      // Nomair Naeem 8th Feb 2006
      // also check if the super class name is not a fully qualified
      // name. in which case if the package is imported no need for
      // the long name

      superClassName =
          RemoveFullyQualifiedName.getReducedName(importList, superClassName, cl.getType());
      out.print(" extends " + superClassName + "");
    }

    // Print interfaces
    {
      Iterator<SootClass> interfaceIt = cl.getInterfaces().iterator();

      if (interfaceIt.hasNext()) {
        if (cl.isInterface()) out.print(" extends ");
        else out.print(" implements ");

        out.print("" + (interfaceIt.next()).getName() + "");

        while (interfaceIt.hasNext()) out.print(", " + (interfaceIt.next()).getName() + "");
      }
    }

    out.println();
    out.println("{");

    // Print fields
    {
      Iterator<SootField> fieldIt = cl.getFields().iterator();
      if (fieldIt.hasNext()) {
        while (fieldIt.hasNext()) {
          SootField f = fieldIt.next();

          if (f.isPhantom()) continue;

          String declaration = null;

          Type fieldType = f.getType();

          String qualifiers = Modifier.toString(f.getModifiers()) + " ";

          qualifiers +=
              RemoveFullyQualifiedName.getReducedName(importList, fieldType.toString(), fieldType);

          qualifiers = qualifiers.trim();

          if (qualifiers.equals("")) declaration = Scene.v().quotedNameOf(f.getName());
          else declaration = qualifiers + " " + Scene.v().quotedNameOf(f.getName()) + "";

          if (f.isFinal() && f.isStatic()) {

            if (fieldType instanceof DoubleType && f.hasTag("DoubleConstantValueTag")) {

              double val =
                  ((DoubleConstantValueTag) f.getTag("DoubleConstantValueTag")).getDoubleValue();
              out.println("    " + declaration + " = " + val + ";");

            } else if (fieldType instanceof FloatType && f.hasTag("FloatConstantValueTag")) {

              float val =
                  ((FloatConstantValueTag) f.getTag("FloatConstantValueTag")).getFloatValue();
              out.println("    " + declaration + " = " + val + "f;");

            } else if (fieldType instanceof LongType && f.hasTag("LongConstantValueTag")) {

              long val = ((LongConstantValueTag) f.getTag("LongConstantValueTag")).getLongValue();
              out.println("    " + declaration + " = " + val + "l;");

            } else if (fieldType instanceof CharType && f.hasTag("IntegerConstantValueTag")) {

              int val =
                  ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
              out.println("    " + declaration + " = '" + ((char) val) + "';");

            } else if (fieldType instanceof BooleanType && f.hasTag("IntegerConstantValueTag")) {

              int val =
                  ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();

              if (val == 0) out.println("    " + declaration + " = false;");
              else out.println("    " + declaration + " = true;");

            } else if ((fieldType instanceof IntType
                    || fieldType instanceof ByteType
                    || fieldType instanceof ShortType)
                && f.hasTag("IntegerConstantValueTag")) {

              int val =
                  ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue();
              out.println("    " + declaration + " = " + val + ";");

            } else if (f.hasTag("StringConstantValueTag")) {

              String val =
                  ((StringConstantValueTag) f.getTag("StringConstantValueTag")).getStringValue();
              out.println("    " + declaration + " = \"" + val + "\";");

            } else {
              // System.out.println("Couldnt find type of
              // field"+f.getDeclaration());
              out.println("    " + declaration + ";");
            }
          } // field is static final
          else {
            out.println("    " + declaration + ";");
          }
        }
      }
    }

    // Print methods
    {
      Iterator<SootMethod> methodIt = cl.methodIterator();

      if (methodIt.hasNext()) {
        if (cl.getMethodCount() != 0) out.println();

        while (methodIt.hasNext()) {
          SootMethod method = (SootMethod) methodIt.next();

          if (method.isPhantom()) continue;

          if (!Modifier.isAbstract(method.getModifiers())
              && !Modifier.isNative(method.getModifiers())) {
            if (!method.hasActiveBody())
              throw new RuntimeException("method " + method.getName() + " has no active body!");
            else printTo(method.getActiveBody(), out);

            if (methodIt.hasNext()) out.println();
          } else {
            // if method is abstract then print the declaration
            out.print("    ");
            out.print(method.getDavaDeclaration());
            out.println(";");

            if (methodIt.hasNext()) out.println();
          }
        }
      }
    }

    /*
     * January 23rd, 2006
     * In trying to handle the suepr class problem we need to introduce an inner class
     * Instead of creating a data structure for it we are right now just going to print it in the form
     * of a string
     *
     * It would be interesting to later have an internal inner class structure so that we could
     * decompile inner classes into inner classes
     */

    if (G.v().SootClassNeedsDavaSuperHandlerClass.contains(cl)) {
      out.println("\n    private static class DavaSuperHandler{");
      out.println("         java.util.Vector myVector = new java.util.Vector();");

      out.println("\n         public Object get(int pos){");
      out.println("            return myVector.elementAt(pos);");
      out.println("         }");

      out.println("\n         public void store(Object obj){");
      out.println("            myVector.add(obj);");
      out.println("         }");
      out.println("    }");
    }

    out.println("}");
  }