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