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;
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<Integer> keys = sw.getKeys().get(i);
List<Object> 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
......@@ -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++) {
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -12,14 +12,14 @@ public final class SwitchRegion extends AbstractRegion {
private final BlockNode header;
private final List<List<Integer>> keys;
private final List<List<Object>> keys;
private final List<IContainer> cases;
private IContainer defCase;
public SwitchRegion(IRegion parent, BlockNode header) {
super(parent);
this.header = header;
this.keys = new ArrayList<List<Integer>>();
this.keys = new ArrayList<List<Object>>();
this.cases = new ArrayList<IContainer>();
}
......@@ -27,7 +27,7 @@ public final class SwitchRegion extends AbstractRegion {
return header;
}
public void addCase(List<Integer> keysList, IContainer c) {
public void addCase(List<Object> keysList, IContainer c) {
keys.add(keysList);
cases.add(c);
}
......@@ -40,7 +40,7 @@ public final class SwitchRegion extends AbstractRegion {
return defCase;
}
public List<List<Integer>> getKeys() {
public List<List<Object>> getKeys() {
return keys;
}
......
......@@ -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;
}
......
......@@ -583,21 +583,21 @@ public class RegionMaker {
int len = insn.getTargets().length;
// 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++) {
int key = insn.getKeys()[i];
Object key = insn.getKeys()[i];
int targ = insn.getTargets()[i];
List<Integer> keys = casesMap.get(targ);
List<Object> keys = casesMap.get(targ);
if (keys == null) {
keys = new ArrayList<Integer>(1);
keys = new ArrayList<Object>(2);
casesMap.put(targ, keys);
}
keys.add(key);
}
Map<BlockNode, List<Integer>> blocksMap = new LinkedHashMap<BlockNode, List<Integer>>(len);
for (Entry<Integer, List<Integer>> entry : casesMap.entrySet()) {
BlockNode c = getBlockByOffset(entry.getKey(), block.getSuccessors());
Map<BlockNode, List<Object>> blocksMap = new LinkedHashMap<BlockNode, List<Object>>(len);
for (Entry<Integer, List<Object>> 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<BlockNode, List<Integer>> entry : blocksMap.entrySet()) {
for (Entry<BlockNode, List<Object>> entry : blocksMap.entrySet()) {
BlockNode c = entry.getKey();
if (stack.containsExit(c)) {
// 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