protected Value marshalObjectToNative(
      Function fn,
      MarshalerMethod marshalerMethod,
      MarshaledArg marshaledArg,
      Type nativeType,
      Value env,
      Value object,
      long flags) {

    Invokestatic invokestatic = marshalerMethod.getInvokeStatic(sootMethod.getDeclaringClass());
    trampolines.add(invokestatic);
    Value handle = call(fn, invokestatic.getFunctionRef(), env, object, new IntegerConstant(flags));

    Variable nativeValue = fn.newVariable(nativeType);
    if (nativeType instanceof StructureType || nativeType instanceof ArrayType) {
      Variable tmp = fn.newVariable(new PointerType(nativeType));
      fn.add(new Inttoptr(tmp, handle, tmp.getType()));
      fn.add(new Load(nativeValue, tmp.ref()));
    } else {
      fn.add(new Inttoptr(nativeValue, handle, nativeType));
    }

    if (marshaledArg != null) {
      marshaledArg.handle = handle;
      marshaledArg.object = object;
    }

    return nativeValue.ref();
  }
 private Function createAllocator() {
   Function fn = FunctionBuilder.allocator(sootClass);
   Value info = getInfoStruct(fn);
   Value result = call(fn, BC_ALLOCATE, fn.getParameterRef(0), info);
   fn.add(new Ret(result));
   return fn;
 }
 private Function createInstanceof() {
   Function fn = FunctionBuilder.instanceOf(sootClass);
   Value info = getInfoStruct(fn);
   Value result = call(fn, BC_INSTANCEOF, fn.getParameterRef(0), info, fn.getParameterRef(1));
   fn.add(new Ret(result));
   return fn;
 }
 private Function createCheckcast() {
   Function fn = FunctionBuilder.checkcast(sootClass);
   Value info = getInfoStruct(fn);
   Value result = call(fn, BC_CHECKCAST, fn.getParameterRef(0), info, fn.getParameterRef(1));
   fn.add(new Ret(result));
   return fn;
 }
  protected Value marshalNativeToArray(
      Function fn,
      MarshalerMethod marshalerMethod,
      Value env,
      String arrayClassName,
      Value nativeValue,
      long flags,
      int[] dimensions) {

    Invokestatic invokeToObject = marshalerMethod.getInvokeStatic(sootMethod.getDeclaringClass());
    trampolines.add(invokeToObject);

    Variable handle = fn.newVariable(I64);
    fn.add(new Ptrtoint(handle, nativeValue, I64));

    Value valueClass = ldcClass(fn, arrayClassName, env);
    List<Value> args = new ArrayList<>();
    args.add(env);
    args.add(valueClass);
    args.add(handle.ref());
    args.add(new IntegerConstant(flags));
    args.addAll(arrayDimensionsValues(dimensions));

    return call(fn, invokeToObject.getFunctionRef(), args);
  }
 private Function createLdcClassWrapper() {
   Function fn = FunctionBuilder.ldcExternal(sootClass);
   Value info = getInfoStruct(fn);
   Value result = call(fn, LDC_CLASS_WRAPPER, fn.getParameterRef(0), info);
   fn.add(new Ret(result));
   return fn;
 }
 protected Value marshalDoubleToMachineSizedFloat(Function fn, Value value) {
   if (config.getArch().is32Bit()) {
     Variable result = fn.newVariable(FLOAT);
     fn.add(new Fptrunc(result, value, FLOAT));
     return result.ref();
   } else {
     return value;
   }
 }
 protected Value marshalMachineSizedUIntToLong(Function fn, Value value) {
   if (config.getArch().is32Bit()) {
     Variable result = fn.newVariable(I64);
     fn.add(new Zext(result, value, I64));
     return result.ref();
   } else {
     return value;
   }
 }
 protected Value marshalFloatToMachineSizedFloat(Function fn, Value value) {
   if (!config.getArch().is32Bit()) {
     Variable result = fn.newVariable(DOUBLE);
     fn.add(new Fpext(result, value, DOUBLE));
     return result.ref();
   } else {
     return value;
   }
 }
 protected Value marshalLongToMachineSizedInt(Function fn, Value value) {
   if (config.getArch().is32Bit()) {
     Variable result = fn.newVariable(I32);
     fn.add(new Trunc(result, value, I32));
     return result.ref();
   } else {
     return value;
   }
 }
