/// <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="defaultAddressSize">Default size of the address.</param>
        /// <returns>All the parsed common information entries</returns>
        public static DwarfCommonInformationEntry[] ParseAll(DwarfMemoryReader data, byte defaultAddressSize)
        {
            Dictionary <int, DwarfCommonInformationEntry> entries = new Dictionary <int, DwarfCommonInformationEntry>();

            while (!data.IsEnd)
            {
                bool  is64bit;
                int   startPosition = data.Position;
                ulong length        = data.ReadLength(out is64bit);
                int   endPosition   = data.Position + (int)length;
                int   offset        = data.ReadOffset(is64bit);
                DwarfCommonInformationEntry entry;

                if (offset == -1)
                {
                    entry = new DwarfCommonInformationEntry(data, defaultAddressSize, endPosition);
                    entries.Add(startPosition, entry);
                }
                else
                {
                    if (!entries.TryGetValue(offset, out entry))
                    {
                        entry = ParseEntry(data, defaultAddressSize, offset);
                        entries.Add(offset, entry);
                    }

                    DwarfFrameDescriptionEntry description = new DwarfFrameDescriptionEntry(data, entry, endPosition);

                    entry.FrameDescriptionEntries.Add(description);
                }
            }

            return(entries.Values.ToArray());
        }
 /// <summary>
 /// Parses the data for this instance.
 /// </summary>
 /// <param name="data">The data memory reader.</param>
 /// <param name="defaultAddressSize">Default size of the address.</param>
 /// <param name="endPosition">The end position.</param>
 private void ParseData(DwarfMemoryReader data, byte defaultAddressSize, int endPosition)
 {
     Version      = data.ReadByte();
     Augmentation = data.ReadString();
     if (!string.IsNullOrEmpty(Augmentation))
     {
         AddressSize           = 4;
         SegmentSelectorSize   = 0;
         CodeAlignmentFactor   = 0;
         DataAlignmentFactor   = 0;
         ReturnAddressRegister = 0;
     }
     else
     {
         if (Version >= 4)
         {
             AddressSize         = data.ReadByte();
             SegmentSelectorSize = data.ReadByte();
         }
         else
         {
             AddressSize         = defaultAddressSize;
             SegmentSelectorSize = 0;
         }
         CodeAlignmentFactor   = data.LEB128();
         DataAlignmentFactor   = data.LEB128();
         ReturnAddressRegister = data.LEB128();
     }
     InitialInstructions = data.ReadBlock((uint)(endPosition - data.Position));
 }
Пример #3
0
        /// <summary>
        /// Reads the file information from the specified stream.
        /// </summary>
        /// <param name="debugLine">The debug line data stream.</param>
        /// <param name="directories">The list of existing directories.</param>
        private static DwarfFileInformation ReadFile(DwarfMemoryReader debugLine, List <string> directories)
        {
            string name             = debugLine.ReadString();
            int    directoryIndex   = (int)debugLine.LEB128();
            uint   lastModification = debugLine.LEB128();
            uint   length           = debugLine.LEB128();
            string directory        = directoryIndex > 0 ? directories[directoryIndex - 1] : null;
            string path             = name;

            try
            {
                path = string.IsNullOrEmpty(directory) || Path.IsPathRooted(path) ? name : Path.Combine(directory, name);
            }
            catch
            {
            }

            return(new DwarfFileInformation()
            {
                Name = name,
                Directory = directory,
                Path = path,
                LastModification = lastModification,
                Length = length,
            });
        }
        /// <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 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));
        }
Пример #6
0
        /// <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());
        }
Пример #7
0
        /// <summary>
        /// Parses the line number programs.
        /// </summary>
        /// <param name="debugLine">The debug line.</param>
        /// <param name="addressNormalizer">Normalize address delegate (<see cref="NormalizeAddressDelegate"/>)</param>
        private static DwarfLineNumberProgram[] ParseLineNumberPrograms(byte[] debugLine, NormalizeAddressDelegate addressNormalizer)
        {
            using (DwarfMemoryReader debugLineReader = new DwarfMemoryReader(debugLine))
            {
                List <DwarfLineNumberProgram> programs = new List <DwarfLineNumberProgram>();

                while (!debugLineReader.IsEnd)
                {
                    DwarfLineNumberProgram program = new DwarfLineNumberProgram(debugLineReader, addressNormalizer);

                    programs.Add(program);
                }

                return(programs.ToArray());
            }
        }
