Replace constants with matched static final fields
This commit is contained in:
@@ -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<Object, FieldNode> getConstFields() {
|
||||
return constFields;
|
||||
}
|
||||
|
||||
public DexNode dex() {
|
||||
return dex;
|
||||
}
|
||||
@@ -323,5 +330,4 @@ public class ClassNode extends AttrNode implements ILoadable {
|
||||
public String toString() {
|
||||
return getFullName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<ClassNode> classes = new ArrayList<ClassNode>();
|
||||
private final String[] strings;
|
||||
|
||||
private final Map<Object, FieldNode> constFields = new HashMap<Object, FieldNode>();
|
||||
|
||||
public DexNode(RootNode root, InputFile input) {
|
||||
this.root = root;
|
||||
this.dexBuf = input.getDexBuffer();
|
||||
@@ -59,6 +63,10 @@ public class DexNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<Object, FieldNode> getConstFields() {
|
||||
return constFields;
|
||||
}
|
||||
|
||||
// DexBuffer wrappers
|
||||
|
||||
public String getString(int index) {
|
||||
@@ -110,5 +118,4 @@ public class DexNode {
|
||||
public String toString() {
|
||||
return "DEX";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user