public InstructionWriter(DexWriter dexWriter, MethodDefinition method)
 {
     DexWriter = dexWriter;
     MethodDefinition = method;
     LookupLast = new Dictionary<Instruction, int>();
     _ip = 0;
     _extraOffset = 0;
 }
 public InstructionReader(Dex dex, MethodDefinition mdef)
 {
     Dex = dex;
     MethodDefinition = mdef;
     Lookup = new Dictionary<int, Instruction>();
     LookupLast = new Dictionary<int, Instruction>();
     LazyInstructionsSetters = new List<Action>();
     _ip = 0;
 }
Exemple #3
0
 public MethodBody(MethodDefinition method, int registersSize)
 {
     Owner = method;
     Registers = new List<Register>();
     for (var i = 0; i < registersSize; i++)
     {
         Registers.Add(new Register(i));
     }
     Instructions = new List<Instruction>();
     Exceptions = new List<ExceptionHandler>();
 }
Exemple #4
0
 public bool Equals(MethodDefinition other)
 {
     // Should be enough (ownership)
     return base.Equals(other);
 }
Exemple #5
0
        private void ReadMethodBody(BinaryReader reader, MethodDefinition mdef, uint codeOffset)
        {
            reader.PreserveCurrentPosition(codeOffset, () =>
            {
                var registersSize = reader.ReadUInt16();
                var incomingArgsSize = reader.ReadUInt16();
                var outgoingArgsSize = reader.ReadUInt16();
                var triesSize = reader.ReadUInt16();
                var debugOffset = reader.ReadUInt32();

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

                var ireader = new InstructionReader(Dex, 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, debugOffset);
            });
        }
Exemple #6
0
        private void ReadExceptionHandlers(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader, ushort triesSize)
        {
            var exceptionLookup = new Dictionary<uint, List<ExceptionHandler>>();
            for (var i = 0; i < triesSize; i++)
            {
                var startOffset = reader.ReadUInt32();
                var insCount = reader.ReadUInt16();
                var 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];
            }

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

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

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

                if (!catchAllPresent)
                    continue;

                var caOffset = reader.ReadULEB128();
                foreach (var ehandler in exceptionLookup[(uint)itemoffset])
                    ehandler.CatchAll = instructionReader.Lookup[(int)caOffset];
            }
        }
Exemple #7
0
        private void ReadDebugInfo(BinaryReader reader, MethodDefinition mdef, uint debugOffset)
        {
            reader.PreserveCurrentPosition(debugOffset, () =>
            {
                var debugInfo = new DebugInfo(mdef.Body);
                mdef.Body.DebugInfo = debugInfo;

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

                var parametersSize = reader.ReadULEB128();
                for (var i = 0; i < parametersSize; i++)
                {
                    var index = reader.ReadULEB128P1();
                    string name = null;
                    if (index != DexConsts.NoIndex && index >= 0)
                        name = Dex.Strings[(int)index];
                    debugInfo.Parameters.Add(name);
                }

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

                    uint registerIndex;
                    long nameIndex;
                    string name;

                    switch (ins.OpCode)
                    {
                        case DebugOpCodes.AdvancePc:
                            // uleb128 addr_diff
                            var addrDiff = reader.ReadULEB128();
                            ins.Operands.Add(addrDiff);
                            break;
                        case DebugOpCodes.AdvanceLine:
                            // sleb128 line_diff
                            var 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 = Dex.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
                            var 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 = Dex.Strings[(int)nameIndex];
                            ins.Operands.Add(name);

                            var typeIndex = reader.ReadULEB128P1();
                            TypeReference type = null;
                            if (typeIndex != DexConsts.NoIndex && typeIndex >= 0)
                                type = Dex.TypeReferences[(int)typeIndex];
                            ins.Operands.Add(type);

                            if (isExtended)
                            {
                                var signatureIndex = reader.ReadULEB128P1();
                                string signature = null;
                                if (signatureIndex != DexConsts.NoIndex && signatureIndex >= 0)
                                    signature = Dex.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;
                    }
                }
            });
        }
Exemple #8
0
        private void PrefetchMethodDefinitions(BinaryReader reader, uint methodcount)
        {
            var methodIndex = 0;
            for (var i = 0; i < methodcount; i++)
            {
                if (i == 0)
                    methodIndex = (int)reader.ReadULEB128();
                else
                    methodIndex += (int)reader.ReadULEB128();

                reader.ReadULEB128();
                reader.ReadULEB128();
                var mdef = new MethodDefinition(Dex.MethodReferences[methodIndex]);
                Dex.MethodReferences[methodIndex] = mdef;
            }
        }
Exemple #9
0
        // ReSharper restore ValueParameterNotUsed

        public bool Equals(MethodDefinition other)
        {
            // Should be enough (ownership)
            return(base.Equals(other));
        }