Пример #8
0
        /// <summary>
        /// Parses the compilation units.
        /// </summary>
        /// <param name="debugData">The debug data.</param>
        /// <param name="debugDataDescription">The debug data description.</param>
        /// <param name="debugStrings">The debug strings.</param>
        /// <param name="addressNormalizer">Normalize address delegate (<see cref="NormalizeAddressDelegate"/>)</param>
        private static DwarfCompilationUnit[] ParseCompilationUnits(byte[] debugData, byte[] debugDataDescription, byte[] debugStrings, NormalizeAddressDelegate addressNormalizer)
        {
            using (DwarfMemoryReader debugDataReader = new DwarfMemoryReader(debugData))
                using (DwarfMemoryReader debugDataDescriptionReader = new DwarfMemoryReader(debugDataDescription))
                    using (DwarfMemoryReader debugStringsReader = new DwarfMemoryReader(debugStrings))
                    {
                        List <DwarfCompilationUnit> compilationUnits = new List <DwarfCompilationUnit>();

                        while (!debugDataReader.IsEnd)
                        {
                            DwarfCompilationUnit compilationUnit = new DwarfCompilationUnit(debugDataReader, debugDataDescriptionReader, debugStringsReader, addressNormalizer);

                            compilationUnits.Add(compilationUnit);
                        }

                        return(compilationUnits.ToArray());
                    }
        }
        /// <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());
        }
Пример #10
0
            public static elf_note_file[] Parse(DwarfMemoryReader reader, bool is64bit)
            {
                ulong count     = is64bit ? reader.ReadUlong() : reader.ReadUint();
                ulong page_size = is64bit ? reader.ReadUlong() : reader.ReadUint();

                elf_note_file[] files = new elf_note_file[count];

                for (int i = 0; i < files.Length; i++)
                {
                    files[i].start    = is64bit ? reader.ReadUlong() : reader.ReadUint();
                    files[i].end      = is64bit ? reader.ReadUlong() : reader.ReadUint();
                    files[i].file_ofs = (is64bit ? reader.ReadUlong() : reader.ReadUint()) * page_size;
                }
                for (int i = 0; i < files.Length; i++)
                {
                    files[i].name = reader.ReadString();
                }
                return(files);
            }
        /// <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>
        /// Parses the single entry from the specified data.
        /// </summary>
        /// <param name="data">The data memory reader.</param>
        /// <param name="defaultAddressSize">Default size of the address.</param>
        /// <param name="startPosition">The start position.</param>
        /// <returns>Parsed common information entry.</returns>
        private static DwarfCommonInformationEntry ParseEntry(DwarfMemoryReader data, byte defaultAddressSize, int startPosition)
        {
            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 != -1)
            {
                throw new Exception("Expected CommonInformationEntry");
            }

            DwarfCommonInformationEntry entry = new DwarfCommonInformationEntry(data, defaultAddressSize, endPosition);

            data.Position = position;
            return(entry);
        }
Пример #13
0
            /// <summary>
            /// Processes the parsed note.
            /// </summary>
            /// <param name="name">The note name.</param>
            /// <param name="content">The note content.</param>
            /// <param name="type">The note type.</param>
            public void ProcessNote(string name, byte[] content, elf_note_type type)
            {
                if (type == elf_note_type.Prstatus)
                {
                    using (DwarfMemoryReader data = new DwarfMemoryReader(content))
                    {
                        elf_prstatus prstatus = data.ReadStructure <elf_prstatus>();

                        threads.Add(prstatus);
                    }
                }
                else if (type == elf_note_type.Prpsinfo)
                {
                    // TODO: Use when needed
                    //using (DwarfMemoryReader data = new DwarfMemoryReader(content))
                    //{
                    //    elf_prpsinfo prpsinfo = data.ReadStructure<elf_prpsinfo>();
                    //    Console.WriteLine($"  Filename: {prpsinfo.Filename}");
                    //    Console.WriteLine($"  ArgList: {prpsinfo.ArgList}");
                    //}
                }
            }
