Commit 4f307c00 authored by Skylot's avatar Skylot

core: allow subblock replace for 'if' region

parent 3bdda551
...@@ -4,7 +4,11 @@ import jadx.core.dex.attributes.AttrNode; ...@@ -4,7 +4,11 @@ import jadx.core.dex.attributes.AttrNode;
import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion; import jadx.core.dex.nodes.IRegion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractRegion extends AttrNode implements IRegion { public abstract class AbstractRegion extends AttrNode implements IRegion {
private static final Logger LOG = LoggerFactory.getLogger(AbstractRegion.class);
private IRegion parent; private IRegion parent;
...@@ -23,7 +27,7 @@ public abstract class AbstractRegion extends AttrNode implements IRegion { ...@@ -23,7 +27,7 @@ public abstract class AbstractRegion extends AttrNode implements IRegion {
@Override @Override
public boolean replaceSubBlock(IContainer oldBlock, IContainer newBlock) { public boolean replaceSubBlock(IContainer oldBlock, IContainer newBlock) {
// TODO: implement for others regions LOG.warn("Replace sub block not supported for class \"{}\"", this.getClass());
return false; return false;
} }
} }
...@@ -102,6 +102,19 @@ public final class IfRegion extends AbstractRegion { ...@@ -102,6 +102,19 @@ public final class IfRegion extends AbstractRegion {
} }
@Override @Override
public boolean replaceSubBlock(IContainer oldBlock, IContainer newBlock) {
if (oldBlock == thenRegion) {
thenRegion = newBlock;
return true;
}
if (oldBlock == elseRegion) {
elseRegion = newBlock;
return true;
}
return false;
}
@Override
public String baseString() { public String baseString() {
if (ternRegion != null) { if (ternRegion != null) {
return ternRegion.baseString(); return ternRegion.baseString();
......
package jadx.core.dex.visitors.regions; package jadx.core.dex.visitors.regions;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IContainer;
...@@ -44,7 +45,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -44,7 +45,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
DepthRegionTraversal.traverseAll(mth, new AbstractRegionVisitor() { DepthRegionTraversal.traverseAll(mth, new AbstractRegionVisitor() {
@Override @Override
public void leaveRegion(MethodNode mth, IRegion region) { public void leaveRegion(MethodNode mth, IRegion region) {
checkAndWrap(tryBlocksMap, region); checkAndWrap(mth, tryBlocksMap, region);
} }
}); });
if (k++ > 100) { if (k++ > 100) {
...@@ -98,13 +99,16 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -98,13 +99,16 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
} }
} }
private static void checkAndWrap(Map<BlockNode, TryCatchBlock> tryBlocksMap, IRegion region) { private static void checkAndWrap(MethodNode mth, Map<BlockNode, TryCatchBlock> tryBlocksMap, IRegion region) {
// search dominator blocks in this region (don't need to go deeper) // search dominator blocks in this region (don't need to go deeper)
for (Map.Entry<BlockNode, TryCatchBlock> entry : tryBlocksMap.entrySet()) { for (Map.Entry<BlockNode, TryCatchBlock> entry : tryBlocksMap.entrySet()) {
BlockNode dominator = entry.getKey(); BlockNode dominator = entry.getKey();
if (region.getSubBlocks().contains(dominator)) { if (region.getSubBlocks().contains(dominator)) {
TryCatchBlock tb = tryBlocksMap.get(dominator); TryCatchBlock tb = tryBlocksMap.get(dominator);
wrapBlocks(region, tb, dominator); if (!wrapBlocks(region, tb, dominator)) {
LOG.warn("Can't wrap try/catch for {}, method: {}", dominator, mth);
mth.add(AFlag.INCONSISTENT_CODE);
}
tryBlocksMap.remove(dominator); tryBlocksMap.remove(dominator);
return; return;
} }
...@@ -114,9 +118,10 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -114,9 +118,10 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
/** /**
* Extract all block dominated by 'dominator' to separate region and mark as try/catch block * Extract all block dominated by 'dominator' to separate region and mark as try/catch block
*/ */
private static void wrapBlocks(IRegion region, TryCatchBlock tb, BlockNode dominator) { private static boolean wrapBlocks(IRegion region, TryCatchBlock tb, BlockNode dominator) {
Region newRegion = new Region(region); Region newRegion = new Region(region);
for (IContainer cont : region.getSubBlocks()) { List<IContainer> subBlocks = region.getSubBlocks();
for (IContainer cont : subBlocks) {
if (RegionUtils.isDominatedBy(dominator, cont)) { if (RegionUtils.isDominatedBy(dominator, cont)) {
if (isHandlerPath(tb, cont)) { if (isHandlerPath(tb, cont)) {
break; break;
...@@ -125,13 +130,14 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -125,13 +130,14 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
} }
} }
if (newRegion.getSubBlocks().isEmpty()) { if (newRegion.getSubBlocks().isEmpty()) {
return; return false;
} }
// replace first node by region // replace first node by region
IContainer firstNode = newRegion.getSubBlocks().get(0); IContainer firstNode = newRegion.getSubBlocks().get(0);
int i = region.getSubBlocks().indexOf(firstNode); if (!region.replaceSubBlock(firstNode, newRegion)) {
region.getSubBlocks().set(i, newRegion); return false;
region.getSubBlocks().removeAll(newRegion.getSubBlocks()); }
subBlocks.removeAll(newRegion.getSubBlocks());
newRegion.addAttr(tb.getCatchAttr()); newRegion.addAttr(tb.getCatchAttr());
...@@ -142,6 +148,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -142,6 +148,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
aReg.setParent(newRegion); aReg.setParent(newRegion);
} }
} }
return true;
} }
private static boolean isHandlerPath(TryCatchBlock tb, IContainer cont) { private static boolean isHandlerPath(TryCatchBlock tb, IContainer cont) {
......
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