From d2718bd7b0575b0d14500554b4095d9d55e6b8f5 Mon Sep 17 00:00:00 2001 From: Graham Date: Sun, 22 Mar 2020 12:55:42 +0000 Subject: [PATCH] Improve code for setting the bytecodeOffset in VarDefinitionHelper --- .../decompiler/vars/VarDefinitionHelper.java | 86 ++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java index 8bb27e3..ec08e46 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java @@ -27,6 +27,7 @@ public class VarDefinitionHelper { private final HashSet implDefVars; + private final Statement root; private final VarProcessor varproc; public VarDefinitionHelper(Statement root, StructMethod mt, VarProcessor varproc) { @@ -35,6 +36,7 @@ public class VarDefinitionHelper { mapStatementVars = new HashMap<>(); implDefVars = new HashSet<>(); + this.root = root; this.varproc = varproc; VarNamesCollector vc = varproc.getVarNamesCollector(); @@ -160,7 +162,6 @@ public class VarDefinitionHelper { // search for the first assignment to var [index] int addindex = 0; - int bytecodeOffset = -1; for (Exprent expr : lst) { if (setDefinition(expr, index)) { defset = true; @@ -171,7 +172,6 @@ public class VarDefinitionHelper { for (Exprent exp : expr.getAllExprents(true)) { if (exp.type == Exprent.EXPRENT_VAR && ((VarExprent)exp).getIndex() == index) { foundvar = true; - bytecodeOffset = ((VarExprent) exp).getBytecodeOffset(); break; } } @@ -183,6 +183,13 @@ public class VarDefinitionHelper { } if (!defset) { + /* + * Use the offset from the first assignment after the declaration. This + * ensures the original PC values are stable even if the deobfuscator + * re-orders code. + */ + int bytecodeOffset = findMinBytecodeOffset(root, index); + VarExprent var = new VarExprent(index, varproc.getVarType(new VarVersionPair(index.intValue(), 0)), varproc, -1, bytecodeOffset); var.setDefinition(true); @@ -191,6 +198,81 @@ public class VarDefinitionHelper { } } + private int findMinBytecodeOffset(Statement statement, int index) { + int minBytecodeOffset = -1; + + List exprs = statement.getExprents(); + if (exprs != null) { + for (Exprent expr : exprs) { + int bytecodeOffset = findMinBytecodeOffset(expr, index); + + if (bytecodeOffset == -1) { + continue; + } + + if (minBytecodeOffset == -1 || bytecodeOffset < minBytecodeOffset) { + minBytecodeOffset = bytecodeOffset; + } + } + } else { + for (Object obj : statement.getSequentialObjects()) { + int bytecodeOffset; + if (obj instanceof Statement) { + bytecodeOffset = findMinBytecodeOffset((Statement) obj, index); + } else if (obj instanceof Exprent) { + bytecodeOffset = findMinBytecodeOffset((Exprent) obj, index); + } else { + throw new IllegalStateException(); + } + + if (bytecodeOffset == -1) { + continue; + } + + if (minBytecodeOffset == -1 || bytecodeOffset < minBytecodeOffset) { + minBytecodeOffset = bytecodeOffset; + } + } + } + + return minBytecodeOffset; + } + + private int findMinBytecodeOffset(Exprent parent, int index) { + int minBytecodeOffset = -1; + + List list = parent.getAllExprents(true); + list.add(parent); + + for (Exprent expr : list) { + if (expr.type != Exprent.EXPRENT_ASSIGNMENT) { + continue; + } + + AssignmentExprent assignment = (AssignmentExprent) expr; + + Exprent left = assignment.getLeft(); + if (left.type != Exprent.EXPRENT_VAR) { + continue; + } + + VarExprent var = (VarExprent) left; + if (var.getIndex() != index) { + continue; + } + + int bytecodeOffset = var.getBytecodeOffset(); + if (bytecodeOffset == -1) { + continue; + } + + if (minBytecodeOffset == -1 || bytecodeOffset < minBytecodeOffset) { + minBytecodeOffset = bytecodeOffset; + } + } + + return minBytecodeOffset; + } // ***************************************************************************** // private methods