use of org.jf.dexlib2.iface.instruction.formats.Instruction22c in project smali by JesusFreke.
the class DexWriter method writeCodeItem.
private int writeCodeItem(@Nonnull DexDataWriter writer, @Nonnull ByteArrayOutputStream ehBuf, @Nonnull MethodKey methodKey, @Nonnull List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks, @Nullable Iterable<? extends Instruction> instructions, int debugItemOffset) throws IOException {
if (instructions == null && debugItemOffset == NO_OFFSET) {
return -1;
}
numCodeItemItems++;
writer.align();
int codeItemOffset = writer.getPosition();
writer.writeUshort(classSection.getRegisterCount(methodKey));
boolean isStatic = AccessFlags.STATIC.isSet(classSection.getMethodAccessFlags(methodKey));
Collection<? extends TypeKey> parameters = typeListSection.getTypes(protoSection.getParameters(methodSection.getPrototype(methodKey)));
writer.writeUshort(MethodUtil.getParameterRegisterCount(parameters, isStatic));
if (instructions != null) {
tryBlocks = TryListBuilder.massageTryBlocks(tryBlocks);
int outParamCount = 0;
int codeUnitCount = 0;
for (Instruction instruction : instructions) {
codeUnitCount += instruction.getCodeUnits();
if (instruction.getOpcode().referenceType == ReferenceType.METHOD) {
ReferenceInstruction refInsn = (ReferenceInstruction) instruction;
MethodReference methodRef = (MethodReference) refInsn.getReference();
int paramCount = MethodUtil.getParameterRegisterCount(methodRef, InstructionUtil.isInvokeStatic(instruction.getOpcode()));
if (paramCount > outParamCount) {
outParamCount = paramCount;
}
}
}
writer.writeUshort(outParamCount);
writer.writeUshort(tryBlocks.size());
writer.writeInt(debugItemOffset);
InstructionWriter instructionWriter = InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection);
writer.writeInt(codeUnitCount);
int codeOffset = 0;
for (Instruction instruction : instructions) {
try {
switch(instruction.getOpcode().format) {
case Format10t:
instructionWriter.write((Instruction10t) instruction);
break;
case Format10x:
instructionWriter.write((Instruction10x) instruction);
break;
case Format11n:
instructionWriter.write((Instruction11n) instruction);
break;
case Format11x:
instructionWriter.write((Instruction11x) instruction);
break;
case Format12x:
instructionWriter.write((Instruction12x) instruction);
break;
case Format20bc:
instructionWriter.write((Instruction20bc) instruction);
break;
case Format20t:
instructionWriter.write((Instruction20t) instruction);
break;
case Format21c:
instructionWriter.write((Instruction21c) instruction);
break;
case Format21ih:
instructionWriter.write((Instruction21ih) instruction);
break;
case Format21lh:
instructionWriter.write((Instruction21lh) instruction);
break;
case Format21s:
instructionWriter.write((Instruction21s) instruction);
break;
case Format21t:
instructionWriter.write((Instruction21t) instruction);
break;
case Format22b:
instructionWriter.write((Instruction22b) instruction);
break;
case Format22c:
instructionWriter.write((Instruction22c) instruction);
break;
case Format22s:
instructionWriter.write((Instruction22s) instruction);
break;
case Format22t:
instructionWriter.write((Instruction22t) instruction);
break;
case Format22x:
instructionWriter.write((Instruction22x) instruction);
break;
case Format23x:
instructionWriter.write((Instruction23x) instruction);
break;
case Format30t:
instructionWriter.write((Instruction30t) instruction);
break;
case Format31c:
instructionWriter.write((Instruction31c) instruction);
break;
case Format31i:
instructionWriter.write((Instruction31i) instruction);
break;
case Format31t:
instructionWriter.write((Instruction31t) instruction);
break;
case Format32x:
instructionWriter.write((Instruction32x) instruction);
break;
case Format35c:
instructionWriter.write((Instruction35c) instruction);
break;
case Format3rc:
instructionWriter.write((Instruction3rc) instruction);
break;
case Format45cc:
instructionWriter.write((Instruction45cc) instruction);
break;
case Format4rcc:
instructionWriter.write((Instruction4rcc) instruction);
break;
case Format51l:
instructionWriter.write((Instruction51l) instruction);
break;
case ArrayPayload:
instructionWriter.write((ArrayPayload) instruction);
break;
case PackedSwitchPayload:
instructionWriter.write((PackedSwitchPayload) instruction);
break;
case SparseSwitchPayload:
instructionWriter.write((SparseSwitchPayload) instruction);
break;
default:
throw new ExceptionWithContext("Unsupported instruction format: %s", instruction.getOpcode().format);
}
} catch (RuntimeException ex) {
throw new ExceptionWithContext(ex, "Error while writing instruction at code offset 0x%x", codeOffset);
}
codeOffset += instruction.getCodeUnits();
}
if (tryBlocks.size() > 0) {
writer.align();
// filter out unique lists of exception handlers
Map<List<? extends ExceptionHandler>, Integer> exceptionHandlerOffsetMap = Maps.newHashMap();
for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), 0);
}
DexDataWriter.writeUleb128(ehBuf, exceptionHandlerOffsetMap.size());
for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
int startAddress = tryBlock.getStartCodeAddress();
int endAddress = startAddress + tryBlock.getCodeUnitCount();
int tbCodeUnitCount = endAddress - startAddress;
writer.writeInt(startAddress);
writer.writeUshort(tbCodeUnitCount);
if (tryBlock.getExceptionHandlers().size() == 0) {
throw new ExceptionWithContext("No exception handlers for the try block!");
}
Integer offset = exceptionHandlerOffsetMap.get(tryBlock.getExceptionHandlers());
if (offset != 0) {
// exception handler has already been written out, just use it
writer.writeUshort(offset);
} else {
// if offset has not been set yet, we are about to write out a new exception handler
offset = ehBuf.size();
writer.writeUshort(offset);
exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), offset);
// check if the last exception handler is a catch-all and adjust the size accordingly
int ehSize = tryBlock.getExceptionHandlers().size();
ExceptionHandler ehLast = tryBlock.getExceptionHandlers().get(ehSize - 1);
if (ehLast.getExceptionType() == null) {
ehSize = ehSize * (-1) + 1;
}
// now let's layout the exception handlers, assuming that catch-all is always last
DexDataWriter.writeSleb128(ehBuf, ehSize);
for (ExceptionHandler eh : tryBlock.getExceptionHandlers()) {
TypeKey exceptionTypeKey = classSection.getExceptionType(eh);
int codeAddress = eh.getHandlerCodeAddress();
if (exceptionTypeKey != null) {
//regular exception handling
DexDataWriter.writeUleb128(ehBuf, typeSection.getItemIndex(exceptionTypeKey));
DexDataWriter.writeUleb128(ehBuf, codeAddress);
} else {
//catch-all
DexDataWriter.writeUleb128(ehBuf, codeAddress);
}
}
}
}
if (ehBuf.size() > 0) {
ehBuf.writeTo(writer);
ehBuf.reset();
}
}
} else {
// no instructions, all we have is the debug item offset
writer.writeUshort(0);
writer.writeUshort(0);
writer.writeInt(debugItemOffset);
writer.writeInt(0);
}
return codeItemOffset;
}
use of org.jf.dexlib2.iface.instruction.formats.Instruction22c in project smali by JesusFreke.
the class SmalideaMethodTest method testSmalideaMethod.
public void testSmalideaMethod() {
String text = ".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" + ".method public someMethodName(I)I\n" + " .registers 4\n" + " .param p1, \"edge\" # I\n" + " goto :here #0: 10t\n" + " :here\n" + " return-void #1: 21c\n" + " const/4 v0, 1234 #2: 11n\n" + " monitor-enter v1, #3: 11x\n" + " move v1, v0 #4: 12x\n" + " goto/16 :here #5: 20t\n" + " sget v0, La/b/c;->blah:I #6: 21c\n" + " const/high16 v0, 0x12340000 #7: 21ih\n" + " const-wide/high16 v0, 0x1234000000000000L #8: 21lh\n" + " const-wide/16 v0, 1234 #9: 21s\n" + " if-eqz v0, :here #10: 21t\n" + " add-int/lit8 v0, v1, 123 #11: 22b\n" + " iget v1, v2, Labc;->blort:Z #12: 22c\n" + " add-int/lit16 v0, v1, 1234 #13: 22s\n" + " if-eq v0, v1, :here #14: 22t\n" + " move/from16 v0, v1 #15: 22x\n" + " cmpl-float v0, v1, v2 #16: 23x\n" + " goto/32 :here #17: 30t\n" + " const-string/jumbo v0, \"abcd\" #18: 31c\n" + " const v0, 1234 #19: 31i\n" + " move/16 v0, v1 #20: 32x\n" + " invoke-virtual {v0, v1, v2, v3, v4}, Lblah;->blort(IIII)I #21: 35c\n" + " invoke-virtual/range {v0..v4}, Lblah;->blort(IIII)I #22: 3rc\n" + " const-wide v0, 0x1234567890L #23: 51i\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);
Assert.assertEquals("Lmy/pkg/blah;", method.getDefiningClass());
Assert.assertEquals("someMethodName", method.getName());
Assert.assertEquals("I", method.getReturnType());
List<? extends CharSequence> parameterTypes = method.getParameterTypes();
Assert.assertEquals(1, parameterTypes.size());
Assert.assertEquals("I", parameterTypes.get(0));
List<? extends MethodParameter> parameters = method.getParameters();
Assert.assertEquals(1, parameters.size());
Assert.assertEquals("I", parameters.get(0).getType());
Assert.assertEquals("edge", parameters.get(0).getName());
Assert.assertEquals(AccessFlags.PUBLIC.getValue(), method.getAccessFlags());
MethodImplementation impl = method.getImplementation();
Assert.assertNotNull(impl);
Assert.assertEquals(4, impl.getRegisterCount());
List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions());
{
Instruction10t instruction = (Instruction10t) instructions.get(0);
Assert.assertEquals(Opcode.GOTO, instruction.getOpcode());
Assert.assertEquals(1, instruction.getCodeOffset());
}
{
Instruction10x instruction = (Instruction10x) instructions.get(1);
Assert.assertEquals(Opcode.RETURN_VOID, instruction.getOpcode());
}
{
Instruction11n instruction = (Instruction11n) instructions.get(2);
Assert.assertEquals(Opcode.CONST_4, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1234, instruction.getNarrowLiteral());
}
{
Instruction11x instruction = (Instruction11x) instructions.get(3);
Assert.assertEquals(Opcode.MONITOR_ENTER, instruction.getOpcode());
Assert.assertEquals(1, instruction.getRegisterA());
}
{
Instruction12x instruction = (Instruction12x) instructions.get(4);
Assert.assertEquals(Opcode.MOVE, instruction.getOpcode());
Assert.assertEquals(1, instruction.getRegisterA());
Assert.assertEquals(0, instruction.getRegisterB());
}
{
Instruction20t instruction = (Instruction20t) instructions.get(5);
Assert.assertEquals(Opcode.GOTO_16, instruction.getOpcode());
Assert.assertEquals(-4, instruction.getCodeOffset());
}
{
Instruction21c instruction = (Instruction21c) instructions.get(6);
Assert.assertEquals(Opcode.SGET, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals("La/b/c;->blah:I", ReferenceUtil.getFieldDescriptor((FieldReference) instruction.getReference()));
}
{
Instruction21ih instruction = (Instruction21ih) instructions.get(7);
Assert.assertEquals(Opcode.CONST_HIGH16, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(0x1234, instruction.getHatLiteral());
Assert.assertEquals(0x12340000, instruction.getNarrowLiteral());
Assert.assertEquals(0x12340000, instruction.getWideLiteral());
}
{
Instruction21lh instruction = (Instruction21lh) instructions.get(8);
Assert.assertEquals(Opcode.CONST_WIDE_HIGH16, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(0x1234, instruction.getHatLiteral());
Assert.assertEquals(0x1234000000000000L, instruction.getWideLiteral());
}
{
Instruction21s instruction = (Instruction21s) instructions.get(9);
Assert.assertEquals(Opcode.CONST_WIDE_16, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1234, instruction.getWideLiteral());
}
{
Instruction21t instruction = (Instruction21t) instructions.get(10);
Assert.assertEquals(Opcode.IF_EQZ, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(-14, instruction.getCodeOffset());
}
{
Instruction22b instruction = (Instruction22b) instructions.get(11);
Assert.assertEquals(Opcode.ADD_INT_LIT8, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1, instruction.getRegisterB());
Assert.assertEquals(123, instruction.getNarrowLiteral());
}
{
Instruction22c instruction = (Instruction22c) instructions.get(12);
Assert.assertEquals(Opcode.IGET, instruction.getOpcode());
Assert.assertEquals(1, instruction.getRegisterA());
Assert.assertEquals(2, instruction.getRegisterB());
Assert.assertEquals("Labc;->blort:Z", ReferenceUtil.getFieldDescriptor((FieldReference) instruction.getReference()));
}
{
Instruction22s instruction = (Instruction22s) instructions.get(13);
Assert.assertEquals(Opcode.ADD_INT_LIT16, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1, instruction.getRegisterB());
Assert.assertEquals(1234, instruction.getNarrowLiteral());
}
{
Instruction22t instruction = (Instruction22t) instructions.get(14);
Assert.assertEquals(Opcode.IF_EQ, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1, instruction.getRegisterB());
Assert.assertEquals(-22, instruction.getCodeOffset());
}
{
Instruction22x instruction = (Instruction22x) instructions.get(15);
Assert.assertEquals(Opcode.MOVE_FROM16, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1, instruction.getRegisterB());
}
{
Instruction23x instruction = (Instruction23x) instructions.get(16);
Assert.assertEquals(Opcode.CMPL_FLOAT, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1, instruction.getRegisterB());
Assert.assertEquals(2, instruction.getRegisterC());
}
{
Instruction30t instruction = (Instruction30t) instructions.get(17);
Assert.assertEquals(Opcode.GOTO_32, instruction.getOpcode());
Assert.assertEquals(-28, instruction.getCodeOffset());
}
{
Instruction31c instruction = (Instruction31c) instructions.get(18);
Assert.assertEquals(Opcode.CONST_STRING_JUMBO, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals("abcd", ((StringReference) instruction.getReference()).getString());
}
{
Instruction31i instruction = (Instruction31i) instructions.get(19);
Assert.assertEquals(Opcode.CONST, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1234, instruction.getNarrowLiteral());
}
{
Instruction32x instruction = (Instruction32x) instructions.get(20);
Assert.assertEquals(Opcode.MOVE_16, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(1, instruction.getRegisterB());
}
{
Instruction35c instruction = (Instruction35c) instructions.get(21);
Assert.assertEquals(Opcode.INVOKE_VIRTUAL, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterC());
Assert.assertEquals(1, instruction.getRegisterD());
Assert.assertEquals(2, instruction.getRegisterE());
Assert.assertEquals(3, instruction.getRegisterF());
Assert.assertEquals(4, instruction.getRegisterG());
Assert.assertEquals("Lblah;->blort(IIII)I", ReferenceUtil.getReferenceString(instruction.getReference()));
}
{
Instruction3rc instruction = (Instruction3rc) instructions.get(22);
Assert.assertEquals(Opcode.INVOKE_VIRTUAL_RANGE, instruction.getOpcode());
Assert.assertEquals(0, instruction.getStartRegister());
Assert.assertEquals(5, instruction.getRegisterCount());
Assert.assertEquals("Lblah;->blort(IIII)I", ReferenceUtil.getReferenceString(instruction.getReference()));
}
{
Instruction51l instruction = (Instruction51l) instructions.get(23);
Assert.assertEquals(Opcode.CONST_WIDE, instruction.getOpcode());
Assert.assertEquals(0, instruction.getRegisterA());
Assert.assertEquals(0x1234567890L, instruction.getWideLiteral());
}
}
Aggregations