// This method is deprecated. Use soot.util.JasminOutputStream instead. public void writeXXXDeprecated(SootClass cl, String outputDir) { String outputDirWithSep = ""; if (!outputDir.equals("")) outputDirWithSep = outputDir + fileSeparator; try { File tempFile = new File(outputDirWithSep + cl.getName() + ".jasmin"); FileOutputStream streamOut = new FileOutputStream(tempFile); PrintWriter writerOut = new PrintWriter(new EscapedWriter(new OutputStreamWriter(streamOut))); if (cl.containsBafBody()) new soot.baf.JasminClass(cl).print(writerOut); else new soot.jimple.JasminClass(cl).print(writerOut); writerOut.close(); if (Options.v().time()) Timers.v().assembleJasminTimer.start(); // Invoke jasmin { String[] args; if (outputDir.equals("")) { args = new String[1]; args[0] = cl.getName() + ".jasmin"; } else { args = new String[3]; args[0] = "-d"; args[1] = outputDir; args[2] = outputDirWithSep + cl.getName() + ".jasmin"; } jasmin.Main.main(args); } tempFile.delete(); if (Options.v().time()) Timers.v().assembleJasminTimer.end(); } catch (IOException e) { throw new RuntimeException("Could not produce new classfile! (" + e + ")"); } }
public void internalTransform(String phaseName, Map opts) { Iterator it = Scene.v().getApplicationClasses().iterator(); while (it.hasNext()) { SootClass sc = (SootClass) it.next(); // make map of first line to each method HashMap<Integer, SootMethod> lineToMeth = new HashMap<Integer, SootMethod>(); Iterator methIt = sc.getMethods().iterator(); while (methIt.hasNext()) { SootMethod meth = (SootMethod) methIt.next(); if (!meth.isConcrete()) continue; Body body = meth.retrieveActiveBody(); Stmt s = (Stmt) body.getUnits().getFirst(); while (s instanceof IdentityStmt) { s = (Stmt) body.getUnits().getSuccOf(s); } if (s.hasTag("LineNumberTag")) { LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag"); lineToMeth.put(new Integer(tag.getLineNumber()), meth); } } Iterator methIt2 = sc.getMethods().iterator(); while (methIt2.hasNext()) { SootMethod meth = (SootMethod) methIt2.next(); if (!meth.isConcrete()) continue; Body body = meth.retrieveActiveBody(); Stmt s = (Stmt) body.getUnits().getFirst(); while (s instanceof IdentityStmt) { s = (Stmt) body.getUnits().getSuccOf(s); } if (s.hasTag("LineNumberTag")) { LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag"); int line_num = tag.getLineNumber() - 1; // already taken if (lineToMeth.containsKey(new Integer(line_num))) { meth.addTag(new LineNumberTag(line_num + 1)); } // still available - so use it for this meth else { meth.addTag(new LineNumberTag(line_num)); } } } } }
public void printTo(SootClass cl, PrintWriter out) { // add jimple line number tags setJimpleLnNum(1); // Print class name + modifiers { StringTokenizer st = new StringTokenizer(Modifier.toString(cl.getModifiers())); while (st.hasMoreTokens()) { String tok = (String) st.nextToken(); if (cl.isInterface() && tok.equals("abstract")) continue; out.print(tok + " "); } String classPrefix = ""; if (!cl.isInterface()) { classPrefix = classPrefix + " class"; classPrefix = classPrefix.trim(); } out.print(classPrefix + " " + Scene.v().quotedNameOf(cl.getName()) + ""); } // Print extension { if (cl.hasSuperclass()) out.print(" extends " + Scene.v().quotedNameOf(cl.getSuperclass().getName()) + ""); } // Print interfaces { Iterator interfaceIt = cl.getInterfaces().iterator(); if (interfaceIt.hasNext()) { out.print(" implements "); out.print("" + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); while (interfaceIt.hasNext()) { out.print(","); out.print(" " + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); } } } out.println(); incJimpleLnNum(); /* if (!addJimpleLn()) { Iterator clTagsIt = cl.getTags().iterator(); while (clTagsIt.hasNext()) { final Tag t = (Tag)clTagsIt.next(); out.println(t); } }*/ out.println("{"); incJimpleLnNum(); if (Options.v().print_tags_in_output()) { Iterator cTagIterator = cl.getTags().iterator(); while (cTagIterator.hasNext()) { Tag t = (Tag) cTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } // Print fields { Iterator fieldIt = cl.getFields().iterator(); if (fieldIt.hasNext()) { while (fieldIt.hasNext()) { SootField f = (SootField) fieldIt.next(); if (f.isPhantom()) continue; if (Options.v().print_tags_in_output()) { Iterator fTagIterator = f.getTags().iterator(); while (fTagIterator.hasNext()) { Tag t = (Tag) fTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.println(" " + f.getDeclaration() + ";"); if (addJimpleLn()) { setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), f)); } // incJimpleLnNum(); } } } // Print methods { Iterator methodIt = cl.methodIterator(); if (methodIt.hasNext()) { if (cl.getMethodCount() != 0) { out.println(); incJimpleLnNum(); } 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 if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } printTo(method.getActiveBody(), out); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } else { if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.print(" "); out.print(method.getDeclaration()); out.println(";"); incJimpleLnNum(); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } } } } out.println("}"); incJimpleLnNum(); }
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()); } }
/** * @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; }