From 6fbca39601e808f35f273a1a1da41205f298a467 Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Thu, 20 Dec 2018 15:54:11 +0000 Subject: dx: workaround a verifier bug Turn the following code move-object vX, vY instance-of vY, vX, LMyClass; into move-object vX, vY nop instance-of vY, vX, LMyClass; Bug: 120985556 Test: run-all-tests --seq --skip 127-merge-stress Change-Id: I52939634e855a0580f253d839ac6ecaa7db77078 --- .../com/android/dx/dex/code/OutputCollector.java | 12 ++++++++ dx/src/com/android/dx/dex/code/OutputFinisher.java | 8 ++++++ dx/src/com/android/dx/dex/code/RopTranslator.java | 32 +++++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/dx/src/com/android/dx/dex/code/OutputCollector.java b/dx/src/com/android/dx/dex/code/OutputCollector.java index 833c0f21b..8c8867a0b 100644 --- a/dx/src/com/android/dx/dex/code/OutputCollector.java +++ b/dx/src/com/android/dx/dex/code/OutputCollector.java @@ -65,6 +65,18 @@ public final class OutputCollector { finisher.add(insn); } + public DalvInsn get(int at) { + if (at >= finisher.size() || at < 0) { + return null; + } else { + return finisher.get(at); + } + } + + public int size() { + return finisher.size(); + } + /** * Reverses a branch which is buried a given number of instructions * backward in the output. It is illegal to call this unless the diff --git a/dx/src/com/android/dx/dex/code/OutputFinisher.java b/dx/src/com/android/dx/dex/code/OutputFinisher.java index 3b711fb32..82a4725f5 100644 --- a/dx/src/com/android/dx/dex/code/OutputFinisher.java +++ b/dx/src/com/android/dx/dex/code/OutputFinisher.java @@ -256,6 +256,14 @@ public final class OutputFinisher { updateInfo(insn); } + public DalvInsn get(int at) { + return insns.get(at); + } + + public int size() { + return insns.size(); + } + /** * Helper for {@link #add} and {@link #insert}, * which updates the position and local info flags. diff --git a/dx/src/com/android/dx/dex/code/RopTranslator.java b/dx/src/com/android/dx/dex/code/RopTranslator.java index 8375f9ee3..517b4f855 100644 --- a/dx/src/com/android/dx/dex/code/RopTranslator.java +++ b/dx/src/com/android/dx/dex/code/RopTranslator.java @@ -762,7 +762,27 @@ public final class RopTranslator { */ di = new CstInsn(opcode, pos, regs, cst); } - + // (b/120985556) update the following code + // move-object vX, vY + // instance-of vY, vX, LMyClass; + // into + // move-object vX, vY + // nop + // instance-of vY, vX, LMyClass; + DalvInsn previousDi = getPrevNonSpecialInsn(); + if (opcode.getOpcode() == Opcodes.INSTANCE_OF && previousDi != null) { + int prevOpcode = previousDi.getOpcode().getOpcode(); + if (prevOpcode == Opcodes.MOVE_OBJECT + || prevOpcode == Opcodes.MOVE_OBJECT_FROM16 + || prevOpcode == Opcodes.MOVE_OBJECT_16) { + if (di.getRegisters().size() > 0 && previousDi.getRegisters().size() > 1 + && (di.getRegisters().get(0).getReg() + == previousDi.getRegisters().get(1).getReg())) { + DalvInsn nopDi = new SimpleInsn(Dops.NOP, pos, RegisterSpecList.EMPTY); + addOutput(nopDi); + } + } + } addOutput(di); } } @@ -830,6 +850,16 @@ public final class RopTranslator { output.add(insn); } + protected DalvInsn getPrevNonSpecialInsn() { + for (int i = output.size() - 1; i >= 0; --i) { + DalvInsn insn = output.get(i); + if (insn.getOpcode().getOpcode() != Opcodes.SPECIAL_FORMAT) { + return insn; + } + } + return null; + } + /** * Adds to the output suffix. * -- cgit v1.2.3