From fb43d716d9b6811790487ae9d8fda34db68cad88 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 1 Jul 2013 23:49:19 +0400 Subject: [PATCH] Replace constants with matched static final fields --- src/main/java/jadx/dex/nodes/ClassNode.java | 24 ++++++++----- src/main/java/jadx/dex/nodes/DexNode.java | 9 ++++- src/main/java/jadx/dex/nodes/FieldNode.java | 24 ++++++------- .../java/jadx/dex/visitors/ModVisitor.java | 35 ++++++++++++++----- .../dex/visitors/regions/RegionMaker.java | 7 +--- src/samples/java/jadx/samples/TestFields.java | 24 ++++++++++++- 6 files changed, 84 insertions(+), 39 deletions(-) diff --git a/src/main/java/jadx/dex/nodes/ClassNode.java b/src/main/java/jadx/dex/nodes/ClassNode.java index 1a82a6b10..2e0932635 100644 --- a/src/main/java/jadx/dex/nodes/ClassNode.java +++ b/src/main/java/jadx/dex/nodes/ClassNode.java @@ -87,9 +87,9 @@ public class ClassNode extends AttrNode implements ILoadable { setFieldsTypesFromSignature(); int sfIdx = cls.getSourceFileIndex(); - if(sfIdx != DexNode.NO_INDEX) { + if (sfIdx != DexNode.NO_INDEX) { String fileName = dex.getString(sfIdx); - if(!this.getFullName().contains(fileName.replace(".java", ""))) { + if (!this.getFullName().contains(fileName.replace(".java", ""))) { this.getAttributes().add(new SourceFileAttr(fileName)); LOG.debug("Class '{}' compiled from '{}'", this, fileName); } @@ -134,10 +134,14 @@ public class ClassNode extends AttrNode implements ILoadable { parser.processFields(staticFields); for (FieldNode f : staticFields) { - if (f.getType().equals(ArgType.STRING)) { + AccessInfo accFlags = f.getAccessFlags(); + if (accFlags.isStatic() && accFlags.isFinal()) { FieldValueAttr fv = (FieldValueAttr) f.getAttributes().get(AttributeType.FIELD_VALUE); if (fv != null && fv.getValue() != null) { - constFields.put(fv.getValue(), f); + if (accFlags.isPublic()) + dex.getConstFields().put(fv.getValue(), f); + else + constFields.put(fv.getValue(), f); } } } @@ -231,6 +235,13 @@ public class ClassNode extends AttrNode implements ILoadable { return fields; } + public FieldNode getConstField(Object o) { + FieldNode field = constFields.get(o); + if(field == null) + field = dex.getConstFields().get(o); + return field; + } + public FieldNode searchFieldById(int id) { String name = FieldInfo.getNameById(dex, id); for (FieldNode f : fields) { @@ -295,10 +306,6 @@ public class ClassNode extends AttrNode implements ILoadable { return accessFlags; } - public Map getConstFields() { - return constFields; - } - public DexNode dex() { return dex; } @@ -323,5 +330,4 @@ public class ClassNode extends AttrNode implements ILoadable { public String toString() { return getFullName(); } - } diff --git a/src/main/java/jadx/dex/nodes/DexNode.java b/src/main/java/jadx/dex/nodes/DexNode.java index 95239bf4e..f3fb1f029 100644 --- a/src/main/java/jadx/dex/nodes/DexNode.java +++ b/src/main/java/jadx/dex/nodes/DexNode.java @@ -7,7 +7,9 @@ import jadx.utils.exceptions.DecodeException; import jadx.utils.files.InputFile; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.android.dx.io.ClassData; import com.android.dx.io.ClassData.Method; @@ -29,6 +31,8 @@ public class DexNode { private final List classes = new ArrayList(); private final String[] strings; + private final Map constFields = new HashMap(); + public DexNode(RootNode root, InputFile input) { this.root = root; this.dexBuf = input.getDexBuffer(); @@ -59,6 +63,10 @@ public class DexNode { return null; } + public Map getConstFields() { + return constFields; + } + // DexBuffer wrappers public String getString(int index) { @@ -110,5 +118,4 @@ public class DexNode { public String toString() { return "DEX"; } - } diff --git a/src/main/java/jadx/dex/nodes/FieldNode.java b/src/main/java/jadx/dex/nodes/FieldNode.java index 28b367a7e..d9624307e 100644 --- a/src/main/java/jadx/dex/nodes/FieldNode.java +++ b/src/main/java/jadx/dex/nodes/FieldNode.java @@ -3,7 +3,6 @@ package jadx.dex.nodes; import jadx.dex.attributes.AttrNode; import jadx.dex.info.AccessInfo; import jadx.dex.info.AccessInfo.AFType; -import jadx.dex.info.ClassInfo; import jadx.dex.info.FieldInfo; import jadx.dex.instructions.args.ArgType; @@ -11,26 +10,27 @@ import com.android.dx.io.ClassData.Field; public class FieldNode extends AttrNode { + private final FieldInfo fieldInfo; private final AccessInfo accFlags; - private final String name; - private final ClassInfo declClass; - private ArgType type; + private ArgType type; // store signature public FieldNode(ClassNode cls, Field field) { - FieldInfo f = FieldInfo.fromDex(cls.dex(), field.getFieldIndex()); - this.name = f.getName(); - this.type = f.getType(); - this.declClass = f.getDeclClass(); + this.fieldInfo = FieldInfo.fromDex(cls.dex(), field.getFieldIndex()); + this.type = fieldInfo.getType(); this.accFlags = new AccessInfo(field.getAccessFlags(), AFType.FIELD); } + public FieldInfo getFieldInfo() { + return fieldInfo; + } + public AccessInfo getAccessFlags() { return accFlags; } public String getName() { - return name; + return fieldInfo.getName(); } public ArgType getType() { @@ -41,12 +41,8 @@ public class FieldNode extends AttrNode { this.type = type; } - public ClassInfo getDeclClass() { - return declClass; - } - @Override public String toString() { - return declClass + "." + name + " " + type; + return fieldInfo.getDeclClass() + "." + fieldInfo.getName() + " " + type; } } diff --git a/src/main/java/jadx/dex/visitors/ModVisitor.java b/src/main/java/jadx/dex/visitors/ModVisitor.java index 024134b9c..d3b23d82f 100644 --- a/src/main/java/jadx/dex/visitors/ModVisitor.java +++ b/src/main/java/jadx/dex/visitors/ModVisitor.java @@ -7,10 +7,13 @@ import jadx.dex.info.MethodInfo; import jadx.dex.instructions.IndexInsnNode; import jadx.dex.instructions.InsnType; import jadx.dex.instructions.InvokeNode; +import jadx.dex.instructions.args.ArgType; import jadx.dex.instructions.args.InsnArg; +import jadx.dex.instructions.args.LiteralArg; import jadx.dex.instructions.args.RegisterArg; import jadx.dex.instructions.mods.ConstructorInsn; import jadx.dex.nodes.BlockNode; +import jadx.dex.nodes.ClassNode; import jadx.dex.nodes.FieldNode; import jadx.dex.nodes.InsnNode; import jadx.dex.nodes.MethodNode; @@ -96,15 +99,31 @@ public class ModVisitor extends AbstractVisitor { break; case CONST: + ClassNode parentClass = mth.getParentClass(); + FieldNode f = null; if (insn.getArgsCount() == 0) { // const-string IndexInsnNode node = (IndexInsnNode) insn; - FieldNode f = mth.getParentClass().getConstFields().get(node.getIndex()); - if (f != null) { - InsnNode inode = new IndexInsnNode(InsnType.SGET, f, 0); - inode.setResult(insn.getResult()); - replaceInsn(block, i, inode); + f = parentClass.getConstField(node.getIndex()); + } else { + LiteralArg arg = (LiteralArg) insn.getArg(0); + ArgType type = arg.getType(); + long lit = arg.getLiteral(); + if (Math.abs(lit) > 0xFF) { + if (type.equals(ArgType.INT)) + f = parentClass.getConstField((int) lit); + else if (type.equals(ArgType.LONG)) + f = parentClass.getConstField(lit); } + if (type.equals(ArgType.DOUBLE)) + f = parentClass.getConstField(Double.longBitsToDouble(lit)); + else if (type.equals(ArgType.FLOAT)) + f = parentClass.getConstField(Float.intBitsToFloat((int) lit)); + } + if (f != null) { + InsnNode inode = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0); + inode.setResult(insn.getResult()); + replaceInsn(block, i, inode); } break; @@ -233,10 +252,10 @@ public class ModVisitor extends AbstractVisitor { } private void checkArgsNames(MethodNode mth) { - for(RegisterArg arg : mth.getArguments(false)) { + for (RegisterArg arg : mth.getArguments(false)) { String name = arg.getTypedVar().getName(); - if(name != null && NameMapper.isReserved(name)) { - name = name + "_" ; + if (name != null && NameMapper.isReserved(name)) { + name = name + "_"; arg.getTypedVar().setName(name); } } diff --git a/src/main/java/jadx/dex/visitors/regions/RegionMaker.java b/src/main/java/jadx/dex/visitors/regions/RegionMaker.java index 3bbcd40fd..c953e6990 100644 --- a/src/main/java/jadx/dex/visitors/regions/RegionMaker.java +++ b/src/main/java/jadx/dex/visitors/regions/RegionMaker.java @@ -407,12 +407,7 @@ public class RegionMaker { otherNode.invertOp(elseOffset); } IfCondition newArg = IfCondition.fromIfBlock(pred); - IfCondition condition; - if (otherNode.getTarget() != pred.getStartOffset()) { - condition = IfCondition.and(ifRegion.getCondition(), newArg); - } else { - condition = IfCondition.or(ifRegion.getCondition(), newArg); - } + IfCondition condition = IfCondition.and(ifRegion.getCondition(), newArg); ifRegion.setCondition(condition); pred.getAttributes().add(AttributeFlag.SKIP); } diff --git a/src/samples/java/jadx/samples/TestFields.java b/src/samples/java/jadx/samples/TestFields.java index f1c2644a0..fbce500e8 100644 --- a/src/samples/java/jadx/samples/TestFields.java +++ b/src/samples/java/jadx/samples/TestFields.java @@ -4,6 +4,14 @@ import java.util.Arrays; public class TestFields extends AbstractTest { + public static class ConstFields { + public static final boolean BOOL = false; + public static final int CONST_INT = 56789; + public static final int ZERO = 0; + public static final String STR = "string"; + public static final double PI = 3.14; + } + private static final boolean fbz = false; private static final boolean fb = true; private static final int fi = 5; @@ -12,14 +20,28 @@ public class TestFields extends AbstractTest { private static final String fstr = "final string"; private static final double fd = 3.14; - private static final double[] fda = new double[] { 3.14, 2.7 }; + private static final double[] fda = new double[]{3.14, 2.7}; private static int si = 5; + public void testConstsFields() { + int r = ConstFields.CONST_INT; + r += ConstFields.BOOL ? 1 : 0; + r += ConstFields.ZERO * 5; + r += ConstFields.STR.length() + ConstFields.STR.indexOf('i'); + r += Math.round(ConstFields.PI); + assertEquals(r, 56801); + } + @Override public boolean testRun() throws Exception { + testConstsFields(); + String str = "" + fbz + fiz + fb + fi + fstr + fd + Arrays.toString(fda) + si; return str.equals("false0true5final string3.14[3.14, 2.7]5"); } + public static void main(String[] args) throws Exception { + new TestFields().testRun(); + } }