/** * @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; }