Search in sources :

Example 1 with ExceptionWithContext

use of org.jf.util.ExceptionWithContext in project atlas by alibaba.

the class MethodDefinition method addTries.

private void addTries(List<MethodItem> methodItems) {
    List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = methodImpl.getTryBlocks();
    if (tryBlocks.size() == 0) {
        return;
    }
    int lastInstructionAddress = instructionOffsetMap.getInstructionCodeOffset(instructions.size() - 1);
    int codeSize = lastInstructionAddress + instructions.get(instructions.size() - 1).getCodeUnits();
    for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
        int startAddress = tryBlock.getStartCodeAddress();
        int endAddress = startAddress + tryBlock.getCodeUnitCount();
        if (startAddress >= codeSize) {
            throw new RuntimeException(String.format("Try start offset %d is past the end of the code block.", startAddress));
        }
        // Note: not >=. endAddress == codeSize is valid, when the try covers the last instruction
        if (endAddress > codeSize) {
            throw new RuntimeException(String.format("Try end offset %d is past the end of the code block.", endAddress));
        }
        /**
             * The end address points to the address immediately after the end of the last
             * instruction that the try block covers. We want the .catch directive and end_try
             * label to be associated with the last covered instruction, so we need to get
             * the address for that instruction
             */
        int lastCoveredIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(endAddress - 1, false);
        int lastCoveredAddress = instructionOffsetMap.getInstructionCodeOffset(lastCoveredIndex);
        for (ExceptionHandler handler : tryBlock.getExceptionHandlers()) {
            int handlerAddress = handler.getHandlerCodeAddress();
            if (handlerAddress >= codeSize) {
                throw new ExceptionWithContext("Exception handler offset %d is past the end of the code block.", handlerAddress);
            }
            //use the address from the last covered instruction
            CatchMethodItem catchMethodItem = new CatchMethodItem(classDef.options, labelCache, lastCoveredAddress, handler.getExceptionType(), startAddress, endAddress, handlerAddress);
            methodItems.add(catchMethodItem);
        }
    }
}
Also used : ExceptionHandler(org.jf.dexlib2.iface.ExceptionHandler) ExceptionWithContext(org.jf.util.ExceptionWithContext)

Example 2 with ExceptionWithContext

use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.

the class AnnotatedBytes method annotate.

/**
     * Add an annotation of the given length at the current location.
     *
     * The location
     *
     *
     * @param length the length of data being annotated
     * @param msg the annotation message
     * @param formatArgs format arguments to pass to String.format
     */
public void annotate(int length, @Nonnull String msg, Object... formatArgs) {
    if (startLimit != -1 && endLimit != -1 && (cursor < startLimit || cursor >= endLimit)) {
        throw new ExceptionWithContext("Annotating outside the parent bounds");
    }
    String formattedMsg;
    if (formatArgs != null && formatArgs.length > 0) {
        formattedMsg = String.format(msg, formatArgs);
    } else {
        formattedMsg = msg;
    }
    int exclusiveEndOffset = cursor + length;
    AnnotationEndpoint endPoint = null;
    // Do we have an endpoint at the beginning of this annotation already?
    AnnotationEndpoint startPoint = annotatations.get(cursor);
    if (startPoint == null) {
        // Nope. We need to check that we're not in the middle of an existing range annotation.
        Map.Entry<Integer, AnnotationEndpoint> previousEntry = annotatations.lowerEntry(cursor);
        if (previousEntry != null) {
            AnnotationEndpoint previousAnnotations = previousEntry.getValue();
            AnnotationItem previousRangeAnnotation = previousAnnotations.rangeAnnotation;
            if (previousRangeAnnotation != null) {
                throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation %s", formatAnnotation(cursor, cursor + length, formattedMsg), formatAnnotation(previousEntry.getKey(), previousRangeAnnotation.annotation));
            }
        }
    } else if (length > 0) {
        AnnotationItem existingRangeAnnotation = startPoint.rangeAnnotation;
        if (existingRangeAnnotation != null) {
            throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation %s", formatAnnotation(cursor, cursor + length, formattedMsg), formatAnnotation(cursor, existingRangeAnnotation.annotation));
        }
    }
    if (length > 0) {
        // Ensure that there is no later annotation that would intersect with this one
        Map.Entry<Integer, AnnotationEndpoint> nextEntry = annotatations.higherEntry(cursor);
        if (nextEntry != null) {
            int nextKey = nextEntry.getKey();
            if (nextKey < exclusiveEndOffset) {
                // there is an endpoint that would intersect with this annotation. Find one of the annotations
                // associated with the endpoint, to print in the error message
                AnnotationEndpoint nextEndpoint = nextEntry.getValue();
                AnnotationItem nextRangeAnnotation = nextEndpoint.rangeAnnotation;
                if (nextRangeAnnotation != null) {
                    throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation %s", formatAnnotation(cursor, cursor + length, formattedMsg), formatAnnotation(nextKey, nextRangeAnnotation.annotation));
                }
                if (nextEndpoint.pointAnnotations.size() > 0) {
                    throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation %s", formatAnnotation(cursor, cursor + length, formattedMsg), formatAnnotation(nextKey, nextKey, nextEndpoint.pointAnnotations.get(0).annotation));
                }
                // There are no annotations on this endpoint. This "shouldn't" happen. We can still throw an exception.
                throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation endpoint at %d", formatAnnotation(cursor, cursor + length, formattedMsg), nextKey);
            }
            if (nextKey == exclusiveEndOffset) {
                // the next endpoint matches the end of the annotation we are adding
                endPoint = nextEntry.getValue();
            }
        }
    }
    // the range annotation
    if (startPoint == null) {
        startPoint = new AnnotationEndpoint();
        annotatations.put(cursor, startPoint);
    }
    if (length == 0) {
        startPoint.pointAnnotations.add(new AnnotationItem(indentLevel, formattedMsg));
    } else {
        startPoint.rangeAnnotation = new AnnotationItem(indentLevel, formattedMsg);
        // If endPoint is null, we need to create a new, empty one and add it to annotations
        if (endPoint == null) {
            endPoint = new AnnotationEndpoint();
            annotatations.put(exclusiveEndOffset, endPoint);
        }
    }
    cursor += length;
}
Also used : ExceptionWithContext(org.jf.util.ExceptionWithContext) TreeMap(java.util.TreeMap) Map(java.util.Map)

