Search in sources :

Example 6 with SparseSwitchPayload

use of org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload 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();
                Opcode opcode = instruction.getOpcode();
                int paramCount;
                if (InstructionUtil.isInvokePolymorphic(opcode)) {
                    paramCount = ((VariableRegisterInstruction) instruction).getRegisterCount();
                } else {
                    paramCount = MethodUtil.getParameterRegisterCount(methodRef, InstructionUtil.isInvokeStatic(opcode));
                }
                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, methodHandleSection, callSiteSection);
        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 Format22cs:
                        instructionWriter.write((Instruction22cs) 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 Format35mi:
                        instructionWriter.write((Instruction35mi) instruction);
                        break;
                    case Format35ms:
                        instructionWriter.write((Instruction35ms) instruction);
                        break;
                    case Format3rc:
                        instructionWriter.write((Instruction3rc) instruction);
                        break;
                    case Format3rmi:
                        instructionWriter.write((Instruction3rmi) instruction);
                        break;
                    case Format3rms:
                        instructionWriter.write((Instruction3rms) 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;
}
Also used : ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) OneRegisterInstruction(org.jf.dexlib2.iface.instruction.OneRegisterInstruction) VariableRegisterInstruction(org.jf.dexlib2.iface.instruction.VariableRegisterInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) ExceptionHandler(org.jf.dexlib2.iface.ExceptionHandler) ExceptionWithContext(org.jf.util.ExceptionWithContext)

Example 7 with SparseSwitchPayload

use of org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload 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);
    }
}
Also used : SwitchElement(org.jf.dexlib2.iface.instruction.SwitchElement) IOException(java.io.IOException)

Example 8 with SparseSwitchPayload

use of org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload in project tinker by Tencent.

the class BuilderMutableMethodImplementation method newBuilderSparseSwitchPayload.

@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);
}
Also used : BuilderSparseSwitchPayload(org.jf.dexlib2.builder.instruction.BuilderSparseSwitchPayload) SwitchElement(org.jf.dexlib2.iface.instruction.SwitchElement) Nonnull(javax.annotation.Nonnull)

Aggregations

SwitchElement (org.jf.dexlib2.iface.instruction.SwitchElement)4 Nonnull (javax.annotation.Nonnull)3 Instruction (org.jf.dexlib2.iface.instruction.Instruction)3 SparseSwitchPayload (org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload)2 ExceptionWithContext (org.jf.util.ExceptionWithContext)2 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 Nullable (javax.annotation.Nullable)1 BuilderSparseSwitchPayload (org.jf.dexlib2.builder.instruction.BuilderSparseSwitchPayload)1 DexReader (org.jf.dexlib2.dexbacked.DexReader)1 DexBackedInstruction (org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction)1 ExceptionHandler (org.jf.dexlib2.iface.ExceptionHandler)1 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)1 OffsetInstruction (org.jf.dexlib2.iface.instruction.OffsetInstruction)1 OneRegisterInstruction (org.jf.dexlib2.iface.instruction.OneRegisterInstruction)1 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)1 VariableRegisterInstruction (org.jf.dexlib2.iface.instruction.VariableRegisterInstruction)1 AnnotatedBytes (org.jf.dexlib2.util.AnnotatedBytes)1 SmaliClass (org.jf.smalidea.psi.impl.SmaliClass)1 SmaliFile (org.jf.smalidea.psi.impl.SmaliFile)1