private boolean needDoubleMod(BinopExpr arg0, String symbol) { if (symbol.equals("%") == false) return false; if (!arg0.getOp1().getType().equals(DoubleType.v()) && !arg0.getOp1().getType().equals(FloatType.v())) return false; if (!arg0.getOp2().getType().equals(DoubleType.v()) && !arg0.getOp2().getType().equals(FloatType.v())) return false; return true; }
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); } }
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); }
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 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); }
public void outADoubleBaseType(ADoubleBaseType node) { mProductions.addLast(DoubleType.v()); }
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; } }