예제 #1
0
        private void ReadMethodBody(BinaryReader reader, MethodDefinition mdef, uint codeOffset)
        {
            reader.PreserveCurrentPosition(codeOffset, () =>
            {
                ushort registersSize    = reader.ReadUInt16();
                ushort incomingArgsSize = reader.ReadUInt16();
                ushort outgoingArgsSize = reader.ReadUInt16();
                ushort triesSize        = reader.ReadUInt16();
                uint debugOffset        = reader.ReadUInt32();

                mdef.Body = new MethodBody(mdef, registersSize);
                mdef.Body.IncomingArguments = incomingArgsSize;
                mdef.Body.OutgoingArguments = outgoingArgsSize;

                var ireader = new InstructionReader(this, mdef);
                ireader.ReadFrom(reader);

                if ((triesSize != 0) && (ireader.Codes.Length % 2 != 0))
                {
                    reader.ReadUInt16(); // padding (4-byte alignment)
                }
                if (triesSize != 0)
                {
                    ReadExceptionHandlers(reader, mdef, ireader,
                                          triesSize);
                }

                if (debugOffset != 0)
                {
                    ReadDebugInfo(reader, mdef, ireader, debugOffset);
                }
            });
        }
예제 #2
0
        private void ReadExceptionHandlers(BinaryReader reader, MethodDefinition mdef,
                                           InstructionReader instructionReader, ushort triesSize)
        {
            var exceptionLookup = new Dictionary <uint, List <ExceptionHandler> >();

            for (int i = 0; i < triesSize; i++)
            {
                uint startOffset   = reader.ReadUInt32();
                uint insCount      = reader.ReadUInt16();
                uint endOffset     = startOffset + insCount - 1;
                uint handlerOffset = reader.ReadUInt16();

                var ehandler = new ExceptionHandler();
                mdef.Body.Exceptions.Add(ehandler);
                if (!exceptionLookup.ContainsKey(handlerOffset))
                {
                    exceptionLookup.Add(handlerOffset, new List <ExceptionHandler>());
                }
                exceptionLookup[handlerOffset].Add(ehandler);
                ehandler.TryStart = instructionReader.Lookup[(int)startOffset];
                // The last code unit covered (inclusive) is start_addr + insn_count - 1
                ehandler.TryEnd = instructionReader.LookupLast[(int)endOffset];
            }

            long baseOffset        = reader.BaseStream.Position;
            uint catchHandlersSize = reader.ReadULEB128();

            for (int i = 0; i < catchHandlersSize; i++)
            {
                long itemoffset      = reader.BaseStream.Position - baseOffset;
                int  catchTypes      = reader.ReadSLEB128();
                bool catchAllPresent = catchTypes <= 0;
                catchTypes = Math.Abs(catchTypes);

                for (int j = 0; j < catchTypes; j++)
                {
                    uint typeIndex = reader.ReadULEB128();
                    uint offset    = reader.ReadULEB128();
                    var  @catch    = new Catch();
                    @catch.Type        = typeReferences[(int)typeIndex];
                    @catch.Instruction = instructionReader.Lookup[(int)offset];

                    // As catch handler can be used in several tries, let's clone the catch
                    foreach (ExceptionHandler ehandler in exceptionLookup[(uint)itemoffset])
                    {
                        ehandler.Catches.Add(@catch.Clone());
                    }
                }

                if (catchAllPresent)
                {
                    uint offset = reader.ReadULEB128();
                    foreach (ExceptionHandler ehandler in exceptionLookup[(uint)itemoffset])
                    {
                        ehandler.CatchAll = instructionReader.Lookup[(int)offset];
                    }
                }
            }
        }
예제 #3
0
        private void ReadMethodBody(BinaryReader reader, MethodDefinition mdef, uint codeOffset)
        {
            reader.PreserveCurrentPosition(codeOffset, () =>
            {
                ushort registersSize = reader.ReadUInt16();
                ushort incomingArgsSize = reader.ReadUInt16();
                ushort outgoingArgsSize = reader.ReadUInt16();
                ushort triesSize = reader.ReadUInt16();
                uint debugOffset = reader.ReadUInt32();

                mdef.Body = new MethodBody(mdef, registersSize);
                mdef.Body.IncomingArguments = incomingArgsSize;
                mdef.Body.OutgoingArguments = outgoingArgsSize;

                var ireader = new InstructionReader(this, mdef);
                ireader.ReadFrom(reader);

                if ((triesSize != 0) && (ireader.Codes.Length%2 != 0))
                    reader.ReadUInt16(); // padding (4-byte alignment)

                if (triesSize != 0)
                    ReadExceptionHandlers(reader, mdef, ireader,
                        triesSize);

                if (debugOffset != 0)
                    ReadDebugInfo(reader, mdef, ireader, debugOffset);
            });
        }
