Example #1
0
 private void loadClasses() {
   Date start = new Date();
   if (entryClass != null) {
     SootUtils.loadClassesForEntry(entryClass);
   } else {
     for (JavaCriticalSection cs : results) {
       String clsname = cs.getClassName();
       String regex = "\\$\\d";
       Pattern pattern = Pattern.compile(regex);
       Matcher matcher = pattern.matcher(clsname);
       if (matcher.find()) {
         System.out.println("can't find the class created randomly by compiler");
         continue;
       }
       SootClass cls = Scene.v().loadClassAndSupport(clsname);
       if (setMainClass == true
           && cls.declaresMethod(
               Scene.v().getSubSigNumberer().findOrAdd("void main(java.lang.String[])"))) {
         Scene.v().setMainClass(cls);
         setMainClass = false;
       }
     }
     Scene.v().loadNecessaryClasses();
   }
   Date end = new Date();
   System.out.println(
       "load " + Scene.v().getClasses().size() + " classes in " + getTimeConsumed(start, end));
 }
  public void staticBlockInlining(SootClass sootClass) {
    this.sootClass = sootClass;
    // retrieve the clinit method if any for sootClass
    if (!sootClass.declaresMethod("void <clinit>()")) {
      System.out.println("no clinit");
      return;
    }

    SootMethod clinit = sootClass.getMethod("void <clinit>()");
    // System.out.println(clinit);

    // retireve the active body
    if (!clinit.hasActiveBody())
      throw new RuntimeException("method " + clinit.getName() + " has no active body!");

    Body clinitBody = clinit.getActiveBody();

    Chain units = ((DavaBody) clinitBody).getUnits();

    if (units.size() != 1) {
      throw new RuntimeException("DavaBody AST doesn't have single root.");
    }

    ASTNode AST = (ASTNode) units.getFirst();
    if (!(AST instanceof ASTMethodNode))
      throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");

    AST.apply(new MethodCallFinder(this));
  }
