void (RootStatement root, StructClass cl) { CancellationManager cancellationManager = DecompilerContext.getCancellationManager(); cancellationManager.checkCanceled(); FlattenStatementsHelper flattenHelper = new FlattenStatementsHelper(); DirectGraph dgraph = flattenHelper.buildDirectGraph(root); // collect finally entry points Set<String> setFinallyShortRangeEntryPoints = new HashSet<>(); for (List<FinallyPathWrapper> wrappers : dgraph.mapShortRangeFinallyPaths.values()) { for (FinallyPathWrapper wrapper : wrappers) { setFinallyShortRangeEntryPoints.add(wrapper.entry); } } Set<String> setFinallyLongRangeEntryPaths = new HashSet<>(); for (List<FinallyPathWrapper> wrappers : dgraph.mapLongRangeFinallyPaths.values()) { for (FinallyPathWrapper wrapper : wrappers) { setFinallyLongRangeEntryPaths.add(wrapper.source + "##" + wrapper.entry); } } Map<String, VarExprent> mapCatch = new HashMap<>(); collectCatchVars(root, flattenHelper, mapCatch); Map<DirectNode, Map<String, PrimitiveExpressionList>> mapData = new HashMap<>(); LinkedList<DirectNode> stack = new LinkedList<>(); LinkedList<LinkedList<String>> stackEntryPoint = new LinkedList<>(); stack.add(dgraph.first); stackEntryPoint.add(new LinkedList<>()); Map<String, PrimitiveExpressionList> map = new HashMap<>(); map.put(EMPTY_ENTRY_POINTS_KEY, new PrimitiveExpressionList()); mapData.put(dgraph.first, map); while (!stack.isEmpty()) { cancellationManager.checkCanceled(); DirectNode node = stack.removeFirst(); LinkedList<String> entryPoints = stackEntryPoint.removeFirst(); PrimitiveExpressionList data; if (mapCatch.containsKey(node.id)) { data = getExpressionData(mapCatch.get(node.id)); } else { data = mapData.get(node).get(buildEntryPointKey(entryPoints)); } BasicBlockStatement block = node.block; if (block != null) { processBlock(block, data, cl); block.setExprents(data.getExpressions()); } String currentEntrypoint = entryPoints.isEmpty() ? null : entryPoints.getLast(); for (DirectNode nd : node.successors) { cancellationManager.checkCanceled(); boolean isSuccessor = true; if (currentEntrypoint != null && dgraph.mapLongRangeFinallyPaths.containsKey(node.id)) { isSuccessor = false; for (FinallyPathWrapper wrapper : dgraph.mapLongRangeFinallyPaths.get(node.id)) { if (wrapper.source.equals(currentEntrypoint) && wrapper.destination.equals(nd.id)) { isSuccessor = true; break; } } } if (isSuccessor) { Map<String, PrimitiveExpressionList> successorMap = mapData.computeIfAbsent(nd, k -> new HashMap<>()); LinkedList<String> nodeEntryPoints = new LinkedList<>(entryPoints); if (setFinallyLongRangeEntryPaths.contains(node.id + "##" + nd.id)) { nodeEntryPoints.addLast(node.id); } else if (!setFinallyShortRangeEntryPoints.contains(nd.id) && dgraph.mapLongRangeFinallyPaths.containsKey(node.id)) { nodeEntryPoints.removeLast(); // currentEntrypoint should not be null at this point } // handling of entry point loops int successorEntryIndex = nodeEntryPoints.indexOf(nd.id); if (successorEntryIndex >= 0) { // we are in a loop (e.g. continue in a 'finally' block): drop all entry points in the list beginning with successor index for (int elementsToRemove = nodeEntryPoints.size() - successorEntryIndex; elementsToRemove > 0; elementsToRemove--) { nodeEntryPoints.removeLast(); } } String nodeEntryKey = buildEntryPointKey(nodeEntryPoints); if (!successorMap.containsKey(nodeEntryKey)) { successorMap.put(nodeEntryKey, data.copy()); stack.add(nd); stackEntryPoint.add(nodeEntryPoints); } } } } initStatementExprents(root); }