예제 #4
0
        private void ReadExceptionHandlers(BinaryReader reader, MethodDefinition mdef,
            InstructionReader instructionReader, ushort triesSize)
        {
            var exceptionLookup = new Dictionary<uint, List<ExceptionHandler>>();
            for (int i = 0; i < triesSize; i++)
            {
                uint startOffset = reader.ReadUInt32();
                uint insCount = reader.ReadUInt16();
                uint endOffset = startOffset + insCount - 1;
                uint handlerOffset = reader.ReadUInt16();

                var ehandler = new ExceptionHandler();
                mdef.Body.Exceptions.Add(ehandler);
                if (!exceptionLookup.ContainsKey(handlerOffset))
                {
                    exceptionLookup.Add(handlerOffset, new List<ExceptionHandler>());
                }
                exceptionLookup[handlerOffset].Add(ehandler);
                ehandler.TryStart = instructionReader.Lookup[(int) startOffset];
                // The last code unit covered (inclusive) is start_addr + insn_count - 1
                ehandler.TryEnd = instructionReader.LookupLast[(int) endOffset];
            }

            long baseOffset = reader.BaseStream.Position;
            uint catchHandlersSize = reader.ReadULEB128();
            for (int i = 0; i < catchHandlersSize; i++)
            {
                long itemoffset = reader.BaseStream.Position - baseOffset;
                int catchTypes = reader.ReadSLEB128();
                bool catchAllPresent = catchTypes <= 0;
                catchTypes = Math.Abs(catchTypes);

                for (int j = 0; j < catchTypes; j++)
                {
                    uint typeIndex = reader.ReadULEB128();
                    uint offset = reader.ReadULEB128();
                    var @catch = new Catch();
                    @catch.Type = typeReferences[(int) typeIndex];
                    @catch.Instruction = instructionReader.Lookup[(int) offset];

                    // As catch handler can be used in several tries, let's clone the catch
                    foreach (ExceptionHandler ehandler in exceptionLookup[(uint) itemoffset])
                        ehandler.Catches.Add(@catch.Clone());
                }

                if (catchAllPresent)
                {
                    uint offset = reader.ReadULEB128();
                    foreach (ExceptionHandler ehandler in exceptionLookup[(uint) itemoffset])
                        ehandler.CatchAll = instructionReader.Lookup[(int) offset];
                }
            }
        }
예제 #5
0
        private void ReadDebugInfo(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader,
            uint debugOffset)
        {
            reader.PreserveCurrentPosition(debugOffset, () =>
            {
                var debugInfo = new DebugInfo(mdef.Body);
                mdef.Body.DebugInfo = debugInfo;

                uint lineStart = reader.ReadULEB128();
                debugInfo.LineStart = lineStart;

                uint parametersSize = reader.ReadULEB128();
                for (int i = 0; i < parametersSize; i++)
                {
                    long index = reader.ReadULEB128p1();
                    string name = null;
                    if (index != DexConsts.NoIndex && index >= 0)
                        name = strings[(int) index];
                    debugInfo.Parameters.Add(name);
                }

                while (true)
                {
                    var ins = new DebugInstruction((DebugOpCodes) reader.ReadByte());
                    debugInfo.DebugInstructions.Add(ins);

                    uint registerIndex;
                    uint addrDiff;
                    long nameIndex;
                    long typeIndex;
                    long signatureIndex;
                    int lineDiff;
                    string name;

                    switch (ins.OpCode)
                    {
                        case DebugOpCodes.AdvancePc:
                            // uleb128 addr_diff
                            addrDiff = reader.ReadULEB128();
                            ins.Operands.Add(addrDiff);
                            break;
                        case DebugOpCodes.AdvanceLine:
                            // sleb128 line_diff
                            lineDiff = reader.ReadSLEB128();
                            ins.Operands.Add(lineDiff);
                            break;
                        case DebugOpCodes.EndLocal:
                        case DebugOpCodes.RestartLocal:
                            // uleb128 register_num
                            registerIndex = reader.ReadULEB128();
                            ins.Operands.Add(mdef.Body.Registers[(int) registerIndex]);
                            break;
                        case DebugOpCodes.SetFile:
                            // uleb128p1 name_idx
                            nameIndex = reader.ReadULEB128p1();
                            name = null;
                            if (nameIndex != DexConsts.NoIndex && nameIndex >= 0)
                                name = strings[(int) nameIndex];
                            ins.Operands.Add(name);
                            break;
                        case DebugOpCodes.StartLocalExtended:
                        case DebugOpCodes.StartLocal:
                            // StartLocalExtended : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx, uleb128p1 sig_idx
                            // StartLocal : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx
                            Boolean isExtended = ins.OpCode ==
                                                 DebugOpCodes.
                                                     StartLocalExtended;

                            registerIndex = reader.ReadULEB128();
                            ins.Operands.Add(mdef.Body.Registers[(int) registerIndex]);

                            nameIndex = reader.ReadULEB128p1();
                            name = null;
                            if (nameIndex != DexConsts.NoIndex && nameIndex >= 0)
                                name = strings[(int) nameIndex];
                            ins.Operands.Add(name);

                            typeIndex = reader.ReadULEB128p1();
                            TypeReference type = null;
                            if (typeIndex != DexConsts.NoIndex && typeIndex >= 0)
                                type = typeReferences[(int) typeIndex];
                            ins.Operands.Add(type);

                            if (isExtended)
                            {
                                signatureIndex = reader.ReadULEB128p1();
                                string signature = null;
                                if (signatureIndex != DexConsts.NoIndex && signatureIndex >= 0)
                                    signature = strings[(int) signatureIndex];
                                ins.Operands.Add(signature);
                            }

                            break;
                        case DebugOpCodes.EndSequence:
                            return;
                        case DebugOpCodes.Special:
                        // between 0x0a and 0xff (inclusive)
                        case DebugOpCodes.SetPrologueEnd:
                        case DebugOpCodes.SetEpilogueBegin:
                        default:
                            break;
                    }
                }
            });
        }
