use of org.jf.dexlib2.iface.instruction.SwitchElement in project smali by JesusFreke.
the class MutableMethodImplementation method newBuilderPackedSwitchPayload.
@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);
}
use of org.jf.dexlib2.iface.instruction.SwitchElement in project smali by JesusFreke.
the class MethodAnalyzer method buildInstructionList.
private void buildInstructionList() {
int registerCount = methodImpl.getRegisterCount();
ImmutableList<Instruction> instructions = ImmutableList.copyOf(methodImpl.getInstructions());
analyzedInstructions.ensureCapacity(instructions.size());
//first, create all the instructions and populate the instructionAddresses array
int currentCodeAddress = 0;
for (int i = 0; i < instructions.size(); i++) {
Instruction instruction = instructions.get(i);
analyzedInstructions.append(currentCodeAddress, new AnalyzedInstruction(this, instruction, i, registerCount));
assert analyzedInstructions.indexOfKey(currentCodeAddress) == i;
currentCodeAddress += instruction.getCodeUnits();
}
//next, populate the exceptionHandlers array. The array item for each instruction that can throw an exception
//and is covered by a try block should be set to a list of the first instructions of each exception handler
//for the try block covering the instruction
List<? extends TryBlock<? extends ExceptionHandler>> tries = methodImpl.getTryBlocks();
tries = TryListBuilder.massageTryBlocks(tries);
int triesIndex = 0;
TryBlock currentTry = null;
AnalyzedInstruction[] currentExceptionHandlers = null;
AnalyzedInstruction[][] exceptionHandlers = new AnalyzedInstruction[instructions.size()][];
if (tries != null) {
for (int i = 0; i < analyzedInstructions.size(); i++) {
AnalyzedInstruction instruction = analyzedInstructions.valueAt(i);
Opcode instructionOpcode = instruction.instruction.getOpcode();
currentCodeAddress = getInstructionAddress(instruction);
//check if we have gone past the end of the current try
if (currentTry != null) {
if (currentTry.getStartCodeAddress() + currentTry.getCodeUnitCount() <= currentCodeAddress) {
currentTry = null;
triesIndex++;
}
}
//check if the next try is applicable yet
if (currentTry == null && triesIndex < tries.size()) {
TryBlock<? extends ExceptionHandler> tryBlock = tries.get(triesIndex);
if (tryBlock.getStartCodeAddress() <= currentCodeAddress) {
assert (tryBlock.getStartCodeAddress() + tryBlock.getCodeUnitCount() > currentCodeAddress);
currentTry = tryBlock;
currentExceptionHandlers = buildExceptionHandlerArray(tryBlock);
}
}
//for the current instruction
if (currentTry != null && instructionOpcode.canThrow()) {
exceptionHandlers[i] = currentExceptionHandlers;
}
}
}
//and no reachable code will have an unreachable predessor or successor
assert analyzedInstructions.size() > 0;
BitSet instructionsToProcess = new BitSet(instructions.size());
addPredecessorSuccessor(startOfMethod, analyzedInstructions.valueAt(0), exceptionHandlers, instructionsToProcess);
while (!instructionsToProcess.isEmpty()) {
int currentInstructionIndex = instructionsToProcess.nextSetBit(0);
instructionsToProcess.clear(currentInstructionIndex);
AnalyzedInstruction instruction = analyzedInstructions.valueAt(currentInstructionIndex);
Opcode instructionOpcode = instruction.instruction.getOpcode();
int instructionCodeAddress = getInstructionAddress(instruction);
if (instruction.instruction.getOpcode().canContinue()) {
if (currentInstructionIndex == analyzedInstructions.size() - 1) {
throw new AnalysisException("Execution can continue past the last instruction");
}
AnalyzedInstruction nextInstruction = analyzedInstructions.valueAt(currentInstructionIndex + 1);
addPredecessorSuccessor(instruction, nextInstruction, exceptionHandlers, instructionsToProcess);
}
if (instruction.instruction instanceof OffsetInstruction) {
OffsetInstruction offsetInstruction = (OffsetInstruction) instruction.instruction;
if (instructionOpcode == Opcode.PACKED_SWITCH || instructionOpcode == Opcode.SPARSE_SWITCH) {
AnalyzedInstruction analyzedSwitchPayload = analyzedInstructions.get(instructionCodeAddress + offsetInstruction.getCodeOffset());
if (analyzedSwitchPayload == null) {
throw new AnalysisException("Invalid switch payload offset");
}
SwitchPayload switchPayload = (SwitchPayload) analyzedSwitchPayload.instruction;
for (SwitchElement switchElement : switchPayload.getSwitchElements()) {
AnalyzedInstruction targetInstruction = analyzedInstructions.get(instructionCodeAddress + switchElement.getOffset());
if (targetInstruction == null) {
throw new AnalysisException("Invalid switch target offset");
}
addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers, instructionsToProcess);
}
} else if (instructionOpcode != Opcode.FILL_ARRAY_DATA) {
int targetAddressOffset = offsetInstruction.getCodeOffset();
AnalyzedInstruction targetInstruction = analyzedInstructions.get(instructionCodeAddress + targetAddressOffset);
addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers, instructionsToProcess);
}
}
}
}
use of org.jf.dexlib2.iface.instruction.SwitchElement in project smali by JesusFreke.
the class InstructionWriter method write.
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);
}
}
use of org.jf.dexlib2.iface.instruction.SwitchElement in project smali by JesusFreke.
the class InstructionWriter method write.
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);
}
}
use of org.jf.dexlib2.iface.instruction.SwitchElement in project smali by JesusFreke.
the class SmalideaMethodTest method testPackedSwitch.
public void testPackedSwitch() {
String text = ".class public LFormat31t;\n" + ".super Ljava/lang/Object;\n" + ".source \"Format31t.smali\"" + "\n" + ".method public test_packed-switch()V\n" + " .registers 1\n" + " .annotation runtime Lorg/junit/Test;\n" + " .end annotation\n" + "\n" + " const v0, 12\n" + "\n" + ":switch\n" + " packed-switch v0, :PackedSwitch\n" + "\n" + ":Label10\n" + " invoke-static {}, Lorg/junit/Assert;->fail()V\n" + " return-void\n" + "\n" + ":Label11\n" + " invoke-static {}, Lorg/junit/Assert;->fail()V\n" + " return-void\n" + "\n" + ":Label12\n" + " return-void\n" + "\n" + ":Label13\n" + " invoke-static {}, Lorg/junit/Assert;->fail()V\n" + " return-void\n" + "\n" + ":PackedSwitch\n" + " .packed-switch 10\n" + " :Label10\n" + " :Label11\n" + " :Label12\n" + " :Label13\n" + " .end packed-switch\n" + ".end method";
SmaliFile file = (SmaliFile) myFixture.addFileToProject("my/pkg/blah.smali", text);
SmaliClass smaliClass = file.getPsiClass();
SmaliMethod smaliMethod = smaliClass.getMethods()[0];
SmalideaMethod method = new SmalideaMethod(smaliMethod);
MethodImplementation impl = method.getImplementation();
Assert.assertNotNull(impl);
List<Instruction> instructions = Lists.newArrayList(impl.getInstructions());
PackedSwitchPayload packedSwitchPayload = (PackedSwitchPayload) instructions.get(9);
List<? extends SwitchElement> switchElements = packedSwitchPayload.getSwitchElements();
Assert.assertEquals(4, switchElements.size());
checkSwitchElement(switchElements.get(0), 10, 6);
checkSwitchElement(switchElements.get(1), 11, 14);
checkSwitchElement(switchElements.get(2), 12, 22);
checkSwitchElement(switchElements.get(3), 13, 24);
}
Aggregations