From 98d8015015d78cd7950b20501eef54f4be83f84b Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 16 Nov 2020 20:54:57 +0000 Subject: [PATCH] refactor: split field init attribute --- .../main/java/jadx/core/codegen/ClassGen.java | 7 +-- .../java/jadx/core/codegen/RegionGen.java | 8 +-- .../java/jadx/core/dex/attributes/AType.java | 1 + .../core/dex/attributes/FieldInitAttr.java | 59 ------------------- .../dex/attributes/fldinit/FieldInitAttr.java | 49 +++++++++++++++ .../fldinit/FieldInitConstAttr.java | 30 ++++++++++ .../attributes/fldinit/FieldInitInsnAttr.java | 36 +++++++++++ .../java/jadx/core/dex/info/ConstStorage.java | 7 +-- .../java/jadx/core/dex/nodes/ClassNode.java | 5 +- .../core/dex/visitors/ExtractFieldInit.java | 2 +- .../main/java/jadx/core/utils/InsnUtils.java | 4 +- .../utils/android/AndroidResourcesUtils.java | 2 +- .../android/TestRFieldRestore.java | 2 +- .../input/data/annotations/EncodedValue.java | 23 +++++++- 14 files changed, 155 insertions(+), 80 deletions(-) delete mode 100644 jadx-core/src/main/java/jadx/core/dex/attributes/FieldInitAttr.java create mode 100644 jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitAttr.java create mode 100644 jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitConstAttr.java create mode 100644 jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitInsnAttr.java diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index e2f04c3b..e2aaff52 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -22,8 +22,7 @@ import jadx.core.Consts; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AttrNode; -import jadx.core.dex.attributes.FieldInitAttr; -import jadx.core.dex.attributes.FieldInitAttr.InitType; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.attributes.nodes.EnumClassAttr; import jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField; import jadx.core.dex.attributes.nodes.JadxError; @@ -395,14 +394,14 @@ public class ClassGen { FieldInitAttr fv = f.get(AType.FIELD_INIT); if (fv != null) { code.add(" = "); - if (fv.getValueType() == InitType.CONST) { + if (fv.isConst()) { EncodedValue encodedValue = fv.getEncodedValue(); if (encodedValue.getType() == EncodedType.ENCODED_NULL) { code.add(TypeGen.literalToString(0, f.getType(), cls, fallback)); } else { annotationGen.encodeValue(cls.root(), code, encodedValue); } - } else if (fv.getValueType() == InitType.INSN) { + } else if (fv.isInsn()) { InsnGen insnGen = makeInsnGen(fv.getInsnMth()); addInsnBody(insnGen, code, fv.getInsn()); } diff --git a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java index dd0852d5..f2024945 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java @@ -10,7 +10,7 @@ import org.slf4j.LoggerFactory; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; -import jadx.core.dex.attributes.FieldInitAttr; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.attributes.nodes.DeclareVariablesAttr; import jadx.core.dex.attributes.nodes.ForceReturnAttr; import jadx.core.dex.attributes.nodes.LoopLabelAttr; @@ -287,10 +287,10 @@ public class RegionGen extends InsnGen { staticField(code, fn.getFieldInfo()); // print original value, sometimes replaced with incorrect field FieldInitAttr valueAttr = fn.get(AType.FIELD_INIT); - if (valueAttr != null && valueAttr.getValueType() == FieldInitAttr.InitType.CONST) { - Object value = valueAttr.getEncodedValue(); + if (valueAttr != null && valueAttr.isConst()) { + Object value = valueAttr.getEncodedValue().getValue(); if (value != null) { - code.add(" /*").add(value.toString()).add("*/"); + code.add(" /* ").add(value.toString()).add(" */"); } } } diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java b/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java index 6174838b..96ff236f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java @@ -6,6 +6,7 @@ import java.util.Set; import jadx.core.dex.attributes.annotations.AnnotationsList; import jadx.core.dex.attributes.annotations.MethodParameters; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.attributes.nodes.DeclareVariablesAttr; import jadx.core.dex.attributes.nodes.EdgeInsnAttr; import jadx.core.dex.attributes.nodes.EnumClassAttr; diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/FieldInitAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/FieldInitAttr.java deleted file mode 100644 index 7522511d..00000000 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/FieldInitAttr.java +++ /dev/null @@ -1,59 +0,0 @@ -package jadx.core.dex.attributes; - -import jadx.api.plugins.input.data.annotations.EncodedValue; -import jadx.core.dex.nodes.InsnNode; -import jadx.core.dex.nodes.MethodNode; - -public class FieldInitAttr implements IAttribute { - - public static final FieldInitAttr NULL_VALUE = constValue(EncodedValue.NULL); - - public enum InitType { - CONST, - INSN - } - - private final Object value; - private final InitType valueType; - private final MethodNode insnMth; - - private FieldInitAttr(InitType valueType, Object value, MethodNode insnMth) { - this.value = value; - this.valueType = valueType; - this.insnMth = insnMth; - } - - public static FieldInitAttr constValue(EncodedValue value) { - return new FieldInitAttr(InitType.CONST, value, null); - } - - public static FieldInitAttr insnValue(MethodNode mth, InsnNode insn) { - return new FieldInitAttr(InitType.INSN, insn, mth); - } - - public EncodedValue getEncodedValue() { - return (EncodedValue) value; - } - - public InsnNode getInsn() { - return (InsnNode) value; - } - - public InitType getValueType() { - return valueType; - } - - public MethodNode getInsnMth() { - return insnMth; - } - - @Override - public AType getType() { - return AType.FIELD_INIT; - } - - @Override - public String toString() { - return "V=" + value; - } -} diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitAttr.java new file mode 100644 index 00000000..43bc9108 --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitAttr.java @@ -0,0 +1,49 @@ +package jadx.core.dex.attributes.fldinit; + +import java.util.Objects; + +import jadx.api.plugins.input.data.annotations.EncodedValue; +import jadx.core.dex.attributes.AType; +import jadx.core.dex.attributes.IAttribute; +import jadx.core.dex.nodes.InsnNode; +import jadx.core.dex.nodes.MethodNode; +import jadx.core.utils.exceptions.JadxRuntimeException; + +public abstract class FieldInitAttr implements IAttribute { + + public static FieldInitAttr constValue(EncodedValue value) { + if (Objects.equals(value, EncodedValue.NULL)) { + return FieldInitConstAttr.NULL_VALUE; + } + return new FieldInitConstAttr(value); + } + + public static FieldInitAttr insnValue(MethodNode mth, InsnNode insn) { + return new FieldInitInsnAttr(mth, insn); + } + + public boolean isConst() { + return false; + } + + public boolean isInsn() { + return false; + } + + public EncodedValue getEncodedValue() { + throw new JadxRuntimeException("Wrong init type"); + } + + public InsnNode getInsn() { + throw new JadxRuntimeException("Wrong init type"); + } + + public MethodNode getInsnMth() { + throw new JadxRuntimeException("Wrong init type"); + } + + @Override + public AType getType() { + return AType.FIELD_INIT; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitConstAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitConstAttr.java new file mode 100644 index 00000000..48232109 --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitConstAttr.java @@ -0,0 +1,30 @@ +package jadx.core.dex.attributes.fldinit; + +import jadx.api.plugins.input.data.annotations.EncodedValue; + +import static java.util.Objects.requireNonNull; + +public final class FieldInitConstAttr extends FieldInitAttr { + public static final FieldInitAttr NULL_VALUE = new FieldInitConstAttr(EncodedValue.NULL); + + private final EncodedValue value; + + FieldInitConstAttr(EncodedValue value) { + this.value = requireNonNull(value); + } + + @Override + public EncodedValue getEncodedValue() { + return value; + } + + @Override + public boolean isConst() { + return true; + } + + @Override + public String toString() { + return "INIT{" + value + '}'; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitInsnAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitInsnAttr.java new file mode 100644 index 00000000..b6cb95a4 --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/fldinit/FieldInitInsnAttr.java @@ -0,0 +1,36 @@ +package jadx.core.dex.attributes.fldinit; + +import jadx.core.dex.nodes.InsnNode; +import jadx.core.dex.nodes.MethodNode; + +import static java.util.Objects.requireNonNull; + +public final class FieldInitInsnAttr extends FieldInitAttr { + private final MethodNode mth; + private final InsnNode insn; + + FieldInitInsnAttr(MethodNode mth, InsnNode insn) { + this.mth = requireNonNull(mth); + this.insn = requireNonNull(insn); + } + + @Override + public InsnNode getInsn() { + return insn; + } + + @Override + public MethodNode getInsnMth() { + return mth; + } + + @Override + public boolean isInsn() { + return true; + } + + @Override + public String toString() { + return "INIT{" + insn + '}'; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java b/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java index 46adf650..e2eb4250 100644 --- a/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java +++ b/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java @@ -13,7 +13,7 @@ import org.jetbrains.annotations.Nullable; import jadx.api.JadxArgs; import jadx.core.dex.attributes.AType; -import jadx.core.dex.attributes.FieldInitAttr; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.PrimitiveType; import jadx.core.dex.nodes.ClassNode; @@ -85,10 +85,7 @@ public class ConstStorage { AccessInfo accFlags = f.getAccessFlags(); if (accFlags.isStatic() && accFlags.isFinal()) { FieldInitAttr fv = f.get(AType.FIELD_INIT); - if (fv != null - && fv.getValueType() == FieldInitAttr.InitType.CONST - && fv != FieldInitAttr.NULL_VALUE - && fv.getEncodedValue() != null) { + if (fv != null && fv.isConst() && fv.getEncodedValue().getValue() != null) { addConstField(cls, f, fv.getEncodedValue().getValue(), accFlags.isPublic()); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java index a75ce900..0072ec39 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java @@ -23,8 +23,9 @@ import jadx.api.plugins.input.data.annotations.IAnnotation; import jadx.core.Consts; import jadx.core.ProcessClass; import jadx.core.dex.attributes.AFlag; -import jadx.core.dex.attributes.FieldInitAttr; import jadx.core.dex.attributes.annotations.AnnotationsList; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; +import jadx.core.dex.attributes.fldinit.FieldInitConstAttr; import jadx.core.dex.attributes.nodes.NotificationAttrNode; import jadx.core.dex.attributes.nodes.SourceFileAttr; import jadx.core.dex.info.AccessInfo; @@ -164,7 +165,7 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN for (FieldNode f : staticFields) { if (f.getAccessFlags().isFinal()) { // incorrect initialization will be removed if assign found in constructor - f.addAttr(FieldInitAttr.NULL_VALUE); + f.addAttr(FieldInitConstAttr.NULL_VALUE); } } try { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java index 9f518fe1..80f6fce9 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java @@ -8,7 +8,7 @@ import java.util.Set; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; -import jadx.core.dex.attributes.FieldInitAttr; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.FieldInfo; import jadx.core.dex.instructions.IndexInsnNode; diff --git a/jadx-core/src/main/java/jadx/core/utils/InsnUtils.java b/jadx-core/src/main/java/jadx/core/utils/InsnUtils.java index 69d88de1..3edde3c4 100644 --- a/jadx-core/src/main/java/jadx/core/utils/InsnUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/InsnUtils.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; -import jadx.core.dex.attributes.FieldInitAttr; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.info.FieldInfo; import jadx.core.dex.instructions.ConstClassNode; import jadx.core.dex.instructions.ConstStringNode; @@ -101,7 +101,7 @@ public class InsnUtils { return null; } FieldInitAttr attr = fieldNode.get(AType.FIELD_INIT); - if (attr != null && attr.getValueType() == FieldInitAttr.InitType.CONST) { + if (attr != null && attr.isConst()) { return EncodedValueUtils.convertToConstValue(root, attr.getEncodedValue()); } return null; diff --git a/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java b/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java index 393ddbe3..2ba5d9f1 100644 --- a/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java @@ -17,7 +17,7 @@ import jadx.core.codegen.CodeWriter; import jadx.core.deobf.NameMapper; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; -import jadx.core.dex.attributes.FieldInitAttr; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.ConstStorage; diff --git a/jadx-core/src/test/java/jadx/tests/integration/android/TestRFieldRestore.java b/jadx-core/src/test/java/jadx/tests/integration/android/TestRFieldRestore.java index cc097bee..7edf8956 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/android/TestRFieldRestore.java +++ b/jadx-core/src/test/java/jadx/tests/integration/android/TestRFieldRestore.java @@ -7,7 +7,7 @@ import java.util.Map; import org.junit.jupiter.api.Test; import jadx.core.dex.attributes.AType; -import jadx.core.dex.attributes.FieldInitAttr; +import jadx.core.dex.attributes.fldinit.FieldInitAttr; import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.FieldNode; import jadx.tests.api.IntegrationTest; diff --git a/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/annotations/EncodedValue.java b/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/annotations/EncodedValue.java index 78b4188d..8c799f73 100644 --- a/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/annotations/EncodedValue.java +++ b/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/annotations/EncodedValue.java @@ -1,7 +1,9 @@ package jadx.api.plugins.input.data.annotations; +import java.util.Objects; + public class EncodedValue { - public static final EncodedValue NULL = new EncodedValue(EncodedType.ENCODED_NULL, new Object()); + public static final EncodedValue NULL = new EncodedValue(EncodedType.ENCODED_NULL, null); private final EncodedType type; private final Object value; @@ -19,9 +21,28 @@ public class EncodedValue { return value; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EncodedValue that = (EncodedValue) o; + return type == that.getType() && Objects.equals(value, that.getValue()); + } + + @Override + public int hashCode() { + return Objects.hash(getType(), getValue()); + } + @Override public String toString() { switch (type) { + case ENCODED_NULL: + return "null"; case ENCODED_STRING: return (String) value; case ENCODED_ARRAY: -- GitLab