From 090e553f34a176bc558f0d70392181c0fbd83fe8 Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Sat, 19 Sep 2009 04:48:50 +0000 Subject: [PATCH] check if a static final field is set within the static constructor, and if so, add a comment stating such if it makes sense to do so (for primitive types, or reference/array types that have a non-null initializer) git-svn-id: https://smali.googlecode.com/svn/trunk@481 55b6fa8a-2a1e-11de-a435-ffa8d773f76a --- .../jf/baksmali/Adaptors/ClassDefinition.java | 63 ++++++++++++++++++- .../jf/baksmali/Adaptors/FieldDefinition.java | 24 ++++++- .../templates/templates/baksmali.stg | 5 +- 3 files changed, 86 insertions(+), 6 deletions(-) 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 cdac63c0..4b5f14b9 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java @@ -30,6 +30,10 @@ package org.jf.baksmali.Adaptors; import org.jf.dexlib.EncodedValue.EncodedValue; import org.jf.dexlib.*; +import org.jf.dexlib.Code.InstructionIterator; +import org.jf.dexlib.Code.Opcode; +import org.jf.dexlib.Code.Format.Format; +import org.jf.dexlib.Code.Format.Instruction21c; import org.jf.dexlib.Util.AccessFlags; import org.jf.dexlib.Util.SparseArray; import org.antlr.stringtemplate.StringTemplate; @@ -46,11 +50,14 @@ public class ClassDefinition { private SparseArray fieldAnnotationsMap; private SparseArray parameterAnnotationsMap; + private SparseArray fieldsSetInStaticConstructor; + public ClassDefinition(StringTemplateGroup stg, ClassDefItem classDefItem) { this.stg = stg; this.classDefItem = classDefItem; this.classDataItem = classDefItem.getClassData(); buildAnnotationMaps(); + findFieldsSetInStaticConstructor(); } public StringTemplate makeTemplate() { @@ -103,6 +110,52 @@ public class ClassDefinition { }); } + private void findFieldsSetInStaticConstructor() { + fieldsSetInStaticConstructor = new SparseArray(); + + if (classDataItem == null) { + return; + } + + for (ClassDataItem.EncodedMethod directMethod: classDataItem.getDirectMethods()) { + if (directMethod.method.getMethodName().getStringValue().equals("")) { + final byte[] encodedInstructions = directMethod.codeItem.getEncodedInstructions(); + + InstructionIterator.IterateInstructions(encodedInstructions, + new InstructionIterator.ProcessRawInstructionDelegate() { + public void ProcessNormalInstruction(Opcode opcode, int index) { + } + + public void ProcessReferenceInstruction(Opcode opcode, int index) { + switch (opcode) { + case SPUT: + case SPUT_BOOLEAN: + case SPUT_BYTE: + case SPUT_CHAR: + case SPUT_OBJECT: + case SPUT_SHORT: + case SPUT_WIDE: + Instruction21c ins = (Instruction21c)Format.Format21c.Factory.makeInstruction( + classDefItem.getDexFile(), opcode, encodedInstructions, index); + FieldIdItem fieldIdItem = (FieldIdItem)ins.getReferencedItem(); + fieldsSetInStaticConstructor.put(fieldIdItem.getIndex(), fieldIdItem); + } + } + + public void ProcessPackedSwitchInstruction(int index, int targetCount, int instructionLength) { + } + + public void ProcessSparseSwitchInstruction(int index, int targetCount, int instructionLength) { + } + + public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount, int instructionLength) { + } + }); + + } + } + } + private List getAccessFlags() { List accessFlags = new ArrayList(); @@ -141,7 +194,7 @@ public class ClassDefinition { interfaces.add(typeIdItem.getTypeDescriptor()); } } - + return interfaces; } @@ -185,7 +238,11 @@ public class ClassDefinition { } AnnotationSetItem annotationSet = fieldAnnotationsMap.get(field.field.getIndex()); - staticFields.add(FieldDefinition.createTemplate(stg, field, encodedValue, annotationSet)); + boolean setInStaticConstructor = + fieldsSetInStaticConstructor.get(field.field.getIndex()) != null; + + staticFields.add(FieldDefinition.createTemplate(stg, field, encodedValue, annotationSet, + setInStaticConstructor)); i++; } } @@ -202,7 +259,7 @@ public class ClassDefinition { } } - return instanceFields; + return instanceFields; } private List getDirectMethods() { diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java index 6c711f47..6e4e6d90 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java @@ -31,6 +31,7 @@ package org.jf.baksmali.Adaptors; import org.jf.baksmali.Adaptors.EncodedValue.EncodedValueAdaptor; import org.jf.dexlib.ClassDataItem; import org.jf.dexlib.EncodedValue.EncodedValue; +import org.jf.dexlib.EncodedValue.NullEncodedValue; import org.jf.dexlib.AnnotationSetItem; import org.jf.dexlib.AnnotationItem; import org.jf.dexlib.Util.AccessFlags; @@ -42,13 +43,32 @@ import java.util.List; public class FieldDefinition { public static StringTemplate createTemplate(StringTemplateGroup stg, ClassDataItem.EncodedField encodedField, - EncodedValue initialValue, AnnotationSetItem annotationSet) { + EncodedValue initialValue, AnnotationSetItem annotationSet, + boolean setInStaticConstructor) { StringTemplate template = stg.getInstanceOf("field"); + String fieldTypeDescriptor = encodedField.field.getFieldType().getTypeDescriptor(); + template.setAttribute("AccessFlags", getAccessFlags(encodedField)); template.setAttribute("FieldName", encodedField.field.getFieldName().getStringValue()); template.setAttribute("FieldType", encodedField.field.getFieldType().getTypeDescriptor()); template.setAttribute("Annotations", getAnnotations(stg, annotationSet)); + + if (setInStaticConstructor && + encodedField.isStatic() && + (encodedField.accessFlags & AccessFlags.FINAL.getValue()) != 0 && + initialValue != null && + ( + //it's a primitive type, or it's an array/reference type and the initial value isn't null + fieldTypeDescriptor.length() == 1 || + initialValue != NullEncodedValue.NullValue + )) { + + template.setAttribute("Comments", + new String[]{"the value of this static final field might be set in the static constructor"}); + } else { + template.setAttribute("Comments", null); + } if (initialValue != null) { template.setAttribute("InitialValue", EncodedValueAdaptor.make(stg, initialValue)); @@ -59,7 +79,7 @@ public class FieldDefinition { public static StringTemplate createTemplate(StringTemplateGroup stg, ClassDataItem.EncodedField encodedField, AnnotationSetItem annotationSet) { - return createTemplate(stg, encodedField, null, annotationSet); + return createTemplate(stg, encodedField, null, annotationSet, false); } private static List getAccessFlags(ClassDataItem.EncodedField encodedField) { diff --git a/baksmali/src/main/resources/templates/templates/baksmali.stg b/baksmali/src/main/resources/templates/templates/baksmali.stg index aa04f2dc..82e2e3b6 100644 --- a/baksmali/src/main/resources/templates/templates/baksmali.stg +++ b/baksmali/src/main/resources/templates/templates/baksmali.stg @@ -80,8 +80,11 @@ annotation(Visibility, AnnotationType, Elements) ::= -field(AccessFlags, FieldName, FieldType, Annotations, InitialValue) ::= +field(AccessFlags, FieldName, FieldType, Annotations, InitialValue, Comments) ::= << +} ; separator="\n"> + + .field }>: =