Пример #14
0
        /// <summary>
        /// Reads the data for this instance.
        /// </summary>
        /// <param name="debugData">The debug data.</param>
        /// <param name="debugDataDescription">The debug data description.</param>
        /// <param name="debugStrings">The debug strings.</param>
        /// <param name="addressNormalizer">Normalize address delegate (<see cref="NormalizeAddressDelegate"/>)</param>
        private void ReadData(DwarfMemoryReader debugData, DwarfMemoryReader debugDataDescription, DwarfMemoryReader debugStrings, NormalizeAddressDelegate addressNormalizer)
        {
            // Read header
            bool   is64bit;
            int    beginPosition = debugData.Position;
            ulong  length        = debugData.ReadLength(out is64bit);
            int    endPosition   = debugData.Position + (int)length;
            ushort version       = debugData.ReadUshort();
            int    debugDataDescriptionOffset = debugData.ReadOffset(is64bit);
            byte   addressSize = debugData.ReadByte();
            DataDescriptionReader dataDescriptionReader = new DataDescriptionReader(debugDataDescription, debugDataDescriptionOffset);

            // Read data
            List <DwarfSymbol>  symbols = new List <DwarfSymbol>();
            Stack <DwarfSymbol> parents = new Stack <DwarfSymbol>();

            while (debugData.Position < endPosition)
            {
                int  dataPosition = debugData.Position;
                uint code         = debugData.LEB128();

                if (code == 0)
                {
                    parents.Pop();
                    continue;
                }

                DataDescription description = dataDescriptionReader.GetDebugDataDescription(code);
                Dictionary <DwarfAttribute, DwarfAttributeValue> attributes = new Dictionary <DwarfAttribute, DwarfAttributeValue>();

                foreach (DataDescriptionAttribute descriptionAttribute in description.Attributes)
                {
                    DwarfAttribute      attribute      = descriptionAttribute.Attribute;
                    DwarfFormat         format         = descriptionAttribute.Format;
                    DwarfAttributeValue attributeValue = new DwarfAttributeValue();

                    switch (format)
                    {
                    case DwarfFormat.Address:
                        attributeValue.Type  = DwarfAttributeValueType.Address;
                        attributeValue.Value = debugData.ReadUlong(addressSize);
                        break;

                    case DwarfFormat.Block:
                        attributeValue.Type  = DwarfAttributeValueType.Block;
                        attributeValue.Value = debugData.ReadBlock(debugData.LEB128());
                        break;

                    case DwarfFormat.Block1:
                        attributeValue.Type  = DwarfAttributeValueType.Block;
                        attributeValue.Value = debugData.ReadBlock(debugData.ReadByte());
                        break;

                    case DwarfFormat.Block2:
                        attributeValue.Type  = DwarfAttributeValueType.Block;
                        attributeValue.Value = debugData.ReadBlock(debugData.ReadUshort());
                        break;

                    case DwarfFormat.Block4:
                        attributeValue.Type  = DwarfAttributeValueType.Block;
                        attributeValue.Value = debugData.ReadBlock(debugData.ReadUint());
                        break;

                    case DwarfFormat.Data1:
                        attributeValue.Type  = DwarfAttributeValueType.Constant;
                        attributeValue.Value = (ulong)debugData.ReadByte();
                        break;

                    case DwarfFormat.Data2:
                        attributeValue.Type  = DwarfAttributeValueType.Constant;
                        attributeValue.Value = (ulong)debugData.ReadUshort();
                        break;

                    case DwarfFormat.Data4:
                        attributeValue.Type  = DwarfAttributeValueType.Constant;
                        attributeValue.Value = (ulong)debugData.ReadUint();
                        break;

                    case DwarfFormat.Data8:
                        attributeValue.Type  = DwarfAttributeValueType.Constant;
                        attributeValue.Value = (ulong)debugData.ReadUlong();
                        break;

                    case DwarfFormat.SData:
                        attributeValue.Type  = DwarfAttributeValueType.Constant;
                        attributeValue.Value = (ulong)debugData.SLEB128();
                        break;

                    case DwarfFormat.UData:
                        attributeValue.Type  = DwarfAttributeValueType.Constant;
                        attributeValue.Value = (ulong)debugData.LEB128();
                        break;

                    case DwarfFormat.String:
                        attributeValue.Type  = DwarfAttributeValueType.String;
                        attributeValue.Value = debugData.ReadString();
                        break;

                    case DwarfFormat.Strp:
                        attributeValue.Type  = DwarfAttributeValueType.String;
                        attributeValue.Value = debugStrings.ReadString(debugData.ReadOffset(is64bit));
                        break;

                    case DwarfFormat.Flag:
                        attributeValue.Type  = DwarfAttributeValueType.Flag;
                        attributeValue.Value = debugData.ReadByte() != 0;
                        break;

                    case DwarfFormat.FlagPresent:
                        attributeValue.Type  = DwarfAttributeValueType.Flag;
                        attributeValue.Value = true;
                        break;

                    case DwarfFormat.Ref1:
                        attributeValue.Type  = DwarfAttributeValueType.Reference;
                        attributeValue.Value = (ulong)debugData.ReadByte() + (ulong)beginPosition;
                        break;

                    case DwarfFormat.Ref2:
                        attributeValue.Type  = DwarfAttributeValueType.Reference;
                        attributeValue.Value = (ulong)debugData.ReadUshort() + (ulong)beginPosition;
                        break;

                    case DwarfFormat.Ref4:
                        attributeValue.Type  = DwarfAttributeValueType.Reference;
                        attributeValue.Value = (ulong)debugData.ReadUint() + (ulong)beginPosition;
                        break;

                    case DwarfFormat.Ref8:
                        attributeValue.Type  = DwarfAttributeValueType.Reference;
                        attributeValue.Value = (ulong)debugData.ReadUlong() + (ulong)beginPosition;
                        break;

                    case DwarfFormat.RefUData:
                        attributeValue.Type  = DwarfAttributeValueType.Reference;
                        attributeValue.Value = (ulong)debugData.LEB128() + (ulong)beginPosition;
                        break;

                    case DwarfFormat.RefAddr:
                        attributeValue.Type  = DwarfAttributeValueType.Reference;
                        attributeValue.Value = (ulong)debugData.ReadOffset(is64bit);
                        break;

                    case DwarfFormat.RefSig8:
                        attributeValue.Type = DwarfAttributeValueType.Invalid;
                        debugData.Position += 8;
                        break;

                    case DwarfFormat.ExpressionLocation:
                        attributeValue.Type  = DwarfAttributeValueType.ExpressionLocation;
                        attributeValue.Value = debugData.ReadBlock(debugData.LEB128());
                        break;

                    case DwarfFormat.SecOffset:
                        attributeValue.Type  = DwarfAttributeValueType.SecOffset;
                        attributeValue.Value = (ulong)debugData.ReadOffset(is64bit);
                        break;

                    default:
                        throw new Exception($"Unsupported DwarfFormat: {format}");
                    }

                    if (attributes.ContainsKey(attribute))
                    {
                        if (attributes[attribute] != attributeValue)
                        {
                            attributes[attribute] = attributeValue;
                        }
                    }
                    else
                    {
                        attributes.Add(attribute, attributeValue);
                    }
                }

                DwarfSymbol symbol = new DwarfSymbol()
                {
                    Tag        = description.Tag,
                    Attributes = attributes,
                    Offset     = dataPosition,
                };

                symbolsByOffset.Add(symbol.Offset, symbol);

                if (parents.Count > 0)
                {
                    parents.Peek().Children.Add(symbol);
                    symbol.Parent = parents.Peek();
                }
                else
                {
                    symbols.Add(symbol);
                }

                if (description.HasChildren)
                {
                    symbol.Children = new List <DwarfSymbol>();
                    parents.Push(symbol);
                }
            }

            SymbolsTree = symbols.ToArray();

            if (SymbolsTree.Length > 0)
            {
                // Add void type symbol
                DwarfSymbol voidSymbol = new DwarfSymbol()
                {
                    Tag        = DwarfTag.BaseType,
                    Offset     = -1,
                    Parent     = SymbolsTree[0],
                    Attributes = new Dictionary <DwarfAttribute, DwarfAttributeValue>()
                    {
                        { DwarfAttribute.Name, new DwarfAttributeValue()
                          {
                              Type = DwarfAttributeValueType.String, Value = "void"
                          } },
                        { DwarfAttribute.ByteSize, new DwarfAttributeValue()
                          {
                              Type = DwarfAttributeValueType.Constant, Value = (ulong)0
                          } },
                    },
                };
                if (SymbolsTree[0].Children == null)
                {
                    SymbolsTree[0].Children = new List <DwarfSymbol>();
                }
                SymbolsTree[0].Children.Insert(0, voidSymbol);
                symbolsByOffset.Add(voidSymbol.Offset, voidSymbol);

                // Post process all symbols
                foreach (DwarfSymbol symbol in Symbols)
                {
                    Dictionary <DwarfAttribute, DwarfAttributeValue> attributes = symbol.Attributes as Dictionary <DwarfAttribute, DwarfAttributeValue>;

                    foreach (DwarfAttributeValue value in attributes.Values)
                    {
                        if (value.Type == DwarfAttributeValueType.Reference)
                        {
                            DwarfSymbol reference;

                            if (symbolsByOffset.TryGetValue((int)value.Address, out reference))
                            {
                                value.Type  = DwarfAttributeValueType.ResolvedReference;
                                value.Value = reference;
                            }
                        }
                        else if (value.Type == DwarfAttributeValueType.Address)
                        {
                            value.Value = addressNormalizer(value.Address);
                        }
                    }

                    if ((symbol.Tag == DwarfTag.PointerType && !attributes.ContainsKey(DwarfAttribute.Type)) ||
                        (symbol.Tag == DwarfTag.Typedef && !attributes.ContainsKey(DwarfAttribute.Type)))
                    {
                        attributes.Add(DwarfAttribute.Type, new DwarfAttributeValue()
                        {
                            Type  = DwarfAttributeValueType.ResolvedReference,
                            Value = voidSymbol,
                        });
                    }
                }

                // Merge specifications
                foreach (DwarfSymbol symbol in Symbols)
                {
                    Dictionary <DwarfAttribute, DwarfAttributeValue> attributes = symbol.Attributes as Dictionary <DwarfAttribute, DwarfAttributeValue>;
                    DwarfAttributeValue specificationValue;

                    if (attributes.TryGetValue(DwarfAttribute.Specification, out specificationValue) && specificationValue.Type == DwarfAttributeValueType.ResolvedReference)
                    {
                        DwarfSymbol reference = specificationValue.Reference;
                        Dictionary <DwarfAttribute, DwarfAttributeValue> referenceAttributes = reference.Attributes as Dictionary <DwarfAttribute, DwarfAttributeValue>;

                        foreach (KeyValuePair <DwarfAttribute, DwarfAttributeValue> kvp in attributes)
                        {
                            if (kvp.Key != DwarfAttribute.Specification)
                            {
                                referenceAttributes[kvp.Key] = kvp.Value;
                            }
                        }
                    }
                }
            }
        }
