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 4b4a7666a..de81ced72 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java @@ -5,8 +5,10 @@ import jadx.core.dex.attributes.AttributeType; import jadx.core.dex.attributes.DeclareVariableAttr; import jadx.core.dex.attributes.ForceReturnAttr; import jadx.core.dex.attributes.IAttribute; +import jadx.core.dex.info.FieldInfo; import jadx.core.dex.instructions.ArithNode; import jadx.core.dex.instructions.IfOp; +import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.args.ArgType; @@ -236,11 +238,16 @@ public class RegionGen extends InsnGen { int size = sw.getKeys().size(); for (int i = 0; i < size; i++) { - List keys = sw.getKeys().get(i); + List keys = sw.getKeys().get(i); IContainer c = sw.getCases().get(i); - for (Integer k : keys) { + for (Object k : keys) { code.startLine("case "); - code.add(TypeGen.literalToString(k, arg.getType())); + if (k instanceof IndexInsnNode) { + code.add(sfield((FieldInfo) ((IndexInsnNode) k).getIndex())); + } + else { + code.add(TypeGen.literalToString((Integer) k, arg.getType())); + } code.add(':'); } makeCaseBlock(c, code); @@ -305,4 +312,12 @@ public class RegionGen extends InsnGen { } } -} + private String sfield(FieldInfo field) { + String thisClass = mth.getParentClass().getFullName(); + if (field.getDeclClass().getFullName().equals(thisClass)) { + return field.getName(); + } else { + return useClass(field.getDeclClass()) + '.' + field.getName(); + } + } +} \ No newline at end of file diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java b/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java index 99d038d1d..18815080f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java @@ -571,19 +571,21 @@ public class InsnDecoder { private InsnNode decodeSwitch(DecodedInstruction insn, int offset, boolean packed) { int payloadOffset = insn.getTarget(); DecodedInstruction payload = insnArr[payloadOffset]; - int[] keys; + Object[] keys; int[] targets; if (packed) { PackedSwitchPayloadDecodedInstruction ps = (PackedSwitchPayloadDecodedInstruction) payload; targets = ps.getTargets(); - keys = new int[targets.length]; + keys = new Object[targets.length]; int k = ps.getFirstKey(); for (int i = 0; i < keys.length; i++) keys[i] = k++; } else { SparseSwitchPayloadDecodedInstruction ss = (SparseSwitchPayloadDecodedInstruction) payload; targets = ss.getTargets(); - keys = ss.getKeys(); + keys = new Object[targets.length]; + for (int i = 0; i < keys.length; i++) + keys[i] = ss.getKeys()[i]; } // convert from relative to absolute offsets for (int i = 0; i < targets.length; i++) { diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchNode.java b/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchNode.java index 82cd9b648..d68be5854 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchNode.java @@ -8,11 +8,11 @@ import java.util.Arrays; public class SwitchNode extends InsnNode { - private final int[] keys; + private final Object[] keys; private final int[] targets; private final int def; // next instruction - public SwitchNode(InsnArg arg, int[] keys, int[] targets, int def) { + public SwitchNode(InsnArg arg, Object[] keys, int[] targets, int def) { super(InsnType.SWITCH, 1); this.keys = keys; this.targets = targets; @@ -24,7 +24,7 @@ public class SwitchNode extends InsnNode { return keys.length; } - public int[] getKeys() { + public Object[] getKeys() { return keys; } 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 7ec8fe206..ac68d653a 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 @@ -237,7 +237,15 @@ public class ClassNode extends LineAttrNode implements ILoadable { } public FieldNode getConstField(Object o) { - FieldNode field = constFields.get(o); + ClassNode cn = this; + FieldNode field; + do { + field = cn.constFields.get(o); + } + while (field == null + && (cn.clsInfo.getParentClass() != null) + && (cn = dex.resolveClass(cn.clsInfo.getParentClass())) != null); + if (field == null) field = dex.getConstFields().get(o); return field; diff --git a/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java b/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java index 9eb52d76a..debd0434d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java +++ b/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java @@ -12,14 +12,14 @@ public final class SwitchRegion extends AbstractRegion { private final BlockNode header; - private final List> keys; + private final List> keys; private final List cases; private IContainer defCase; public SwitchRegion(IRegion parent, BlockNode header) { super(parent); this.header = header; - this.keys = new ArrayList>(); + this.keys = new ArrayList>(); this.cases = new ArrayList(); } @@ -27,7 +27,7 @@ public final class SwitchRegion extends AbstractRegion { return header; } - public void addCase(List keysList, IContainer c) { + public void addCase(List keysList, IContainer c) { keys.add(keysList); cases.add(c); } @@ -40,7 +40,7 @@ public final class SwitchRegion extends AbstractRegion { return defCase; } - public List> getKeys() { + public List> getKeys() { return keys; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java index 36621fae0..fd5602dad 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java @@ -9,6 +9,7 @@ import jadx.core.dex.instructions.FillArrayNode; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InvokeNode; +import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.LiteralArg; @@ -114,16 +115,16 @@ public class ModVisitor extends AbstractVisitor { LiteralArg arg = (LiteralArg) insn.getArg(0); ArgType type = arg.getType(); long lit = arg.getLiteral(); - if (Math.abs(lit) > 0xFF) { + if (type.equals(ArgType.DOUBLE)) + f = parentClass.getConstField(Double.longBitsToDouble(lit)); + else if (type.equals(ArgType.FLOAT)) + f = parentClass.getConstField(Float.intBitsToFloat((int) lit)); + else if (Math.abs(lit) > 0x1) { 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); @@ -132,6 +133,19 @@ public class ModVisitor extends AbstractVisitor { } break; + case SWITCH: + SwitchNode sn = (SwitchNode) insn; + parentClass = mth.getParentClass(); + f = null; + for (int k = 0; k < sn.getCasesCount(); k++) { + f = parentClass.getConstField((Integer) sn.getKeys()[k]); + if (f != null) { + InsnNode inode = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0); + sn.getKeys()[k] = inode; + } + } + break; + default: break; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java index fb7f77018..dbe80836d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java @@ -583,21 +583,21 @@ public class RegionMaker { int len = insn.getTargets().length; // sort by target - Map> casesMap = new LinkedHashMap>(len); + Map> casesMap = new LinkedHashMap>(len); for (int i = 0; i < len; i++) { - int key = insn.getKeys()[i]; + Object key = insn.getKeys()[i]; int targ = insn.getTargets()[i]; - List keys = casesMap.get(targ); + List keys = casesMap.get(targ); if (keys == null) { - keys = new ArrayList(1); + keys = new ArrayList(2); casesMap.put(targ, keys); } keys.add(key); } - Map> blocksMap = new LinkedHashMap>(len); - for (Entry> entry : casesMap.entrySet()) { - BlockNode c = getBlockByOffset(entry.getKey(), block.getSuccessors()); + Map> blocksMap = new LinkedHashMap>(len); + for (Entry> entry : casesMap.entrySet()) { + BlockNode c = getBlockByOffset((int) entry.getKey(), block.getSuccessors()); assert c != null; blocksMap.put(c, entry.getValue()); } @@ -650,7 +650,7 @@ public class RegionMaker { if (!stack.containsExit(defCase)) { sw.setDefaultCase(makeRegion(defCase, stack)); } - for (Entry> entry : blocksMap.entrySet()) { + for (Entry> entry : blocksMap.entrySet()) { BlockNode c = entry.getKey(); if (stack.containsExit(c)) { // empty case block