Commit fa8f9ccf authored by Skylot's avatar Skylot

core: move debug code to separate class

parent 8a264ca3
......@@ -234,7 +234,7 @@ public class MethodGen {
/**
* Return fallback variant of method codegen
*/
static MethodGen getFallbackMethodGen(MethodNode mth) {
public static MethodGen getFallbackMethodGen(MethodNode mth) {
ClassGen clsGen = new ClassGen(mth.getParentClass(), null, true);
return new MethodGen(clsGen, mth);
}
......
......@@ -4,7 +4,6 @@ import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.loops.LoopRegion;
......@@ -13,7 +12,6 @@ import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.exceptions.JadxException;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.slf4j.Logger;
......@@ -30,8 +28,6 @@ public class CheckRegions extends AbstractVisitor {
return;
}
// printRegion(mth);
// check if all blocks included in regions
final Set<BlockNode> blocksInRegions = new HashSet<BlockNode>();
DepthRegionTraversal.traverse(mth, new AbstractRegionVisitor() {
......@@ -51,7 +47,6 @@ public class CheckRegions extends AbstractVisitor {
// TODO
// mth.add(AFlag.INCONSISTENT_CODE);
LOG.debug(" Duplicated block: {} in {}", block, mth);
// printRegionsWithBlock(mth, block);
}
}
});
......@@ -79,33 +74,4 @@ public class CheckRegions extends AbstractVisitor {
}
});
}
private static void printRegionsWithBlock(MethodNode mth, final BlockNode block) {
final Set<IRegion> regions = new LinkedHashSet<IRegion>();
DepthRegionTraversal.traverse(mth, new TracedRegionVisitor() {
@Override
public void processBlockTraced(MethodNode mth, IBlock container, IRegion currentRegion) {
if (block.equals(container)) {
regions.add(currentRegion);
}
}
});
LOG.debug(" Found block: {} in regions: {}", block, regions);
}
private void printRegion(MethodNode mth) {
LOG.debug("|{}", mth.toString());
printRegion(mth, mth.getRegion(), "| ");
}
private void printRegion(MethodNode mth, IRegion region, String indent) {
LOG.debug("{}{}", indent, region);
for (IContainer container : region.getSubBlocks()) {
if (container instanceof IRegion) {
printRegion(mth, (IRegion) container, indent + " ");
} else {
LOG.debug("{} {}", indent, container);
}
}
}
}
package jadx.core.utils;
import jadx.core.codegen.CodeWriter;
import jadx.core.codegen.InsnGen;
import jadx.core.codegen.MethodGen;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.PhiListAttr;
import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.PhiInsn;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.DotGraphVisitor;
import jadx.core.dex.visitors.regions.DepthRegionTraversal;
import jadx.core.dex.visitors.regions.TracedRegionVisitor;
import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Deprecated
public class DebugUtils {
private static final Logger LOG = LoggerFactory.getLogger(DebugUtils.class);
public static void dump(MethodNode mth) {
File out = new File("test-graph-tmp");
DotGraphVisitor.dump(out).visit(mth);
DotGraphVisitor.dumpRaw(out).visit(mth);
DotGraphVisitor.dumpRegions(out).visit(mth);
}
public static void printRegionsWithBlock(MethodNode mth, final BlockNode block) {
final Set<IRegion> regions = new LinkedHashSet<IRegion>();
DepthRegionTraversal.traverse(mth, new TracedRegionVisitor() {
@Override
public void processBlockTraced(MethodNode mth, IBlock container, IRegion currentRegion) {
if (block.equals(container)) {
regions.add(currentRegion);
}
}
});
LOG.debug(" Found block: {} in regions: {}", block, regions);
}
public static void printRegions(MethodNode mth) {
printRegions(mth, false);
}
public static void printRegions(MethodNode mth, boolean printInsns) {
LOG.debug("|{}", mth.toString());
printRegion(mth, mth.getRegion(), "| ", printInsns);
}
private static void printRegion(MethodNode mth, IRegion region, String indent, boolean printInsns) {
LOG.debug("{}{}", indent, region);
indent += "| ";
for (IContainer container : region.getSubBlocks()) {
if (container instanceof IRegion) {
printRegion(mth, (IRegion) container, indent, printInsns);
} else {
LOG.debug("{}{}", indent, container);
if (printInsns && container instanceof IBlock) {
IBlock block = (IBlock) container;
printInsns(mth, indent, block);
}
}
}
}
private static void printInsns(MethodNode mth, String indent, IBlock block) {
for (InsnNode insn : block.getInstructions()) {
try {
MethodGen mg = MethodGen.getFallbackMethodGen(mth);
InsnGen ig = new InsnGen(mg, true);
CodeWriter code = new CodeWriter();
ig.makeInsn(insn, code);
String insnStr = code.toString().substring(CodeWriter.NL.length());
LOG.debug("{} - {}", indent, insnStr);
} catch (CodegenException e) {
LOG.debug("{} - {}", indent, insn);
}
}
}
public static void checkSSA(MethodNode mth) {
for (BlockNode block : mth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) {
if (insn.getResult() != null) {
checkSSAVar(mth, insn, insn.getResult());
}
for (InsnArg arg : insn.getArguments()) {
if (arg instanceof RegisterArg) {
checkSSAVar(mth, insn, ((RegisterArg) arg));
}
}
}
}
checkPHI(mth);
}
private static void checkSSAVar(MethodNode mth, InsnNode insn, RegisterArg reg) {
SSAVar sVar = reg.getSVar();
if (sVar == null) {
throw new JadxRuntimeException("Null SSA var in " + insn + ", mth: " + mth);
}
for (RegisterArg useArg : sVar.getUseList()) {
InsnNode parentInsn = useArg.getParentInsn();
if (parentInsn != null) {
if (!parentInsn.containsArg(useArg)) {
throw new JadxRuntimeException("Incorrect use info in PHI insn");
}
}
}
}
private static void checkPHI(MethodNode mth) {
for (BlockNode block : mth.getBasicBlocks()) {
List<PhiInsn> phis = new ArrayList<PhiInsn>();
for (InsnNode insn : block.getInstructions()) {
if (insn.getType() == InsnType.PHI) {
PhiInsn phi = ((PhiInsn) insn);
phis.add(phi);
if (phi.getArgsCount() != phi.getBlockBinds().size()) {
throw new JadxRuntimeException("Incorrect args and binds in PHI");
}
if (phi.getArgsCount() == 0) {
throw new JadxRuntimeException("No args and binds in PHI");
}
for (InsnArg arg : insn.getArguments()) {
if (arg instanceof RegisterArg) {
BlockNode b = phi.getBlockByArg((RegisterArg) arg);
if (b == null) {
throw new JadxRuntimeException("Predecessor block not found");
}
} else {
throw new JadxRuntimeException("Not register in phi insn");
}
}
}
}
PhiListAttr phiListAttr = block.get(AType.PHI_LIST);
if (phiListAttr == null) {
if (!phis.isEmpty()) {
throw new JadxRuntimeException("Missing PHI list attribute");
}
} else {
List<PhiInsn> phiList = phiListAttr.getList();
if (phiList.isEmpty()) {
throw new JadxRuntimeException("Empty PHI list attribute");
}
if (!phis.containsAll(phiList) || !phiList.containsAll(phis)) {
throw new JadxRuntimeException("Instructions not match");
}
}
}
for (SSAVar ssaVar : mth.getSVars()) {
PhiInsn usedInPhi = ssaVar.getUsedInPhi();
if (usedInPhi != null) {
boolean found = false;
for (RegisterArg useArg : ssaVar.getUseList()) {
InsnNode parentInsn = useArg.getParentInsn();
if (parentInsn != null && parentInsn == usedInPhi) {
found = true;
}
}
if (!found) {
throw new JadxRuntimeException("Used in phi incorrect");
}
}
}
}
}
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