Пример #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DwarfLineNumberProgram"/> class.
 /// </summary>
 /// <param name="debugLine">The debug line data stream.</param>
 /// <param name="addressNormalizer">Normalize address delegate (<see cref="NormalizeAddressDelegate"/>)</param>
 public DwarfLineNumberProgram(DwarfMemoryReader debugLine, NormalizeAddressDelegate addressNormalizer)
 {
     Files = ReadData(debugLine, addressNormalizer);
 }
Пример #16
0
        /// <summary>
        /// Reads the data for single instance.
        /// </summary>
        /// <param name="debugLine">The debug line data stream.</param>
        /// <param name="addressNormalizer">Normalize address delegate (<see cref="NormalizeAddressDelegate"/>)</param>
        /// <returns>List of file information.</returns>
        private static List <DwarfFileInformation> ReadData(DwarfMemoryReader debugLine, NormalizeAddressDelegate addressNormalizer)
        {
            // Read header
            bool   is64bit;
            int    beginPosition            = debugLine.Position;
            ulong  length                   = debugLine.ReadLength(out is64bit);
            int    endPosition              = debugLine.Position + (int)length;
            ushort version                  = debugLine.ReadUshort();
            int    headerLength             = debugLine.ReadOffset(is64bit);
            byte   minimumInstructionLength = debugLine.ReadByte();
            bool   defaultIsStatement       = debugLine.ReadByte() != 0;
            sbyte  lineBase                 = (sbyte)debugLine.ReadByte();
            byte   lineRange                = debugLine.ReadByte();
            byte   operationCodeBase        = debugLine.ReadByte();

            // Read operation code lengths
            uint[] operationCodeLengths = new uint[operationCodeBase];

            operationCodeLengths[0] = 0;
            for (int i = 1; i < operationCodeLengths.Length && debugLine.Position < endPosition; i++)
            {
                operationCodeLengths[i] = debugLine.LEB128();
            }

            // Read directories
            List <string> directories = new List <string>();

            while (debugLine.Position < endPosition && debugLine.Peek() != 0)
            {
                string directory = debugLine.ReadString();

                directory = directory.Replace('/', Path.DirectorySeparatorChar);
                directories.Add(directory);
            }
            debugLine.ReadByte(); // Skip zero termination byte

            // Read files
            List <DwarfFileInformation> files = new List <DwarfFileInformation>();

            while (debugLine.Position < endPosition && debugLine.Peek() != 0)
            {
                files.Add(ReadFile(debugLine, directories));
            }
            debugLine.ReadByte(); // Skip zero termination byte

            // Parse lines
            ParsingState state       = new ParsingState(files.FirstOrDefault(), defaultIsStatement, minimumInstructionLength);
            uint         lastAddress = 0;

            while (debugLine.Position < endPosition)
            {
                byte operationCode = debugLine.ReadByte();

                if (operationCode >= operationCodeLengths.Length)
                {
                    // Special operation code
                    int adjustedOperationCode = operationCode - operationCodeBase;
                    int operationAdvance      = adjustedOperationCode / lineRange;
                    state.AdvanceAddress(operationAdvance);
                    int lineAdvance = lineBase + (adjustedOperationCode % lineRange);
                    state.Line += (uint)lineAdvance;
                    state.AddCurrentLineInfo();
                    state.IsBasicBlock  = false;
                    state.IsPrologueEnd = false;
                    state.IsEpilogueEnd = false;
                    state.Discriminator = 0;
                }
                else
                {
                    switch ((DwarfLineNumberStandardOpcode)operationCode)
                    {
                    case DwarfLineNumberStandardOpcode.Extended:
                    {
                        uint extendedLength = debugLine.LEB128();
                        int  newPosition    = debugLine.Position + (int)extendedLength;
                        DwarfLineNumberExtendedOpcode extendedCode = (DwarfLineNumberExtendedOpcode)debugLine.ReadByte();

                        switch (extendedCode)
                        {
                        case DwarfLineNumberExtendedOpcode.EndSequence:
                            lastAddress         = state.Address;
                            state.IsSequenceEnd = true;
                            state.AddCurrentLineInfo();
                            state.Reset(files.FirstOrDefault());
                            break;

                        case DwarfLineNumberExtendedOpcode.SetAddress:
                        {
                            state.Address = debugLine.ReadUint();
                            if (state.Address == 0)
                            {
                                state.Address = lastAddress;
                            }
                            state.OperationIndex = 0;
                        }
                        break;

                        case DwarfLineNumberExtendedOpcode.DefineFile:
                            state.File = ReadFile(debugLine, directories);
                            files.Add(state.File);
                            break;

                        case DwarfLineNumberExtendedOpcode.SetDiscriminator:
                            state.Discriminator = debugLine.LEB128();
                            break;

                        default:
                            throw new Exception($"Unsupported DwarfLineNumberExtendedOpcode: {extendedCode}");
                        }
                        debugLine.Position = newPosition;
                    }
                    break;

                    case DwarfLineNumberStandardOpcode.Copy:
                        state.AddCurrentLineInfo();
                        state.IsBasicBlock  = false;
                        state.IsPrologueEnd = false;
                        state.IsEpilogueEnd = false;
                        state.Discriminator = 0;
                        break;

                    case DwarfLineNumberStandardOpcode.AdvancePc:
                        state.AdvanceAddress((int)debugLine.LEB128());
                        break;

                    case DwarfLineNumberStandardOpcode.AdvanceLine:
                        state.Line += debugLine.SLEB128();
                        break;

                    case DwarfLineNumberStandardOpcode.SetFile:
                        state.File = files[(int)debugLine.LEB128() - 1];
                        break;

                    case DwarfLineNumberStandardOpcode.SetColumn:
                        state.Column = debugLine.LEB128();
                        break;

                    case DwarfLineNumberStandardOpcode.NegateStmt:
                        state.IsStatement = !state.IsStatement;
                        break;

                    case DwarfLineNumberStandardOpcode.SetBasicBlock:
                        state.IsBasicBlock = true;
                        break;

                    case DwarfLineNumberStandardOpcode.ConstAddPc:
                        state.AdvanceAddress((255 - operationCodeBase) / lineRange);
                        break;

                    case DwarfLineNumberStandardOpcode.FixedAdvancePc:
                        state.Address       += debugLine.ReadUshort();
                        state.OperationIndex = 0;
                        break;

                    case DwarfLineNumberStandardOpcode.SetPrologueEnd:
                        state.IsPrologueEnd = true;
                        break;

                    case DwarfLineNumberStandardOpcode.SetEpilogueBegin:
                        state.IsEpilogueEnd = true;
                        break;

                    case DwarfLineNumberStandardOpcode.SetIsa:
                        state.Isa = debugLine.LEB128();
                        break;

                    default:
                        throw new Exception($"Unsupported DwarfLineNumberStandardOpcode: {(DwarfLineNumberStandardOpcode)operationCode}");
                    }
                }
            }

            // Fix lines in files...
            foreach (DwarfFileInformation file in files)
            {
                for (int i = 0; i < file.Lines.Count; i++)
                {
                    file.Lines[i].Address = (uint)addressNormalizer(file.Lines[i].Address);
                }
            }
            return(files);
        }
