Search in sources :

Example 1 with LineNumber

use of org.jf.dexlib2.iface.debug.LineNumber in project smali by JesusFreke.

the class FixOffsetsTest method testFixOffsets.

@Test
public void testFixOffsets() {
    MethodImplementationBuilder builder = new MethodImplementationBuilder(1);
    Label firstGotoTarget = builder.getLabel("firstGotoTarget");
    builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, firstGotoTarget));
    builder.addLineNumber(1);
    for (int i = 0; i < 250; i++) {
        builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    }
    builder.addLabel("tryStart");
    builder.addLineNumber(2);
    for (int i = 0; i < 250; i++) {
        builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    }
    builder.addLineNumber(3);
    Label secondGotoTarget = builder.getLabel("secondGotoTarget");
    builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, secondGotoTarget));
    builder.addLineNumber(4);
    builder.addLabel("handler");
    for (int i = 0; i < 500; i++) {
        builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    }
    builder.addLineNumber(5);
    builder.addLabel("tryEnd");
    builder.addLabel("firstGotoTarget");
    builder.addLabel("secondGotoTarget");
    builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
    Label tryStart = builder.getLabel("tryStart");
    Label tryEnd = builder.getLabel("tryEnd");
    Label handler = builder.getLabel("handler");
    builder.addCatch(tryStart, tryEnd, handler);
    MethodImplementation impl = builder.getMethodImplementation();
    List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions());
    Assert.assertEquals(1003, instructions.size());
    Assert.assertEquals(Opcode.GOTO_16, instructions.get(0).getOpcode());
    Assert.assertEquals(1004, ((OffsetInstruction) instructions.get(0)).getCodeOffset());
    Assert.assertEquals(Opcode.GOTO_16, instructions.get(501).getOpcode());
    Assert.assertEquals(502, ((OffsetInstruction) instructions.get(501)).getCodeOffset());
    List<? extends TryBlock<? extends ExceptionHandler>> exceptionHandlers = impl.getTryBlocks();
    Assert.assertEquals(1, exceptionHandlers.size());
    Assert.assertEquals(252, exceptionHandlers.get(0).getStartCodeAddress());
    Assert.assertEquals(752, exceptionHandlers.get(0).getCodeUnitCount());
    Assert.assertEquals(1, exceptionHandlers.get(0).getExceptionHandlers().size());
    ExceptionHandler exceptionHandler = exceptionHandlers.get(0).getExceptionHandlers().get(0);
    Assert.assertEquals(504, exceptionHandler.getHandlerCodeAddress());
    List<DebugItem> debugItems = Lists.newArrayList(impl.getDebugItems());
    Assert.assertEquals(5, debugItems.size());
    Assert.assertEquals(1, ((LineNumber) debugItems.get(0)).getLineNumber());
    Assert.assertEquals(2, debugItems.get(0).getCodeAddress());
    Assert.assertEquals(2, ((LineNumber) debugItems.get(1)).getLineNumber());
    Assert.assertEquals(252, debugItems.get(1).getCodeAddress());
    Assert.assertEquals(3, ((LineNumber) debugItems.get(2)).getLineNumber());
    Assert.assertEquals(502, debugItems.get(2).getCodeAddress());
    Assert.assertEquals(4, ((LineNumber) debugItems.get(3)).getLineNumber());
    Assert.assertEquals(504, debugItems.get(3).getCodeAddress());
    Assert.assertEquals(5, ((LineNumber) debugItems.get(4)).getLineNumber());
    Assert.assertEquals(1004, debugItems.get(4).getCodeAddress());
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) ExceptionHandler(org.jf.dexlib2.iface.ExceptionHandler) BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction10t(org.jf.dexlib2.builder.instruction.BuilderInstruction10t) DebugItem(org.jf.dexlib2.iface.debug.DebugItem) Test(org.junit.Test)

Example 2 with LineNumber

use of org.jf.dexlib2.iface.debug.LineNumber 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();
        }
    };
}
Also used : DexReader(org.jf.dexlib2.dexbacked.DexReader) Nonnull(javax.annotation.Nonnull) AnnotatedBytes(org.jf.dexlib2.util.AnnotatedBytes) Nullable(javax.annotation.Nullable) Nonnull(javax.annotation.Nonnull)

Example 3 with LineNumber

use of org.jf.dexlib2.iface.debug.LineNumber in project smali by JesusFreke.

the class DexWriter method writeDebugItem.

private int writeDebugItem(@Nonnull DexDataWriter writer, @Nonnull DebugWriter<StringKey, TypeKey> debugWriter, @Nullable Iterable<? extends StringKey> parameterNames, @Nullable Iterable<? extends DebugItem> debugItems) throws IOException {
    int parameterCount = 0;
    int lastNamedParameterIndex = -1;
    if (parameterNames != null) {
        parameterCount = Iterables.size(parameterNames);
        int index = 0;
        for (StringKey parameterName : parameterNames) {
            if (parameterName != null) {
                lastNamedParameterIndex = index;
            }
            index++;
        }
    }
    if (lastNamedParameterIndex == -1 && (debugItems == null || Iterables.isEmpty(debugItems))) {
        return NO_OFFSET;
    }
    numDebugInfoItems++;
    int debugItemOffset = writer.getPosition();
    int startingLineNumber = 0;
    if (debugItems != null) {
        for (org.jf.dexlib2.iface.debug.DebugItem debugItem : debugItems) {
            if (debugItem instanceof LineNumber) {
                startingLineNumber = ((LineNumber) debugItem).getLineNumber();
                break;
            }
        }
    }
    writer.writeUleb128(startingLineNumber);
    writer.writeUleb128(parameterCount);
    if (parameterNames != null) {
        int index = 0;
        for (StringKey parameterName : parameterNames) {
            if (index == parameterCount) {
                break;
            }
            index++;
            writer.writeUleb128(stringSection.getNullableItemIndex(parameterName) + 1);
        }
    }
    if (debugItems != null) {
        debugWriter.reset(startingLineNumber);
        for (DebugItem debugItem : debugItems) {
            classSection.writeDebugItem(debugWriter, debugItem);
        }
    }
    // write an END_SEQUENCE opcode, to end the debug item
    writer.write(0);
    return debugItemOffset;
}
Also used : DebugItem(org.jf.dexlib2.iface.debug.DebugItem) DebugItem(org.jf.dexlib2.iface.debug.DebugItem) LineNumber(org.jf.dexlib2.iface.debug.LineNumber)

Aggregations

DebugItem (org.jf.dexlib2.iface.debug.DebugItem)2 Nonnull (javax.annotation.Nonnull)1 Nullable (javax.annotation.Nullable)1 BuilderInstruction10t (org.jf.dexlib2.builder.instruction.BuilderInstruction10t)1 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)1 DexReader (org.jf.dexlib2.dexbacked.DexReader)1 ExceptionHandler (org.jf.dexlib2.iface.ExceptionHandler)1 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)1 LineNumber (org.jf.dexlib2.iface.debug.LineNumber)1 AnnotatedBytes (org.jf.dexlib2.util.AnnotatedBytes)1 Test (org.junit.Test)1