Example 3 with ExceptionWithContext

use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.

the class DexWriter method writeDebugAndCodeItems.

private void writeDebugAndCodeItems(@Nonnull DexDataWriter offsetWriter, @Nonnull DeferredOutputStream temp) throws IOException {
    ByteArrayOutputStream ehBuf = new ByteArrayOutputStream();
    debugSectionOffset = offsetWriter.getPosition();
    DebugWriter<StringKey, TypeKey> debugWriter = new DebugWriter<StringKey, TypeKey>(stringSection, typeSection, offsetWriter);
    DexDataWriter codeWriter = new DexDataWriter(temp, 0);
    List<CodeItemOffset<MethodKey>> codeOffsets = Lists.newArrayList();
    for (ClassKey classKey : classSection.getSortedClasses()) {
        Collection<? extends MethodKey> directMethods = classSection.getSortedDirectMethods(classKey);
        Collection<? extends MethodKey> virtualMethods = classSection.getSortedVirtualMethods(classKey);
        Iterable<MethodKey> methods = Iterables.concat(directMethods, virtualMethods);
        for (MethodKey methodKey : methods) {
            List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = classSection.getTryBlocks(methodKey);
            Iterable<? extends Instruction> instructions = classSection.getInstructions(methodKey);
            Iterable<? extends DebugItem> debugItems = classSection.getDebugItems(methodKey);
            if (instructions != null && stringSection.hasJumboIndexes()) {
                boolean needsFix = false;
                for (Instruction instruction : instructions) {
                    if (instruction.getOpcode() == Opcode.CONST_STRING) {
                        if (stringSection.getItemIndex((StringRef) ((ReferenceInstruction) instruction).getReference()) >= 65536) {
                            needsFix = true;
                            break;
                        }
                    }
                }
                if (needsFix) {
                    MutableMethodImplementation mutableMethodImplementation = classSection.makeMutableMethodImplementation(methodKey);
                    fixInstructions(mutableMethodImplementation);
                    instructions = mutableMethodImplementation.getInstructions();
                    tryBlocks = mutableMethodImplementation.getTryBlocks();
                    debugItems = mutableMethodImplementation.getDebugItems();
                }
            }
            int debugItemOffset = writeDebugItem(offsetWriter, debugWriter, classSection.getParameterNames(methodKey), debugItems);
            int codeItemOffset;
            try {
                codeItemOffset = writeCodeItem(codeWriter, ehBuf, methodKey, tryBlocks, instructions, debugItemOffset);
            } catch (RuntimeException ex) {
                throw new ExceptionWithContext(ex, "Exception occurred while writing code_item for method %s", methodSection.getMethodReference(methodKey));
            }
            if (codeItemOffset != -1) {
                codeOffsets.add(new CodeItemOffset<MethodKey>(methodKey, codeItemOffset));
            }
        }
    }
    offsetWriter.align();
    codeSectionOffset = offsetWriter.getPosition();
    codeWriter.close();
    temp.writeTo(offsetWriter);
    temp.close();
    for (CodeItemOffset<MethodKey> codeOffset : codeOffsets) {
        classSection.setCodeItemOffset(codeOffset.method, codeSectionOffset + codeOffset.codeOffset);
    }
}
Also used : ByteArrayOutputStream(java.io.ByteArrayOutputStream) OneRegisterInstruction(org.jf.dexlib2.iface.instruction.OneRegisterInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) ExceptionWithContext(org.jf.util.ExceptionWithContext) MutableMethodImplementation(org.jf.dexlib2.builder.MutableMethodImplementation)

