Example #1
0
  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());
      }
  }
Example #2
0
  /**
   * Converts method and method parameters annotations from Dexlib to Jimple
   *
   * @param h
   * @param method
   */
  void handleMethodAnnotation(Host h, Method method) {
    Set<? extends Annotation> aSet = method.getAnnotations();
    if (!(aSet == null || aSet.isEmpty())) {
      List<Tag> tags = handleAnnotation(aSet, null);
      if (tags != null)
        for (Tag t : tags)
          if (t != null) {
            h.addTag(t);
            Debug.printDbg("add method annotation: ", t);
          }
    }

    ArrayList<String> parameterNames = new ArrayList<String>();
    boolean addParameterNames = false;
    for (MethodParameter p : method.getParameters()) {
      String name = p.getName();
      parameterNames.add(name);
      if (name != null) addParameterNames = true;
    }
    if (addParameterNames) {
      h.addTag(new ParamNamesTag(parameterNames));
    }

    // Is there any parameter annotation?
    boolean doParam = false;
    List<? extends MethodParameter> parameters = method.getParameters();
    for (MethodParameter p : parameters) {
      Debug.printDbg("parameter ", p, " annotations: ", p.getAnnotations());
      if (p.getAnnotations().size() > 0) {
        doParam = true;
        break;
      }
    }

    if (doParam) {
      VisibilityParameterAnnotationTag tag =
          new VisibilityParameterAnnotationTag(
              parameters.size(), AnnotationConstants.RUNTIME_VISIBLE);
      for (MethodParameter p : parameters) {
        List<Tag> tags = handleAnnotation(p.getAnnotations(), null);

        // If we have no tag for this parameter, add a placeholder
        // so that we keep the order intact.
        if (tags == null) {
          tag.addVisibilityAnnotation(null);
          continue;
        }

        VisibilityAnnotationTag paramVat =
            new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_VISIBLE);
        tag.addVisibilityAnnotation(paramVat);

        for (Tag t : tags) {
          if (t == null) continue;

          AnnotationTag vat = null;
          if (!(t instanceof VisibilityAnnotationTag)) {
            if (t instanceof DeprecatedTag) {
              vat = new AnnotationTag("Ljava/lang/Deprecated;");
            } else if (t instanceof SignatureTag) {
              SignatureTag sig = (SignatureTag) t;

              ArrayList<AnnotationElem> sigElements = new ArrayList<AnnotationElem>();
              for (String s : SootToDexUtils.splitSignature(sig.getSignature()))
                sigElements.add(new AnnotationStringElem(s, 's', "value"));

              AnnotationElem elem = new AnnotationArrayElem(sigElements, 's', "value");
              vat = new AnnotationTag("Ldalvik/annotation/Signature;", Collections.singleton(elem));
            } else {
              throw new RuntimeException(
                  "error: unhandled tag for parameter annotation in method " + h + " (" + t + ").");
            }
          } else {
            vat = ((VisibilityAnnotationTag) t).getAnnotations().get(0);
          }

          Debug.printDbg("add parameter annotation: ", t);
          paramVat.addAnnotation(vat);
        }
      }
      if (tag.getVisibilityAnnotations().size() > 0) h.addTag(tag);
    }
  }