Commit 76cf4f05 authored by Skylot's avatar Skylot

Merge branch 'master' into type-inference-wip

parents 6a1717a6 eadf046b
...@@ -54,7 +54,7 @@ allprojects { ...@@ -54,7 +54,7 @@ allprojects {
} }
jacoco { jacoco {
toolVersion = "0.8.1" toolVersion = "0.8.2"
} }
jacocoTestReport { jacocoTestReport {
reports { reports {
......
...@@ -116,14 +116,16 @@ class DeobfPresets { ...@@ -116,14 +116,16 @@ class DeobfPresets {
} }
} }
for (FieldInfo fld : deobfuscator.getFldMap().keySet()) { for (FieldInfo fld : deobfuscator.getFldMap().keySet()) {
list.add(String.format("f %s = %s", fld.getFullId(), fld.getAlias())); list.add(String.format("f %s = %s", fld.getRawFullId(), fld.getAlias()));
} }
for (MethodInfo mth : deobfuscator.getMthMap().keySet()) { for (MethodInfo mth : deobfuscator.getMthMap().keySet()) {
list.add(String.format("m %s = %s", mth.getFullId(), mth.getAlias())); list.add(String.format("m %s = %s", mth.getRawFullId(), mth.getAlias()));
} }
Collections.sort(list); Collections.sort(list);
FileUtils.writeLines(deobfMapFile, MAP_FILE_CHARSET, list); FileUtils.writeLines(deobfMapFile, MAP_FILE_CHARSET, list);
list.clear(); if (LOG.isDebugEnabled()) {
LOG.debug("Deobfuscation map file saved as: {}", deobfMapFile);
}
} }
private static void dfsPackageName(List<String> list, String prefix, PackageNode node) { private static void dfsPackageName(List<String> list, String prefix, PackageNode node) {
...@@ -140,11 +142,11 @@ class DeobfPresets { ...@@ -140,11 +142,11 @@ class DeobfPresets {
} }
public String getForFld(FieldInfo fld) { public String getForFld(FieldInfo fld) {
return fldPresetMap.get(fld.getFullId()); return fldPresetMap.get(fld.getRawFullId());
} }
public String getForMth(MethodInfo mth) { public String getForMth(MethodInfo mth) {
return mthPresetMap.get(mth.getFullId()); return mthPresetMap.get(mth.getRawFullId());
} }
public void clear() { public void clear() {
......
...@@ -409,6 +409,9 @@ public class Deobfuscator { ...@@ -409,6 +409,9 @@ public class Deobfuscator {
@Nullable @Nullable
private String getMethodAlias(MethodNode mth) { private String getMethodAlias(MethodNode mth) {
MethodInfo methodInfo = mth.getMethodInfo(); MethodInfo methodInfo = mth.getMethodInfo();
if (methodInfo.isClassInit() || methodInfo.isConstructor()) {
return null;
}
String alias = mthMap.get(methodInfo); String alias = mthMap.get(methodInfo);
if (alias != null) { if (alias != null) {
return alias; return alias;
......
...@@ -57,6 +57,10 @@ public final class FieldInfo { ...@@ -57,6 +57,10 @@ public final class FieldInfo {
return declClass.getFullName() + "." + name + ":" + TypeGen.signature(type); return declClass.getFullName() + "." + name + ":" + TypeGen.signature(type);
} }
public String getRawFullId() {
return declClass.makeRawFullName() + "." + name + ":" + TypeGen.signature(type);
}
public boolean isRenamed() { public boolean isRenamed() {
return !name.equals(alias); return !name.equals(alias);
} }
......
...@@ -68,6 +68,10 @@ public final class MethodInfo { ...@@ -68,6 +68,10 @@ public final class MethodInfo {
return declClass.getFullName() + "." + shortId; return declClass.getFullName() + "." + shortId;
} }
public String getRawFullId() {
return declClass.makeRawFullName() + "." + shortId;
}
/** /**
* Method name and signature * Method name and signature
*/ */
......
...@@ -23,6 +23,6 @@ public class SplitterBlockAttr implements IAttribute { ...@@ -23,6 +23,6 @@ public class SplitterBlockAttr implements IAttribute {
@Override @Override
public String toString() { public String toString() {
return "Splitter: " + block; return "Splitter:" + block;
} }
} }
...@@ -26,7 +26,7 @@ public class BlockFinish extends AbstractVisitor { ...@@ -26,7 +26,7 @@ public class BlockFinish extends AbstractVisitor {
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
block.updateCleanSuccessors(); block.updateCleanSuccessors();
fixSplitterBlock(block); fixSplitterBlock(mth, block);
} }
mth.finishBasicBlocks(); mth.finishBasicBlocks();
...@@ -36,7 +36,7 @@ public class BlockFinish extends AbstractVisitor { ...@@ -36,7 +36,7 @@ public class BlockFinish extends AbstractVisitor {
* For evey exception handler must be only one splitter block, * For evey exception handler must be only one splitter block,
* select correct one and remove others if necessary. * select correct one and remove others if necessary.
*/ */
private static void fixSplitterBlock(BlockNode block) { private static void fixSplitterBlock(MethodNode mth, BlockNode block) {
ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER); ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER);
if (excHandlerAttr == null) { if (excHandlerAttr == null) {
return; return;
...@@ -58,7 +58,7 @@ public class BlockFinish extends AbstractVisitor { ...@@ -58,7 +58,7 @@ public class BlockFinish extends AbstractVisitor {
} }
BlockNode topSplitter = BlockUtils.getTopBlock(splitters.keySet()); BlockNode topSplitter = BlockUtils.getTopBlock(splitters.keySet());
if (topSplitter == null) { if (topSplitter == null) {
LOG.warn("Unknown top splitter block from list: {}", splitters); mth.addWarn("Unknown top exception splitter block from list: " + splitters);
return; return;
} }
for (Map.Entry<BlockNode, SplitterBlockAttr> entry : splitters.entrySet()) { for (Map.Entry<BlockNode, SplitterBlockAttr> entry : splitters.entrySet()) {
......
...@@ -226,12 +226,13 @@ public class BlockSplitter extends AbstractVisitor { ...@@ -226,12 +226,13 @@ public class BlockSplitter extends AbstractVisitor {
BlockNode thisBlock = getBlock(jump.getDest(), blocksMap); BlockNode thisBlock = getBlock(jump.getDest(), blocksMap);
connect(srcBlock, thisBlock); connect(srcBlock, thisBlock);
} }
connectExceptionHandlers(block, insn); connectExceptionHandlers(block, insn, blocksMap);
} }
} }
} }
private static void connectExceptionHandlers(BlockNode block, InsnNode insn) { private static void connectExceptionHandlers(BlockNode block, InsnNode insn,
Map<Integer, BlockNode> blocksMap) {
CatchAttr catches = insn.get(AType.CATCH_BLOCK); CatchAttr catches = insn.get(AType.CATCH_BLOCK);
SplitterBlockAttr spl = block.get(AType.SPLITTER_BLOCK); SplitterBlockAttr spl = block.get(AType.SPLITTER_BLOCK);
if (catches == null || spl == null) { if (catches == null || spl == null) {
...@@ -240,7 +241,7 @@ public class BlockSplitter extends AbstractVisitor { ...@@ -240,7 +241,7 @@ public class BlockSplitter extends AbstractVisitor {
BlockNode splitterBlock = spl.getBlock(); BlockNode splitterBlock = spl.getBlock();
boolean tryEnd = insn.contains(AFlag.TRY_LEAVE); boolean tryEnd = insn.contains(AFlag.TRY_LEAVE);
for (ExceptionHandler h : catches.getTryBlock().getHandlers()) { for (ExceptionHandler h : catches.getTryBlock().getHandlers()) {
BlockNode handlerBlock = h.getHandlerBlock(); BlockNode handlerBlock = initHandlerBlock(h, blocksMap);
// skip self loop in handler // skip self loop in handler
if (splitterBlock != handlerBlock) { if (splitterBlock != handlerBlock) {
if (!handlerBlock.contains(AType.SPLITTER_BLOCK)) { if (!handlerBlock.contains(AType.SPLITTER_BLOCK)) {
...@@ -254,6 +255,16 @@ public class BlockSplitter extends AbstractVisitor { ...@@ -254,6 +255,16 @@ public class BlockSplitter extends AbstractVisitor {
} }
} }
private static BlockNode initHandlerBlock(ExceptionHandler excHandler, Map<Integer, BlockNode> blocksMap) {
BlockNode handlerBlock = excHandler.getHandlerBlock();
if (handlerBlock != null) {
return handlerBlock;
}
BlockNode blockByOffset = getBlock(excHandler.getHandleOffset(), blocksMap);
excHandler.setHandlerBlock(blockByOffset);
return blockByOffset;
}
private static boolean isSplitByJump(InsnNode prevInsn, InsnNode currentInsn) { private static boolean isSplitByJump(InsnNode prevInsn, InsnNode currentInsn) {
List<JumpInfo> pJumps = prevInsn.getAll(AType.JUMP); List<JumpInfo> pJumps = prevInsn.getAll(AType.JUMP);
for (JumpInfo jump : pJumps) { for (JumpInfo jump : pJumps) {
......
...@@ -60,7 +60,7 @@ public class CheckRegions extends AbstractVisitor { ...@@ -60,7 +60,7 @@ public class CheckRegions extends AbstractVisitor {
&& !block.getInstructions().isEmpty() && !block.getInstructions().isEmpty()
&& !block.contains(AFlag.SKIP)) { && !block.contains(AFlag.SKIP)) {
String blockCode = getBlockInsnStr(mth, block); String blockCode = getBlockInsnStr(mth, block);
mth.addWarn("Missing block: " + block + ", code:" + CodeWriter.NL + blockCode); mth.addWarn("Missing block: " + block + ", code skipped:" + CodeWriter.NL + blockCode);
} }
} }
} }
......
...@@ -27,7 +27,6 @@ import jadx.core.dex.trycatch.TryCatchBlock; ...@@ -27,7 +27,6 @@ import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.ErrorsCounter; import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.RegionUtils; import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;
/** /**
* Extract blocks to separate try/catch region * Extract blocks to separate try/catch region
...@@ -67,9 +66,14 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -67,9 +66,14 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
// for each try block search nearest dominator block // for each try block search nearest dominator block
for (TryCatchBlock tb : tryBlocks) { for (TryCatchBlock tb : tryBlocks) {
if (tb.getHandlersCount() == 0) { if (tb.getHandlersCount() == 0) {
LOG.warn("No exception handlers in catch block, method: {}", mth); mth.addWarn("No exception handlers in catch block: " + tb);
continue; continue;
} }
processTryCatchBlock(mth, tb, tryBlocksMap);
}
}
private static void processTryCatchBlock(MethodNode mth, TryCatchBlock tb, Map<BlockNode, TryCatchBlock> tryBlocksMap) {
BitSet bs = new BitSet(mth.getBasicBlocks().size()); BitSet bs = new BitSet(mth.getBasicBlocks().size());
for (ExceptionHandler excHandler : tb.getHandlers()) { for (ExceptionHandler excHandler : tb.getHandlers()) {
BlockNode handlerBlock = excHandler.getHandlerBlock(); BlockNode handlerBlock = excHandler.getHandlerBlock();
...@@ -86,15 +90,15 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -86,15 +90,15 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
if (domBlocks.size() != 1) { if (domBlocks.size() != 1) {
domBlock = BlockUtils.getTopBlock(domBlocks); domBlock = BlockUtils.getTopBlock(domBlocks);
if (domBlock == null) { if (domBlock == null) {
throw new JadxRuntimeException("Exception block dominator not found, method:" + mth + ", dom blocks: " + domBlocks); mth.addWarn("Exception block dominator not found, dom blocks: " + domBlocks);
return;
} }
} else { } else {
domBlock = domBlocks.get(0); domBlock = domBlocks.get(0);
} }
TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb); TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb);
if (prevTB != null) { if (prevTB != null) {
ErrorsCounter.methodWarn(mth, "Failed to process nested try/catch"); mth.addWarn("Failed to process nested try/catch");
}
} }
} }
...@@ -105,7 +109,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -105,7 +109,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
if (region.getSubBlocks().contains(dominator)) { if (region.getSubBlocks().contains(dominator)) {
TryCatchBlock tb = tryBlocksMap.get(dominator); TryCatchBlock tb = tryBlocksMap.get(dominator);
if (!wrapBlocks(region, tb, dominator)) { if (!wrapBlocks(region, tb, dominator)) {
ErrorsCounter.methodWarn(mth, "Can't wrap try/catch for " + region); ErrorsCounter.methodWarn(mth, "Can't wrap try/catch for region: " + region);
} }
tryBlocksMap.remove(dominator); tryBlocksMap.remove(dominator);
return true; return true;
......
...@@ -932,7 +932,7 @@ public class RegionMaker { ...@@ -932,7 +932,7 @@ public class RegionMaker {
} }
} }
for (ExceptionHandler handler : tc.getHandlers()) { for (ExceptionHandler handler : tc.getHandlers()) {
processExcHandler(handler, exits); processExcHandler(mth, handler, exits);
} }
} }
return processHandlersOutBlocks(mth, tcs); return processHandlersOutBlocks(mth, tcs);
...@@ -971,12 +971,12 @@ public class RegionMaker { ...@@ -971,12 +971,12 @@ public class RegionMaker {
return excOutRegion; return excOutRegion;
} }
private void processExcHandler(ExceptionHandler handler, Set<BlockNode> exits) { private void processExcHandler(MethodNode mth, ExceptionHandler handler, Set<BlockNode> exits) {
BlockNode start = handler.getHandlerBlock(); BlockNode start = handler.getHandlerBlock();
if (start == null) { if (start == null) {
return; return;
} }
RegionStack stack = new RegionStack(mth); RegionStack stack = new RegionStack(this.mth);
BlockNode dom; BlockNode dom;
if (handler.isFinally()) { if (handler.isFinally()) {
SplitterBlockAttr splitterAttr = start.get(AType.SPLITTER_BLOCK); SplitterBlockAttr splitterAttr = start.get(AType.SPLITTER_BLOCK);
...@@ -989,11 +989,11 @@ public class RegionMaker { ...@@ -989,11 +989,11 @@ public class RegionMaker {
stack.addExits(exits); stack.addExits(exits);
} }
BitSet domFrontier = dom.getDomFrontier(); BitSet domFrontier = dom.getDomFrontier();
List<BlockNode> handlerExits = BlockUtils.bitSetToBlocks(mth, domFrontier); List<BlockNode> handlerExits = BlockUtils.bitSetToBlocks(this.mth, domFrontier);
boolean inLoop = mth.getLoopForBlock(start) != null; boolean inLoop = this.mth.getLoopForBlock(start) != null;
for (BlockNode exit : handlerExits) { for (BlockNode exit : handlerExits) {
if ((!inLoop || BlockUtils.isPathExists(start, exit)) if ((!inLoop || BlockUtils.isPathExists(start, exit))
&& RegionUtils.isRegionContainsBlock(mth.getRegion(), exit)) { && RegionUtils.isRegionContainsBlock(this.mth.getRegion(), exit)) {
stack.addExit(exit); stack.addExit(exit);
} }
} }
...@@ -1001,7 +1001,7 @@ public class RegionMaker { ...@@ -1001,7 +1001,7 @@ public class RegionMaker {
ExcHandlerAttr excHandlerAttr = start.get(AType.EXC_HANDLER); ExcHandlerAttr excHandlerAttr = start.get(AType.EXC_HANDLER);
if (excHandlerAttr == null) { if (excHandlerAttr == null) {
LOG.warn("Missing exception handler attribute for start block"); mth.addWarn("Missing exception handler attribute for start block: " + start);
} else { } else {
handler.getHandlerRegion().addAttr(excHandlerAttr); handler.getHandlerRegion().addAttr(excHandlerAttr);
} }
......
...@@ -135,22 +135,35 @@ public abstract class BaseExternalTest extends IntegrationTest { ...@@ -135,22 +135,35 @@ public abstract class BaseExternalTest extends IntegrationTest {
String[] lines = code.split(CodeWriter.NL); String[] lines = code.split(CodeWriter.NL);
for (MethodNode mth : classNode.getMethods()) { for (MethodNode mth : classNode.getMethods()) {
if (isMthMatch(mth, mthPattern)) { if (isMthMatch(mth, mthPattern)) {
int decompiledLine = mth.getDecompiledLine(); int decompiledLine = mth.getDecompiledLine() - 1;
StringBuilder mthCode = new StringBuilder(); StringBuilder mthCode = new StringBuilder();
int startLine = getCommentLinesCount(lines, decompiledLine);
int brackets = 0; int brackets = 0;
for (int i = decompiledLine - 1; i > 0 && i < lines.length; i++) { for (int i = startLine; i > 0 && i < lines.length; i++) {
String line = lines[i]; String line = lines[i];
mthCode.append(line).append(CodeWriter.NL); mthCode.append(line).append(CodeWriter.NL);
if (i >= decompiledLine) {
brackets += StringUtils.countMatches(line, '{'); brackets += StringUtils.countMatches(line, '{');
brackets -= StringUtils.countMatches(line, '}'); brackets -= StringUtils.countMatches(line, '}');
if (brackets <= 0) { if (brackets <= 0) {
break; break;
} }
} }
LOG.info("{}\n{}", mth.getMethodInfo().getShortId(), mthCode);
} }
LOG.info("Print method: {}\n{}", mth.getMethodInfo().getShortId(), mthCode);
} }
} }
}
protected int getCommentLinesCount(String[] lines, int line) {
for (int i = line - 1; i > 0 && i < lines.length; i--) {
String str = lines[i];
if (str.isEmpty() || str.equals(CodeWriter.NL)) {
return i + 1;
}
}
return 0;
}
private void printErrorReport(JadxDecompiler jadx) { private void printErrorReport(JadxDecompiler jadx) {
jadx.printErrorsReport(); jadx.printErrorsReport();
......
plugins { plugins {
id 'edu.sc.seis.launch4j' version '2.4.4' id 'edu.sc.seis.launch4j' version '2.4.4'
id 'com.github.johnrengelman.shadow' version '2.0.4' id 'com.github.johnrengelman.shadow' version '4.0.3'
} }
apply plugin: 'application' apply plugin: 'application'
......
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