Example 4 with ExceptionWithContext

use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.

the class InstructionOffsetMapTest method testInstructionOffsetMap.

@Test
public void testInstructionOffsetMap() {
    ImmutableList<ImmutableInstruction> instructions = ImmutableList.of(/*00: 0x00*/
    new ImmutableInstruction10t(Opcode.GOTO, 1), /*01: 0x01*/
    new ImmutableInstruction10x(Opcode.NOP), /*02: 0x02*/
    new ImmutableInstruction11n(Opcode.CONST_4, 2, 3), /*03: 0x03*/
    new ImmutableInstruction11x(Opcode.RETURN, 4), /*04: 0x04*/
    new ImmutableInstruction12x(Opcode.ARRAY_LENGTH, 5, 6), /*05: 0x05*/
    new ImmutableInstruction20t(Opcode.GOTO_16, 7), /*06: 0x07*/
    new ImmutableInstruction21c(Opcode.CONST_STRING, 8, new ImmutableStringReference("blah")), /*07: 0x09*/
    new ImmutableInstruction21ih(Opcode.CONST_HIGH16, 9, 0x10000), /*08: 0x0b*/
    new ImmutableInstruction21lh(Opcode.CONST_WIDE_HIGH16, 10, 0x1000000000000L), /*09: 0x0d*/
    new ImmutableInstruction21s(Opcode.CONST_16, 11, 12), /*10: 0x0f*/
    new ImmutableInstruction21t(Opcode.IF_EQZ, 12, 13), /*11: 0x11*/
    new ImmutableInstruction22b(Opcode.ADD_INT_LIT8, 14, 15, 16), /*12: 0x13*/
    new ImmutableInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Ltype;")), /*13: 0x15*/
    new ImmutableInstruction22s(Opcode.ADD_INT_LIT16, 2, 3, 17), /*14: 0x17*/
    new ImmutableInstruction22t(Opcode.IF_EQ, 4, 5, 18), /*15: 0x19*/
    new ImmutableInstruction22x(Opcode.MOVE_FROM16, 19, 20), /*16: 0x1b*/
    new ImmutableInstruction23x(Opcode.AGET, 21, 22, 23), /*17: 0x1d*/
    new ImmutableInstruction30t(Opcode.GOTO_32, 24), /*18: 0x20*/
    new ImmutableInstruction31c(Opcode.CONST_STRING_JUMBO, 25, new ImmutableStringReference("this is a string")), /*19: 0x23*/
    new ImmutableInstruction31i(Opcode.CONST, 26, 27), /*20: 0x26*/
    new ImmutableInstruction31t(Opcode.FILL_ARRAY_DATA, 28, 29), /*21: 0x29*/
    new ImmutableInstruction32x(Opcode.MOVE_16, 30, 31), /*22: 0x2c*/
    new ImmutableInstruction35c(Opcode.FILLED_NEW_ARRAY, 0, 0, 0, 0, 0, 0, new ImmutableTypeReference("Ltype;")), /*23: 0x2f*/
    new ImmutableInstruction3rc(Opcode.FILLED_NEW_ARRAY_RANGE, 0, 0, new ImmutableTypeReference("Ltype;")), /*24: 0x32*/
    new ImmutableInstruction51l(Opcode.CONST_WIDE, 32, 33), /*25: 0x37*/
    new ImmutableInstruction10t(Opcode.GOTO, 1));
    ImmutableMethodImplementation impl = new ImmutableMethodImplementation(33, instructions, null, null);
    InstructionOffsetMap instructionOffsetMap = new InstructionOffsetMap(instructions);
    int[] expectedOffsets = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x37 };
    for (int i = 0; i < instructions.size(); i++) {
        Assert.assertEquals(expectedOffsets[i], instructionOffsetMap.getInstructionCodeOffset(i));
        Assert.assertEquals(i, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[i], true));
        Assert.assertEquals(i, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[i], false));
    }
    int instructionIndex = -1;
    for (int codeOffset = 0; codeOffset <= expectedOffsets[expectedOffsets.length - 1]; codeOffset++) {
        if (codeOffset == expectedOffsets[instructionIndex + 1]) {
            // this offset is at the beginning of an instruction
            instructionIndex++;
        } else {
            // this offset is in the middle of an instruction
            Assert.assertEquals(instructionIndex, instructionOffsetMap.getInstructionIndexAtCodeOffset(codeOffset, false));
            try {
                instructionOffsetMap.getInstructionIndexAtCodeOffset(codeOffset, true);
                Assert.fail(String.format("Exception exception didn't occur for code offset 0x%x", codeOffset));
            } catch (ExceptionWithContext ex) {
            // expected exception
            }
        }
    }
    Assert.assertEquals(expectedOffsets.length - 1, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[expectedOffsets.length - 1] + 1, false));
    Assert.assertEquals(expectedOffsets.length - 1, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[expectedOffsets.length - 1] + 10, false));
}
Also used : ExceptionWithContext(org.jf.util.ExceptionWithContext) ImmutableMethodImplementation(org.jf.dexlib2.immutable.ImmutableMethodImplementation) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) Test(org.junit.Test)

