protected String getTypeString(SootField soot_field) { Type type = soot_field.getType(); String name = type.toString(); char[] name_array = name.toCharArray(); name_array[0] = Character.toUpperCase(name_array[0]); return new String(name_array); }
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]; }
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('.', '/') + ";"; } }
/** Returns a hashCode consistent with object equality. */ public int hashCode() { if (!isHashCodeChosen) { // Set the hash code for this object if (name != null & type != null) fixedHashCode = name.hashCode() + 19 * type.hashCode(); else if (name != null) fixedHashCode = name.hashCode(); else if (type != null) fixedHashCode = type.hashCode(); else fixedHashCode = 1; isHashCodeChosen = true; } return fixedHashCode; }
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 Type getSootType(AnnotationElem e) { Type annotationType; switch (e.getKind()) { case '[': // array // Until now we only know it's some kind of array. annotationType = ARRAY_TYPE; AnnotationArrayElem array = (AnnotationArrayElem) e; if (array.getNumValues() > 0) { // Try to determine type of the array AnnotationElem firstElement = array.getValueAt(0); Type type = getSootType(firstElement); if (type == null) return null; if (type.equals(ARRAY_TYPE)) return ARRAY_TYPE; return ArrayType.v(type, 1); } break; case 's': // string annotationType = RefType.v("java.lang.String"); break; case 'c': // class annotationType = RefType.v("java.lang.Class"); break; case 'e': // enum AnnotationEnumElem enumElem = (AnnotationEnumElem) e; annotationType = Util.getType(enumElem.getTypeName()); ; break; case 'L': case 'J': case 'S': case 'D': case 'I': case 'F': case 'B': case 'C': case 'V': case 'Z': annotationType = Util.getType(String.valueOf(e.getKind())); break; default: annotationType = null; break; } return annotationType; }
public void type(Type t) { handleIndent(); if (t instanceof RefType) { String name = ((RefType) t).getSootClass().getJavaStyleName(); /* * March 30th 2006, Nomair * Adding check to check that the fully qualified name can actually be removed */ if (!name.equals(((RefType) t).getSootClass().toString())) { // means javaStyle name is probably shorter check that there is no class clash in imports // for this // System.out.println(">>>>Type is"+t.toString()); // System.out.println(">>>>Name is"+name); name = RemoveFullyQualifiedName.getReducedName( body.getImportList(), ((RefType) t).getSootClass().toString(), t); } output.append(name); } else if (t instanceof ArrayType) { ((ArrayType) t).toString(this); } else { output.append(t.toString()); } }
@Override public String toString() { if (isEmptyReg()) { return "the empty reg"; } return "reg(" + number + "):" + type.toString(); }
@Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; }
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; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof ReturnValueTaint)) return false; ReturnValueTaint other = (ReturnValueTaint) obj; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; return true; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Register other = (Register) obj; if (number != other.number) return false; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; return true; }
/** * Returns true if an instance of type taintType is assignable to a declaration of type * declaredType. */ public static boolean isAssignable(Type taintType, Type declaredType) { if (taintType instanceof ArrayType) taintType = ((ArrayType) taintType).getArrayElementType(); if (declaredType instanceof ArrayType) declaredType = ((ArrayType) declaredType).getArrayElementType(); if (taintType.equals(declaredType)) return true; if (!(taintType instanceof RefType)) return false; if (!(declaredType instanceof RefType)) { return false; } return isAssignable( ((RefType) taintType).getSootClass(), ((RefType) declaredType).getSootClass()); }
private Set<SootField> filter(JavaCriticalSection cs, Set<SootField> fields) { Local lock = cs.getLockVariable(); Type lockVarType = null; if (lock == null) { lockVarType = cs.getSootMethod().getDeclaringClass().getType(); } else { lockVarType = lock.getType(); if (lockVarType.toString().equals("java.lang.Object")) return new HashSet<SootField>(0); } FastHierarchy fastHier = new FastHierarchy(); Set<SootField> filteredSet = new HashSet<SootField>(); for (SootField field : fields) { SootClass fieldDC = field.getDeclaringClass(); Type fieldClsType = fieldDC.getType(); if (fastHier.canStoreType(fieldClsType, lockVarType) || fastHier.canStoreType(lockVarType, fieldClsType)) { filteredSet.add(field); } } return filteredSet; }
public void printTo(SootClass cl, PrintWriter out) { // IterableSet packagesUsed = new IterableSet(); IterableSet importList = new IterableSet(); { String curPackage = cl.getJavaPackageName(); if (!curPackage.equals("")) { out.println("package " + curPackage + ";"); out.println(); } if (cl.hasSuperclass()) { SootClass superClass = cl.getSuperclass(); importList.add(superClass.toString()); // packagesUsed.add(superClass.getJavaPackageName()); } Iterator<SootClass> interfaceIt = cl.getInterfaces().iterator(); while (interfaceIt.hasNext()) { String interfacePackage = ((SootClass) interfaceIt.next()).toString(); if (!importList.contains(interfacePackage)) importList.add(interfacePackage); // if (!packagesUsed.contains(interfacePackage)) // packagesUsed.add(interfacePackage); } Iterator<SootMethod> methodIt = cl.methodIterator(); while (methodIt.hasNext()) { SootMethod dm = (SootMethod) methodIt.next(); if (dm.hasActiveBody()) { // packagesUsed = packagesUsed.union(((DavaBody) dm.getActiveBody()).get_PackagesUsed()); importList = importList.union(((DavaBody) dm.getActiveBody()).getImportList()); } Iterator<SootClass> eit = dm.getExceptions().iterator(); while (eit.hasNext()) { String thrownPackage = eit.next().toString(); if (!importList.contains(thrownPackage)) importList.add(thrownPackage); // if (!packagesUsed.contains(thrownPackage)) // packagesUsed.add(thrownPackage); } Iterator<Type> pit = dm.getParameterTypes().iterator(); while (pit.hasNext()) { Type t = (Type) pit.next(); if (t instanceof RefType) { String paramPackage = ((RefType) t).getSootClass().toString(); if (!importList.contains(paramPackage)) importList.add(paramPackage); // if (packagesUsed.contains(paramPackage) == false) // packagesUsed.add(paramPackage); } } Type t = dm.getReturnType(); if (t instanceof RefType) { String returnPackage = ((RefType) t).getSootClass().toString(); if (!importList.contains(returnPackage)) importList.add(returnPackage); // if (packagesUsed.contains(returnPackage) == false) // packagesUsed.add(returnPackage); } } Iterator<SootField> fieldIt = cl.getFields().iterator(); while (fieldIt.hasNext()) { SootField f = (SootField) fieldIt.next(); if (f.isPhantom()) continue; Type t = f.getType(); if (t instanceof RefType) { String fieldPackage = ((RefType) t).getSootClass().toString(); if (!importList.contains(fieldPackage)) importList.add(fieldPackage); } } Iterator<String> pit = importList.iterator(); List<String> toImport = new ArrayList<String>(); while (pit.hasNext()) { /* * dont import any file which has currentPackage.className * dont import any file which starts with java.lang */ String temp = (String) pit.next(); // System.out.println("temp is "+temp); if (temp.indexOf("java.lang") > -1) { // problem is that we need to import sub packages java.lang.ref // for instance if the type is java.lang.ref.WeakReference String tempClassName = RemoveFullyQualifiedName.getClassName(temp); if (temp.equals("java.lang." + tempClassName)) { // System.out.println("temp was not printed as it belongs to java.lang"); continue; } } if (curPackage.length() > 0 && temp.indexOf(curPackage) > -1) { // System.out.println("here "+temp); continue; } if (cl.toString().equals(temp)) continue; // System.out.println("printing"+); toImport.add(temp); } /* * Check that we are not importing two classes with the same last name * If yes then remove explicit import and import the whole package * else output explicit import statement */ Iterator it = toImport.iterator(); while (it.hasNext()) { String temp = (String) it.next(); if (RemoveFullyQualifiedName.containsMultiple(toImport.iterator(), temp, null)) { // there are atleast two imports with this className // import package add * if (temp.lastIndexOf('.') > -1) { temp = temp.substring(0, temp.lastIndexOf('.')); out.println("import " + temp + ".*;"); } else throw new DecompilationException("Cant find the DOT . for fullyqualified name"); } else { if (temp.lastIndexOf('.') == -1) { // dot not found this is a class belonging to this package so dont add } else out.println("import " + temp + ";"); } } boolean addNewLine = false; addNewLine = true; // out.println("import " + temp + ";"); if (addNewLine) out.println(); /*if (!packagesUsed.isEmpty()) out.println(); packagesUsed.add("java.lang"); packagesUsed.add(curPackage); */ Dava.v().set_CurrentPackageContext(importList); // Dava.v().set_CurrentPackageContext(packagesUsed); Dava.v().set_CurrentPackage(curPackage); } // Print class name + modifiers { String classPrefix = ""; classPrefix = classPrefix + " " + Modifier.toString(cl.getModifiers()); classPrefix = classPrefix.trim(); if (!cl.isInterface()) { classPrefix = classPrefix + " class"; classPrefix = classPrefix.trim(); } out.print(classPrefix + " " + cl.getShortJavaStyleName()); } // Print extension if (cl.hasSuperclass() && !(cl.getSuperclass().getName().equals("java.lang.Object"))) { String superClassName = cl.getSuperclass().getName(); // Nomair Naeem 8th Feb 2006 // also check if the super class name is not a fully qualified // name. in which case if the package is imported no need for // the long name superClassName = RemoveFullyQualifiedName.getReducedName(importList, superClassName, cl.getType()); out.print(" extends " + superClassName + ""); } // Print interfaces { Iterator<SootClass> interfaceIt = cl.getInterfaces().iterator(); if (interfaceIt.hasNext()) { if (cl.isInterface()) out.print(" extends "); else out.print(" implements "); out.print("" + (interfaceIt.next()).getName() + ""); while (interfaceIt.hasNext()) out.print(", " + (interfaceIt.next()).getName() + ""); } } out.println(); out.println("{"); // Print fields { Iterator<SootField> fieldIt = cl.getFields().iterator(); if (fieldIt.hasNext()) { while (fieldIt.hasNext()) { SootField f = fieldIt.next(); if (f.isPhantom()) continue; String declaration = null; Type fieldType = f.getType(); String qualifiers = Modifier.toString(f.getModifiers()) + " "; qualifiers += RemoveFullyQualifiedName.getReducedName(importList, fieldType.toString(), fieldType); qualifiers = qualifiers.trim(); if (qualifiers.equals("")) declaration = Scene.v().quotedNameOf(f.getName()); else declaration = qualifiers + " " + Scene.v().quotedNameOf(f.getName()) + ""; if (f.isFinal() && f.isStatic()) { if (fieldType instanceof DoubleType && f.hasTag("DoubleConstantValueTag")) { double val = ((DoubleConstantValueTag) f.getTag("DoubleConstantValueTag")).getDoubleValue(); out.println(" " + declaration + " = " + val + ";"); } else if (fieldType instanceof FloatType && f.hasTag("FloatConstantValueTag")) { float val = ((FloatConstantValueTag) f.getTag("FloatConstantValueTag")).getFloatValue(); out.println(" " + declaration + " = " + val + "f;"); } else if (fieldType instanceof LongType && f.hasTag("LongConstantValueTag")) { long val = ((LongConstantValueTag) f.getTag("LongConstantValueTag")).getLongValue(); out.println(" " + declaration + " = " + val + "l;"); } else if (fieldType instanceof CharType && f.hasTag("IntegerConstantValueTag")) { int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue(); out.println(" " + declaration + " = '" + ((char) val) + "';"); } else if (fieldType instanceof BooleanType && f.hasTag("IntegerConstantValueTag")) { int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue(); if (val == 0) out.println(" " + declaration + " = false;"); else out.println(" " + declaration + " = true;"); } else if ((fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType) && f.hasTag("IntegerConstantValueTag")) { int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue(); out.println(" " + declaration + " = " + val + ";"); } else if (f.hasTag("StringConstantValueTag")) { String val = ((StringConstantValueTag) f.getTag("StringConstantValueTag")).getStringValue(); out.println(" " + declaration + " = \"" + val + "\";"); } else { // System.out.println("Couldnt find type of // field"+f.getDeclaration()); out.println(" " + declaration + ";"); } } // field is static final else { out.println(" " + declaration + ";"); } } } } // Print methods { Iterator<SootMethod> methodIt = cl.methodIterator(); if (methodIt.hasNext()) { if (cl.getMethodCount() != 0) out.println(); while (methodIt.hasNext()) { SootMethod method = (SootMethod) methodIt.next(); if (method.isPhantom()) continue; if (!Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers())) { if (!method.hasActiveBody()) throw new RuntimeException("method " + method.getName() + " has no active body!"); else printTo(method.getActiveBody(), out); if (methodIt.hasNext()) out.println(); } else { // if method is abstract then print the declaration out.print(" "); out.print(method.getDavaDeclaration()); out.println(";"); if (methodIt.hasNext()) out.println(); } } } } /* * January 23rd, 2006 * In trying to handle the suepr class problem we need to introduce an inner class * Instead of creating a data structure for it we are right now just going to print it in the form * of a string * * It would be interesting to later have an internal inner class structure so that we could * decompile inner classes into inner classes */ if (G.v().SootClassNeedsDavaSuperHandlerClass.contains(cl)) { out.println("\n private static class DavaSuperHandler{"); out.println(" java.util.Vector myVector = new java.util.Vector();"); out.println("\n public Object get(int pos){"); out.println(" return myVector.elementAt(pos);"); out.println(" }"); out.println("\n public void store(Object obj){"); out.println(" myVector.add(obj);"); out.println(" }"); out.println(" }"); } out.println("}"); }
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; } }
public String getTypeString() { return type.toString(); }
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); }
/** Returns a hash code for this object, consistent with structural equality. */ public int equivHashCode() { return name.hashCode() * 101 + type.hashCode() * 17; }
/** * @param annotations * @return */ private List<Tag> handleAnnotation( Set<? extends org.jf.dexlib2.iface.Annotation> annotations, String classType) { if (annotations == null || annotations.size() == 0) return null; List<Tag> tags = new ArrayList<Tag>(); VisibilityAnnotationTag[] vatg = new VisibilityAnnotationTag[3]; // RUNTIME_VISIBLE, RUNTIME_INVISIBLE, SOURCE_VISIBLE, see // soot.tagkit.AnnotationConstants for (Annotation a : annotations) { int v = getVisibility(a.getVisibility()); Tag t = null; Type atype = DexType.toSoot(a.getType()); String atypes = atype.toString(); int eSize = a.getElements().size(); Debug.printDbg("annotation type: ", atypes, " elements: ", eSize); if (atypes.equals("dalvik.annotation.AnnotationDefault")) { if (eSize != 1) throw new RuntimeException( "error: expected 1 element for annotation Default. Got " + eSize + " instead."); // get element AnnotationElem e = getElements(a.getElements()).get(0); AnnotationTag adt = new AnnotationTag(a.getType()); adt.addElem(e); if (vatg[v] == null) vatg[v] = new VisibilityAnnotationTag(v); vatg[v].addAnnotation(adt); } else if (atypes.equals("dalvik.annotation.EnclosingClass")) { if (eSize != 1) throw new RuntimeException( "error: expected 1 element for annotation EnclosingClass. Got " + eSize + " instead."); for (AnnotationElement elem : a.getElements()) { String outerClass = ((TypeEncodedValue) elem.getValue()).getValue(); outerClass = Util.dottedClassName(outerClass); deps.typesToSignature.add(RefType.v(outerClass)); clazz.setOuterClass(SootResolver.v().makeClassRef(outerClass)); assert clazz.getOuterClass() != clazz; } // EnclosingClass comes in pair with InnerClass. // Those are generated from a single InnerClassTag, // that is re-constructed only for the InnerClass Dalvik // annotation. continue; } else if (atypes.equals("dalvik.annotation.EnclosingMethod")) { if (eSize != 1) throw new RuntimeException( "error: expected 1 element for annotation EnclosingMethod. Got " + eSize + " instead."); AnnotationStringElem e = (AnnotationStringElem) getElements(a.getElements()).get(0); String[] split1 = e.getValue().split("\\ \\|"); String classString = split1[0]; String methodString = split1[1]; String parameters = split1[2]; String returnType = split1[3]; String methodSigString = "(" + parameters + ")" + returnType; t = new EnclosingMethodTag(classString, methodString, methodSigString); String outerClass = classString.replace("/", "."); deps.typesToSignature.add(RefType.v(outerClass)); clazz.setOuterClass(SootResolver.v().makeClassRef(outerClass)); assert clazz.getOuterClass() != clazz; } else if (atypes.equals("dalvik.annotation.InnerClass")) { int accessFlags = -1; // access flags of the inner class String name = null; // name of the inner class for (AnnotationElem ele : getElements(a.getElements())) { if (ele instanceof AnnotationIntElem && ele.getName().equals("accessFlags")) accessFlags = ((AnnotationIntElem) ele).getValue(); else if (ele instanceof AnnotationStringElem && ele.getName().equals("name")) name = ((AnnotationStringElem) ele).getValue(); else throw new RuntimeException("Unexpected inner class annotation element"); } String outerClass; // outer class name if (name == null) outerClass = classType.replaceAll("\\$[0-9,a-z,A-Z]*;$", ";"); else outerClass = classType.replaceFirst("\\$" + name + ";$", ";"); // Make sure that no funny business is going on if the // annotation is broken and does not end in $nn. if (outerClass.equals(classType)) { outerClass = null; } Tag innerTag = new InnerClassTag( DexType.toSootICAT(classType), outerClass == null ? null : DexType.toSootICAT(outerClass), name, accessFlags); tags.add(innerTag); if (outerClass != null && !clazz.hasOuterClass()) { String sootOuterClass = Util.dottedClassName(outerClass); deps.typesToSignature.add(RefType.v(sootOuterClass)); clazz.setOuterClass(SootResolver.v().makeClassRef(sootOuterClass)); assert clazz.getOuterClass() != clazz; } continue; } else if (atypes.equals("dalvik.annotation.MemberClasses")) { AnnotationArrayElem e = (AnnotationArrayElem) getElements(a.getElements()).get(0); for (AnnotationElem ae : e.getValues()) { AnnotationClassElem c = (AnnotationClassElem) ae; String innerClass = c.getDesc(); String outerClass = innerClass.replaceAll("\\$[^\\$]*$", ""); String name = innerClass.replaceAll("^.*\\$", "").replaceAll(";$", ""); if (name.replaceAll("[0-9].*", "").equals("")) { // anonymous or local inner classes name = null; } int accessFlags = 0; // seems like this information is lost during the .class -- dx --> .dex process. Tag innerTag = new InnerClassTag( DexType.toSootICAT(innerClass), DexType.toSootICAT(outerClass), name, accessFlags); tags.add(innerTag); } continue; } else if (atypes.equals("dalvik.annotation.Signature")) { if (eSize != 1) throw new RuntimeException( "error: expected 1 element for annotation Signature. Got " + eSize + " instead."); AnnotationArrayElem e = (AnnotationArrayElem) getElements(a.getElements()).get(0); String sig = ""; for (AnnotationElem ae : e.getValues()) { AnnotationStringElem s = (AnnotationStringElem) ae; sig += s.getValue(); } t = new SignatureTag(sig); } else if (atypes.equals("dalvik.annotation.Throws")) { // this is handled in soot.dexpler.DexMethod continue; } else if (atypes.equals("java.lang.Deprecated")) { if (eSize != 0) throw new RuntimeException( "error: expected 1 element for annotation Deprecated. Got " + eSize + " instead."); t = new DeprecatedTag(); AnnotationTag adt = new AnnotationTag("Ljava/lang/Deprecated;"); if (vatg[v] == null) vatg[v] = new VisibilityAnnotationTag(v); vatg[v].addAnnotation(adt); } else { Debug.printDbg("read visibility tag: ", a.getType()); if (vatg[v] == null) vatg[v] = new VisibilityAnnotationTag(v); AnnotationTag tag = new AnnotationTag(a.getType()); for (AnnotationElem e : getElements(a.getElements())) tag.addElem(e); vatg[v].addAnnotation(tag); } tags.add(t); } for (VisibilityAnnotationTag vat : vatg) if (vat != null) tags.add(vat); return tags; }
void handleClassAnnotation(ClassDef classDef) { Set<? extends Annotation> aSet = classDef.getAnnotations(); if (aSet == null || aSet.isEmpty()) return; List<Tag> tags = handleAnnotation(aSet, classDef.getType()); if (tags == null) return; InnerClassAttribute ica = null; for (Tag t : tags) if (t != null) { if (t instanceof InnerClassTag) { if (ica == null) { // Do we already have an InnerClassAttribute? ica = (InnerClassAttribute) clazz.getTag("InnerClassAttribute"); // If not, create one if (ica == null) { ica = new InnerClassAttribute(); clazz.addTag(ica); } } ica.add((InnerClassTag) t); } else if (t instanceof VisibilityAnnotationTag) { // If a dalvik/annotation/AnnotationDefault tag is present // in a class, its AnnotationElements must be propagated // to methods through the creation of new AnnotationDefaultTag. VisibilityAnnotationTag vt = (VisibilityAnnotationTag) t; for (AnnotationTag a : vt.getAnnotations()) { if (a.getType().equals("Ldalvik/annotation/AnnotationDefault;")) { for (AnnotationElem ae : a.getElems()) { if (ae instanceof AnnotationAnnotationElem) { AnnotationAnnotationElem aae = (AnnotationAnnotationElem) ae; AnnotationTag at = aae.getValue(); // extract default elements Map<String, AnnotationElem> defaults = new HashMap<String, AnnotationElem>(); for (AnnotationElem aelem : at.getElems()) { defaults.put(aelem.getName(), aelem); } // create default tags containing default elements // and add tags on methods for (SootMethod sm : clazz.getMethods()) { String methodName = sm.getName(); if (defaults.containsKey(methodName)) { AnnotationElem e = defaults.get(methodName); // Okay, the name is the same, but is it actually the same type? Type annotationType = getSootType(e); boolean isCorrectType = false; if (annotationType == null) { // we do not know the type of the annotation, so we guess it's the correct // type. isCorrectType = true; } else { if (annotationType.equals(sm.getReturnType())) { isCorrectType = true; } else if (annotationType.equals(ARRAY_TYPE)) { if (sm.getReturnType() instanceof ArrayType) isCorrectType = true; } } if (isCorrectType && sm.getParameterCount() == 0) { e.setName("default"); AnnotationDefaultTag d = new AnnotationDefaultTag(e); sm.addTag(d); // In case there is more than one matching method, we only use the first one defaults.remove(sm.getName()); } } } for (Entry<String, AnnotationElem> leftOverEntry : defaults.entrySet()) { // We were not able to find a matching method for the tag, because the return // signature // does not match SootMethod found = clazz.getMethodByNameUnsafe(leftOverEntry.getKey()); AnnotationElem element = leftOverEntry.getValue(); if (found != null) { element.setName("default"); AnnotationDefaultTag d = new AnnotationDefaultTag(element); found.addTag(d); } } } } } } if (!(vt.getVisibility() == AnnotationConstants.RUNTIME_INVISIBLE)) clazz.addTag(vt); } else { clazz.addTag(t); } Debug.printDbg("add class annotation: ", t, " type: ", t.getClass()); } }
public SootClass getReferencedClass(Type soottype) { refclass = null; soottype.apply(this); return refclass; }
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(); }
public static boolean isUnsigned(soot.Type type) { return type.equals(CharType.v()); }