/// <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; }