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('.', '/') + ";"; } }
private static boolean hasFinalizer(SootClass clazz) { // Don't search interfaces or java.lang.Object if (clazz.isInterface() || !clazz.hasSuperclass()) { return false; } return clazz.declaresMethod("finalize", Collections.emptyList(), VoidType.v()); }
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; } }
private Type signatureToType(String desc) { String rawDesc = desc.replaceAll("<.*>", ""); String internalName = rawDesc.replaceAll("^\\[*", ""); int dims = rawDesc.length() - internalName.length(); internalName = Types.getInternalNameFromDescriptor(internalName); soot.Type sootType = SootResolver.v().makeClassRef(internalName.replace('/', '.')).getType(); for (int i = 0; i < dims; i++) { sootType = sootType.makeArrayType(); } SootMethod m = new SootMethod("foo", Arrays.asList(sootType), VoidType.v()); m.addTag(new SignatureTag("(" + desc + ")V")); SootMethodType mType = new SootMethodType(m); return mType.getGenericParameterTypes()[0]; }
protected void readNonRefField(OpenCLField field) { SootField soot_field = field.getSootField(); String function_name = "read" + getTypeString(soot_field); BytecodeLanguage bcl = m_bcl.top(); bcl.pushMethod(m_currMem.top(), function_name, soot_field.getType()); Local data = bcl.invokeMethodRet(m_currMem.top()); SootClass soot_class = Scene.v().getSootClass(soot_field.getDeclaringClass().getName()); if (soot_class.isApplicationClass()) { if (field.isInstance()) { bcl.setInstanceField(soot_field, m_objSerializing.top(), data); } else { bcl.setStaticField(soot_field, data); } } else { SootClass obj = Scene.v().getSootClass("java.lang.Object"); SootClass string = Scene.v().getSootClass("java.lang.String"); String static_str; SootClass first_param_type; Value first_param; if (field.isInstance()) { static_str = ""; first_param_type = obj; first_param = m_objSerializing.top(); } else { static_str = "Static"; first_param_type = Scene.v().getSootClass("java.lang.Class"); first_param = ClassConstant.v(soot_class.getName()); } String private_field_fun_name = "write" + static_str + getTypeString(soot_field); Local private_fields = bcl.newInstance("org.trifort.rootbeer.runtime.PrivateFields"); bcl.pushMethod( private_fields, private_field_fun_name, VoidType.v(), first_param_type.getType(), string.getType(), string.getType(), soot_field.getType()); bcl.invokeMethodNoRet( private_fields, first_param, StringConstant.v(soot_field.getName()), StringConstant.v(soot_field.getDeclaringClass().getName()), data); } }
protected SootMethod createFakeStructRetMethod(SootMethod originalMethod) { // Create a new method with the same parameters but a @StructRet parameter inserted first @SuppressWarnings("unchecked") ArrayList<soot.Type> newParameterTypes = new ArrayList<soot.Type>(originalMethod.getParameterTypes()); newParameterTypes.add(0, originalMethod.getReturnType()); SootMethod method = new SootMethod( originalMethod.getName(), newParameterTypes, VoidType.v(), originalMethod.getModifiers()); method.setDeclaringClass(originalMethod.getDeclaringClass()); method.setDeclared(true); // Copy all annotations from the original method copyAnnotations(originalMethod, method, Visibility.Any); // Copy all parameter annotations from the original method to the copy shifting by 1 copyParameterAnnotations( originalMethod, method, 0, originalMethod.getParameterCount(), 1, Visibility.Any); // Add @StructRet to parameter 0 addRuntimeVisibleParameterAnnotation(method, 0, STRUCT_RET); return method; }
public void outAVoidType(AVoidType node) { mProductions.addLast(VoidType.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 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(); }
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(); } }
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); }
@Before public void setup() { BOOLEAN = new SootTypeType(BooleanType.v()); VOID = new SootTypeType(VoidType.v()); }