Example 5 with ExceptionWithContext

use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.

the class ClassPool method intern.

public void intern(@Nonnull ClassDef classDef) {
    PoolClassDef poolClassDef = new PoolClassDef(classDef);
    PoolClassDef prev = internedItems.put(poolClassDef.getType(), poolClassDef);
    if (prev != null) {
        throw new ExceptionWithContext("Class %s has already been interned", poolClassDef.getType());
    }
    dexPool.typeSection.intern(poolClassDef.getType());
    dexPool.typeSection.internNullable(poolClassDef.getSuperclass());
    dexPool.typeListSection.intern(poolClassDef.getInterfaces());
    dexPool.stringSection.internNullable(poolClassDef.getSourceFile());
    HashSet<String> fields = new HashSet<String>();
    for (Field field : poolClassDef.getFields()) {
        String fieldDescriptor = ReferenceUtil.getShortFieldDescriptor(field);
        if (!fields.add(fieldDescriptor)) {
            throw new ExceptionWithContext("Multiple definitions for field %s->%s", poolClassDef.getType(), fieldDescriptor);
        }
        dexPool.fieldSection.intern(field);
        EncodedValue initialValue = field.getInitialValue();
        if (initialValue != null) {
            dexPool.internEncodedValue(initialValue);
        }
        dexPool.annotationSetSection.intern(field.getAnnotations());
    }
    HashSet<String> methods = new HashSet<String>();
    for (PoolMethod method : poolClassDef.getMethods()) {
        String methodDescriptor = ReferenceUtil.getMethodDescriptor(method, true);
        if (!methods.add(methodDescriptor)) {
            throw new ExceptionWithContext("Multiple definitions for method %s->%s", poolClassDef.getType(), methodDescriptor);
        }
        dexPool.methodSection.intern(method);
        internCode(method);
        internDebug(method);
        dexPool.annotationSetSection.intern(method.getAnnotations());
        for (MethodParameter parameter : method.getParameters()) {
            dexPool.annotationSetSection.intern(parameter.getAnnotations());
        }
    }
    dexPool.annotationSetSection.intern(poolClassDef.getAnnotations());
}
Also used : EncodedValue(org.jf.dexlib2.iface.value.EncodedValue) ExceptionWithContext(org.jf.util.ExceptionWithContext)

Aggregations

ExceptionWithContext (org.jf.util.ExceptionWithContext)14 Opcode (org.jf.dexlib2.Opcode)4 Instruction (org.jf.dexlib2.iface.instruction.Instruction)4 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)4 Nonnull (javax.annotation.Nonnull)2 ReferenceType (org.jf.dexlib2.ReferenceType)2 MutableMethodImplementation (org.jf.dexlib2.builder.MutableMethodImplementation)2 InvalidItemIndex (org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex)2 DexBackedInstruction (org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction)2 ExceptionHandler (org.jf.dexlib2.iface.ExceptionHandler)2 OneRegisterInstruction (org.jf.dexlib2.iface.instruction.OneRegisterInstruction)2 Instruction20bc (org.jf.dexlib2.iface.instruction.formats.Instruction20bc)2 Instruction31t (org.jf.dexlib2.iface.instruction.formats.Instruction31t)2 UnknownInstruction (org.jf.dexlib2.iface.instruction.formats.UnknownInstruction)2 FieldReference (org.jf.dexlib2.iface.reference.FieldReference)2 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)2 Reference (org.jf.dexlib2.iface.reference.Reference)2 MethodDefinition (com.taobao.android.baksmali.adaptors.MethodDefinition)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 Map (java.util.Map)1