private void createLookupFunction(SootMethod m) { // TODO: This should use a virtual method table or interface method table. Function function = FunctionBuilder.lookup(m); mb.addFunction(function); Variable reserved0 = function.newVariable(I8_PTR_PTR); function.add(new Getelementptr(reserved0, function.getParameterRef(0), 0, 4)); Variable reserved1 = function.newVariable(I8_PTR_PTR); function.add(new Getelementptr(reserved1, function.getParameterRef(0), 0, 5)); function.add(new Store(getString(m.getName()), reserved0.ref())); function.add(new Store(getString(getDescriptor(m)), reserved1.ref())); Value lookupFn = sootClass.isInterface() ? BC_LOOKUP_INTERFACE_METHOD : BC_LOOKUP_VIRTUAL_METHOD; List<Value> args = new ArrayList<Value>(); args.add(function.getParameterRef(0)); if (sootClass.isInterface()) { Value info = getInfoStruct(function); args.add(info); } args.add(function.getParameterRef(1)); args.add(getString(m.getName())); args.add(getString(getDescriptor(m))); Value fptr = call(function, lookupFn, args); Variable f = function.newVariable(function.getType()); function.add(new Bitcast(f, fptr, f.getType())); Value result = call(function, f.ref(), function.getParameterRefs()); function.add(new Ret(result)); }
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 ITable get(SootClass clazz) { if (!clazz.isInterface()) { throw new IllegalArgumentException("Not an interface: " + clazz.getName()); } ITable itable = cache.get(clazz.getName()); if (itable != null) { return itable; } itable = new ITable(clazz); cache.put(clazz.getName(), itable); return itable; }
public static HashSet<SootMethod> getAllImplementations(SootMethod method) { Chain appClasses = Scene.v().getApplicationClasses(); HashSet<SootClass> implementingClasses = new HashSet<SootClass>(1); HashSet<SootMethod> overridingMethods = new HashSet<SootMethod>(1); SootClass t = method.getDeclaringClass(); if ( /*t.isAbstract() || */ t.isPhantom() || t.isPhantomClass()) { boolean b1 = t.isAbstract(); boolean be = t.isPhantom(); boolean b3 = t.isPhantomClass(); try { throw new Exception("Need to implement for Plantom Classes"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (t.isAbstract()) { for (Object object : appClasses) { SootClass clazz = (SootClass) object; SootClass superClass = clazz.getSuperclass(); { if (superClass.getName().equals(t.toString())) { implementingClasses.add(clazz); SootMethod m2 = clazz.getMethod( method.getName(), method.getParameterTypes(), method.getReturnType()); overridingMethods.add(m2); } } } } if (t.isInterface()) { for (Object object : appClasses) { SootClass clazz = (SootClass) object; Chain<SootClass> interfaces = clazz.getInterfaces(); for (SootClass sootClass : interfaces) { if (sootClass.getName().equals(t.toString())) { implementingClasses.add(clazz); SootMethod m2 = clazz.getMethod( method.getName(), method.getParameterTypes(), method.getReturnType()); overridingMethods.add(m2); } } } } return overridingMethods; }
/** For instance invokes */ public static ArrayList<SootMethod> resolveAppCall(Type tgtType, SootMethodRef methodRef) { final NumberedString mSubsignature = methodRef.getSubSignature(); if (tgtType instanceof RefType) { // find first class upwards in hierarchy, starting from cls, that implements method (i.e., // *concrete* method) SootClass cls = ((RefType) tgtType).getSootClass(); while (!cls.declaresMethod(mSubsignature)) cls = cls .getSuperclass(); // if method not in this class, it HAS to be in a superclass, so a // superclass must exist if (!cls.hasTag(ClassTag.TAG_NAME)) return null; // not an app method // finally, store resolved app method SootMethod m = cls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); methods.add(m); // just one element, directly resolved return methods; } if (tgtType instanceof AnySubType) { // return set of all app subtypes that implement referenced method SootClass baseCls = ((AnySubType) tgtType).getBase().getSootClass(); List subClasses = baseCls.isInterface() ? Scene.v().getActiveHierarchy().getImplementersOf(baseCls) : Scene.v().getActiveHierarchy().getSubclassesOf(baseCls); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); for (Object oSubCls : subClasses) { SootClass subCls = (SootClass) oSubCls; if (subCls.hasTag(ClassTag.TAG_NAME)) { try { SootMethod m = subCls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); if (!m.isAbstract()) methods.add(m); } catch (RuntimeException e) { } } } return methods; } assert tgtType instanceof ArrayType; // only other case observed so far return new ArrayList(); // no array class/method is in app }
public VTable get(SootClass clazz) { if (clazz.isInterface()) { throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName()); } VTable vtable = cache.get(clazz.getName()); if (vtable != null) { return vtable; } VTable parent = null; if (clazz.hasSuperclass()) { parent = get(clazz.getSuperclass()); } vtable = new VTable(clazz, parent); cache.put(clazz.getName(), vtable); return vtable; }
private void addGUIClasses(StringBuffer buf) { if (buf.length() > 0 && ',' != buf.charAt(buf.length() - 1)) buf.append(','); int i = 0; int j = 0; for (SootClass clz : Scene.v().getClasses()) { if (clz.isInterface()) continue; j++; if (API.v().isGUIClass(clz)) { buf.append(clz + ","); i++; logger.info("Adding class to limit heap context list of spark: {}", clz); } } System.out.println("GUI no context " + i); System.out.println("Total classes: " + j); }
public StructureConstant getStruct(SootClass clazz) { if (clazz.isInterface()) { throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName()); } ArrayConstantBuilder table = new ArrayConstantBuilder(I8_PTR); for (Entry entry : entries) { ResolvedEntry resolvedEntry = entry.resolve(clazz); if (resolvedEntry == null || Modifier.isAbstract(resolvedEntry.getModifiers())) { table.add(new ConstantBitcast(BC_ABSTRACT_METHOD_CALLED, I8_PTR)); } else if (!Modifier.isPublic(resolvedEntry.getModifiers())) { table.add(new ConstantBitcast(BC_NON_PUBLIC_METHOD_CALLED, I8_PTR)); } else { table.add(new ConstantBitcast(resolvedEntry.getFunctionRef(), I8_PTR)); } } return new StructureConstantBuilder() .add(new IntegerConstant((short) entries.length)) .add(table.build()) .build(); }
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 StructureConstant createClassInfoErrorStruct() { /* * Check that clazz can be loaded, i.e. that the superclass * and interfaces of the class exist and are accessible to the * class. Also check that any exception the class uses in catch * clauses exist and is accessible to the class. If the class * cannot be loaded we override the ClassInfoHeader struct * produced by the ClassCompiler for the class with one which * tells the code in bc.c to throw an appropriate exception * whenever clazz is accessed. */ int errorType = ClassCompiler.CI_ERROR_TYPE_NONE; String errorMessage = null; if (!sootClass.isInterface() && sootClass.hasSuperclass()) { // Check superclass SootClass superclazz = sootClass.getSuperclass(); if (superclazz.isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = superclazz.getName(); } else if (!checkClassAccessible(superclazz, sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, superclazz, sootClass); } else if (superclazz.isInterface()) { errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE; errorMessage = String.format("class %s has interface %s as super class", sootClass, superclazz); } // No need to check for ClassCircularityError. Soot doesn't handle // such problems so the compilation will fail earlier. } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { // Check interfaces for (SootClass interfaze : sootClass.getInterfaces()) { if (interfaze.isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = interfaze.getName(); break; } else if (!checkClassAccessible(interfaze, sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, interfaze, sootClass); break; } else if (!interfaze.isInterface()) { errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE; errorMessage = String.format( "class %s tries to implement class %s as interface", sootClass, interfaze); break; } } } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { // Check exceptions used in catch clauses. I cannot find any info in // the VM spec specifying that this has to be done when the class is loaded. // However, this is how it's done in other VMs so we do it too. for (String exName : catches) { Clazz ex = config.getClazzes().load(exName); if (ex == null || ex.getSootClass().isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = exName; break; } else if (!checkClassAccessible(ex.getSootClass(), sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, ex, sootClass); break; } } } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { return null; } // Create a ClassInfoError struct StructureConstantBuilder error = new StructureConstantBuilder(); error.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct error.add(new IntegerConstant(ClassCompiler.CI_ERROR)); error.add(getString(getInternalName(sootClass))); error.add(new IntegerConstant(errorType)); error.add(getString(errorMessage)); return error.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 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("}"); }