diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java index 87710768..6cf81fe6 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java @@ -40,6 +40,7 @@ public class ClassDefinition { private HashMap methodAnnotations = new HashMap(); private HashMap fieldAnnotations = new HashMap(); + private HashMap parameterAnnotations = new HashMap(); public ClassDefinition(ClassDefItem classDefItem) { this.classDefItem = classDefItem; @@ -54,18 +55,26 @@ public class ClassDefinition { } List methodAnnotationList = annotationDirectory.getMethodAnnotations(); - if (methodAnnotations != null) { + if (methodAnnotationList != null) { for (AnnotationDirectoryItem.MethodAnnotation methodAnnotation: methodAnnotationList) { methodAnnotations.put(methodAnnotation.getMethod().getIndex(), methodAnnotation.getAnnotationSet()); } } List fieldAnnotationList = annotationDirectory.getFieldAnnotations(); - if (fieldAnnotations != null) { + if (fieldAnnotationList != null) { for (AnnotationDirectoryItem.FieldAnnotation fieldAnnotation: fieldAnnotationList) { fieldAnnotations.put(fieldAnnotation.getField().getIndex(), fieldAnnotation.getAnnotationSet()); } } + + List parameterAnnotationList = + annotationDirectory.getParameterAnnotations(); + if (parameterAnnotationList != null) { + for (AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation: parameterAnnotationList) { + parameterAnnotations.put(parameterAnnotation.getMethod().getIndex(), parameterAnnotation.getParameterAnnotations()); + } + } } public List getAccessFlags() { @@ -151,7 +160,8 @@ public class ClassDefinition { if (classDataItem != null) { for (ClassDataItem.EncodedMethod method: classDataItem.getDirectMethods()) { AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex()); - directMethods.add(new MethodDefinition(method, annotationSet)); + AnnotationSetRefList parameterAnnotationList = parameterAnnotations.get(method.getMethod().getIndex()); + directMethods.add(new MethodDefinition(method, annotationSet, parameterAnnotationList)); } } @@ -164,7 +174,8 @@ public class ClassDefinition { if (classDataItem != null) { for (ClassDataItem.EncodedMethod method: classDataItem.getVirtualMethods()) { AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex()); - virtualMethods.add(new MethodDefinition(method, annotationSet)); + AnnotationSetRefList parameterAnnotationList = parameterAnnotations.get(method.getMethod().getIndex()); + virtualMethods.add(new MethodDefinition(method, annotationSet, parameterAnnotationList)); } } diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java index b9fe9ee4..8ca4b85a 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java @@ -44,12 +44,15 @@ public class MethodDefinition { private MethodIdItem methodIdItem; private CodeItem codeItem; private AnnotationSetItem annotationSet; + private AnnotationSetRefList parameterAnnotations; - public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod, AnnotationSetItem annotationSet) { + public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod, AnnotationSetItem annotationSet, + AnnotationSetRefList parameterAnnotations) { this.encodedMethod = encodedMethod; this.methodIdItem = encodedMethod.getMethod(); this.codeItem = encodedMethod.getCodeItem(); this.annotationSet = annotationSet; + this.parameterAnnotations = parameterAnnotations; } private String methodName = null; @@ -113,6 +116,86 @@ public class MethodDefinition { return annotationAdaptors; } + public List getParameters() { + DebugInfoItem debugInfoItem = null; + if (codeItem != null) { + debugInfoItem = codeItem.getDebugInfo(); + } + + int parameterCount = 0; + + List annotations = new ArrayList(); + if (parameterAnnotations != null) { + List _annotations = parameterAnnotations.getAnnotationSets(); + if (_annotations != null) { + annotations.addAll(_annotations); + } + + parameterCount = annotations.size(); + } + + List parameterNames = new ArrayList(); + if (debugInfoItem != null) { + List _parameterNames = debugInfoItem.getParameterNames(); + if (_parameterNames != null) { + parameterNames.addAll(_parameterNames); + } + + if (parameterCount < parameterNames.size()) { + parameterCount = parameterNames.size(); + } + } + + List parameterAdaptors = new ArrayList(); + for (int i=0; i> getParameterAnnotations() { + if (parameterAnnotations == null) { + return null; + } + + List> parameterAnnotationList = new ArrayList>(); + + List annotationSets = parameterAnnotations.getAnnotationSets(); + + for (AnnotationSetItem annotationSet: annotationSets) { + List parameterAnnotationAdaptors = new ArrayList(); + for (AnnotationItem annotationItem: annotationSet.getAnnotationItems()) { + parameterAnnotationAdaptors.add(new AnnotationAdaptor(annotationItem)); + } + parameterAnnotationList.add(parameterAnnotationAdaptors); + } + + return parameterAnnotationList; + } + + public List getParameterNames() { + if (codeItem == null) { + return null; + } + + DebugInfoItem debugInfoItem = codeItem.getDebugInfo(); + if (debugInfoItem == null) { + return null; + } + + return debugInfoItem.getParameterNames(); + } private List methodItems = null; public List getMethodItems() { @@ -358,7 +441,7 @@ public class MethodDefinition { if (debugInfoItem == null) { return; } - + DebugInfoDecoder decoder = new DebugInfoDecoder(debugInfoItem, new DebugInfoDelegate(), codeItem.getRegisterCount()); decoder.decode(); diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ParameterAdaptor.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ParameterAdaptor.java new file mode 100644 index 00000000..d91d4c18 --- /dev/null +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ParameterAdaptor.java @@ -0,0 +1,61 @@ +/* + * [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.AnnotationSetItem; +import org.jf.dexlib.AnnotationItem; + +import java.util.List; +import java.util.ArrayList; + +public class ParameterAdaptor { + private String parameterName; + private AnnotationSetItem parameterAnnotations; + + public ParameterAdaptor(String parameterName, AnnotationSetItem parameterAnnotations) { + this.parameterName = parameterName; + this.parameterAnnotations = parameterAnnotations; + } + + public String getParameterName() { + return parameterName; + } + + public List getAnnotations() { + if (parameterAnnotations == null) { + return null; + } + + List annotations = new ArrayList(); + for (AnnotationItem annotationItem: parameterAnnotations.getAnnotationItems()) { + annotations.add(new AnnotationAdaptor(annotationItem)); + } + return annotations; + } +} diff --git a/baksmali/src/main/resources/templates/baksmali.stg b/baksmali/src/main/resources/templates/baksmali.stg index 25ffa4e6..2cbe4d55 100644 --- a/baksmali/src/main/resources/templates/baksmali.stg +++ b/baksmali/src/main/resources/templates/baksmali.stg @@ -93,6 +93,9 @@ method(methodDef) ::= .method .registers + + + @@ -111,6 +114,15 @@ MethodItem(MethodItem) ::= >> +Parameter(Parameter) ::= +<< +.parameter "" + + +.end parameter + +>> + Format31tLabelMap ::= [ diff --git a/baksmali/src/test/smali/baksmali_test_class.smali b/baksmali/src/test/smali/baksmali_test_class.smali index ddc1f70b..6ae17270 100644 --- a/baksmali/src/test/smali/baksmali_test_class.smali +++ b/baksmali/src/test/smali/baksmali_test_class.smali @@ -166,9 +166,27 @@ .end method -.method public debugTest()V +.method public debugTest(IIIII)V .registers 10 + .parameter "Blah" + .parameter + .parameter "BlahWithAnnotations" + .annotation runtime Lsome/annotation; + something = "some value" + somethingelse = 1234 + .end annotation + .annotation runtime La/second/annotation; + .end annotation + .end parameter + .parameter + .annotation runtime Lsome/annotation; + something = "some value" + somethingelse = 1234 + .end annotation + .end parameter + .parameter "LastParam" + .prologue nop diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java index 7936fa80..568399a7 100644 --- a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java @@ -131,6 +131,9 @@ public class AnnotationDirectoryItem extends OffsettedItem)fieldAnnotationList.clone(); } + public List getParameterAnnotations() { + return (List)parameterAnnotationList.clone(); + } public static class FieldAnnotation extends CompositeField @@ -204,27 +207,36 @@ public class AnnotationDirectoryItem extends OffsettedItem implements Comparable { - private final IndexedItemReference method; - private final OffsettedItemReference parameterAnnotations; - + private final IndexedItemReference methodReferenceField; + private final OffsettedItemReference parameterAnnotationsReferenceField; + public ParameterAnnotation(DexFile dexFile) { super("parameter_annotation"); fields = new Field[] { - method = new IndexedItemReference(dexFile.MethodIdsSection, + methodReferenceField = new IndexedItemReference(dexFile.MethodIdsSection, new IntegerField(null), "method_idx"), - parameterAnnotations = new OffsettedItemReference( + parameterAnnotationsReferenceField = new OffsettedItemReference( dexFile.AnnotationSetRefListsSection, new IntegerField(null), "annotations_off") }; } public ParameterAnnotation(DexFile dexFile, MethodIdItem method, AnnotationSetRefList parameterAnnotations) { this(dexFile); - this.method.setReference(method); - this.parameterAnnotations.setReference(parameterAnnotations); + this.methodReferenceField.setReference(method); + this.parameterAnnotationsReferenceField.setReference(parameterAnnotations); } public int compareTo(ParameterAnnotation o) { - return ((Integer)method.getReference().getIndex()).compareTo(o.method.getReference().getIndex()); + return ((Integer) methodReferenceField.getReference().getIndex()).compareTo(o.methodReferenceField.getReference().getIndex()); } + + public MethodIdItem getMethod() { + return methodReferenceField.getReference(); + } + + public AnnotationSetRefList getParameterAnnotations() { + return parameterAnnotationsReferenceField.getReference(); + } + } } diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java index 431ed724..98aed076 100644 --- a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java +++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java @@ -74,4 +74,18 @@ public class AnnotationSetRefList extends OffsettedItem { public String getConciseIdentity() { return "annotation_set_item @0x" + Integer.toHexString(getOffset()); } + + public int getCount() { + return annotationSetReferences.size(); + } + + public List getAnnotationSets() { + List annotationSets = new ArrayList(); + + for (OffsettedItemReference annotationSetReference: annotationSetReferences) { + annotationSets.add(annotationSetReference.getReference()); + } + + return annotationSets; + } } diff --git a/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java b/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java index c6dfc003..675a9eaa 100644 --- a/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java @@ -98,6 +98,20 @@ public class DebugInfoItem extends OffsettedItem { return (List)instructionFields.clone(); } + public List getParameterNames() { + List parameterNamesList = new ArrayList(); + + for (IndexedItemReference parameterNameReference: parameterNames) { + StringIdItem parameterNameItem = parameterNameReference.getReference(); + if (parameterNameItem == null) { + parameterNamesList.add(null); + } else { + parameterNamesList.add(parameterNameItem.getStringValue()); + } + } + return parameterNamesList; + } + private class DebugInstructionList implements Field {