Exemple #11
0
 private Value getClassFieldPtr(Function f, SootField field) {
   Value info = getInfoStruct(f);
   Variable base = f.newVariable(I8_PTR);
   f.add(new Load(base, info));
   return getFieldPtr(
       f,
       new VariableRef(base),
       offsetof(classType, 1, classFields.indexOf(field), 1),
       getType(field.getType()));
 }
Exemple #12
0
 private Function createFieldSetter(SootField field) {
   Function fn = FunctionBuilder.setter(field);
   Value fieldPtr = null;
   Value value = null;
   if (field.isStatic()) {
     fieldPtr = getClassFieldPtr(fn, field);
     value = fn.getParameterRef(1);
   } else {
     fieldPtr = getInstanceFieldPtr(fn, fn.getParameterRef(1), field);
     value = fn.getParameterRef(2);
   }
   if (Modifier.isVolatile(field.getModifiers())
       || !field.isStatic() && Modifier.isFinal(field.getModifiers())) {
     if (LongType.v().equals(field.getType())) {
       fn.add(new Store(value, fieldPtr, false, Ordering.unordered, 8));
     } else {
       fn.add(new Store(value, fieldPtr));
     }
     fn.add(new Fence(Ordering.seq_cst));
   } else {
     fn.add(new Store(value, fieldPtr));
   }
   fn.add(new Ret());
   return fn;
 }
 protected Value ldcClass(Function fn, String name, Value env) {
   if (isArray(name) && isPrimitiveBaseType(name)) {
     String primitiveDesc = name.substring(name.length() - 1);
     Variable result = fn.newVariable(OBJECT_PTR);
     fn.add(
         new Load(
             result,
             new ConstantBitcast(
                 new GlobalRef("array_" + primitiveDesc, CLASS_PTR),
                 new PointerType(OBJECT_PTR))));
     return result.ref();
   } else {
     FunctionRef ldcClassFn = null;
     if (name.equals(this.className)) {
       ldcClassFn = FunctionBuilder.ldcInternal(this.className).ref();
     } else {
       Trampoline trampoline = new LdcClass(this.className, name);
       trampolines.add(trampoline);
       ldcClassFn = trampoline.getFunctionRef();
     }
     return call(fn, ldcClassFn, env);
   }
 }
  protected Value marshalNativeToObject(
      Function fn,
      MarshalerMethod marshalerMethod,
      MarshaledArg marshaledArg,
      Value env,
      String valueClassName,
      Value nativeValue,
      long flags) {

    if (nativeValue.getType() instanceof StructureType) {
      nativeValue = createStackCopy(fn, nativeValue);
    }

    Invokestatic invokestatic = marshalerMethod.getInvokeStatic(sootMethod.getDeclaringClass());
    trampolines.add(invokestatic);

    Value valueClass = ldcClass(fn, valueClassName, env);

    Variable handle = fn.newVariable(I64);
    fn.add(new Ptrtoint(handle, nativeValue, I64));

    Value object =
        call(
            fn,
            invokestatic.getFunctionRef(),
            env,
            valueClass,
            handle.ref(),
            new IntegerConstant(flags));

    if (marshaledArg != null) {
      marshaledArg.handle = handle.ref();
      marshaledArg.object = object;
    }

    return object;
  }
