use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockSplitter method connectNewBlock.
static BlockNode connectNewBlock(MethodNode mth, BlockNode block, int offset) {
BlockNode newBlock = startNewBlock(mth, offset);
connect(block, newBlock);
return newBlock;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockSplitter method splitBasicBlocks.
private static Map<Integer, BlockNode> splitBasicBlocks(MethodNode mth) {
BlockNode enterBlock = startNewBlock(mth, -1);
enterBlock.add(AFlag.MTH_ENTER_BLOCK);
mth.setEnterBlock(enterBlock);
BlockNode exitBlock = startNewBlock(mth, -1);
exitBlock.add(AFlag.MTH_EXIT_BLOCK);
mth.setExitBlock(exitBlock);
Map<Integer, BlockNode> blocksMap = new HashMap<>();
BlockNode curBlock = enterBlock;
InsnNode prevInsn = null;
for (InsnNode insn : mth.getInstructions()) {
if (insn == null) {
continue;
}
if (insn.getType() == InsnType.NOP && insn.isAttrStorageEmpty()) {
continue;
}
int insnOffset = insn.getOffset();
if (prevInsn == null) {
// first block after method enter block
curBlock = connectNewBlock(mth, curBlock, insnOffset);
} else {
InsnType prevType = prevInsn.getType();
switch(prevType) {
case RETURN:
case THROW:
case GOTO:
case IF:
case SWITCH:
// split without connect to next block
curBlock = startNewBlock(mth, insnOffset);
break;
default:
if (isSeparate(prevType) || isSeparate(insn.getType()) || insn.contains(AFlag.TRY_ENTER) || prevInsn.contains(AFlag.TRY_LEAVE) || insn.contains(AType.EXC_HANDLER) || isSplitByJump(prevInsn, insn) || isDoWhile(blocksMap, curBlock, insn)) {
curBlock = connectNewBlock(mth, curBlock, insnOffset);
}
break;
}
}
blocksMap.put(insnOffset, curBlock);
curBlock.getInstructions().add(insn);
prevInsn = insn;
}
return blocksMap;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockSplitter method detachBlock.
static void detachBlock(BlockNode block) {
for (BlockNode pred : block.getPredecessors()) {
pred.getSuccessors().remove(block);
pred.updateCleanSuccessors();
}
for (BlockNode successor : block.getSuccessors()) {
successor.getPredecessors().remove(block);
}
block.add(AFlag.REMOVE);
block.getInstructions().clear();
block.getPredecessors().clear();
block.getSuccessors().clear();
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockSplitter method insertBlockBetween.
static BlockNode insertBlockBetween(MethodNode mth, BlockNode source, BlockNode target) {
BlockNode newBlock = startNewBlock(mth, target.getStartOffset());
newBlock.add(AFlag.SYNTHETIC);
removeConnection(source, target);
connect(source, newBlock);
connect(newBlock, target);
replaceTarget(source, target, newBlock);
source.updateCleanSuccessors();
newBlock.updateCleanSuccessors();
return newBlock;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockSplitter method addTempConnectionsForExcHandlers.
/**
* Connect exception handlers to the throw block.
* This temporary connection needed to build close to final dominators tree.
* Will be used and removed in {@code jadx.core.dex.visitors.blocks.BlockExceptionHandler}
*/
private static void addTempConnectionsForExcHandlers(MethodNode mth, Map<Integer, BlockNode> blocksMap) {
for (BlockNode block : mth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) {
CatchAttr catchAttr = insn.get(AType.EXC_CATCH);
if (catchAttr == null) {
continue;
}
for (ExceptionHandler handler : catchAttr.getHandlers()) {
BlockNode handlerBlock = getBlock(handler.getHandlerOffset(), blocksMap);
if (!handlerBlock.contains(AType.TMP_EDGE)) {
List<BlockNode> preds = block.getPredecessors();
if (preds.isEmpty()) {
throw new JadxRuntimeException("Unexpected missing predecessor for block: " + block);
}
BlockNode start = preds.size() == 1 ? preds.get(0) : block;
if (!start.getSuccessors().contains(handlerBlock)) {
connect(start, handlerBlock);
handlerBlock.addAttr(new TmpEdgeAttr(start));
}
}
}
}
}
}
Aggregations