Пример #17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ElfCoreDump"/> class.
        /// </summary>
        /// <param name="coreDumpPath">The core dump path.</param>
        public ElfCoreDump(string coreDumpPath)
        {
            elf = ELFReader.Load <ulong>(coreDumpPath);
            if (elf.Type != FileType.Core)
            {
                throw new Exception($"Expected core dump, but got: {elf.Type}");
            }
            switch (elf.Machine)
            {
            case Machine.Intel386:
                instance = new Intel386Instance(elf);
                break;

            case Machine.AMD64:
                instance = new AMD64Instance(elf);
                break;

            default:
                throw new Exception($"Unsupported machine type: {elf.Machine}");
            }
            Path = coreDumpPath;

            foreach (var segment in elf.Segments)
            {
                if (segment.Type == SegmentType.Note)
                {
                    using (DwarfMemoryReader reader = new DwarfMemoryReader(ReadSegment(segment)))
                    {
                        int noteStructSize = Marshal.SizeOf <elf_32note>();

                        while (reader.Position + noteStructSize < reader.Data.Length)
                        {
                            // Read note
                            elf_32note note    = reader.ReadStructure <elf_32note>();
                            int        nameEnd = reader.Position + (int)note.NameSize;

                            // Check if note is available to be read
                            if (nameEnd + note.n_descsz > reader.Data.Length)
                            {
                                break;
                            }

                            // Read name and content
                            string name = reader.ReadString();
                            reader.Position = nameEnd;
                            byte[] content = reader.ReadBlock(note.n_descsz);

                            instance.ProcessNote(name, content, note.n_type);
                            if (note.n_type == elf_note_type.File)
                            {
                                using (DwarfMemoryReader data = new DwarfMemoryReader(content))
                                {
                                    files = elf_note_file.Parse(data, Is64bit);
                                }
                            }
                            else if (note.n_type == elf_note_type.Auxv)
                            {
                                using (DwarfMemoryReader data = new DwarfMemoryReader(content))
                                {
                                    uint addressSize = elf.Class == Class.Bit32 ? 4U : 8U;

                                    while (!data.IsEnd)
                                    {
                                        AuxvEntry entry = new AuxvEntry
                                        {
                                            Type  = (AuxvEntryType)data.ReadUlong(addressSize),
                                            Value = data.ReadUlong(addressSize)
                                        };

                                        if (entry.Type == AuxvEntryType.Null)
                                        {
                                            break;
                                        }

                                        if (entry.Type == AuxvEntryType.Ignore)
                                        {
                                            continue;
                                        }

                                        auxVector.Add(entry);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            DumpFileMemoryReader = new CoreDumpReader(coreDumpPath, elf.Segments.Where(s => s.Type == SegmentType.Load));
        }
        /// <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);
        }
Пример #19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DataDescriptionReader"/> class.
 /// </summary>
 /// <param name="debugDataDescription">The debug data description.</param>
 /// <param name="startingPosition">The starting position.</param>
 public DataDescriptionReader(DwarfMemoryReader debugDataDescription, int startingPosition)
 {
     readDescriptions          = new Dictionary <uint, DataDescription>();
     lastReadPosition          = startingPosition;
     this.debugDataDescription = debugDataDescription;
 }
 /// <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);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DwarfCommonInformationEntry"/> class.
 /// </summary>
 /// <param name="data">The data memory reader.</param>
 /// <param name="defaultAddressSize">Default size of the address.</param>
 /// <param name="endPosition">The end position in the memory stream.</param>
 private DwarfCommonInformationEntry(DwarfMemoryReader data, byte defaultAddressSize, int endPosition)
 {
     ParseData(data, defaultAddressSize, endPosition);
 }
Пример #22
0
        /// <summary>
        /// Parses the specified data.
        /// </summary>
        /// <param name="data">The PE image data.</param>
        private void ParseData(byte[] data)
        {
            using (DwarfMemoryReader reader = new DwarfMemoryReader(data))
            {
                dosHeader = reader.ReadStructure <IMAGE_DOS_HEADER>();
                if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE)
                {
                    throw new ArgumentException($"Invalid IMAGE_DOS_HEADER magic constant. Expected: 0x{IMAGE_DOS_SIGNATURE:X}, Got: 0x{dosHeader.e_magic:X}");
                }

                reader.Position = (int)dosHeader.e_lfanew;
                ntHeaders32     = reader.ReadStructure <IMAGE_NT_HEADERS32>();
                if (ntHeaders32.Signature != IMAGE_NT_SIGNATURE)
                {
                    throw new ArgumentException($"Invalid optional header signature. Expected: 0x{IMAGE_NT_SIGNATURE:X}, Got: 0x{ntHeaders32.Signature:X}");
                }
                if (ntHeaders32.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ||
                    ntHeaders32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64)
                {
                    reader.Position   = (int)dosHeader.e_lfanew;
                    ntHeaders64       = reader.ReadStructure <IMAGE_NT_HEADERS64>();
                    Is64bit           = true;
                    fileHeader        = ntHeaders64.FileHeader;
                    reader.Position  += ntHeaders64.FileHeader.SizeOfOptionalHeader - Marshal.SizeOf <IMAGE_OPTIONAL_HEADER64>();
                    CodeSegmentOffset = ntHeaders64.OptionalHeader.ImageBase;
                }
                else
                {
                    Is64bit           = false;
                    fileHeader        = ntHeaders32.FileHeader;
                    reader.Position  += ntHeaders32.FileHeader.SizeOfOptionalHeader - Marshal.SizeOf <IMAGE_OPTIONAL_HEADER32>();
                    CodeSegmentOffset = ntHeaders32.OptionalHeader.ImageBase;
                }

                // Load image section headers
                uint stringTablePosition = fileHeader.PointerToSymbolTable + fileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL;

                imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
                for (int section = 0; section < imageSectionHeaders.Length; section++)
                {
                    IMAGE_SECTION_HEADER imageSectionHeader = reader.ReadStructure <IMAGE_SECTION_HEADER>();
                    imageSectionHeaders[section] = imageSectionHeader;
                    string name = imageSectionHeader.Section;
                    if (imageSectionHeader.Name[0] == '/')
                    {
                        uint position = stringTablePosition + uint.Parse(imageSectionHeader.Section.Substring(1));

                        name = reader.ReadString((int)position);
                    }

                    switch (name)
                    {
                    case ".debug_info":
                        DebugData = reader.ReadBlock(imageSectionHeader.SizeInImage, (int)imageSectionHeader.PointerToRawData);
                        break;

                    case ".debug_abbrev":
                        DebugDataDescription = reader.ReadBlock(imageSectionHeader.SizeInImage, (int)imageSectionHeader.PointerToRawData);
                        break;

                    case ".debug_line":
                        DebugLine = reader.ReadBlock(imageSectionHeader.SizeInImage, (int)imageSectionHeader.PointerToRawData);
                        break;

                    case ".debug_frame":
                        DebugFrame = reader.ReadBlock(imageSectionHeader.SizeInImage, (int)imageSectionHeader.PointerToRawData);
                        break;

                    case ".debug_str":
                        DebugDataStrings = reader.ReadBlock(imageSectionHeader.SizeInImage, (int)imageSectionHeader.PointerToRawData);
                        break;

                    case ".eh_frame":
                        EhFrame        = reader.ReadBlock(imageSectionHeader.SizeInImage, (int)imageSectionHeader.PointerToRawData);
                        EhFrameAddress = imageSectionHeader.PointerToRawData + CodeSegmentOffset;
                        break;

                    case ".data":
                        DataSectionAddress = imageSectionHeader.PointerToRawData + CodeSegmentOffset;
                        break;

                    case ".text":
                        TextSectionAddress = imageSectionHeader.PointerToRawData + CodeSegmentOffset;
                        break;
                    }
                }

                // Load image symbols
                List <PublicSymbol> publicSymbols = new List <PublicSymbol>();
                byte toSkip = 0;

                reader.Position = (int)fileHeader.PointerToSymbolTable;
                for (uint i = 0; i < fileHeader.NumberOfSymbols; i++)
                {
                    int          position = reader.Position;
                    IMAGE_SYMBOL symbol   = reader.ReadStructure <IMAGE_SYMBOL>();

                    if (toSkip == 0)
                    {
                        string name = symbol.SymbolName;

                        if (string.IsNullOrEmpty(name))
                        {
                            int stringPosition = (int)reader.ReadUint(position);
                            stringPosition = (int)reader.ReadUint(position + 4);

                            name = reader.ReadString((int)stringTablePosition + stringPosition);
                        }


                        if (symbol.SectionNumber > 0 && symbol.SectionNumber <= imageSectionHeaders.Length)
                        {
                            uint sectionAddress = imageSectionHeaders[symbol.SectionNumber - 1].VirtualAddress;
                            sectionAddress += symbol.Value;

                            publicSymbols.Add(new PublicSymbol(name, sectionAddress));
                        }

                        toSkip = symbol.NumberOfAuxSymbols;
                    }
                    else
                    {
                        toSkip--;
                    }
                }
                PublicSymbols = publicSymbols;
            }
        }
Пример #23
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DwarfCompilationUnit"/> class.
 /// </summary>
 /// <param name="debugData">The debug data stream.</param>
 /// <param name="debugDataDescription">The debug data description stream.</param>
 /// <param name="debugStrings">The debug strings.</param>
 /// <param name="addressNormalizer">Normalize address delegate (<see cref="NormalizeAddressDelegate"/>)</param>
 public DwarfCompilationUnit(DwarfMemoryReader debugData, DwarfMemoryReader debugDataDescription, DwarfMemoryReader debugStrings, NormalizeAddressDelegate addressNormalizer)
 {
     ReadData(debugData, debugDataDescription, debugStrings, addressNormalizer);
 }