Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored data clumps with the help of LLMs (research project) #2164

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import jadx.core.dex.visitors.JadxVisitor;
import jadx.core.dex.visitors.ssa.SSATransform;
import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor;
import jadx.core.dex.visitors.typeinference.TypeUpdateParam;
import jadx.core.dex.visitors.typeinference.TypeUpdateResult;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.exceptions.JadxException;
Expand Down Expand Up @@ -134,7 +135,8 @@ public static boolean applyDebugInfo(MethodNode mth, SSAVar ssaVar, RegisterArg
}

public static boolean applyDebugInfo(MethodNode mth, SSAVar ssaVar, ArgType type, String varName) {
TypeUpdateResult result = mth.root().getTypeUpdate().applyWithWiderIgnoreUnknown(mth, ssaVar, type);
TypeUpdateParam param = new TypeUpdateParam(mth, ssaVar, type);
TypeUpdateResult result = mth.root().getTypeUpdate().applyWithWiderIgnoreUnknown(param);
if (result == TypeUpdateResult.REJECT) {
if (Consts.DEBUG_TYPE_INFERENCE) {
LOG.debug("Reject debug info of type: {} and name: '{}' for {}, mth: {}", type, varName, ssaVar, mth);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ private boolean calculateFromBounds(MethodNode mth, SSAVar ssaVar) {
return false;
}
ArgType candidateType = bestTypeOpt.get();
TypeUpdateResult result = typeUpdate.apply(mth, ssaVar, candidateType);
TypeUpdateParam param = new TypeUpdateParam(mth, ssaVar, candidateType);
TypeUpdateResult result = typeUpdate.apply(param);
if (result == TypeUpdateResult.REJECT) {
if (Consts.DEBUG_TYPE_INFERENCE) {
if (ssaVar.getTypeInfo().getType().equals(candidateType)) {
Expand All @@ -180,7 +181,8 @@ private boolean tryPossibleTypes(MethodNode mth, SSAVar var, ArgType type) {
return false;
}
for (ArgType candidateType : types) {
TypeUpdateResult result = typeUpdate.apply(mth, var, candidateType);
TypeUpdateParam param = new TypeUpdateParam(mth, var, candidateType);
TypeUpdateResult result = typeUpdate.apply(param);
if (result == TypeUpdateResult.CHANGED) {
return true;
}
Expand Down Expand Up @@ -286,7 +288,8 @@ private boolean tryRawType(MethodNode mth, SSAVar var) {
private boolean checkRawType(MethodNode mth, SSAVar var, ArgType objType) {
if (objType.isObject() && objType.containsGeneric()) {
ArgType rawType = objType.isGenericType() ? ArgType.OBJECT : ArgType.object(objType.getObject());
TypeUpdateResult result = typeUpdate.applyWithWiderAllow(mth, var, rawType);
TypeUpdateParam param = new TypeUpdateParam(mth, var, rawType);
TypeUpdateResult result = typeUpdate.applyWithWiderAllow(param);
return result == TypeUpdateResult.CHANGED;
}
return false;
Expand Down Expand Up @@ -669,7 +672,8 @@ private boolean tryWiderObjects(MethodNode mth, SSAVar var) {
for (ArgType objType : objTypes) {
for (String ancestor : clsp.getSuperTypes(objType.getObject())) {
ArgType ancestorType = ArgType.object(ancestor);
TypeUpdateResult result = typeUpdate.applyWithWiderAllow(mth, var, ancestorType);
TypeUpdateParam param = new TypeUpdateParam(mth, var, ancestorType);
TypeUpdateResult result = typeUpdate.applyWithWiderAllow(param);
if (result == TypeUpdateResult.CHANGED) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ private void setImmutableType(MethodNode mth, SSAVar ssaVar) {
try {
ArgType immutableType = ssaVar.getImmutableType();
if (immutableType != null) {
TypeUpdateResult result = typeUpdate.applyWithWiderIgnSame(mth, ssaVar, immutableType);
TypeUpdateParam param = new TypeUpdateParam(mth, ssaVar, immutableType);
TypeUpdateResult result = typeUpdate.applyWithWiderIgnSame(param);
if (Consts.DEBUG_TYPE_INFERENCE && result == TypeUpdateResult.REJECT) {
LOG.info("Reject initial immutable type {} for {}", immutableType, ssaVar);
}
Expand Down Expand Up @@ -142,7 +143,8 @@ private void calculateFromBounds(MethodNode mth, SSAVar ssaVar) {
return;
}
ArgType candidateType = bestTypeOpt.get();
TypeUpdateResult result = typeUpdate.apply(mth, ssaVar, candidateType);
TypeUpdateParam param = new TypeUpdateParam(mth, ssaVar, candidateType);
TypeUpdateResult result = typeUpdate.apply(param);
if (Consts.DEBUG_TYPE_INFERENCE && result == TypeUpdateResult.REJECT) {
if (ssaVar.getTypeInfo().getType().equals(candidateType)) {
LOG.info("Same type rejected: {} -> {}, bounds: {}", ssaVar, candidateType, bounds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ private boolean applyResolvedVars() {
}
boolean applySuccess = true;
for (TypeSearchVarInfo var : updatedVars) {
TypeUpdateResult res = typeUpdate.applyWithWiderIgnSame(mth, var.getVar(), var.getCurrentType());
TypeUpdateParam param = new TypeUpdateParam(mth, var.getVar(), var.getCurrentType());
TypeUpdateResult res = typeUpdate.applyWithWiderIgnSame(param);
if (res == TypeUpdateResult.REJECT) {
mth.addDebugComment("Multi-variable search result rejected for " + var);
applySuccess = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.nodes.IMethodDetails;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.nodes.utils.TypeUtils;
import jadx.core.utils.exceptions.JadxOverflowException;
Expand All @@ -52,43 +51,43 @@ public TypeUpdate(RootNode root) {
/**
* Perform recursive type checking and type propagation for all related variables
*/
public TypeUpdateResult apply(MethodNode mth, SSAVar ssaVar, ArgType candidateType) {
return apply(mth, ssaVar, candidateType, TypeUpdateFlags.FLAGS_EMPTY);
public TypeUpdateResult apply(TypeUpdateParam params) {
return apply(params, TypeUpdateFlags.FLAGS_EMPTY);
}

/**
* Allow wider types for apply from debug info and some special cases
*/
public TypeUpdateResult applyWithWiderAllow(MethodNode mth, SSAVar ssaVar, ArgType candidateType) {
return apply(mth, ssaVar, candidateType, TypeUpdateFlags.FLAGS_WIDER);
public TypeUpdateResult applyWithWiderAllow(TypeUpdateParam params) {
return apply(params, TypeUpdateFlags.FLAGS_WIDER);
}

/**
* Force type setting
*/
public TypeUpdateResult applyWithWiderIgnSame(MethodNode mth, SSAVar ssaVar, ArgType candidateType) {
return apply(mth, ssaVar, candidateType, TypeUpdateFlags.FLAGS_WIDER_IGNORE_SAME);
public TypeUpdateResult applyWithWiderIgnSame(TypeUpdateParam params) {
return apply(params, TypeUpdateFlags.FLAGS_WIDER_IGNORE_SAME);
}

public TypeUpdateResult applyWithWiderIgnoreUnknown(MethodNode mth, SSAVar ssaVar, ArgType candidateType) {
return apply(mth, ssaVar, candidateType, TypeUpdateFlags.FLAGS_WIDER_IGNORE_UNKNOWN);
public TypeUpdateResult applyWithWiderIgnoreUnknown(TypeUpdateParam params) {
return apply(params, TypeUpdateFlags.FLAGS_WIDER_IGNORE_UNKNOWN);
}

private TypeUpdateResult apply(MethodNode mth, SSAVar ssaVar, ArgType candidateType, TypeUpdateFlags flags) {
if (candidateType == null || !candidateType.isTypeKnown()) {
private TypeUpdateResult apply(TypeUpdateParam params, TypeUpdateFlags flags) {
if (params.getCandidateType() == null || !params.getCandidateType().isTypeKnown()) {
return REJECT;
}

TypeUpdateInfo updateInfo = new TypeUpdateInfo(mth, flags);
TypeUpdateResult result = updateTypeChecked(updateInfo, ssaVar.getAssign(), candidateType);
TypeUpdateInfo updateInfo = new TypeUpdateInfo(params.getMethodNode(), flags);
TypeUpdateResult result = updateTypeChecked(updateInfo, params.getSSAVar().getAssign(), params.getCandidateType());
if (result == REJECT) {
return result;
}
if (updateInfo.isEmpty()) {
return SAME;
}
if (Consts.DEBUG_TYPE_INFERENCE) {
LOG.debug("Applying type {} to {}:", candidateType, ssaVar.toShortString());
LOG.debug("Applying type {} to {}:", params.getCandidateType(), params.getSSAVar().toShortString());
updateInfo.getSortedUpdates().forEach(upd -> LOG.debug(" {} -> {} in {}",
upd.getType(), upd.getArg().toShortString(), upd.getArg().getParentInsn()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package jadx.core.dex.visitors.typeinference;

import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.nodes.MethodNode;

public class TypeUpdateParam {
private final MethodNode mth;
private final SSAVar ssaVar;
private final ArgType candidateType;

public TypeUpdateParam(MethodNode mth, SSAVar ssaVar, ArgType candidateType) {
this.mth = mth;
this.ssaVar = ssaVar;
this.candidateType = candidateType;
}

public MethodNode getMethodNode() {
return mth;
}

public SSAVar getSSAVar() {
return ssaVar;
}

public ArgType getCandidateType() {
return candidateType;
}
}