/// <summary> /// Parses the data for this instance. /// </summary> /// <param name="data">The data memory reader.</param> /// <param name="endPosition">The end position.</param> /// <param name="input">The input data for parsing configuration.</param> private void ParseData(DwarfMemoryReader data, int endPosition, DwarfExceptionHandlingFrameParsingInput input) { Version = data.ReadByte(); Augmentation = data.ReadString(); CodeAlignmentFactor = data.LEB128(); DataAlignmentFactor = data.SLEB128(); if (Version == 1) { ReturnAddressRegister = data.ReadByte(); } else { ReturnAddressRegister = data.LEB128(); } AddressSize = input.DefaultAddressSize; SegmentSelectorSize = 0; int instructionsStart = -1; for (int i = 0; i < Augmentation.Length; i++) { if (Augmentation[i] == 'z') { uint length = data.LEB128(); instructionsStart = data.Position + (int)length; } else if (Augmentation[i] == 'L') { LanguageSpecificDataAreaEncoding = (DwarfExceptionHandlingEncoding)data.ReadByte(); } else if (Augmentation[i] == 'R') { FrameDescriptionAddressEncoding = (DwarfExceptionHandlingEncoding)data.ReadByte(); } else if (Augmentation[i] == 'S') { StackFrame = true; } else if (Augmentation[i] == 'P') { PersonalityEncoding = (DwarfExceptionHandlingEncoding)data.ReadByte(); PersonalityLocation = ReadEncodedAddress(data, PersonalityEncoding, input); } else { break; } } if (instructionsStart >= 0) { data.Position = instructionsStart; } InitialInstructions = data.ReadBlock((uint)(endPosition - data.Position)); }
/// <summary> /// Parses the common information entries. /// </summary> /// <param name="debugFrame">The debug frame.</param> /// <param name="ehFrame">The exception handling frames.</param> /// <param name="input">The input data for parsing configuration.</param> private static DwarfCommonInformationEntry[] ParseCommonInformationEntries(byte[] debugFrame, byte[] ehFrame, DwarfExceptionHandlingFrameParsingInput input) { List <DwarfCommonInformationEntry> entries = new List <DwarfCommonInformationEntry>(); using (DwarfMemoryReader debugFrameReader = new DwarfMemoryReader(debugFrame)) { entries.AddRange(DwarfCommonInformationEntry.ParseAll(debugFrameReader, input.DefaultAddressSize)); } using (DwarfMemoryReader ehFrameReader = new DwarfMemoryReader(ehFrame)) { entries.AddRange(DwarfExceptionHandlingCommonInformationEntry.ParseAll(ehFrameReader, input)); } return(entries.ToArray()); }
/// <summary> /// Parses the single entry from the specified data. /// </summary> /// <param name="data">The data memory reader.</param> /// <param name="startPosition">The start position.</param> /// <param name="input">The input data for parsing configuration.</param> /// <returns>Parsed common information entry.</returns> private static DwarfExceptionHandlingCommonInformationEntry ParseEntry(DwarfMemoryReader data, int startPosition, DwarfExceptionHandlingFrameParsingInput input) { int position = data.Position; data.Position = startPosition; bool is64bit; ulong length = data.ReadLength(out is64bit); int endPosition = data.Position + (int)length; int offset = data.ReadOffset(is64bit); if (offset != 0) { throw new Exception("Expected CommonInformationEntry"); } DwarfExceptionHandlingCommonInformationEntry entry = new DwarfExceptionHandlingCommonInformationEntry(data, endPosition, input); data.Position = position; return(entry); }
/// <summary> /// Reads encoded address from the specified data memory reader. /// </summary> /// <param name="data">The data memory reader.</param> /// <param name="encoding">Encoding used for storing address value.</param> /// <param name="input">The input data for parsing configuration.</param> /// <returns>Decoded address value.</returns> private static ulong ReadEncodedAddress(DwarfMemoryReader data, DwarfExceptionHandlingEncoding encoding, DwarfExceptionHandlingFrameParsingInput input) { bool signExtendValue = false; ulong baseAddress = 0; switch (encoding & DwarfExceptionHandlingEncoding.Modifiers) { case DwarfExceptionHandlingEncoding.PcRelative: signExtendValue = true; baseAddress = (ulong)data.Position; if (input.PcRelativeAddress != ulong.MaxValue) { baseAddress += input.PcRelativeAddress; } break; case DwarfExceptionHandlingEncoding.TextRelative: signExtendValue = true; if (input.TextAddress != ulong.MaxValue) { baseAddress = input.TextAddress; } break; case DwarfExceptionHandlingEncoding.DataRelative: signExtendValue = true; if (input.DataAddress != ulong.MaxValue) { baseAddress = input.DataAddress; } break; case DwarfExceptionHandlingEncoding.FunctionRelative: signExtendValue = true; break; case DwarfExceptionHandlingEncoding.Aligned: { int alignment = data.Position % input.DefaultAddressSize; if (alignment > 0) { data.Position += input.DefaultAddressSize - alignment; } } break; } ulong address = 0; switch (encoding & DwarfExceptionHandlingEncoding.Mask) { case DwarfExceptionHandlingEncoding.Signed: case DwarfExceptionHandlingEncoding.AbsolutePointer: address = data.ReadUlong(input.DefaultAddressSize); break; case DwarfExceptionHandlingEncoding.UnsignedData2: address = data.ReadUshort(); break; case DwarfExceptionHandlingEncoding.UnsignedData4: address = data.ReadUint(); break; case DwarfExceptionHandlingEncoding.SignedData8: case DwarfExceptionHandlingEncoding.UnsignedData8: address = data.ReadUlong(); break; case DwarfExceptionHandlingEncoding.Uleb128: address = data.LEB128(); break; case DwarfExceptionHandlingEncoding.Sleb128: address = data.SLEB128(); break; case DwarfExceptionHandlingEncoding.SignedData2: address = (ulong)(long)(short)data.ReadUshort(); break; case DwarfExceptionHandlingEncoding.SignedData4: address = (ulong)(long)(int)data.ReadUint(); break; } if (signExtendValue && input.DefaultAddressSize < System.Runtime.InteropServices.Marshal.SizeOf(address.GetType())) { ulong sign_bit = 1UL << ((input.DefaultAddressSize * 8) - 1); if ((sign_bit & address) != 0) { ulong mask = ~sign_bit + 1; address |= mask; } } return(baseAddress + address); }
/// <summary> /// Parses frame description from the specified data memory reader. /// </summary> /// <param name="data">The data memory reader.</param> /// <param name="entry">Common information entry for parsed frame description.</param> /// <param name="endPosition">Position in the data reader where parsed frame description ends.</param> /// <param name="input">The input data for parsing configuration.</param> /// <returns>Parsed frame description.</returns> private static DwarfFrameDescriptionEntry ParseDescription(DwarfMemoryReader data, DwarfExceptionHandlingCommonInformationEntry entry, int endPosition, DwarfExceptionHandlingFrameParsingInput input) { DwarfFrameDescriptionEntry description = new DwarfFrameDescriptionEntry(); description.InitialLocation = ReadEncodedAddress(data, entry.FrameDescriptionAddressEncoding, input); description.AddressRange = ReadEncodedAddress(data, entry.FrameDescriptionAddressEncoding & DwarfExceptionHandlingEncoding.Mask, input); description.CommonInformationEntry = entry; int instructionsStart = -1; if (entry.Augmentation.Length >= 1 && entry.Augmentation[0] == 'z') { uint length = data.LEB128(); instructionsStart = data.Position + (int)length; if (entry.LanguageSpecificDataAreaEncoding != DwarfExceptionHandlingEncoding.Omit) { ulong lsdaDataFileAddress = ReadEncodedAddress(data, entry.LanguageSpecificDataAreaEncoding, input); } } if (instructionsStart >= 0) { data.Position = instructionsStart; } description.Instructions = data.ReadBlock((uint)(endPosition - data.Position)); return(description); }
/// <summary> /// Parses the specified data for all common information entries and frame description entries. /// </summary> /// <param name="data">The data memory reader.</param> /// <param name="input">The input data for parsing configuration.</param> /// <returns>All the parsed common information entries</returns> public static DwarfExceptionHandlingCommonInformationEntry[] ParseAll(DwarfMemoryReader data, DwarfExceptionHandlingFrameParsingInput input) { Dictionary <int, DwarfExceptionHandlingCommonInformationEntry> entries = new Dictionary <int, DwarfExceptionHandlingCommonInformationEntry>(); while (!data.IsEnd) { bool is64bit; int startPosition = data.Position; ulong length = data.ReadLength(out is64bit); int endPosition = data.Position + (int)length; if (length == 0 || endPosition >= data.Data.Length) { break; } int offsetBase = data.Position; int offset = data.ReadOffset(is64bit); DwarfExceptionHandlingCommonInformationEntry entry; if (offset == 0) { entry = new DwarfExceptionHandlingCommonInformationEntry(data, endPosition, input); entries.Add(startPosition, entry); } else { int entryOffset = offsetBase - offset; if (!entries.TryGetValue(entryOffset, out entry)) { entry = ParseEntry(data, entryOffset, input); entries.Add(entryOffset, entry); } DwarfFrameDescriptionEntry description = ParseDescription(data, entry, endPosition, input); entry.FrameDescriptionEntries.Add(description); } } return(entries.Values.ToArray()); }
/// <summary> /// Initializes a new instance of the <see cref="DwarfExceptionHandlingCommonInformationEntry"/> class. /// </summary> /// <param name="data">The data memory reader.</param> /// <param name="endPosition">The end position in the memory stream.</param> /// <param name="input">The input data for parsing configuration.</param> public DwarfExceptionHandlingCommonInformationEntry(DwarfMemoryReader data, int endPosition, DwarfExceptionHandlingFrameParsingInput input) { ParseData(data, endPosition, input); }