diff --git a/src/LibObjectFile.CodeGen/dwarf.h b/src/LibObjectFile.CodeGen/dwarf.h index 3090c55..0a23ad0 100644 --- a/src/LibObjectFile.CodeGen/dwarf.h +++ b/src/LibObjectFile.CodeGen/dwarf.h @@ -338,7 +338,7 @@ extern "C" { #define DW_AT_associated 0x4f /* DWARF3 */ #define DW_AT_data_location 0x50 /* DWARF3 */ #define DW_AT_byte_stride 0x51 /* DWARF3f */ -#define DW_AT_stride 0x51 /* DWARF3 (do not use) */ +#define DW_AT_stride 0x51 /* DWARF2 (do not use) */ #define DW_AT_entry_pc 0x52 /* DWARF3 */ #define DW_AT_use_UTF8 0x53 /* DWARF3 */ #define DW_AT_extension 0x54 /* DWARF3 */ diff --git a/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs b/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs index ecdfccc..30624ac 100644 --- a/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs +++ b/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs @@ -15,6 +15,20 @@ namespace LibObjectFile.Tests.Dwarf; public class DwarfTests : ElfTestBase { [TestMethod] + public void ReadDwarf_version2_should_be_successfull() + { + string ResourceName = Path.Combine(AppContext.BaseDirectory, "TestFiles", "TestDwarf2.elf"); + + ElfFile elf = OpenAndLoadElf(ResourceName); + var elfContext = new DwarfElfContext(elf); + var inputContext = new DwarfReaderContext(elfContext); + inputContext.DebugLinePrinter = Console.Out; + var dwarf = DwarfFile.Read(inputContext); + + Assert.IsNotNull(dwarf); + } + + [DataTestMethod] [DataRow(0UL)] [DataRow(1UL)] [DataRow(50UL)] @@ -301,7 +315,7 @@ public void TestDebugInfoSmall() DebugAbbrevStream = new MemoryStream(), DebugLineStream = new MemoryStream(), DebugInfoStream = new MemoryStream(), - DebugStringStream = new MemoryStream(), + DebugStringStream = new MemoryStream(), DebugAddressRangeStream = new MemoryStream() }; dwarf.Write(outputContext); diff --git a/src/LibObjectFile.Tests/Elf/ElfTestBase.cs b/src/LibObjectFile.Tests/Elf/ElfTestBase.cs index 92f6c58..bf4b315 100644 --- a/src/LibObjectFile.Tests/Elf/ElfTestBase.cs +++ b/src/LibObjectFile.Tests/Elf/ElfTestBase.cs @@ -71,6 +71,12 @@ protected async Task LoadAndVerifyElf(string name) ByteArrayAssert.AreEqual(originalBinary, newBinary, "Invalid binary diff between write -> read -> write"); } + protected ElfFile OpenAndLoadElf(string absolutePath) + { + using var stream = File.OpenRead(absolutePath); + return ElfFile.Read(stream); + } + protected ElfFile LoadElf(string name) { var file = GetFile(name); diff --git a/src/LibObjectFile.Tests/LibObjectFile.Tests.csproj b/src/LibObjectFile.Tests/LibObjectFile.Tests.csproj index 671bc4d..77332fe 100644 --- a/src/LibObjectFile.Tests/LibObjectFile.Tests.csproj +++ b/src/LibObjectFile.Tests/LibObjectFile.Tests.csproj @@ -100,4 +100,10 @@ + + + PreserveNewest + + + diff --git a/src/LibObjectFile.Tests/TestFiles/TestDwarf2.elf b/src/LibObjectFile.Tests/TestFiles/TestDwarf2.elf new file mode 100644 index 0000000..e3a786f Binary files /dev/null and b/src/LibObjectFile.Tests/TestFiles/TestDwarf2.elf differ diff --git a/src/LibObjectFile/Dwarf/DwarfAbbreviation.cs b/src/LibObjectFile/Dwarf/DwarfAbbreviation.cs index 2996406..e5b6acb 100644 --- a/src/LibObjectFile/Dwarf/DwarfAbbreviation.cs +++ b/src/LibObjectFile/Dwarf/DwarfAbbreviation.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Linq; using LibObjectFile.Diagnostics; namespace LibObjectFile.Dwarf; @@ -13,15 +14,14 @@ namespace LibObjectFile.Dwarf; [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] public sealed class DwarfAbbreviation : DwarfObject { - private readonly List _items; - private readonly Dictionary _mapItems; // Only used if code are non contiguous + private readonly Dictionary _mapUlongToItems; + private readonly Dictionary _mapKeyToItem; private ulong _nextCode; public DwarfAbbreviation() { - _items = new List(); - _mapItems = new Dictionary(); + _mapUlongToItems = new Dictionary(); _mapKeyToItem = new Dictionary(); _nextCode = 1; } @@ -29,54 +29,30 @@ public DwarfAbbreviation() public void Reset() { // Reset parent dependency - foreach (var dwarfAbbreviationItem in _items) - { - dwarfAbbreviationItem.Parent = null; - } - - if (_mapItems.Count > 0) + foreach (var keyPair in _mapUlongToItems.Values) { - foreach (var keyPair in _mapItems) - { - keyPair.Value.Parent = null; - } + keyPair.Parent = null; } - - _items.Clear(); - _mapItems.Clear(); + _mapUlongToItems.Clear(); _mapKeyToItem.Clear(); _nextCode = 1; } - public IEnumerable Items => _mapItems.Count > 0 ? GetMapItems() : _items; + public IEnumerable Items => _mapUlongToItems.Values; - private IEnumerable GetMapItems() - { - foreach (var item in _mapItems.Values) - { - yield return item; - } - } - public DwarfAbbreviationItem GetOrCreate(DwarfAbbreviationItemKey itemKey) { - if (!_mapKeyToItem.TryGetValue(itemKey, out var item)) + if (!TryFindByKey(itemKey, out var item)) { item = new DwarfAbbreviationItem(_nextCode, itemKey.Tag, itemKey.HasChildren, itemKey.Descriptors) { Parent = this }; - if (_mapItems.Count > 0) - { - - _mapItems[_nextCode] = item; - } - else - { - _items.Add(item); - } + // insert or update new item + _mapUlongToItems[_nextCode] = item; + // not found insert new item _mapKeyToItem[itemKey] = item; _nextCode++; @@ -93,24 +69,16 @@ public bool TryFindByCode(ulong code, [NotNullWhen(true)] out DwarfAbbreviationI return false; } - code--; - - if (_mapItems.Count > 0) - { - return _mapItems.TryGetValue(code, out item); - } - - if (code < int.MaxValue && (int)code < _items.Count) - { - item = _items[(int) code]; - return true; - } + return _mapUlongToItems.TryGetValue(code, out item); + } + public bool TryFindByKey(DwarfAbbreviationItemKey key, [NotNullWhen(true)] out DwarfAbbreviationItem? item) + { item = null; - return false; + return _mapKeyToItem.TryGetValue(key, out item); } - private string DebuggerDisplay => $"Count = {(_mapItems.Count > 0 ? _mapItems.Count : _items.Count)}"; + private string DebuggerDisplay => $"Count = {_mapUlongToItems.Count}"; private bool TryReadNext(DwarfReader reader) { @@ -123,45 +91,27 @@ private bool TryReadNext(DwarfReader reader) var item = new DwarfAbbreviationItem { - Position = startOffset, + Position = startOffset, Code = code }; - var index = code - 1; - bool canAddToList = _mapItems.Count == 0 && index < int.MaxValue && _items.Count == (int)index; - item.Read(reader); - if (canAddToList) + if (_mapUlongToItems.ContainsKey(code)) { - _items.Add(item); - _nextCode++; + reader.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"Invalid code {code} found while another code already exists in this abbreviation."); + return false; } - else - { - if (_mapItems.Count == 0) - { - for (var i = 0; i < _items.Count; i++) - { - var previousItem = _items[i]; - _mapItems.Add((ulong)i + 1, previousItem); - } - _items.Clear(); - } - - // TODO: check collisions - if (_mapItems.ContainsKey(code)) - { - reader.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"Invalid code {code} found while another code already exists in this abbreviation."); - return false; - } - _mapItems.Add(code, item); - _nextCode = Math.Max(code, _nextCode) + 1; - } + _mapUlongToItems.Add(code, item); + _nextCode = Math.Max(code, _nextCode) + 1; var key = new DwarfAbbreviationItemKey(item.Tag, item.HasChildren, item.Descriptors); - _mapKeyToItem.Add(key, item); + + if (!_mapKeyToItem.ContainsKey(key)) + { + _mapKeyToItem.Add(key, item); + } return true; } @@ -180,24 +130,9 @@ public override void Write(DwarfWriter writer) { var startOffset = writer.Position; Debug.Assert(startOffset == Position); - if (_mapItems.Count > 0) + foreach (var item in _mapUlongToItems.Values) { - foreach (var itemPair in _mapItems) - { - var item = itemPair.Value; - item.Write(writer); - } - - } - else - { - if (_items.Count > 0) - { - foreach (var item in _items) - { - item.Write(writer); - } - } + item.Write(writer); } // End of abbreviation item @@ -210,28 +145,11 @@ protected override void UpdateLayoutCore(DwarfLayoutContext context) { var endOffset = Position; - if (_mapItems.Count > 0) + foreach (var item in _mapUlongToItems.Values) { - foreach (var itemPair in _mapItems) - { - var item = itemPair.Value; - item.Position = endOffset; - item.UpdateLayout(context); - endOffset += item.Size; - } - - } - else - { - if (_items.Count > 0) - { - foreach (var item in _items) - { - item.Position = endOffset; - item.UpdateLayout(context); - endOffset += item.Size; - } - } + item.Position = endOffset; + item.UpdateLayout(context); + endOffset += item.Size; } endOffset += DwarfHelper.SizeOfULEB128(0); diff --git a/src/LibObjectFile/Dwarf/DwarfUnit.cs b/src/LibObjectFile/Dwarf/DwarfUnit.cs index 102e284..9962da1 100644 --- a/src/LibObjectFile/Dwarf/DwarfUnit.cs +++ b/src/LibObjectFile/Dwarf/DwarfUnit.cs @@ -171,7 +171,7 @@ public override void Read(DwarfReader reader) DwarfUnitKindEx unitKind = reader.DefaultUnitKind; - if (version <= 2 || version > 5) + if (version < 2 || version > 5) { reader.Diagnostics.Error(DiagnosticId.DWARF_ERR_VersionNotSupported, $"Version {version} is not supported"); return null; diff --git a/src/LibObjectFile/generated/LibObjectFile.Dwarf.generated.cs b/src/LibObjectFile/generated/LibObjectFile.Dwarf.generated.cs index 5edce90..28e4c09 100644 --- a/src/LibObjectFile/generated/LibObjectFile.Dwarf.generated.cs +++ b/src/LibObjectFile/generated/LibObjectFile.Dwarf.generated.cs @@ -759,7 +759,7 @@ public static unsafe partial class DwarfNative public const ushort DW_AT_byte_stride = 81; /// - /// DWARF3 (do not use) + /// DWARF2 (do not use) /// public const ushort DW_AT_stride = 81; @@ -4183,9 +4183,15 @@ public enum DwarfAttributeKind : ushort ReturnAddr = DwarfNative.DW_AT_return_addr, StartScope = DwarfNative.DW_AT_start_scope, - + + /// + /// DWARF3 name + /// BitStride = DwarfNative.DW_AT_bit_stride, - + + /// + /// DWARF2 name + /// StrideSize = DwarfNative.DW_AT_stride_size, UpperBound = DwarfNative.DW_AT_upper_bound, @@ -4253,9 +4259,15 @@ public enum DwarfAttributeKind : ushort Associated = DwarfNative.DW_AT_associated, DataLocation = DwarfNative.DW_AT_data_location, - + + /// + /// DWARF3f + /// ByteStride = DwarfNative.DW_AT_byte_stride, - + + /// + /// DWARF2 + /// Stride = DwarfNative.DW_AT_stride, EntryPC = DwarfNative.DW_AT_entry_pc,