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 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 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)); }
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 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); }
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; } }
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())); }
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 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; }
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 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(); }
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; }
protected Value marshalLongToPointer(Function fn, Value handle) { Variable result = fn.newVariable(I8_PTR); fn.add(new Inttoptr(result, handle, I8_PTR)); return result.ref(); }