mirror of
https://github.com/revanced/smali.git
synced 2025-06-13 04:27:38 +02:00
Implemented class and method annotations
git-svn-id: https://smali.googlecode.com/svn/trunk@166 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2009 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.dexlib.AnnotationItem;
|
||||
import org.jf.baksmali.Adaptors.EncodedValue.AnnotationEncodedValueAdaptor;
|
||||
import org.jf.baksmali.Adaptors.Reference.TypeReference;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AnnotationAdaptor {
|
||||
private AnnotationItem annotationItem;
|
||||
private AnnotationEncodedValueAdaptor encodedAnnotationAdaptor;
|
||||
|
||||
public AnnotationAdaptor(AnnotationItem annotationItem) {
|
||||
this.annotationItem = annotationItem;
|
||||
this.encodedAnnotationAdaptor = new AnnotationEncodedValueAdaptor(annotationItem.getEncodedAnnotation());
|
||||
}
|
||||
|
||||
public String getVisibility() {
|
||||
switch (annotationItem.getVisibility()) {
|
||||
case 0:
|
||||
return "build";
|
||||
case 1:
|
||||
return "runtime";
|
||||
case 2:
|
||||
return "system";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TypeReference getAnnotationType() {
|
||||
return encodedAnnotationAdaptor.getAnnotationType();
|
||||
}
|
||||
|
||||
public List<AnnotationEncodedValueAdaptor.AnnotationElementAdaptor> getElements() {
|
||||
return encodedAnnotationAdaptor.getElements();
|
||||
}
|
||||
}
|
@ -28,23 +28,37 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.dexlib.ClassDataItem;
|
||||
import org.jf.dexlib.ClassDefItem;
|
||||
import org.jf.dexlib.EncodedArrayItem;
|
||||
import org.jf.dexlib.EncodedValue.EncodedValue;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.util.AccessFlags;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class ClassDefinition {
|
||||
private ClassDefItem classDefItem;
|
||||
private ClassDataItem classDataItem;
|
||||
|
||||
private HashMap<Integer, AnnotationSetItem> methodAnnotations = new HashMap<Integer, AnnotationSetItem>();
|
||||
|
||||
public ClassDefinition(ClassDefItem classDefItem) {
|
||||
this.classDefItem = classDefItem;
|
||||
this.classDataItem = classDefItem.getClassData();
|
||||
buildAnnotationMaps();
|
||||
}
|
||||
|
||||
private void buildAnnotationMaps() {
|
||||
AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotationDirectory();
|
||||
if (annotationDirectory == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotationList = annotationDirectory.getMethodAnnotations();
|
||||
|
||||
if (methodAnnotations != null) {
|
||||
for (AnnotationDirectoryItem.MethodAnnotation methodAnnotation: methodAnnotationList) {
|
||||
methodAnnotations.put(methodAnnotation.getMethod().getIndex(), methodAnnotation.getAnnotationSet());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> accessFlags = null;
|
||||
@ -142,7 +156,8 @@ public class ClassDefinition {
|
||||
|
||||
if (classDataItem != null) {
|
||||
for (ClassDataItem.EncodedMethod method: classDataItem.getDirectMethods()) {
|
||||
directMethods.add(new MethodDefinition(method));
|
||||
AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex());
|
||||
directMethods.add(new MethodDefinition(method, annotationSet));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,10 +171,30 @@ public class ClassDefinition {
|
||||
|
||||
if (classDataItem != null) {
|
||||
for (ClassDataItem.EncodedMethod method: classDataItem.getVirtualMethods()) {
|
||||
virtualMethods.add(new MethodDefinition(method));
|
||||
AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex());
|
||||
virtualMethods.add(new MethodDefinition(method, annotationSet));
|
||||
}
|
||||
}
|
||||
}
|
||||
return virtualMethods;
|
||||
}
|
||||
|
||||
public List<AnnotationAdaptor> getAnnotations() {
|
||||
AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotationDirectory();
|
||||
if (annotationDirectory == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AnnotationSetItem annotationSet = annotationDirectory.getClassAnnotations();
|
||||
if (annotationSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<AnnotationAdaptor> annotationAdaptors = new ArrayList<AnnotationAdaptor>();
|
||||
|
||||
for (AnnotationItem annotationItem: annotationSet.getAnnotationItems()) {
|
||||
annotationAdaptors.add(new AnnotationAdaptor(annotationItem));
|
||||
}
|
||||
return annotationAdaptors;
|
||||
}
|
||||
}
|
||||
|
@ -29,9 +29,7 @@
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.Adaptors.Format.*;
|
||||
import org.jf.dexlib.ClassDataItem;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
import org.jf.dexlib.MethodIdItem;
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.code.Format.*;
|
||||
import org.jf.dexlib.code.Instruction;
|
||||
import org.jf.dexlib.code.InstructionField;
|
||||
@ -44,11 +42,13 @@ public class MethodDefinition {
|
||||
private ClassDataItem.EncodedMethod encodedMethod;
|
||||
private MethodIdItem methodIdItem;
|
||||
private CodeItem codeItem;
|
||||
private AnnotationSetItem annotationSet;
|
||||
|
||||
public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod) {
|
||||
public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod, AnnotationSetItem annotationSet) {
|
||||
this.encodedMethod = encodedMethod;
|
||||
this.methodIdItem = encodedMethod.getMethod();
|
||||
this.codeItem = encodedMethod.getCodeItem();
|
||||
this.annotationSet = annotationSet;
|
||||
}
|
||||
|
||||
private String methodName = null;
|
||||
@ -99,6 +99,19 @@ public class MethodDefinition {
|
||||
return registerCount;
|
||||
}
|
||||
|
||||
public List<AnnotationAdaptor> getAnnotations() {
|
||||
if (annotationSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<AnnotationAdaptor> annotationAdaptors = new ArrayList<AnnotationAdaptor>();
|
||||
|
||||
for (AnnotationItem annotationItem: annotationSet.getAnnotationItems()) {
|
||||
annotationAdaptors.add(new AnnotationAdaptor(annotationItem));
|
||||
}
|
||||
return annotationAdaptors;
|
||||
}
|
||||
|
||||
|
||||
private List<MethodItem> methodItems = null;
|
||||
public List<MethodItem> getMethodItems() {
|
||||
|
@ -9,6 +9,13 @@ smaliFile(classDef) ::=
|
||||
# interfaces
|
||||
<classDef.Interfaces: implement(it); separator="\n">
|
||||
|
||||
<endif>
|
||||
<if(classDef.Annotations)>
|
||||
|
||||
|
||||
# annotations
|
||||
<classDef.Annotations: annotation(it); separator="\n\n">
|
||||
|
||||
<endif>
|
||||
<if(classDef.StaticFields)>
|
||||
|
||||
@ -49,6 +56,19 @@ implement(interface) ::=
|
||||
>>
|
||||
|
||||
|
||||
annotation(annotationAdaptor) ::=
|
||||
<<
|
||||
.annotation <annotationAdaptor.Visibility> <Reference(annotationAdaptor.AnnotationType)>
|
||||
<if(annotationAdaptor.Elements)>
|
||||
<annotationAdaptor.Elements: AnnotationElement(it); separator="\n">
|
||||
<endif>
|
||||
<if(annotationAdaptor.Elements)>
|
||||
|
||||
|
||||
<endif>
|
||||
.end annotation
|
||||
>>
|
||||
|
||||
|
||||
|
||||
field(fieldDef) ::=
|
||||
@ -62,10 +82,17 @@ method(methodDef) ::=
|
||||
.method <methodDef.AccessFlags; separator=" "> <methodDef.MethodName><methodDef.Prototype>
|
||||
<if(methodDef.hasCode)>
|
||||
.registers <methodDef.RegisterCount>
|
||||
<if(methodDef.Annotations)>
|
||||
<methodDef.Annotations: annotation(it); separator="\n\n">
|
||||
<endif>
|
||||
|
||||
<methodDef.MethodItems: MethodItem(it); separator="\n">
|
||||
<endif>
|
||||
.end method
|
||||
<elseif(methodDef.Annotations)>
|
||||
<methodDef.Annotations: annotation(it); separator="\n\n">
|
||||
.end method
|
||||
<endif>
|
||||
|
||||
>>
|
||||
|
||||
MethodItem(MethodItem) ::=
|
||||
@ -291,7 +318,7 @@ EnumEncodedValue(EncodedValue) ::=
|
||||
|
||||
AnnotationEncodedValue(EncodedValue) ::=
|
||||
<<
|
||||
.subannotation EncodedValue.Type
|
||||
.subannotation <Reference(EncodedValue.AnnotationType)>
|
||||
<EncodedValue.Elements: AnnotationElement(it); separator="\n">
|
||||
.end subannotation
|
||||
>>
|
||||
|
@ -5,6 +5,19 @@
|
||||
.implements Lsome/other/interface;
|
||||
|
||||
|
||||
.annotation build Lsome/annotation;
|
||||
value1 = "test"
|
||||
value2 = .subannotation Lsome/annotation;
|
||||
value1 = "test2"
|
||||
value2 = Lsome/enum;
|
||||
.end subannotation
|
||||
.end annotation
|
||||
|
||||
.annotation system Lsome/annotation;
|
||||
.end annotation
|
||||
|
||||
|
||||
|
||||
.field public static aStaticFieldWithoutAnInitializer:I
|
||||
|
||||
.field public static longStaticField:J = 0x300000000L
|
||||
@ -63,6 +76,12 @@
|
||||
|
||||
.method public testMethod(ILjava/lang/String;)Ljava/lang/String;
|
||||
.registers 3
|
||||
.annotation runtime Lorg/junit/Test;
|
||||
.end annotation
|
||||
.annotation system Lyet/another/annotation;
|
||||
somevalue = 1234
|
||||
anothervalue = 3.14159
|
||||
.end annotation
|
||||
|
||||
const-string v0, "testing\n123"
|
||||
|
||||
@ -96,3 +115,13 @@
|
||||
|
||||
.end method
|
||||
|
||||
.method public abstract testMethod2()V
|
||||
.annotation runtime Lsome/annotation;
|
||||
subannotation = .subannotation Lsome/other/annotation;
|
||||
value = "value"
|
||||
.end subannotation
|
||||
.end annotation
|
||||
.annotation runtime Lorg/junit/Test;
|
||||
.end annotation
|
||||
.end method
|
||||
|
||||
|
@ -119,6 +119,14 @@ public class AnnotationDirectoryItem extends OffsettedItem<AnnotationDirectoryIt
|
||||
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
public AnnotationSetItem getClassAnnotations() {
|
||||
return classAnnotationsReferenceField.getReference();
|
||||
}
|
||||
|
||||
public List<MethodAnnotation> getMethodAnnotations() {
|
||||
return methodAnnotationList;
|
||||
}
|
||||
|
||||
public static class FieldAnnotation extends CompositeField<FieldAnnotation>
|
||||
implements Comparable<FieldAnnotation> {
|
||||
private final IndexedItemReference<FieldIdItem> fieldReferenceField;
|
||||
@ -170,6 +178,14 @@ public class AnnotationDirectoryItem extends OffsettedItem<AnnotationDirectoryIt
|
||||
public int compareTo(MethodAnnotation o) {
|
||||
return ((Integer)method.getReference().getIndex()).compareTo(o.method.getReference().getIndex());
|
||||
}
|
||||
|
||||
public MethodIdItem getMethod() {
|
||||
return method.getReference();
|
||||
}
|
||||
|
||||
public AnnotationSetItem getAnnotationSet() {
|
||||
return annotationSet.getReference();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ParameterAnnotation extends CompositeField<ParameterAnnotation>
|
||||
|
@ -60,4 +60,12 @@ public class AnnotationItem extends OffsettedItem<AnnotationItem> {
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
public byte getVisibility() {
|
||||
return (byte)visibilityField.getCachedValue();
|
||||
}
|
||||
|
||||
public AnnotationEncodedValueSubField getEncodedAnnotation() {
|
||||
return annotationField;
|
||||
}
|
||||
}
|
||||
|
@ -74,4 +74,13 @@ public class AnnotationSetItem extends OffsettedItem<AnnotationSetItem> {
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
public List<AnnotationItem> getAnnotationItems() {
|
||||
List<AnnotationItem> annotationItems = new ArrayList<AnnotationItem>();
|
||||
|
||||
for (OffsettedItemReference<AnnotationItem> annotationItemReference: annotationReferences) {
|
||||
annotationItems.add(annotationItemReference.getReference());
|
||||
}
|
||||
return annotationItems;
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +129,10 @@ public class ClassDefItem extends IndexedItem<ClassDefItem> {
|
||||
return classDataReferenceField.getReference();
|
||||
}
|
||||
|
||||
public AnnotationDirectoryItem getAnnotationDirectory() {
|
||||
return classAnnotationsReferenceField.getReference();
|
||||
}
|
||||
|
||||
public String getConciseIdentity() {
|
||||
return "class_def_item: " + getClassName();
|
||||
}
|
||||
|
Reference in New Issue
Block a user