/**
   * Clone given method into this class with given name. Update necessary state of prior analyses.
   */
  private SootMethod cloneMethod(SootMethod ancestorM, String cloneName) {
    // check if we are cloning a method multiple times
    if (clonedToOriginal.containsValue(ancestorM)) {
      logger.error("Cloning method twice: {}", ancestorM);
      droidsafe.main.Main.exit(1);
    }

    SootMethod newMeth =
        new SootMethod(
            cloneName,
            ancestorM.getParameterTypes(),
            ancestorM.getReturnType(),
            ancestorM.getModifiers(),
            ancestorM.getExceptions());

    // System.out.printf("\tAdding method %s.\n", ancestorM);
    // register method
    methods.addMethod(newMeth);
    clazz.addMethod(newMeth);

    clonedToOriginal.put(newMeth, ancestorM);

    API.v().cloneMethodClassifications(ancestorM, newMeth);

    // clone body
    Body newBody = (Body) ancestorM.retrieveActiveBody().clone();
    newMeth.setActiveBody(newBody);

    JSAStrings.v().updateJSAResults(ancestorM.retrieveActiveBody(), newBody);

    return newMeth;
  }
Beispiel #2
0
  public static SootMethod mockSootMethod(
      String clsName, String methodSubSignature, boolean isStatic) {
    SootClass sc = mockSootClass(clsName);

    SootMethod sm = null;

    try {
      sm = sc.getMethod(methodSubSignature);
    } catch (Exception ex) {
      sm = null;
    }

    if (null == sm) {
      int m = Modifier.PUBLIC;
      if (isStatic) {
        m = m | Modifier.STATIC;
      }

      List<Type> paramTypes = new ArrayList<Type>();
      paramTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1));

      String[] strs = methodSubSignature.split(" ");
      String methodName = strs[1].trim().substring(0, strs[1].trim().indexOf("("));

      if (null == methodName || methodName.isEmpty()) {
        return null;
      }

      sm = new SootMethod(methodName, paramTypes, RefType.v("java.lang.Object"), m);
      sc.addMethod(sm);

      // Add body of sm
      JimpleBody b = Jimple.v().newBody(sm);
      sm.setActiveBody(b);
      // LocalGenerator lg = new LocalGenerator(b);
      {
        b.insertIdentityStmts();

        // Local rtLoc = lg.generateLocal(RefType.v("java.lang.Object"));

        // Local param0 = lg.generateLocal(ArrayType.v(RefType.v("java.lang.Object"), 1));
        // Unit param0U = Jimple.v().newIdentityStmt(rtLoc,
        // Jimple.v().newParameterRef(ArrayType.v(RefType.v("java.lang.Object"), 1), 0));

        // Unit rtLocAssignU = Jimple.v().newAssignStmt(rtLoc, param0);

        Unit returnU = Jimple.v().newReturnStmt(b.getParameterLocal(0));

        // b.getUnits().add(param0U);
        b.getUnits().add(returnU);
      }

      System.out.println("validation:" + b);
      b.validate();
    }

    return sm;
  }
  public static SootMethod createSootMethod(
      SootClass sootClass, String name, List<Type> paramTypes, Type returnType, boolean isStatic) {
    int modifier = Modifier.PUBLIC;

    if (isStatic) {
      modifier = modifier | Modifier.STATIC;
    }

    SootMethod sootMethod = new SootMethod(name, paramTypes, returnType, modifier);
    sootClass.addMethod(sootMethod);

    Body body = Jimple.v().newBody(sootMethod);
    sootMethod.setActiveBody(body);

    return sootMethod;
  }
Beispiel #4
0
  /** Conveniently create a class deriving from Code.testClass */
  public Pair<SootClass, SignatureTable<Level>> makeDerivedClass(
      String name, SootClass superClass, List<MethodWithSignature<Level>> methods) {
    SootClass result = makeFreshClass(name);
    result.setSuperclass(superClass);
    SignatureTable<Level> newSignatures = this.signatures;
    for (MethodWithSignature<Level> m : methods) {
      result.addMethod(m.method);
      newSignatures =
          newSignatures.extendWith(
              m.method,
              Interop.asJavaStream(m.signature.constraints.stream()).collect(Collectors.toList()),
              m.signature.effects);
    }

    return Pair.of(result, newSignatures);
  }
