use of jadx.core.utils.exceptions.JadxRuntimeException in project jadx by skylot.
the class ArithNode method build.
public static ArithNode build(InsnData insn, ArithOp op, ArgType type) {
RegisterArg resArg = InsnArg.reg(insn, 0, fixResultType(op, type));
ArgType argType = fixArgType(op, type);
switch(insn.getRegsCount()) {
case 2:
return new ArithNode(op, resArg, InsnArg.reg(insn, 0, argType), InsnArg.reg(insn, 1, argType));
case 3:
return new ArithNode(op, resArg, InsnArg.reg(insn, 1, argType), InsnArg.reg(insn, 2, argType));
default:
throw new JadxRuntimeException("Unexpected registers count in " + insn);
}
}
use of jadx.core.utils.exceptions.JadxRuntimeException in project jadx by skylot.
the class ArithNode method buildLit.
public static ArithNode buildLit(InsnData insn, ArithOp op, ArgType type) {
RegisterArg resArg = InsnArg.reg(insn, 0, fixResultType(op, type));
ArgType argType = fixArgType(op, type);
LiteralArg litArg = InsnArg.lit(insn, argType);
switch(insn.getRegsCount()) {
case 1:
return new ArithNode(op, resArg, InsnArg.reg(insn, 0, argType), litArg);
case 2:
return new ArithNode(op, resArg, InsnArg.reg(insn, 1, argType), litArg);
default:
throw new JadxRuntimeException("Unexpected registers count in " + insn);
}
}
use of jadx.core.utils.exceptions.JadxRuntimeException in project jadx by skylot.
the class RegionMaker method processSwitch.
private BlockNode processSwitch(IRegion currentRegion, BlockNode block, SwitchInsn insn, RegionStack stack) {
// map case blocks to keys
int len = insn.getTargets().length;
Map<BlockNode, List<Object>> blocksMap = new LinkedHashMap<>(len);
BlockNode[] targetBlocksArr = insn.getTargetBlocks();
for (int i = 0; i < len; i++) {
List<Object> keys = blocksMap.computeIfAbsent(targetBlocksArr[i], k -> new ArrayList<>(2));
keys.add(insn.getKey(i));
}
BlockNode defCase = insn.getDefTargetBlock();
if (defCase != null) {
List<Object> keys = blocksMap.computeIfAbsent(defCase, k -> new ArrayList<>(1));
keys.add(SwitchRegion.DEFAULT_CASE_KEY);
}
// search 'out' block - 'next' block after whole switch statement
BlockNode out;
LoopInfo loop = mth.getLoopForBlock(block);
if (loop == null) {
out = calcPostDomOut(mth, block, mth.getPreExitBlocks());
} else {
BlockNode loopEnd = loop.getEnd();
stack.addExit(loop.getStart());
if (stack.containsExit(block) || block == loopEnd || loopEnd.getPredecessors().contains(block)) {
// in exits or last insn in loop => no 'out' block
out = null;
} else {
// treat 'continue' as exit
out = calcPostDomOut(mth, block, loopEnd.getPredecessors());
if (out != null) {
insertContinueInSwitch(block, out, loopEnd);
} else {
// no 'continue'
out = calcPostDomOut(mth, block, Collections.singletonList(loopEnd));
}
}
if (out == loop.getStart()) {
// no other outs instead back edge to loop start
out = null;
}
}
if (out != null && processedBlocks.get(out.getId())) {
// out block already processed, prevent endless loop
throw new JadxRuntimeException("Failed to find switch 'out' block");
}
SwitchRegion sw = new SwitchRegion(currentRegion, block);
currentRegion.getSubBlocks().add(sw);
stack.push(sw);
stack.addExit(out);
// detect fallthrough cases
Map<BlockNode, BlockNode> fallThroughCases = new LinkedHashMap<>();
if (out != null) {
BitSet caseBlocks = BlockUtils.blocksToBitSet(mth, blocksMap.keySet());
caseBlocks.clear(out.getId());
for (BlockNode successor : block.getCleanSuccessors()) {
BlockNode fallThroughBlock = searchFallThroughCase(successor, out, caseBlocks);
if (fallThroughBlock != null) {
fallThroughCases.put(successor, fallThroughBlock);
}
}
// check fallthrough cases order
if (!fallThroughCases.isEmpty() && isBadCasesOrder(blocksMap, fallThroughCases)) {
Map<BlockNode, List<Object>> newBlocksMap = reOrderSwitchCases(blocksMap, fallThroughCases);
if (isBadCasesOrder(newBlocksMap, fallThroughCases)) {
mth.addWarnComment("Can't fix incorrect switch cases order, some code will duplicate");
fallThroughCases.clear();
} else {
blocksMap = newBlocksMap;
}
}
}
for (Entry<BlockNode, List<Object>> entry : blocksMap.entrySet()) {
List<Object> keysList = entry.getValue();
BlockNode caseBlock = entry.getKey();
if (stack.containsExit(caseBlock)) {
sw.addCase(keysList, new Region(stack.peekRegion()));
} else {
BlockNode next = fallThroughCases.get(caseBlock);
stack.addExit(next);
Region caseRegion = makeRegion(caseBlock, stack);
stack.removeExit(next);
if (next != null) {
next.add(AFlag.FALL_THROUGH);
caseRegion.add(AFlag.FALL_THROUGH);
}
sw.addCase(keysList, caseRegion);
// 'break' instruction will be inserted in RegionMakerVisitor.PostRegionVisitor
}
}
removeEmptyCases(insn, sw, defCase);
stack.pop();
return out;
}
use of jadx.core.utils.exceptions.JadxRuntimeException in project jadx by skylot.
the class CodeShrinkVisitor method canMoveBetweenBlocks.
private static boolean canMoveBetweenBlocks(MethodNode mth, InsnNode assignInsn, BlockNode assignBlock, BlockNode useBlock, InsnNode useInsn) {
if (!BlockUtils.isPathExists(assignBlock, useBlock)) {
return false;
}
List<RegisterArg> argsList = ArgsInfo.getArgs(assignInsn);
BitSet args = new BitSet();
for (RegisterArg arg : argsList) {
args.set(arg.getRegNum());
}
boolean startCheck = false;
for (InsnNode insn : assignBlock.getInstructions()) {
if (startCheck && (!insn.canReorder() || ArgsInfo.usedArgAssign(insn, args))) {
return false;
}
if (insn == assignInsn) {
startCheck = true;
}
}
Set<BlockNode> pathsBlocks = BlockUtils.getAllPathsBlocks(assignBlock, useBlock);
pathsBlocks.remove(assignBlock);
pathsBlocks.remove(useBlock);
for (BlockNode block : pathsBlocks) {
if (block.contains(AFlag.DONT_GENERATE)) {
if (BlockUtils.checkLastInsnType(block, InsnType.MONITOR_EXIT)) {
if (RegionUtils.isBlocksInSameRegion(mth, assignBlock, useBlock)) {
// allow move inside same synchronized region
} else {
// don't move from synchronized block
return false;
}
}
// skip checks for not generated blocks
continue;
}
for (InsnNode insn : block.getInstructions()) {
if (!insn.canReorder() || ArgsInfo.usedArgAssign(insn, args)) {
return false;
}
}
}
for (InsnNode insn : useBlock.getInstructions()) {
if (insn == useInsn) {
return true;
}
if (!insn.canReorder() || ArgsInfo.usedArgAssign(insn, args)) {
return false;
}
}
throw new JadxRuntimeException("Can't process instruction move : " + assignBlock);
}
use of jadx.core.utils.exceptions.JadxRuntimeException in project jadx by skylot.
the class ArgsInfo method canMove.
private boolean canMove(int from, int to) {
ArgsInfo startInfo = argsList.get(from);
List<RegisterArg> movedArgs = startInfo.getArgs();
int start = from + 1;
if (start == to) {
// previous instruction or on edge of inline border
return true;
}
if (start > to) {
throw new JadxRuntimeException("Invalid inline insn positions: " + start + " - " + to);
}
BitSet movedSet;
if (movedArgs.isEmpty()) {
if (startInfo.insn.isConstInsn()) {
return true;
}
movedSet = EmptyBitSet.EMPTY;
} else {
movedSet = new BitSet();
for (RegisterArg arg : movedArgs) {
movedSet.set(arg.getRegNum());
}
}
boolean canReorder = startInfo.insn.canReorder();
for (int i = start; i < to; i++) {
ArgsInfo argsInfo = argsList.get(i);
if (argsInfo.getInlinedInsn() == this) {
continue;
}
InsnNode curInsn = argsInfo.insn;
if (canReorder) {
if (usedArgAssign(curInsn, movedSet)) {
return false;
}
} else {
if (!curInsn.canReorder() || usedArgAssign(curInsn, movedSet)) {
return false;
}
}
}
return true;
}
Aggregations