private Type getReturnType(String anno, SootMethod method) { soot.Type sootType = method.getReturnType(); if (hasPointerAnnotation(method)) { if (!sootType.equals(LongType.v())) { throw new IllegalArgumentException( anno + " annotated method " + method + " must return long when annotated with @Pointer"); } return I8_PTR; } if (hasMachineSizedFloatAnnotation(method)) { if (!sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) { throw new IllegalArgumentException( anno + " annotated method " + method + " must return float or double when annotated with @MachineSizedFloat"); } return config.getArch().is32Bit() ? FLOAT : DOUBLE; } if (hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method)) { if (!sootType.equals(LongType.v())) { throw new IllegalArgumentException( anno + " annotated method " + method + " must return long when annotated with @MachineSizedSInt or @MachineSizedUInt"); } return config.getArch().is32Bit() ? I32 : I64; } if (isStruct(sootType)) { if (!isPassByValue(method)) { // Structs are returned by reference by default return new PointerType(getStructType(sootType)); } return getStructType(sootType); } else if (isNativeObject(sootType)) { // NativeObjects are always returned by reference. return I8_PTR; } else if (sootType instanceof PrimType || sootType == VoidType.v()) { return getType(sootType); } MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method)); if (marshalerMethod instanceof ValueMarshalerMethod) { return ((ValueMarshalerMethod) marshalerMethod).getNativeType(config.getArch()); } else { return I8_PTR; } }
protected Value marshalPrimitiveToNative(Function fn, SootMethod method, Value value) { soot.Type type = method.getReturnType(); if (hasPointerAnnotation(method)) { value = marshalLongToPointer(fn, value); } else if (hasMachineSizedFloatAnnotation(method) && type.equals(DoubleType.v())) { value = marshalDoubleToMachineSizedFloat(fn, value); } else if (hasMachineSizedFloatAnnotation(method) && type.equals(FloatType.v())) { value = marshalFloatToMachineSizedFloat(fn, value); } else if (hasMachineSizedSIntAnnotation(method) && type.equals(LongType.v())) { value = marshalLongToMachineSizedInt(fn, value); } else if (hasMachineSizedUIntAnnotation(method) && type.equals(LongType.v())) { value = marshalLongToMachineSizedInt(fn, value); } return value; }
private static int getFieldAlignment(SootField f) { soot.Type t = f.getType(); if (LongType.v().equals(t) && Modifier.isVolatile(f.getModifiers())) { // On ARM volatile longs must be 8 byte aligned return 8; } if (LongType.v().equals(t) && !f.isStatic() && Modifier.isFinal(f.getModifiers())) { // The Java Memory Model requires final instance fields to be written to using // volatile semantics. Because of ARM's alignment requirements we return 8 here too. return 8; } if (LongType.v().equals(t) || DoubleType.v().equals(t)) { return 4; } return getFieldSize(f); }
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 marshalNativeToPrimitive( Function fn, SootMethod method, int paramIndex, Value value) { soot.Type type = method.getParameterType(paramIndex); if (hasPointerAnnotation(method, paramIndex)) { value = marshalPointerToLong(fn, value); } else if (hasMachineSizedFloatAnnotation(method, paramIndex) && type.equals(DoubleType.v())) { value = marshalMachineSizedFloatToDouble(fn, value); } else if (hasMachineSizedFloatAnnotation(method, paramIndex) && type.equals(FloatType.v())) { value = marshalMachineSizedFloatToFloat(fn, value); } else if (hasMachineSizedSIntAnnotation(method, paramIndex) && type.equals(LongType.v())) { value = marshalMachineSizedSIntToLong(fn, value); } else if (hasMachineSizedUIntAnnotation(method, paramIndex) && type.equals(LongType.v())) { value = marshalMachineSizedUIntToLong(fn, value); } return value; }
public static String getDescriptor(soot.Type t) { if (t instanceof PrimType) { if (t.equals(BooleanType.v())) { return "Z"; } else if (t.equals(ByteType.v())) { return "B"; } else if (t.equals(ShortType.v())) { return "S"; } else if (t.equals(CharType.v())) { return "C"; } else if (t.equals(IntType.v())) { return "I"; } else if (t.equals(LongType.v())) { return "J"; } else if (t.equals(FloatType.v())) { return "F"; } else { // DoubleType return "D"; } } else if (t.equals(VoidType.v())) { return "V"; } else if (t instanceof soot.ArrayType) { soot.ArrayType at = (soot.ArrayType) t; return "[" + getDescriptor(at.getElementType()); } else { // RefType RefType rt = (RefType) t; return "L" + rt.getClassName().replace('.', '/') + ";"; } }
public static Type getType(soot.Type sootType) { if (sootType.equals(soot.BooleanType.v())) { return Type.I8; } else if (sootType.equals(soot.ByteType.v())) { return Type.I8; } else if (sootType.equals(soot.ShortType.v())) { return Type.I16; } else if (sootType.equals(soot.CharType.v())) { return Type.I16; } else if (sootType.equals(soot.IntType.v())) { return Type.I32; } else if (sootType.equals(soot.LongType.v())) { return Type.I64; } else if (sootType.equals(soot.FloatType.v())) { return Type.FLOAT; } else if (sootType.equals(soot.DoubleType.v())) { return Type.DOUBLE; } else if (sootType.equals(soot.VoidType.v())) { return Type.VOID; } else if (sootType instanceof soot.RefLikeType || sootType.equals(BottomType.v())) { return OBJECT_PTR; } else { throw new IllegalArgumentException("Unknown Type: " + sootType); } }
public static int getFieldSize(Arch arch, SootField f) { soot.Type t = f.getType(); if (LongType.v().equals(t) || DoubleType.v().equals(t)) { return 8; } if (IntType.v().equals(t) || FloatType.v().equals(t)) { return 4; } if (t instanceof RefLikeType) { return arch.is32Bit() ? 4 : 8; } if (ShortType.v().equals(t) || CharType.v().equals(t)) { return 2; } if (ByteType.v().equals(t) || BooleanType.v().equals(t)) { return 1; } throw new IllegalArgumentException("Unknown Type: " + t); }
private static int getFieldSize(SootField f) { soot.Type t = f.getType(); if (LongType.v().equals(t) || DoubleType.v().equals(t)) { return 8; } if (IntType.v().equals(t) || FloatType.v().equals(t)) { return 4; } if (t instanceof RefLikeType) { // Assume pointers are 32-bit return 4; } if (ShortType.v().equals(t) || CharType.v().equals(t)) { return 2; } if (ByteType.v().equals(t) || BooleanType.v().equals(t)) { return 1; } throw new IllegalArgumentException("Unknown Type: " + t); }
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; }
public void outALongBaseType(ALongBaseType node) { mProductions.addLast(LongType.v()); }
protected void readRefField(OpenCLField ref_field) { SootField soot_field = ref_field.getSootField(); SootClass soot_class = Scene.v().getSootClass(soot_field.getDeclaringClass().getName()); BytecodeLanguage bcl = m_bcl.top(); Local gc_obj_visit = m_gcObjVisitor.top(); BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top()); Local ref = bcl_mem.readRef(); bcl_mem.useInstancePointer(); bcl_mem.pushAddress(); bcl_mem.setAddress(ref); // bcl.println("reading field: "+ref_field.getName()); SootClass obj_class = Scene.v().getSootClass("java.lang.Object"); SootClass string = Scene.v().getSootClass("java.lang.String"); SootClass class_class = Scene.v().getSootClass("java.lang.Class"); Local original_field_value; if (soot_class.isApplicationClass() == false) { if (ref_field.isInstance()) { bcl.pushMethod( gc_obj_visit, "readField", obj_class.getType(), obj_class.getType(), string.getType()); original_field_value = bcl.invokeMethodRet( gc_obj_visit, m_objSerializing.top(), StringConstant.v(soot_field.getName())); } else { bcl.pushMethod( gc_obj_visit, "readStaticField", obj_class.getType(), class_class.getType(), string.getType()); Local cls = bcl.classConstant(soot_field.getDeclaringClass().getType()); original_field_value = bcl.invokeMethodRet(gc_obj_visit, cls, StringConstant.v(soot_field.getName())); } } else { if (ref_field.isInstance()) { original_field_value = bcl.refInstanceField(m_objSerializing.top(), ref_field.getName()); } else { original_field_value = bcl.refStaticField(soot_class.getType(), ref_field.getName()); } } bcl.pushMethod( gc_obj_visit, "readFromHeap", obj_class.getType(), obj_class.getType(), BooleanType.v(), LongType.v()); int should_read = 1; Local ret_obj = bcl.invokeMethodRet(gc_obj_visit, original_field_value, IntConstant.v(should_read), ref); Type type = soot_field.getType(); Local ret = bcl.cast(type, ret_obj); if (soot_class.isApplicationClass() == false) { if (ref_field.isInstance()) { bcl.pushMethod( gc_obj_visit, "writeField", VoidType.v(), obj_class.getType(), string.getType(), obj_class.getType()); bcl.invokeMethodNoRet( gc_obj_visit, m_objSerializing.top(), StringConstant.v(soot_field.getName()), ret); } else { bcl.pushMethod( gc_obj_visit, "writeStaticField", VoidType.v(), class_class.getType(), string.getType(), obj_class.getType()); Local cls = bcl.classConstant(soot_field.getDeclaringClass().getType()); bcl.invokeMethodNoRet(gc_obj_visit, cls, StringConstant.v(soot_field.getName()), ret); } } else { if (ref_field.isInstance()) { bcl.setInstanceField(soot_field, m_objSerializing.top(), ret); } else { bcl.setStaticField(soot_field, ret); } } bcl_mem.popAddress(); }
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(); }
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); }
private Type getParameterType(String anno, SootMethod method, int i) { soot.Type sootType = method.getParameterType(i); if (hasPointerAnnotation(method, i)) { if (!sootType.equals(LongType.v())) { throw new IllegalArgumentException( "Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be of type long when annotated with @Pointer."); } return I8_PTR; } if (hasMachineSizedFloatAnnotation(method, i)) { if (!sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) { throw new IllegalArgumentException( "Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be of type float or double when annotated with @MachineSizedFloat."); } return config.getArch().is32Bit() ? FLOAT : DOUBLE; } if (hasMachineSizedSIntAnnotation(method, i) || hasMachineSizedUIntAnnotation(method, i)) { if (!sootType.equals(LongType.v())) { throw new IllegalArgumentException( "Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be of type long when annotated with " + "@MachineSizedSInt or @MachineSizedUInt"); } return config.getArch().is32Bit() ? I32 : I64; } if (hasStructRetAnnotation(method, i)) { if (i > 0) { throw new IllegalArgumentException( "Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " cannot be annotated with @StructRet. Only the first" + " parameter may have this annotation."); } if (!isStruct(sootType)) { throw new IllegalArgumentException( "Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be a sub class of Struct when annotated with @StructRet."); } // @StructRet implies pass by reference return new PointerType(getStructType(sootType)); } if (isStruct(sootType)) { StructureType structType = getStructType(sootType); if (hasByValAnnotation(method, i)) { return getStructType(sootType); } return new PointerType(structType); } else if (isNativeObject(sootType)) { // NativeObjects are always passed by reference. return I8_PTR; } else if (sootType instanceof PrimType) { return getType(sootType); } MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, i)); if (marshalerMethod instanceof ValueMarshalerMethod) { return ((ValueMarshalerMethod) marshalerMethod).getNativeType(config.getArch()); } else { return I8_PTR; } }