use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.
the class PayloadAlignmentTest method testPayloadAlignmentRemoveNopWithReferent.
@Test
public void testPayloadAlignmentRemoveNopWithReferent() {
MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
Label label = implBuilder.getLabel("array_payload");
implBuilder.addInstruction(new BuilderInstruction31t(Opcode.FILL_ARRAY_DATA, 0, label));
implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addLabel("array_payload");
implBuilder.addInstruction(new BuilderArrayPayload(4, null));
List<Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
checkInstructions(instructions, new Opcode[] { Opcode.FILL_ARRAY_DATA, Opcode.MOVE, Opcode.MOVE, Opcode.MOVE, Opcode.ARRAY_PAYLOAD });
Instruction31t referent = (Instruction31t) instructions.get(0);
Assert.assertEquals(6, referent.getCodeOffset());
}
use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.
the class PayloadAlignmentTest method testPayloadAlignmentRemoveNop.
@Test
public void testPayloadAlignmentRemoveNop() {
MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addInstruction(new BuilderArrayPayload(4, null));
List<? extends Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
Assert.assertEquals(instructions.size(), 1);
Instruction instruction = instructions.get(0);
Assert.assertEquals(instruction.getOpcode(), Opcode.ARRAY_PAYLOAD);
}
use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.
the class MutableMethodImplementationTest method testNewLabelByAddress.
@Test
public void testNewLabelByAddress() {
MethodImplementationBuilder builder = new MethodImplementationBuilder(10);
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction32x(Opcode.MOVE_16, 0, 0));
MutableMethodImplementation mutableMethodImplementation = new MutableMethodImplementation(builder.getMethodImplementation());
mutableMethodImplementation.addCatch(mutableMethodImplementation.newLabelForAddress(0), mutableMethodImplementation.newLabelForAddress(8), mutableMethodImplementation.newLabelForAddress(1));
Assert.assertEquals(0, mutableMethodImplementation.getTryBlocks().get(0).getStartCodeAddress());
Assert.assertEquals(8, mutableMethodImplementation.getTryBlocks().get(0).getCodeUnitCount());
Assert.assertEquals(1, mutableMethodImplementation.getTryBlocks().get(0).getExceptionHandlers().get(0).getHandlerCodeAddress());
}
use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.
the class MutableMethodImplementationTest method testTryEndAtEndOfMethod.
@Test
public void testTryEndAtEndOfMethod() {
MethodImplementationBuilder builder = new MethodImplementationBuilder(10);
Label startLabel = builder.addLabel("start");
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
builder.addInstruction(new BuilderInstruction32x(Opcode.MOVE_16, 0, 0));
Label endLabel = builder.addLabel("end");
builder.addCatch(startLabel, endLabel, startLabel);
MethodImplementation methodImplementation = builder.getMethodImplementation();
Assert.assertEquals(0, methodImplementation.getTryBlocks().get(0).getStartCodeAddress());
Assert.assertEquals(8, methodImplementation.getTryBlocks().get(0).getCodeUnitCount());
methodImplementation = new MutableMethodImplementation(methodImplementation);
Assert.assertEquals(0, methodImplementation.getTryBlocks().get(0).getStartCodeAddress());
Assert.assertEquals(8, methodImplementation.getTryBlocks().get(0).getCodeUnitCount());
}
use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project tinker by Tencent.
the class BuilderMutableMethodImplementation method fixInstructions.
private void fixInstructions() {
HashSet<MethodLocation> payloadLocations = Sets.newHashSet();
for (MethodLocation location : instructionList) {
BuilderInstruction instruction = location.instruction;
if (instruction != null) {
switch(instruction.getOpcode()) {
case SPARSE_SWITCH:
case PACKED_SWITCH:
{
MethodLocation targetLocation = ((BuilderOffsetInstruction) instruction).getTarget().getLocation();
BuilderInstruction targetInstruction = targetLocation.instruction;
if (targetInstruction == null) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d points to the end of the method.", location.codeAddress, location.index));
}
if (targetInstruction.getOpcode() == Opcode.NOP) {
targetInstruction = getFirstNonNop(targetLocation.index + 1);
}
if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d does not refer to a payload instruction.", location.codeAddress, location.index));
}
if ((instruction.opcode == Opcode.PACKED_SWITCH && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD) || (instruction.opcode == Opcode.SPARSE_SWITCH && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d refers to the wrong type of payload instruction.", location.codeAddress, location.index));
}
if (!payloadLocations.add(targetLocation)) {
throw new IllegalStateException("Multiple switch instructions refer to the same payload. " + "This is not currently supported. Please file a bug :)");
}
((BuilderSwitchPayload) targetInstruction).referrer = location;
break;
}
default:
{
break;
}
}
}
}
boolean madeChanges;
do {
madeChanges = false;
for (int index = 0; index < instructionList.size(); index++) {
MethodLocation location = instructionList.get(index);
BuilderInstruction instruction = location.instruction;
if (instruction != null) {
switch(instruction.getOpcode()) {
case GOTO:
{
int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
if (offset < Byte.MIN_VALUE || offset > Byte.MAX_VALUE) {
BuilderOffsetInstruction replacement;
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
} else {
replacement = new BuilderInstruction20t(Opcode.GOTO_16, ((BuilderOffsetInstruction) instruction).getTarget());
}
replaceInstruction(location.index, replacement);
madeChanges = true;
}
break;
}
case GOTO_16:
{
int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
BuilderOffsetInstruction replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
replaceInstruction(location.index, replacement);
madeChanges = true;
}
break;
}
case SPARSE_SWITCH_PAYLOAD:
case PACKED_SWITCH_PAYLOAD:
if (((BuilderSwitchPayload) instruction).referrer == null) {
// if the switch payload isn't referenced, just remove it
removeInstruction(index);
index--;
madeChanges = true;
break;
}
// intentional fall-through
case ARRAY_PAYLOAD:
{
if ((location.codeAddress & 0x01) != 0) {
int previousIndex = location.index - 1;
MethodLocation previousLocation = instructionList.get(previousIndex);
Instruction previousInstruction = previousLocation.instruction;
assert previousInstruction != null;
if (previousInstruction.getOpcode() == Opcode.NOP) {
removeInstruction(previousIndex);
index--;
} else {
addInstruction(location.index, new BuilderInstruction10x(Opcode.NOP));
index++;
}
madeChanges = true;
}
break;
}
default:
{
break;
}
}
}
}
} while (madeChanges);
fixInstructions = false;
}
Aggregations