@Nonnull private BuilderPackedSwitchPayload newBuilderPackedSwitchPayload(@Nonnull MethodLocation location, @Nonnull int[] codeAddressToIndex, @Nonnull PackedSwitchPayload instruction) { List<? extends SwitchElement> switchElements = instruction.getSwitchElements(); if (switchElements.size() == 0) { return new BuilderPackedSwitchPayload(0, null); } MethodLocation switchLocation = findSwitchForPayload(location); int baseAddress; if (switchLocation == null) { baseAddress = 0; } else { baseAddress = switchLocation.codeAddress; } List<Label> labels = Lists.newArrayList(); for (SwitchElement element : switchElements) { labels.add(newLabel(codeAddressToIndex, element.getOffset() + baseAddress)); } return new BuilderPackedSwitchPayload(switchElements.get(0).getKey(), labels); }
@Nonnull private BuilderSparseSwitchPayload newBuilderSparseSwitchPayload(@Nonnull MethodLocation location, @Nonnull int[] codeAddressToIndex, @Nonnull SparseSwitchPayload instruction) { List<? extends SwitchElement> switchElements = instruction.getSwitchElements(); if (switchElements.size() == 0) { return new BuilderSparseSwitchPayload(null); } MethodLocation switchLocation = findSwitchForPayload(location); int baseAddress; if (switchLocation == null) { baseAddress = 0; } else { baseAddress = switchLocation.codeAddress; } List<SwitchLabelElement> labelElements = Lists.newArrayList(); for (SwitchElement element : switchElements) { labelElements.add(new SwitchLabelElement(element.getKey(), newLabel(codeAddressToIndex, element.getOffset() + baseAddress))); } return new BuilderSparseSwitchPayload(labelElements); }
@Test public void payloadOpHasExpectedToString() { when(instruction.getOpcode()).thenReturn(Opcode.PACKED_SWITCH_PAYLOAD); List<SwitchElement> elements = new LinkedList<SwitchElement>(); doReturn(elements).when((SwitchPayload) instruction).getSwitchElements(); SwitchElement element1 = mock(SwitchElement.class); when(element1.getKey()).thenReturn(1); when(element1.getOffset()).thenReturn(10); SwitchElement element2 = mock(SwitchElement.class); when(element2.getKey()).thenReturn(2); when(element2.getOffset()).thenReturn(20); elements.add(element2); elements.add(element1); op = (SwitchPayloadOp) opFactory.create(location, addressToLocation, vm); assertEquals("packed-switch-payload [1 -> :addr_10, 2 -> :addr_20]", op.toString()); }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { SwitchPayload instr = (SwitchPayload) location.getInstruction(); TIntIntMap targetKeyToOffset = new TIntIntHashMap(); for (SwitchElement element : instr.getSwitchElements()) { targetKeyToOffset.put(element.getKey(), element.getOffset()); } return new SwitchPayloadOp(location, addressToLocation, targetKeyToOffset); }
@Override protected Stmt switchStatement(DexBody body, Instruction targetData, Local key) { PackedSwitchPayload i = (PackedSwitchPayload) targetData; List<? extends SwitchElement> seList = i.getSwitchElements(); // the default target always follows the switch statement int defaultTargetAddress = codeAddress + instruction.getCodeUnits(); Unit defaultTarget = body.instructionAtAddress(defaultTargetAddress).getUnit(); List<IntConstant> lookupValues = new ArrayList<IntConstant>(); List<Unit> targets = new ArrayList<Unit>(); for (SwitchElement se : seList) { lookupValues.add(IntConstant.v(se.getKey())); int offset = se.getOffset(); targets.add(body.instructionAtAddress(codeAddress + offset).getUnit()); } LookupSwitchStmt switchStmt = Jimple.v().newLookupSwitchStmt(key, lookupValues, targets, defaultTarget); setUnit(switchStmt); if (IDalvikTyper.ENABLE_DVKTYPER) { DalvikTyper.v().setType(switchStmt.getKeyBox(), IntType.v(), true); } return switchStmt; }
@Override protected Stmt switchStatement(DexBody body, Instruction targetData, Local key) { SparseSwitchPayload i = (SparseSwitchPayload) targetData; List<? extends SwitchElement> seList = i.getSwitchElements(); // the default target always follows the switch statement int defaultTargetAddress = codeAddress + instruction.getCodeUnits(); Unit defaultTarget = body.instructionAtAddress(defaultTargetAddress).getUnit(); List<IntConstant> lookupValues = new ArrayList<IntConstant>(); List<Unit> targets = new ArrayList<Unit>(); for (SwitchElement se : seList) { lookupValues.add(IntConstant.v(se.getKey())); int offset = se.getOffset(); targets.add(body.instructionAtAddress(codeAddress + offset).getUnit()); } LookupSwitchStmt switchStmt = Jimple.v().newLookupSwitchStmt(key, lookupValues, targets, defaultTarget); setUnit(switchStmt); addTags(switchStmt); if (IDalvikTyper.ENABLE_DVKTYPER) { DalvikTyper.v().setType(switchStmt.getKeyBox(), IntType.v(), true); } return switchStmt; }
@Nonnull public static ImmutableSwitchElement of(SwitchElement switchElement) { if (switchElement instanceof ImmutableSwitchElement) { return (ImmutableSwitchElement)switchElement; } return new ImmutableSwitchElement( switchElement.getKey(), switchElement.getOffset()); }
@Nonnull public static ImmutableSwitchElement of(SwitchElement switchElement) { if (switchElement instanceof ImmutableSwitchElement) { return (ImmutableSwitchElement)switchElement; } return new ImmutableSwitchElement( switchElement.getKey(), switchElement.getOffset()); }
@Nonnull public static ImmutableSwitchElement of(SwitchElement switchElement) { if (switchElement instanceof ImmutableSwitchElement) { return (ImmutableSwitchElement)switchElement; } return new ImmutableSwitchElement( switchElement.getKey(), switchElement.getOffset()); }
public PackedSwitchPad(SwitchPayload inst, int defaultOffset) { int i = 0; this.offsets = new int[inst.getSwitchElements().size()]; for(SwitchElement elt : inst.getSwitchElements()) { if (i == 0) { firstValue = elt.getKey(); } offsets[i++] = elt.getOffset(); } this.defaultOffset = defaultOffset; }
public PackedSwitchPad(SwitchPayload inst, int defaultOffset) { int i = 0; this.offsets = new int[inst.getSwitchElements().size()]; for(SwitchElement elt : inst.getSwitchElements()) { if (i == 0) { firstValue = elt.getKey(); } offsets[i++] = elt.getOffset(); } this.defaultOffset = defaultOffset; }
public SparseSwitchPad(SwitchPayload inst, int defaultOffset) { int i = 0; this.values = new int[ inst.getSwitchElements().size() ]; this.offsets = new int[ inst.getSwitchElements().size() ]; for(SwitchElement elt : inst.getSwitchElements()) { values[i] = elt.getKey(); offsets[i++] = elt.getOffset(); } this.defaultOffset = defaultOffset; }
public SparseSwitchPad(SwitchPayload inst, int defaultOffset) { int i = 0; this.values = new int[ inst.getSwitchElements().size() ]; this.offsets = new int[ inst.getSwitchElements().size() ]; for(SwitchElement elt : inst.getSwitchElements()) { values[i] = elt.getKey(); offsets[i++] = elt.getOffset(); } this.defaultOffset = defaultOffset; }
public SparseSwitchMethodItem(MethodDefinition methodDef, int codeAddress, SparseSwitchPayload instruction) { super(methodDef, codeAddress, instruction); int baseCodeAddress = methodDef.getSparseSwitchBaseAddress(codeAddress); targets = new ArrayList<SparseSwitchTarget>(); if (baseCodeAddress >= 0) { for (SwitchElement switchElement: instruction.getSwitchElements()) { LabelMethodItem label = methodDef.getLabelCache().internLabel( new LabelMethodItem( methodDef.classDef.options, baseCodeAddress + switchElement.getOffset(), "sswitch_")); targets.add(new SparseSwitchLabelTarget(switchElement.getKey(), label)); } } else { commentedOut = true; //if we couldn't determine a base address, just use relative offsets rather than labels for (SwitchElement switchElement: instruction.getSwitchElements()) { targets.add(new SparseSwitchOffsetTarget(switchElement.getKey(), switchElement.getOffset())); } } }
public void write(@Nonnull PackedSwitchPayload instruction) { try { writer.writeUbyte(0); writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8); List<? extends SwitchElement> elements = instruction.getSwitchElements(); writer.writeUshort(elements.size()); if (elements.size() == 0) { writer.writeInt(0); } else { writer.writeInt(elements.get(0).getKey()); for (SwitchElement element: elements) { writer.writeInt(element.getOffset()); } } } catch (IOException ex) { throw new RuntimeException(ex); } }
public void write(@Nonnull SparseSwitchPayload instruction) { try { writer.writeUbyte(0); writer.writeUbyte(instruction.getOpcode().value >> 8); List<? extends SwitchElement> elements = instruction.getSwitchElements(); writer.writeUshort(elements.size()); for (SwitchElement element: elements) { writer.writeInt(element.getKey()); } for (SwitchElement element: elements) { writer.writeInt(element.getOffset()); } } catch (IOException ex) { throw new RuntimeException(ex); } }
public void write(@Nonnull SparseSwitchPayload instruction) { try { writer.writeUbyte(0); writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8); List<? extends SwitchElement> elements = Ordering.from(switchElementComparator).immutableSortedCopy( instruction.getSwitchElements()); writer.writeUshort(elements.size()); for (SwitchElement element: elements) { writer.writeInt(element.getKey()); } for (SwitchElement element: elements) { writer.writeInt(element.getOffset()); } } catch (IOException ex) { throw new RuntimeException(ex); } }
public void write(@Nonnull SparseSwitchPayload instruction) { try { writer.writeUbyte(0); writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8); List<? extends SwitchElement> elements = Ordering.from(switchElementComparator).immutableSortedCopy( instruction.getSwitchElements()); writer.writeUshort(elements.size()); for (SwitchElement element: elements) { writer.writeInt(element.getKey()); } for (SwitchElement element: elements) { writer.writeInt(element.getOffset()); } } catch (IOException ex) { throw new RuntimeException(ex); } }