Example #1
0
        /// <summary>Decode instructions for the given method.</summary>
        /// <param name="method">The method to be decoded.</param>
        /// <param name="objectResolver">An implementation of an object resolver to be
        /// used for retrieving classes and constant strings referenced from the bytecode.
        /// </param>
        /// <returns>An array indexed by the offset within method byte code and storing
        /// the instruction starting at this offset (if any).</returns>
        private static DalvikInstruction[] BuildInstructionList(IMethod method,
            IResolver objectResolver)
        {
            DalvikInstruction[] result = new DalvikInstruction[method.ByteCodeSize];
            byte[] byteCode = method.GetByteCode();
            List<uint> pendingInstructionsOffset = new List<uint>();

            // Add entry point.
            pendingInstructionsOffset.Add(0);
            // As well as catch blocks from the exception because they aren't
            // referenced from normal code.
            foreach (ITryBlock tryBlock in method.EnumerateTryBlocks()) {
                foreach (IGuardHandler handler in tryBlock.EnumerateHandlers()) {
                    uint addedOffset = handler.HandlerMethodOffset;
                    // For debugging purpose. Should never occur.
                    if (addedOffset >= byteCode.Length) { throw new ApplicationException(); }
                    pendingInstructionsOffset.Add(addedOffset);
                }
            }
            Console.WriteLine(
                "Decoding '{0}' method bytecode on {1} bytes starting at 0x{2:X8}.",
                Helpers.BuildMethodDeclarationString(method), byteCode.Length,
                method.ByteCodeRawAddress);

            while (0 < pendingInstructionsOffset.Count) {
                uint opCodeIndex = pendingInstructionsOffset[0];
                pendingInstructionsOffset.RemoveAt(0);
                bool fallInSequence = true;

                while (fallInSequence) {
                    // Avoid targeting twice a single instruction.
                    if (null != result[opCodeIndex]) { break; }
                    DalvikInstruction newNode = OpCodeDecoder.Decode(byteCode,
                        method.ByteCodeRawAddress, objectResolver, result,
                        ref opCodeIndex);

                    // Analyse possible targets after this instruction and augment
                    // pending instructions list accordingly.
                    fallInSequence = newNode.ContinueInSequence;
                    uint[] otherTargetMethodOffsets = newNode.AdditionalTargetMethodOffsets;
                    if (null != otherTargetMethodOffsets) {
                        for(int index = 0; index < otherTargetMethodOffsets.Length; index++) {
                            uint targetOffset = otherTargetMethodOffsets[index];

                            if (targetOffset >= byteCode.Length) { throw new ApplicationException(); }
                            if (!pendingInstructionsOffset.Contains(targetOffset)
                                && (null == result[targetOffset])) {
                                pendingInstructionsOffset.Add(targetOffset);
                            }
                        }
                    }
                }
            }
            return result;
        }