Commit 86b04586 authored by 13.beta2's avatar 13.beta2

core: replace switch labels with matched static final fields, searching up to root ClassNode

parent 36cfc9d1
...@@ -5,8 +5,10 @@ import jadx.core.dex.attributes.AttributeType; ...@@ -5,8 +5,10 @@ import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.attributes.DeclareVariableAttr; import jadx.core.dex.attributes.DeclareVariableAttr;
import jadx.core.dex.attributes.ForceReturnAttr; import jadx.core.dex.attributes.ForceReturnAttr;
import jadx.core.dex.attributes.IAttribute; import jadx.core.dex.attributes.IAttribute;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.instructions.ArithNode; import jadx.core.dex.instructions.ArithNode;
import jadx.core.dex.instructions.IfOp; import jadx.core.dex.instructions.IfOp;
import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.SwitchNode;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
...@@ -236,11 +238,16 @@ public class RegionGen extends InsnGen { ...@@ -236,11 +238,16 @@ public class RegionGen extends InsnGen {
int size = sw.getKeys().size(); int size = sw.getKeys().size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
List<Integer> keys = sw.getKeys().get(i); List<Object> keys = sw.getKeys().get(i);
IContainer c = sw.getCases().get(i); IContainer c = sw.getCases().get(i);
for (Integer k : keys) { for (Object k : keys) {
code.startLine("case "); 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(':'); code.add(':');
} }
makeCaseBlock(c, code); makeCaseBlock(c, code);
...@@ -305,4 +312,12 @@ public class RegionGen extends InsnGen { ...@@ -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
...@@ -571,19 +571,21 @@ public class InsnDecoder { ...@@ -571,19 +571,21 @@ public class InsnDecoder {
private InsnNode decodeSwitch(DecodedInstruction insn, int offset, boolean packed) { private InsnNode decodeSwitch(DecodedInstruction insn, int offset, boolean packed) {
int payloadOffset = insn.getTarget(); int payloadOffset = insn.getTarget();
DecodedInstruction payload = insnArr[payloadOffset]; DecodedInstruction payload = insnArr[payloadOffset];
int[] keys; Object[] keys;
int[] targets; int[] targets;
if (packed) { if (packed) {
PackedSwitchPayloadDecodedInstruction ps = (PackedSwitchPayloadDecodedInstruction) payload; PackedSwitchPayloadDecodedInstruction ps = (PackedSwitchPayloadDecodedInstruction) payload;
targets = ps.getTargets(); targets = ps.getTargets();
keys = new int[targets.length]; keys = new Object[targets.length];
int k = ps.getFirstKey(); int k = ps.getFirstKey();
for (int i = 0; i < keys.length; i++) for (int i = 0; i < keys.length; i++)
keys[i] = k++; keys[i] = k++;
} else { } else {
SparseSwitchPayloadDecodedInstruction ss = (SparseSwitchPayloadDecodedInstruction) payload; SparseSwitchPayloadDecodedInstruction ss = (SparseSwitchPayloadDecodedInstruction) payload;
targets = ss.getTargets(); 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 // convert from relative to absolute offsets
for (int i = 0; i < targets.length; i++) { for (int i = 0; i < targets.length; i++) {
......
...@@ -8,11 +8,11 @@ import java.util.Arrays; ...@@ -8,11 +8,11 @@ import java.util.Arrays;
public class SwitchNode extends InsnNode { public class SwitchNode extends InsnNode {
private final int[] keys; private final Object[] keys;
private final int[] targets; private final int[] targets;
private final int def; // next instruction 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); super(InsnType.SWITCH, 1);
this.keys = keys; this.keys = keys;
this.targets = targets; this.targets = targets;
...@@ -24,7 +24,7 @@ public class SwitchNode extends InsnNode { ...@@ -24,7 +24,7 @@ public class SwitchNode extends InsnNode {
return keys.length; return keys.length;
} }
public int[] getKeys() { public Object[] getKeys() {
return keys; return keys;
} }
......
...@@ -237,7 +237,15 @@ public class ClassNode extends LineAttrNode implements ILoadable { ...@@ -237,7 +237,15 @@ public class ClassNode extends LineAttrNode implements ILoadable {
} }
public FieldNode getConstField(Object o) { 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) if (field == null)
field = dex.getConstFields().get(o); field = dex.getConstFields().get(o);
return field; return field;
......
...@@ -12,14 +12,14 @@ public final class SwitchRegion extends AbstractRegion { ...@@ -12,14 +12,14 @@ public final class SwitchRegion extends AbstractRegion {
private final BlockNode header; private final BlockNode header;
private final List<List<Integer>> keys; private final List<List<Object>> keys;
private final List<IContainer> cases; private final List<IContainer> cases;
private IContainer defCase; private IContainer defCase;
public SwitchRegion(IRegion parent, BlockNode header) { public SwitchRegion(IRegion parent, BlockNode header) {
super(parent); super(parent);
this.header = header; this.header = header;
this.keys = new ArrayList<List<Integer>>(); this.keys = new ArrayList<List<Object>>();
this.cases = new ArrayList<IContainer>(); this.cases = new ArrayList<IContainer>();
} }
...@@ -27,7 +27,7 @@ public final class SwitchRegion extends AbstractRegion { ...@@ -27,7 +27,7 @@ public final class SwitchRegion extends AbstractRegion {
return header; return header;
} }
public void addCase(List<Integer> keysList, IContainer c) { public void addCase(List<Object> keysList, IContainer c) {
keys.add(keysList); keys.add(keysList);
cases.add(c); cases.add(c);
} }
...@@ -40,7 +40,7 @@ public final class SwitchRegion extends AbstractRegion { ...@@ -40,7 +40,7 @@ public final class SwitchRegion extends AbstractRegion {
return defCase; return defCase;
} }
public List<List<Integer>> getKeys() { public List<List<Object>> getKeys() {
return keys; return keys;
} }
......
...@@ -9,6 +9,7 @@ import jadx.core.dex.instructions.FillArrayNode; ...@@ -9,6 +9,7 @@ import jadx.core.dex.instructions.FillArrayNode;
import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.InvokeNode; 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.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.LiteralArg;
...@@ -114,16 +115,16 @@ public class ModVisitor extends AbstractVisitor { ...@@ -114,16 +115,16 @@ public class ModVisitor extends AbstractVisitor {
LiteralArg arg = (LiteralArg) insn.getArg(0); LiteralArg arg = (LiteralArg) insn.getArg(0);
ArgType type = arg.getType(); ArgType type = arg.getType();
long lit = arg.getLiteral(); 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)) if (type.equals(ArgType.INT))
f = parentClass.getConstField((int) lit); f = parentClass.getConstField((int) lit);
else if (type.equals(ArgType.LONG)) else if (type.equals(ArgType.LONG))
f = parentClass.getConstField(lit); 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) { if (f != null) {
InsnNode inode = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0); InsnNode inode = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
...@@ -132,6 +133,19 @@ public class ModVisitor extends AbstractVisitor { ...@@ -132,6 +133,19 @@ public class ModVisitor extends AbstractVisitor {
} }
break; 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: default:
break; break;
} }
......
...@@ -583,21 +583,21 @@ public class RegionMaker { ...@@ -583,21 +583,21 @@ public class RegionMaker {
int len = insn.getTargets().length; int len = insn.getTargets().length;
// sort by target // sort by target
Map<Integer, List<Integer>> casesMap = new LinkedHashMap<Integer, List<Integer>>(len); Map<Integer, List<Object>> casesMap = new LinkedHashMap<Integer, List<Object>>(len);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
int key = insn.getKeys()[i]; Object key = insn.getKeys()[i];
int targ = insn.getTargets()[i]; int targ = insn.getTargets()[i];
List<Integer> keys = casesMap.get(targ); List<Object> keys = casesMap.get(targ);
if (keys == null) { if (keys == null) {
keys = new ArrayList<Integer>(1); keys = new ArrayList<Object>(2);
casesMap.put(targ, keys); casesMap.put(targ, keys);
} }
keys.add(key); keys.add(key);
} }
Map<BlockNode, List<Integer>> blocksMap = new LinkedHashMap<BlockNode, List<Integer>>(len); Map<BlockNode, List<Object>> blocksMap = new LinkedHashMap<BlockNode, List<Object>>(len);
for (Entry<Integer, List<Integer>> entry : casesMap.entrySet()) { for (Entry<Integer, List<Object>> entry : casesMap.entrySet()) {
BlockNode c = getBlockByOffset(entry.getKey(), block.getSuccessors()); BlockNode c = getBlockByOffset((int) entry.getKey(), block.getSuccessors());
assert c != null; assert c != null;
blocksMap.put(c, entry.getValue()); blocksMap.put(c, entry.getValue());
} }
...@@ -650,7 +650,7 @@ public class RegionMaker { ...@@ -650,7 +650,7 @@ public class RegionMaker {
if (!stack.containsExit(defCase)) { if (!stack.containsExit(defCase)) {
sw.setDefaultCase(makeRegion(defCase, stack)); sw.setDefaultCase(makeRegion(defCase, stack));
} }
for (Entry<BlockNode, List<Integer>> entry : blocksMap.entrySet()) { for (Entry<BlockNode, List<Object>> entry : blocksMap.entrySet()) {
BlockNode c = entry.getKey(); BlockNode c = entry.getKey();
if (stack.containsExit(c)) { if (stack.containsExit(c)) {
// empty case block // empty case block
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment