mirror of
https://github.com/revanced/smali.git
synced 2025-05-29 12:20:11 +02:00
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
This commit is contained in:
parent
05c9404ecd
commit
090e553f34
@ -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<AnnotationSetItem> fieldAnnotationsMap;
|
||||
private SparseArray<AnnotationSetRefList> parameterAnnotationsMap;
|
||||
|
||||
private SparseArray<FieldIdItem> 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<FieldIdItem>();
|
||||
|
||||
if (classDataItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ClassDataItem.EncodedMethod directMethod: classDataItem.getDirectMethods()) {
|
||||
if (directMethod.method.getMethodName().getStringValue().equals("<clinit>")) {
|
||||
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<String> getAccessFlags() {
|
||||
List<String> accessFlags = new ArrayList<String>();
|
||||
|
||||
@ -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<StringTemplate> getDirectMethods() {
|
||||
|
@ -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<String> getAccessFlags(ClassDataItem.EncodedField encodedField) {
|
||||
|
@ -80,8 +80,11 @@ annotation(Visibility, AnnotationType, Elements) ::=
|
||||
|
||||
|
||||
|
||||
field(AccessFlags, FieldName, FieldType, Annotations, InitialValue) ::=
|
||||
field(AccessFlags, FieldName, FieldType, Annotations, InitialValue, Comments) ::=
|
||||
<<
|
||||
<if(Comments)><Comments: {#<it>} ; separator="\n">
|
||||
|
||||
<endif>
|
||||
.field <AccessFlags: {<it> }><FieldName>:<FieldType><if(InitialValue)> = <InitialValue><endif>
|
||||
<if(Annotations)>
|
||||
<Annotations; separator="\n\n">
|
||||
|
Loading…
x
Reference in New Issue
Block a user