use of org.jf.dexlib2.Opcode in project smali by JesusFreke.
the class PayloadAlignmentTest method testPackedSwitchAlignment.
@Test
public void testPackedSwitchAlignment() {
MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
implBuilder.addLabel("switch_target_1");
implBuilder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, implBuilder.getLabel("goto_target")));
implBuilder.addLabel("switch_payload");
implBuilder.addInstruction(new BuilderPackedSwitchPayload(0, Lists.newArrayList(implBuilder.getLabel("switch_target_1"), implBuilder.getLabel("switch_target_2"), implBuilder.getLabel("switch_target_3"))));
implBuilder.addLabel("goto_target");
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addLabel("switch_target_2");
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addLabel("switch_target_3");
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addInstruction(new BuilderInstruction31t(Opcode.PACKED_SWITCH, 0, implBuilder.getLabel("switch_payload")));
List<Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
checkInstructions(instructions, new Opcode[] { Opcode.GOTO, Opcode.NOP, Opcode.PACKED_SWITCH_PAYLOAD, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.PACKED_SWITCH });
OffsetInstruction gotoInstruction = (OffsetInstruction) instructions.get(0);
Assert.assertEquals(12, gotoInstruction.getCodeOffset());
PackedSwitchPayload payload = (PackedSwitchPayload) instructions.get(2);
Assert.assertEquals(3, payload.getSwitchElements().size());
Assert.assertEquals(-16, payload.getSwitchElements().get(0).getOffset());
Assert.assertEquals(-2, payload.getSwitchElements().get(1).getOffset());
Assert.assertEquals(-1, payload.getSwitchElements().get(2).getOffset());
OffsetInstruction referent = (OffsetInstruction) instructions.get(7);
Assert.assertEquals(-14, referent.getCodeOffset());
}
use of org.jf.dexlib2.Opcode in project smali by JesusFreke.
the class PayloadAlignmentTest method testSparseSwitchAlignment.
@Test
public void testSparseSwitchAlignment() {
MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
implBuilder.addLabel("switch_target_1");
implBuilder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, implBuilder.getLabel("goto_target")));
implBuilder.addLabel("switch_payload");
implBuilder.addInstruction(new BuilderSparseSwitchPayload(Lists.newArrayList(new SwitchLabelElement(0, implBuilder.getLabel("switch_target_1")), new SwitchLabelElement(5, implBuilder.getLabel("switch_target_2")), new SwitchLabelElement(10, implBuilder.getLabel("switch_target_3")))));
implBuilder.addLabel("goto_target");
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addLabel("switch_target_2");
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addLabel("switch_target_3");
implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
implBuilder.addInstruction(new BuilderInstruction31t(Opcode.SPARSE_SWITCH, 0, implBuilder.getLabel("switch_payload")));
List<Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
checkInstructions(instructions, new Opcode[] { Opcode.GOTO, Opcode.NOP, Opcode.SPARSE_SWITCH_PAYLOAD, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.NOP, Opcode.SPARSE_SWITCH });
OffsetInstruction gotoInstruction = (OffsetInstruction) instructions.get(0);
Assert.assertEquals(16, gotoInstruction.getCodeOffset());
SparseSwitchPayload payload = (SparseSwitchPayload) instructions.get(2);
Assert.assertEquals(3, payload.getSwitchElements().size());
Assert.assertEquals(-20, payload.getSwitchElements().get(0).getOffset());
Assert.assertEquals(-2, payload.getSwitchElements().get(1).getOffset());
Assert.assertEquals(-1, payload.getSwitchElements().get(2).getOffset());
OffsetInstruction referent = (OffsetInstruction) instructions.get(7);
Assert.assertEquals(-18, referent.getCodeOffset());
}
use of org.jf.dexlib2.Opcode in project smali by JesusFreke.
the class DebugInfoItem method makeAnnotator.
@Nonnull
public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) {
return new SectionAnnotator(annotator, mapItem) {
@Nonnull
@Override
public String getItemName() {
return "debug_info_item";
}
@Override
public void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
DexReader reader = dexFile.readerAt(out.getCursor());
int lineStart = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "line_start = %d", lineStart);
int parametersSize = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "parameters_size = %d", parametersSize);
if (parametersSize > 0) {
out.annotate(0, "parameters:");
out.indent();
for (int i = 0; i < parametersSize; i++) {
int paramaterIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "%s", StringIdItem.getOptionalReferenceAnnotation(dexFile, paramaterIndex, true));
}
out.deindent();
}
out.annotate(0, "debug opcodes:");
out.indent();
int codeAddress = 0;
int lineNumber = lineStart;
loop: while (true) {
int opcode = reader.readUbyte();
switch(opcode) {
case DebugItemType.END_SEQUENCE:
{
out.annotateTo(reader.getOffset(), "DBG_END_SEQUENCE");
break loop;
}
case DebugItemType.ADVANCE_PC:
{
out.annotateTo(reader.getOffset(), "DBG_ADVANCE_PC");
out.indent();
int addressDiff = reader.readSmallUleb128();
codeAddress += addressDiff;
out.annotateTo(reader.getOffset(), "addr_diff = +0x%x: 0x%x", addressDiff, codeAddress);
out.deindent();
break;
}
case DebugItemType.ADVANCE_LINE:
{
out.annotateTo(reader.getOffset(), "DBG_ADVANCE_LINE");
out.indent();
int lineDiff = reader.readSleb128();
lineNumber += lineDiff;
out.annotateTo(reader.getOffset(), "line_diff = +%d: %d", Math.abs(lineDiff), lineNumber);
out.deindent();
break;
}
case DebugItemType.START_LOCAL:
{
out.annotateTo(reader.getOffset(), "DBG_START_LOCAL");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
int nameIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "name_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, nameIndex, true));
int typeIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "type_idx = %s", TypeIdItem.getOptionalReferenceAnnotation(dexFile, typeIndex));
out.deindent();
break;
}
case DebugItemType.START_LOCAL_EXTENDED:
{
out.annotateTo(reader.getOffset(), "DBG_START_LOCAL_EXTENDED");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
int nameIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "name_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, nameIndex, true));
int typeIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "type_idx = %s", TypeIdItem.getOptionalReferenceAnnotation(dexFile, typeIndex));
int sigIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "sig_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, sigIndex, true));
out.deindent();
break;
}
case DebugItemType.END_LOCAL:
{
out.annotateTo(reader.getOffset(), "DBG_END_LOCAL");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
out.deindent();
break;
}
case DebugItemType.RESTART_LOCAL:
{
out.annotateTo(reader.getOffset(), "DBG_RESTART_LOCAL");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
out.deindent();
break;
}
case DebugItemType.PROLOGUE_END:
{
out.annotateTo(reader.getOffset(), "DBG_SET_PROLOGUE_END");
break;
}
case DebugItemType.EPILOGUE_BEGIN:
{
out.annotateTo(reader.getOffset(), "DBG_SET_EPILOGUE_BEGIN");
break;
}
case DebugItemType.SET_SOURCE_FILE:
{
out.annotateTo(reader.getOffset(), "DBG_SET_FILE");
out.indent();
int nameIdx = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "name_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, nameIdx));
out.deindent();
break;
}
default:
int adjusted = opcode - 0x0A;
int addressDiff = adjusted / 15;
int lineDiff = (adjusted % 15) - 4;
codeAddress += addressDiff;
lineNumber += lineDiff;
out.annotateTo(reader.getOffset(), "address_diff = +0x%x:0x%x, line_diff = +%d:%d, ", addressDiff, codeAddress, lineDiff, lineNumber);
break;
}
}
out.deindent();
}
};
}
use of org.jf.dexlib2.Opcode in project smali by JesusFreke.
the class MethodDefinition method addInstructionMethodItems.
private void addInstructionMethodItems(List<MethodItem> methodItems) {
int currentCodeAddress = 0;
for (int i = 0; i < effectiveInstructions.size(); i++) {
Instruction instruction = effectiveInstructions.get(i);
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction);
methodItems.add(methodItem);
if (i != effectiveInstructions.size() - 1) {
methodItems.add(new BlankMethodItem(currentCodeAddress));
}
if (classDef.options.codeOffsets) {
methodItems.add(new MethodItem(currentCodeAddress) {
@Override
public double getSortOrder() {
return -1000;
}
@Override
public boolean writeTo(IndentingWriter writer) throws IOException {
writer.write("#@");
writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
return true;
}
});
}
if (classDef.options.accessorComments && classDef.options.syntheticAccessorResolver != null && (instruction instanceof ReferenceInstruction)) {
Opcode opcode = instruction.getOpcode();
if (opcode.referenceType == ReferenceType.METHOD) {
MethodReference methodReference = null;
try {
methodReference = (MethodReference) ((ReferenceInstruction) instruction).getReference();
} catch (InvalidItemIndex ex) {
// just ignore it for now. We'll deal with it later, when processing the instructions
// themselves
}
if (methodReference != null && SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodReference.getName())) {
AccessedMember accessedMember = classDef.options.syntheticAccessorResolver.getAccessedMember(methodReference);
if (accessedMember != null) {
methodItems.add(new SyntheticAccessCommentMethodItem(accessedMember, currentCodeAddress));
}
}
}
}
currentCodeAddress += instruction.getCodeUnits();
}
}
use of org.jf.dexlib2.Opcode in project smali by JesusFreke.
the class MethodDefinition method findPayloadOffset.
public int findPayloadOffset(int targetOffset, Opcode type) {
int targetIndex;
try {
targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset);
} catch (InvalidInstructionOffset ex) {
throw new InvalidSwitchPayload(targetOffset);
}
//TODO: does dalvik let you pad with multiple nops?
//TODO: does dalvik let a switch instruction point to a non-payload instruction?
Instruction instruction = instructions.get(targetIndex);
if (instruction.getOpcode() != type) {
// maybe it's pointing to a NOP padding instruction. Look at the next instruction
if (instruction.getOpcode() == Opcode.NOP) {
targetIndex += 1;
if (targetIndex < instructions.size()) {
instruction = instructions.get(targetIndex);
if (instruction.getOpcode() == type) {
return instructionOffsetMap.getInstructionCodeOffset(targetIndex);
}
}
}
throw new InvalidSwitchPayload(targetOffset);
} else {
return targetOffset;
}
}
Aggregations