예제 #6
0
        private void ReadDebugInfo(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader,
                                   uint debugOffset)
        {
            reader.PreserveCurrentPosition(debugOffset, () =>
            {
                var debugInfo       = new DebugInfo(mdef.Body);
                mdef.Body.DebugInfo = debugInfo;

                uint lineStart      = reader.ReadULEB128();
                debugInfo.LineStart = lineStart;

                uint parametersSize = reader.ReadULEB128();
                for (int i = 0; i < parametersSize; i++)
                {
                    long index  = reader.ReadULEB128p1();
                    string name = null;
                    if (index != DexConsts.NoIndex && index >= 0)
                    {
                        name = strings[(int)index];
                    }
                    debugInfo.Parameters.Add(name);
                }

                while (true)
                {
                    var ins = new DebugInstruction((DebugOpCodes)reader.ReadByte());
                    debugInfo.DebugInstructions.Add(ins);

                    uint registerIndex;
                    uint addrDiff;
                    long nameIndex;
                    long typeIndex;
                    long signatureIndex;
                    int lineDiff;
                    string name;

                    switch (ins.OpCode)
                    {
                    case DebugOpCodes.AdvancePc:
                        // uleb128 addr_diff
                        addrDiff = reader.ReadULEB128();
                        ins.Operands.Add(addrDiff);
                        break;

                    case DebugOpCodes.AdvanceLine:
                        // sleb128 line_diff
                        lineDiff = reader.ReadSLEB128();
                        ins.Operands.Add(lineDiff);
                        break;

                    case DebugOpCodes.EndLocal:
                    case DebugOpCodes.RestartLocal:
                        // uleb128 register_num
                        registerIndex = reader.ReadULEB128();
                        ins.Operands.Add(mdef.Body.Registers[(int)registerIndex]);
                        break;

                    case DebugOpCodes.SetFile:
                        // uleb128p1 name_idx
                        nameIndex = reader.ReadULEB128p1();
                        name      = null;
                        if (nameIndex != DexConsts.NoIndex && nameIndex >= 0)
                        {
                            name = strings[(int)nameIndex];
                        }
                        ins.Operands.Add(name);
                        break;

                    case DebugOpCodes.StartLocalExtended:
                    case DebugOpCodes.StartLocal:
                        // StartLocalExtended : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx, uleb128p1 sig_idx
                        // StartLocal : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx
                        Boolean isExtended = ins.OpCode ==
                                             DebugOpCodes.
                                             StartLocalExtended;

                        registerIndex = reader.ReadULEB128();
                        ins.Operands.Add(mdef.Body.Registers[(int)registerIndex]);

                        nameIndex = reader.ReadULEB128p1();
                        name      = null;
                        if (nameIndex != DexConsts.NoIndex && nameIndex >= 0)
                        {
                            name = strings[(int)nameIndex];
                        }
                        ins.Operands.Add(name);

                        typeIndex          = reader.ReadULEB128p1();
                        TypeReference type = null;
                        if (typeIndex != DexConsts.NoIndex && typeIndex >= 0)
                        {
                            type = typeReferences[(int)typeIndex];
                        }
                        ins.Operands.Add(type);

                        if (isExtended)
                        {
                            signatureIndex   = reader.ReadULEB128p1();
                            string signature = null;
                            if (signatureIndex != DexConsts.NoIndex && signatureIndex >= 0)
                            {
                                signature = strings[(int)signatureIndex];
                            }
                            ins.Operands.Add(signature);
                        }

                        break;

                    case DebugOpCodes.EndSequence:
                        return;

                    case DebugOpCodes.Special:
                    // between 0x0a and 0xff (inclusive)
                    case DebugOpCodes.SetPrologueEnd:
                    case DebugOpCodes.SetEpilogueBegin:
                    default:
                        break;
                    }
                }
            });
        }