Beispiel #5
0
  public void outAMethodMember(AMethodMember node) {
    int modifier = 0;
    Type type;
    String name;
    List parameterList = null;
    List throwsClause = null;
    JimpleBody methodBody = null;

    if (node.getMethodBody() instanceof AFullMethodBody)
      methodBody = (JimpleBody) mProductions.removeLast();

    if (node.getThrowsClause() != null) throwsClause = (List) mProductions.removeLast();

    if (node.getParameterList() != null) {
      parameterList = (List) mProductions.removeLast();
    } else {
      parameterList = new ArrayList();
    }

    Object o = mProductions.removeLast();

    name = (String) o;
    type = (Type) mProductions.removeLast();
    modifier = processModifiers(node.getModifier());

    SootMethod method;

    if (throwsClause != null)
      method = new SootMethod(name, parameterList, type, modifier, throwsClause);
    else method = new SootMethod(name, parameterList, type, modifier);

    mSootClass.addMethod(method);

    if (method.isConcrete()) {
      methodBody.setMethod(method);
      method.setActiveBody(methodBody);

    } else if (node.getMethodBody() instanceof AFullMethodBody)
      throw new RuntimeException("Impossible: !concrete => ! instanceof");
  }
Beispiel #6
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();
  }
Beispiel #7
0
  public static void mockConstructor(SootClass sc) {
    SootMethod sm = null;

    // Without parameters
    String methodSubSignature = "void <init>()";

    try {
      sm = sc.getMethod(methodSubSignature);
    } catch (Exception ex) {
      sm = null;
    }

    int m = Modifier.PUBLIC;

    if (null == sm) {
      sm = new SootMethod("<init>", new ArrayList<Type>(), VoidType.v(), m);
      sc.addMethod(sm);

      // Add body
      JimpleBody b = Jimple.v().newBody(sm);
      sm.setActiveBody(b);
      {
        b.insertIdentityStmts();
        b.getUnits().add(Jimple.v().newReturnVoidStmt());
      }

      System.out.println("validation:" + b);
      b.validate();
    }

    // Static init
    /*
    methodSubSignature = "void <clinit>()";

    try
    {
    	sm = sc.getMethod(methodSubSignature);
    }
    catch (Exception ex)
    {
    	sm = null;
    }

    if (null == sm)
    {
    	sm = new SootMethod("<clinit>", new ArrayList<Type>(), VoidType.v(), m | Modifier.STATIC);
    	sc.addMethod(sm);

    	//Add body
    	JimpleBody b = Jimple.v().newBody(sm);
           sm.setActiveBody(b);
    	{
    		b.getUnits().add(Jimple.v().newReturnVoidStmt());
    	}

    	b.validate();
    	System.out.println("validation:" + b);
    }
    */

    // With parameter
    methodSubSignature = "void <init>(java.lang.Object[])";

    try {
      sm = sc.getMethod(methodSubSignature);
    } catch (Exception ex) {
      sm = null;
    }

    if (null == sm) {
      List<Type> paramTypes = new ArrayList<Type>();
      paramTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1));

      sm = new SootMethod("<init>", paramTypes, VoidType.v(), m);
      sc.addMethod(sm);

      // Add body
      JimpleBody b = Jimple.v().newBody(sm);
      sm.setActiveBody(b);
      // LocalGenerator lg = new LocalGenerator(b);
      {
        b.insertIdentityStmts();

        // Local rtLoc = lg.generateLocal(RefType.v("java.lang.Object"));
        // Local param0Loc = lg.generateLocal(ArrayType.v(RefType.v("java.lang.Object"), 1));
        // Unit param0U = Jimple.v().newIdentityStmt(rtLoc,
        // Jimple.v().newParameterRef(ArrayType.v(RefType.v("java.lang.Object"), 1), 0));
        // Unit assignU = Jimple.v().newAssignStmt(rtLoc, Jimple.v().newCastExpr(param0Loc,
        // RefType.v("java.lang.Object")));
        // b.getUnits().add(param0U);
        // b.getUnits().add(assignU);
        b.getUnits().add(Jimple.v().newReturnVoidStmt());
      }

      System.out.println("validation:" + b);
      b.validate();
    }
  }