refactor: move constant collection into separate pass (#2119)
This commit is contained in:
@@ -54,6 +54,7 @@ import jadx.core.dex.visitors.debuginfo.DebugInfoApplyVisitor;
|
||||
import jadx.core.dex.visitors.debuginfo.DebugInfoAttachVisitor;
|
||||
import jadx.core.dex.visitors.finaly.MarkFinallyVisitor;
|
||||
import jadx.core.dex.visitors.kotlin.ProcessKotlinInternals;
|
||||
import jadx.core.dex.visitors.prepare.CollectConstValues;
|
||||
import jadx.core.dex.visitors.regions.CheckRegions;
|
||||
import jadx.core.dex.visitors.regions.CleanRegions;
|
||||
import jadx.core.dex.visitors.regions.IfRegionVisitor;
|
||||
@@ -96,6 +97,7 @@ public class Jadx {
|
||||
List<IDexTreeVisitor> passes = new ArrayList<>();
|
||||
passes.add(new SignatureProcessor());
|
||||
passes.add(new OverrideMethodVisitor());
|
||||
passes.add(new CollectConstValues());
|
||||
|
||||
// rename and deobfuscation
|
||||
passes.add(new DeobfuscatorVisitor());
|
||||
|
||||
@@ -2,7 +2,6 @@ package jadx.core.dex.info;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -10,14 +9,13 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.plugins.input.data.annotations.EncodedValue;
|
||||
import jadx.api.plugins.input.data.attributes.JadxAttrType;
|
||||
import jadx.core.dex.instructions.args.LiteralArg;
|
||||
import jadx.core.dex.instructions.args.PrimitiveType;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.IFieldInfoRef;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.dex.visitors.prepare.CollectConstValues;
|
||||
|
||||
public class ConstStorage {
|
||||
|
||||
@@ -75,18 +73,6 @@ public class ConstStorage {
|
||||
this.replaceEnabled = args.isReplaceConsts();
|
||||
}
|
||||
|
||||
public void processConstFields(List<FieldNode> staticFields) {
|
||||
if (!replaceEnabled || staticFields.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (FieldNode f : staticFields) {
|
||||
Object value = getFieldConstValue(f);
|
||||
if (value != null) {
|
||||
addConstField(f, value, f.getAccessFlags().isPublic());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addConstField(FieldNode fld, Object value, boolean isPublic) {
|
||||
if (isPublic) {
|
||||
addGlobalConstField(fld, value);
|
||||
@@ -99,15 +85,12 @@ public class ConstStorage {
|
||||
globalValues.put(value, fld);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use method from CollectConstValues class
|
||||
*/
|
||||
@Deprecated
|
||||
public static @Nullable Object getFieldConstValue(FieldNode fld) {
|
||||
AccessInfo accFlags = fld.getAccessFlags();
|
||||
if (accFlags.isStatic() && accFlags.isFinal()) {
|
||||
EncodedValue constVal = fld.get(JadxAttrType.CONSTANT_VALUE);
|
||||
if (constVal != null) {
|
||||
return constVal.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return CollectConstValues.getFieldConstValue(fld);
|
||||
}
|
||||
|
||||
public void removeForClass(ClassNode cls) {
|
||||
|
||||
@@ -9,7 +9,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -248,19 +247,15 @@ public class ClassNode extends NotificationAttrNode
|
||||
if (fields.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<FieldNode> staticFields = fields.stream().filter(FieldNode::isStatic).collect(Collectors.toList());
|
||||
for (FieldNode f : staticFields) {
|
||||
if (f.getAccessFlags().isFinal() && f.get(JadxAttrType.CONSTANT_VALUE) == null) {
|
||||
// incorrect initialization will be removed if assign found in constructor
|
||||
f.addAttr(EncodedValue.NULL);
|
||||
// bytecode can omit field initialization to 0 (of any type)
|
||||
// add explicit init to all static final fields
|
||||
// incorrect initializations will be removed if assign found in class init
|
||||
for (FieldNode fld : fields) {
|
||||
AccessInfo accFlags = fld.getAccessFlags();
|
||||
if (accFlags.isStatic() && accFlags.isFinal() && fld.get(JadxAttrType.CONSTANT_VALUE) == null) {
|
||||
fld.addAttr(EncodedValue.NULL);
|
||||
}
|
||||
}
|
||||
try {
|
||||
// process const fields
|
||||
root().getConstValues().processConstFields(staticFields);
|
||||
} catch (Exception e) {
|
||||
this.addWarnComment("Failed to load initial values for static fields", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkSourceFilenameAttr() {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package jadx.core.dex.visitors.prepare;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.api.plugins.input.data.annotations.EncodedValue;
|
||||
import jadx.api.plugins.input.data.attributes.JadxAttrType;
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
import jadx.core.dex.info.ConstStorage;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.dex.visitors.AbstractVisitor;
|
||||
import jadx.core.dex.visitors.JadxVisitor;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
|
||||
@JadxVisitor(
|
||||
name = "CollectConstValues",
|
||||
desc = "Collect and store values from static final fields"
|
||||
)
|
||||
public class CollectConstValues extends AbstractVisitor {
|
||||
|
||||
@Override
|
||||
public boolean visit(ClassNode cls) throws JadxException {
|
||||
RootNode root = cls.root();
|
||||
if (!root.getArgs().isReplaceConsts()) {
|
||||
return true;
|
||||
}
|
||||
if (cls.getFields().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
ConstStorage constStorage = root.getConstValues();
|
||||
for (FieldNode fld : cls.getFields()) {
|
||||
try {
|
||||
Object value = getFieldConstValue(fld);
|
||||
if (value != null) {
|
||||
constStorage.addConstField(fld, value, fld.getAccessFlags().isPublic());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
cls.addWarnComment("Failed to process value of field: " + fld, e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static @Nullable Object getFieldConstValue(FieldNode fld) {
|
||||
AccessInfo accFlags = fld.getAccessFlags();
|
||||
if (accFlags.isStatic() && accFlags.isFinal()) {
|
||||
EncodedValue constVal = fld.get(JadxAttrType.CONSTANT_VALUE);
|
||||
if (constVal != null && constVal != EncodedValue.NULL) {
|
||||
return constVal.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user