Exemple #15
0
 public static Value getFieldPtr(Function f, Value base, Constant offset, Type fieldType) {
   Variable baseI8Ptr = f.newVariable(I8_PTR);
   f.add(new Bitcast(baseI8Ptr, base, I8_PTR));
   Variable fieldI8Ptr = f.newVariable(I8_PTR);
   f.add(new Getelementptr(fieldI8Ptr, baseI8Ptr.ref(), offset));
   Variable fieldPtr = f.newVariable(new PointerType(fieldType));
   f.add(new Bitcast(fieldPtr, fieldI8Ptr.ref(), fieldPtr.getType()));
   return fieldPtr.ref();
 }
  protected void marshalArrayToNative(
      Function fn,
      MarshalerMethod marshalerMethod,
      Value env,
      Value object,
      Value destPtr,
      long flags,
      int[] dimensions) {

    Invokestatic invokestatic = marshalerMethod.getInvokeStatic(sootMethod.getDeclaringClass());
    trampolines.add(invokestatic);

    Variable handle = fn.newVariable(I64);
    fn.add(new Ptrtoint(handle, destPtr, I64));

    List<Value> args = new ArrayList<>();
    args.add(env);
    args.add(object);
    args.add(handle.ref());
    args.add(new IntegerConstant(flags));
    args.addAll(arrayDimensionsValues(dimensions));

    call(fn, invokestatic.getFunctionRef(), args);
  }
  protected void storeValueForSetter(
      SootMethod method,
      Function function,
      Type memberType,
      Value memberPtr,
      Value env,
      Value value,
      long flags) {

    soot.Type type = method.getParameterType(0);
    if (needsMarshaler(type)) {
      MarshalerMethod marshalerMethod =
          config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, 0));

      if (memberType instanceof PrimitiveType) {
        value =
            marshalValueObjectToNative(function, marshalerMethod, memberType, env, value, flags);
      } else {
        if (memberType instanceof StructureType || memberType instanceof ArrayType) {
          // The parameter must not be null. We assume that Structs
          // never have a NULL handle so we just check that the Java
          // Object isn't null.
          call(function, CHECK_NULL, env, value);
        }

        if (memberType instanceof ArrayType) {
          // Array
          marshalArrayToNative(
              function,
              marshalerMethod,
              env,
              value,
              memberPtr,
              flags,
              getArrayDimensions(method, 0));
          value = null;
        } else {
          value =
              marshalObjectToNative(function, marshalerMethod, null, memberType, env, value, flags);
        }
      }
    } else {
      value = marshalPrimitiveToNative(function, method, 0, value);
    }
    if (value != null) {
      function.add(new Store(value, memberPtr));
    }
  }
Exemple #18
0
 private Function createFieldGetter(SootField field) {
   Function fn = FunctionBuilder.getter(field);
   Value fieldPtr = null;
   if (field.isStatic()) {
     fieldPtr = getClassFieldPtr(fn, field);
   } else {
     fieldPtr = getInstanceFieldPtr(fn, fn.getParameterRef(1), field);
   }
   Variable result = fn.newVariable(getType(field.getType()));
   if (Modifier.isVolatile(field.getModifiers())) {
     fn.add(new Fence(Ordering.seq_cst));
     if (LongType.v().equals(field.getType())) {
       fn.add(new Load(result, fieldPtr, false, Ordering.unordered, 8));
     } else {
       fn.add(new Load(result, fieldPtr));
     }
   } else {
     fn.add(new Load(result, fieldPtr));
   }
   fn.add(new Ret(new VariableRef(result)));
   return fn;
 }
 protected Value createStackCopy(Function fn, Value value) {
   Variable stackCopy = fn.newVariable(new PointerType(value.getType()));
   fn.add(new Alloca(stackCopy, value.getType()));
   fn.add(new Store(value, stackCopy.ref()));
   return stackCopy.ref();
 }
 protected Value marshalPointerToLong(Function fn, Value pointer) {
   Variable result = fn.newVariable(I64);
   fn.add(new Ptrtoint(result, pointer, I64));
   return result.ref();
 }
Exemple #21
0
  private void createLookupFunction(SootMethod m) {
    // TODO: This should use a virtual method table or interface method table.
    Function function = FunctionBuilder.lookup(m);
    mb.addFunction(function);

    Variable reserved0 = function.newVariable(I8_PTR_PTR);
    function.add(new Getelementptr(reserved0, function.getParameterRef(0), 0, 4));
    Variable reserved1 = function.newVariable(I8_PTR_PTR);
    function.add(new Getelementptr(reserved1, function.getParameterRef(0), 0, 5));
    function.add(new Store(getString(m.getName()), reserved0.ref()));
    function.add(new Store(getString(getDescriptor(m)), reserved1.ref()));

    Value lookupFn =
        sootClass.isInterface() ? BC_LOOKUP_INTERFACE_METHOD : BC_LOOKUP_VIRTUAL_METHOD;
    List<Value> args = new ArrayList<Value>();
    args.add(function.getParameterRef(0));
    if (sootClass.isInterface()) {
      Value info = getInfoStruct(function);
      args.add(info);
    }
    args.add(function.getParameterRef(1));
    args.add(getString(m.getName()));
    args.add(getString(getDescriptor(m)));
    Value fptr = call(function, lookupFn, args);
    Variable f = function.newVariable(function.getType());
    function.add(new Bitcast(f, fptr, f.getType()));
    Value result = call(function, f.ref(), function.getParameterRefs());
    function.add(new Ret(result));
  }
