Projects STRLCPY jadx Commits 988628a2
🤬
  • core: fix variable declaration used in several loops

  • Loading...
  • Skylot committed 9 years ago
    988628a2
    1 parent c24cdf5c
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/Jadx.java
    skipped 81 lines
    82 82   
    83 83   passes.add(new CodeShrinker());
    84 84   passes.add(new SimplifyVisitor());
    85  - passes.add(new ProcessVariables());
    86 85   passes.add(new CheckRegions());
    87 86   
    88 87   if (args.isCFGOutput()) {
    skipped 4 lines
    93 92   passes.add(new ClassModifier());
    94 93   passes.add(new PrepareForCodeGen());
    95 94   passes.add(new LoopRegionVisitor());
     95 + passes.add(new ProcessVariables());
    96 96   }
    97 97   passes.add(new CodeGen(args));
    98 98   return passes;
    skipped 22 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java
    skipped 14 lines
    15 15  import jadx.core.dex.nodes.MethodNode;
    16 16  import jadx.core.dex.regions.SwitchRegion;
    17 17  import jadx.core.dex.regions.conditions.IfRegion;
     18 +import jadx.core.dex.regions.loops.ForLoop;
     19 +import jadx.core.dex.regions.loops.LoopRegion;
     20 +import jadx.core.dex.regions.loops.LoopType;
    18 21  import jadx.core.dex.visitors.AbstractVisitor;
    19 22  import jadx.core.utils.RegionUtils;
    20 23  import jadx.core.utils.exceptions.JadxException;
    skipped 91 lines
    112 115   }
    113 116   }
    114 117   
     118 + private static class CollectUsageRegionVisitor extends TracedRegionVisitor {
     119 + private final List<RegisterArg> args;
     120 + private final Map<Variable, Usage> usageMap;
     121 + 
     122 + public CollectUsageRegionVisitor(Map<Variable, Usage> usageMap) {
     123 + this.usageMap = usageMap;
     124 + args = new ArrayList<RegisterArg>();
     125 + }
     126 + 
     127 + @Override
     128 + public void processBlockTraced(MethodNode mth, IBlock container, IRegion curRegion) {
     129 + regionProcess(mth, curRegion);
     130 + int len = container.getInstructions().size();
     131 + for (int i = 0; i < len; i++) {
     132 + InsnNode insn = container.getInstructions().get(i);
     133 + if (insn.contains(AFlag.SKIP)) {
     134 + continue;
     135 + }
     136 + args.clear();
     137 + processInsn(insn, curRegion);
     138 + }
     139 + }
     140 + 
     141 + private void regionProcess(MethodNode mth, IRegion region) {
     142 + if (region instanceof LoopRegion) {
     143 + LoopRegion loopRegion = (LoopRegion) region;
     144 + LoopType loopType = loopRegion.getType();
     145 + if (loopType instanceof ForLoop) {
     146 + ForLoop forLoop = (ForLoop) loopType;
     147 + processInsn(forLoop.getInitInsn(), region);
     148 + processInsn(forLoop.getIncrInsn(), region);
     149 + }
     150 + }
     151 + }
     152 + 
     153 + void processInsn(InsnNode insn, IRegion curRegion) {
     154 + if (insn == null) {
     155 + return;
     156 + }
     157 + // result
     158 + RegisterArg result = insn.getResult();
     159 + if (result != null && result.isRegister()) {
     160 + Usage u = addToUsageMap(result, usageMap);
     161 + if (u.getArg() == null) {
     162 + u.setArg(result);
     163 + u.setArgRegion(curRegion);
     164 + }
     165 + u.getAssigns().add(curRegion);
     166 + }
     167 + // args
     168 + args.clear();
     169 + insn.getRegisterArgs(args);
     170 + for (RegisterArg arg : args) {
     171 + Usage u = addToUsageMap(arg, usageMap);
     172 + u.getUseRegions().add(curRegion);
     173 + }
     174 + }
     175 + }
     176 + 
    115 177   @Override
    116 178   public void visit(MethodNode mth) throws JadxException {
    117 179   if (mth.isNoCode()) {
    118 180   return;
    119 181   }
    120  - 
    121 182   final Map<Variable, Usage> usageMap = new LinkedHashMap<Variable, Usage>();
    122 183   for (RegisterArg arg : mth.getArguments(true)) {
    123 184   addToUsageMap(arg, usageMap);
    124 185   }
    125 186   
    126 187   // collect all variables usage
    127  - IRegionVisitor collect = new TracedRegionVisitor() {
    128  - @Override
    129  - public void processBlockTraced(MethodNode mth, IBlock container, IRegion curRegion) {
    130  - int len = container.getInstructions().size();
    131  - List<RegisterArg> args = new ArrayList<RegisterArg>();
    132  - for (int i = 0; i < len; i++) {
    133  - InsnNode insn = container.getInstructions().get(i);
    134  - // result
    135  - RegisterArg result = insn.getResult();
    136  - if (result != null && result.isRegister()) {
    137  - Usage u = addToUsageMap(result, usageMap);
    138  - if (u.getArg() == null) {
    139  - u.setArg(result);
    140  - u.setArgRegion(curRegion);
    141  - }
    142  - u.getAssigns().add(curRegion);
    143  - }
    144  - // args
    145  - args.clear();
    146  - insn.getRegisterArgs(args);
    147  - for (RegisterArg arg : args) {
    148  - Usage u = addToUsageMap(arg, usageMap);
    149  - u.getUseRegions().add(curRegion);
    150  - }
    151  - }
    152  - }
    153  - };
     188 + IRegionVisitor collect = new CollectUsageRegionVisitor(usageMap);
    154 189   DepthRegionTraversal.traverseAll(mth, collect);
    155 190   
    156 191   // reduce assigns map
    skipped 32 lines
    189 224   for (IRegion assignRegion : u.getAssigns()) {
    190 225   if (u.getArgRegion() == assignRegion
    191 226   && canDeclareInRegion(u, assignRegion, regionsOrder)) {
    192  - u.getArg().getParentInsn().add(AFlag.DECLARE_VAR);
    193  - processVar(u.getArg());
    194  - it.remove();
    195  - break;
     227 + if (declareAtAssign(u)) {
     228 + it.remove();
     229 + break;
     230 + }
    196 231   }
    197 232   }
    198 233   }
    skipped 40 lines
    239 274   }
    240 275   }
    241 276   
    242  - Usage addToUsageMap(RegisterArg arg, Map<Variable, Usage> usageMap) {
     277 + private static Usage addToUsageMap(RegisterArg arg, Map<Variable, Usage> usageMap) {
    243 278   Variable varId = new Variable(arg);
    244 279   Usage usage = usageMap.get(varId);
    245 280   if (usage == null) {
    skipped 14 lines
    260 295   return usage;
    261 296   }
    262 297   
     298 + private static boolean declareAtAssign(Usage u) {
     299 + RegisterArg arg = u.getArg();
     300 + InsnNode parentInsn = arg.getParentInsn();
     301 + if (!arg.equals(parentInsn.getResult())) {
     302 + return false;
     303 + }
     304 + parentInsn.add(AFlag.DECLARE_VAR);
     305 + processVar(arg);
     306 + return true;
     307 + }
     308 + 
    263 309   private static void declareVar(IContainer region, RegisterArg arg) {
    264 310   DeclareVariablesAttr dv = region.get(AType.DECLARE_VARIABLES);
    265 311   if (dv == null) {
    skipped 41 lines
    307 353   if (pos == null) {
    308 354   LOG.debug("TODO: Not found order for region {} for {}", region, u);
    309 355   return false;
     356 + }
     357 + // workaround for declare variables used in several loops
     358 + if (region instanceof LoopRegion) {
     359 + for (IRegion r : u.getAssigns()) {
     360 + if (!RegionUtils.isRegionContainsRegion(region, r)) {
     361 + return false;
     362 + }
     363 + }
    310 364   }
    311 365   return isAllRegionsAfter(region, pos, u.getAssigns(), regionsOrder)
    312 366   && isAllRegionsAfter(region, pos, u.getUseRegions(), regionsOrder);
    skipped 33 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/integration/names/TestNameAssign2.java
     1 +package jadx.tests.integration.names;
     2 + 
     3 +import jadx.core.dex.nodes.BlockNode;
     4 +import jadx.core.dex.nodes.ClassNode;
     5 +import jadx.core.dex.nodes.MethodNode;
     6 +import jadx.core.dex.visitors.ssa.LiveVarAnalysis;
     7 +import jadx.tests.api.IntegrationTest;
     8 + 
     9 +import java.util.BitSet;
     10 +import java.util.Deque;
     11 +import java.util.LinkedList;
     12 +import java.util.List;
     13 + 
     14 +import org.junit.Test;
     15 + 
     16 +import static jadx.tests.api.utils.JadxMatchers.containsOne;
     17 +import static org.junit.Assert.assertThat;
     18 + 
     19 +public class TestNameAssign2 extends IntegrationTest {
     20 + 
     21 + public static class TestCls {
     22 + 
     23 + private static void test(MethodNode mth, int regNum, LiveVarAnalysis la) {
     24 + List<BlockNode> blocks = mth.getBasicBlocks();
     25 + int blocksCount = blocks.size();
     26 + BitSet hasPhi = new BitSet(blocksCount);
     27 + BitSet processed = new BitSet(blocksCount);
     28 + Deque<BlockNode> workList = new LinkedList<BlockNode>();
     29 + 
     30 + BitSet assignBlocks = la.getAssignBlocks(regNum);
     31 + for (int id = assignBlocks.nextSetBit(0); id >= 0; id = assignBlocks.nextSetBit(id + 1)) {
     32 + processed.set(id);
     33 + workList.add(blocks.get(id));
     34 + }
     35 + while (!workList.isEmpty()) {
     36 + BlockNode block = workList.pop();
     37 + BitSet domFrontier = block.getDomFrontier();
     38 + for (int id = domFrontier.nextSetBit(0); id >= 0; id = domFrontier.nextSetBit(id + 1)) {
     39 + if (!hasPhi.get(id) && la.isLive(id, regNum)) {
     40 + BlockNode df = blocks.get(id);
     41 + addPhi(df, regNum);
     42 + hasPhi.set(id);
     43 + if (!processed.get(id)) {
     44 + processed.set(id);
     45 + workList.add(df);
     46 + }
     47 + }
     48 + }
     49 + }
     50 + }
     51 + 
     52 + private static void addPhi(BlockNode df, int regNum) {
     53 + }
     54 + }
     55 + 
     56 + @Test
     57 + public void test() {
     58 + ClassNode cls = getClassNode(TestCls.class);
     59 + String code = cls.getCode().toString();
     60 + 
     61 + // TODO:
     62 + assertThat(code, containsOne("int id;"));
     63 + }
     64 +}
     65 + 
Please wait...
Page is in error, reload to recover