Example #3
0
 private static boolean hasFinalizer(SootClass clazz) {
   // Don't search interfaces or java.lang.Object
   if (clazz.isInterface() || !clazz.hasSuperclass()) {
     return false;
   }
   return clazz.declaresMethod("finalize", Collections.emptyList(), VoidType.v());
 }
  /**
   * 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;
      }
    }
  }
Example #5
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();
  }
Example #6
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
  }
  public ASTMethodNode inline(SootMethod maybeInline) {
    // check if this method should be inlined

    if (sootClass != null) {
      // 1, method should belong to the same class as the clinit method
      if (sootClass.declaresMethod(maybeInline.getSubSignature())) {
        // System.out.println("The method invoked is from the same class");
        // 2, method should be static

        if (Modifier.isStatic(maybeInline.getModifiers())) {
          // decided to inline
          // send the ASTMethod node of the TO BE INLINED METHOD

          // retireve the active body
          if (!maybeInline.hasActiveBody())
            throw new RuntimeException("method " + maybeInline.getName() + " has no active body!");

          Body bod = maybeInline.getActiveBody();

          Chain units = ((DavaBody) bod).getUnits();

          if (units.size() != 1) {
            throw new RuntimeException("DavaBody AST doesn't have single root.");
          }

          ASTNode ASTtemp = (ASTNode) units.getFirst();
          if (!(ASTtemp instanceof ASTMethodNode))
            throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");

          // restricting to methods which do not have any variables declared
          ASTMethodNode toReturn = (ASTMethodNode) ASTtemp;

          ASTStatementSequenceNode declarations = toReturn.getDeclarations();
          if (declarations.getStatements().size() == 0) {
            // inline only if there are no declarations in the method inlined
            System.out.println("No declarations in the method. we can inline this method");
            return toReturn;
          }
        }
      }
    }
    return null; // meaning dont inline
  }
Example #8
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();
  }
Example #9
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 Value mutate(Value value) {
   if (value instanceof FieldRef) {
     FieldRef ref = (FieldRef) value;
     SootField field = ref.getField();
     Type type = field.getType();
     if (type instanceof RefType) {
       RefType ref_type = (RefType) type;
       SootClass soot_class = ref_type.getSootClass();
       if (shouldMap(soot_class)) {
         addField(field, ref);
       }
     } else if (type instanceof ArrayType) {
       ArrayType array_type = (ArrayType) type;
       Type base_type = array_type.baseType;
       if (base_type instanceof RefType) {
         RefType ref_type = (RefType) base_type;
         SootClass soot_class = ref_type.getSootClass();
         if (shouldMap(soot_class)) {
           addField(field, ref);
         }
       }
     }
     SootClass soot_class = field.getDeclaringClass();
     if (shouldMap(soot_class)) {
       addField(field, ref);
     }
     return value;
   } else if (value instanceof InvokeExpr) {
     InvokeExpr expr = (InvokeExpr) value;
     SootMethodRef ref = expr.getMethodRef();
     SootClass soot_class = ref.declaringClass();
     final NumberedString subSignature = ref.getSubSignature();
     if (shouldMap(soot_class)) {
       SootClass new_class = getMapping(soot_class);
       if (new_class.declaresMethod(subSignature)) {
         SootMethod new_method = RootbeerScene.v().getMethod(new_class, subSignature.getString());
         addAddedMethod(new_method);
         fixArguments(new_method);
         RootbeerScene.v().getDfsInfo().addReachableMethodSig(new_method.getSignature());
         expr.setMethodRef(new_method.makeRef());
       }
     } else {
       if (soot_class.declaresMethod(ref.getSubSignature())) {
         SootMethod method = soot_class.getMethod(ref.getSubSignature());
         fixArguments(method);
       }
     }
     ref = remapRef(ref);
     try {
       if (shouldMap(soot_class)) {
         soot_class = getMapping(soot_class);
       }
       SootMethod method = soot_class.getMethod(ref.getSubSignature());
       RootbeerScene.v().getDfsInfo().addReachableMethodSig(method.getSignature());
       expr.setMethodRef(method.makeRef());
     } catch (Exception ex) {
       // ex.printStackTrace();
     }
     return value;
   } else if (value instanceof NewExpr) {
     NewExpr expr = (NewExpr) value;
     RefType base_type = expr.getBaseType();
     SootClass soot_class = base_type.getSootClass();
     if (shouldMap(soot_class)) {
       SootClass new_class = getMapping(soot_class);
       expr.setBaseType(new_class.getType());
     }
     return value;
   } else if (value instanceof NewArrayExpr) {
     NewArrayExpr expr = (NewArrayExpr) value;
     Type base_type = expr.getBaseType();
     base_type = fixType(base_type);
     expr.setBaseType(base_type);
     return value;
   } else if (value instanceof NewMultiArrayExpr) {
     NewMultiArrayExpr expr = (NewMultiArrayExpr) value;
     ArrayType array_type = expr.getBaseType();
     Type base_type = array_type.baseType;
     if (base_type instanceof RefType) {
       RefType ref_type = (RefType) base_type;
       SootClass soot_class = ref_type.getSootClass();
       if (shouldMap(soot_class)) {
         SootClass new_class = getMapping(soot_class);
         ArrayType new_type = ArrayType.v(new_class.getType(), array_type.numDimensions);
         expr.setBaseType(new_type);
       }
     }
     return value;
   } else if (value instanceof CastExpr) {
     CastExpr expr = (CastExpr) value;
     Type cast_type = expr.getCastType();
     cast_type = fixType(cast_type);
     expr.setCastType(cast_type);
     return value;
   } else if (value instanceof ParameterRef) {
     ParameterRef ref = (ParameterRef) value;
     Type new_type = fixType(ref.getType());
     return new ParameterRef(new_type, ref.getIndex());
   } else if (value instanceof ThisRef) {
     ThisRef ref = (ThisRef) value;
     Type new_type = fixType(ref.getType());
     return new ThisRef((RefType) new_type);
   } else if (value instanceof Local) {
     Local local = (Local) value;
     Type type = local.getType();
     local.setType(fixType(type));
     return value;
   } else {
     return value;
   }
 }