Exemple #22
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();
  }
 protected Value marshalLongToPointer(Function fn, Value handle) {
   Variable result = fn.newVariable(I8_PTR);
   fn.add(new Inttoptr(result, handle, I8_PTR));
   return result.ref();
 }
Exemple #24
0
 private Function createClassInitWrapperFunction(FunctionRef targetFn) {
   Function fn = FunctionBuilder.clinitWrapper(targetFn);
   Value info = getInfoStruct(fn);
   Variable infoHeader = fn.newVariable(new PointerType(new StructureType(I8_PTR, I32)));
   fn.add(new Bitcast(infoHeader, info, infoHeader.getType()));
   Variable infoHeaderFlags = fn.newVariable(new PointerType(I32));
   fn.add(new Getelementptr(infoHeaderFlags, infoHeader.ref(), 0, 1));
   Variable flags = fn.newVariable(I32);
   fn.add(new Load(flags, infoHeaderFlags.ref()));
   Variable initializedFlag = fn.newVariable(I32);
   fn.add(new And(initializedFlag, flags.ref(), new IntegerConstant(CI_INITIALIZED)));
   Variable initialized = fn.newVariable(I1);
   fn.add(
       new Icmp(
           initialized,
           Icmp.Condition.eq,
           initializedFlag.ref(),
           new IntegerConstant(CI_INITIALIZED)));
   Label trueLabel = new Label();
   Label falseLabel = new Label();
   fn.add(
       new Br(initialized.ref(), fn.newBasicBlockRef(trueLabel), fn.newBasicBlockRef(falseLabel)));
   fn.newBasicBlock(trueLabel);
   Value result = call(fn, targetFn, fn.getParameterRefs());
   fn.add(new Ret(result));
   fn.newBasicBlock(falseLabel);
   call(fn, BC_INITIALIZE_CLASS, fn.getParameterRef(0), info);
   fn.add(new Br(fn.newBasicBlockRef(trueLabel)));
   return fn;
 }
  protected Value loadValueForGetter(
      SootMethod method,
      Function fn,
      Type memberType,
      Value memberPtr,
      Value env,
      boolean dereference,
      long flags) {

    soot.Type type = method.getReturnType();

    Value result = null;
    if (memberType instanceof StructureType) {
      // The member is a child struct contained in the current struct
      result = memberPtr;
    } else if (memberType instanceof ArrayType) {
      // The member is an array contained in the current struct
      result = memberPtr;
    } else if (dereference) {
      Variable tmp = fn.newVariable(memberType);
      fn.add(new Load(tmp, memberPtr));
      result = tmp.ref();
    } else {
      // Do not dereference the pointer but use it as is. This is needed for
      // global values such as _dispatch_main_q which is a struct and not a
      // pointer which we should load. We want the address of the struct.
      Variable tmp = fn.newVariable(memberType);
      fn.add(new Bitcast(tmp, memberPtr, tmp.getType()));
      result = tmp.ref();
    }

    if (needsMarshaler(type)) {
      MarshalerMethod marshalerMethod =
          config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
      String targetClassName = getInternalName(type);

      if (memberType instanceof PrimitiveType) {
        // Value type wrapping a primitive value (e.g. Enum, Integer and Bits)
        result =
            marshalNativeToValueObject(fn, marshalerMethod, env, targetClassName, result, flags);
      } else {
        if (memberType instanceof ArrayType) {
          // Array
          result =
              marshalNativeToArray(
                  fn,
                  marshalerMethod,
                  env,
                  targetClassName,
                  result,
                  flags,
                  getArrayDimensions(method));
        } else {
          result =
              marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, result, flags);
        }
      }
    } else {
      result = marshalNativeToPrimitive(fn, method, result);
    }
    return result;
  }