Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/LibObjectFile.CodeGen/dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
17 changes: 16 additions & 1 deletion src/LibObjectFile.Tests/Dwarf/DwarfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ namespace LibObjectFile.Tests.Dwarf;
[TestClass]
public class DwarfTests : ElfTestBase
{
[TestMethod]
public void ReadDwarf_version2_should_be_successfull()
{
const string ResourceName = @".\TestFiles\TestDwarf2.elf";
Comment thread
xoofx marked this conversation as resolved.
Outdated

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)]
Expand Down Expand Up @@ -301,7 +316,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);
Expand Down
6 changes: 6 additions & 0 deletions src/LibObjectFile.Tests/Elf/ElfTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/LibObjectFile.Tests/LibObjectFile.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,10 @@
<Folder Include="Verified\" />
</ItemGroup>

<ItemGroup>
<None Update=".\src\LibObjectFile.Tests\TestFiles\TestDwarf2.elf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Binary file added src/LibObjectFile.Tests/TestFiles/TestDwarf2.elf
Binary file not shown.
152 changes: 35 additions & 117 deletions src/LibObjectFile/Dwarf/DwarfAbbreviation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,53 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using LibObjectFile.Diagnostics;

namespace LibObjectFile.Dwarf;

[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
public sealed class DwarfAbbreviation : DwarfObject<DwarfAbbreviationTable>
{
private readonly List<DwarfAbbreviationItem> _items;
private readonly Dictionary<ulong, DwarfAbbreviationItem> _mapItems; // Only used if code are non contiguous
private readonly Dictionary<ulong, DwarfAbbreviationItem> _mapUlongToItems;

private readonly Dictionary<DwarfAbbreviationItemKey, DwarfAbbreviationItem> _mapKeyToItem;
private ulong _nextCode;

public DwarfAbbreviation()
{
_items = new List<DwarfAbbreviationItem>();
_mapItems = new Dictionary<ulong, DwarfAbbreviationItem>();
_mapUlongToItems = new Dictionary<ulong, DwarfAbbreviationItem>();
_mapKeyToItem = new Dictionary<DwarfAbbreviationItemKey, DwarfAbbreviationItem>();
_nextCode = 1;
}

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<DwarfAbbreviationItem> Items => _mapItems.Count > 0 ? GetMapItems() : _items;
public IEnumerable<DwarfAbbreviationItem> Items => _mapUlongToItems.Values;

private IEnumerable<DwarfAbbreviationItem> 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++;
Expand All @@ -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)
{
Expand All @@ -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;
}
Expand All @@ -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
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/LibObjectFile/Dwarf/DwarfUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
22 changes: 17 additions & 5 deletions src/LibObjectFile/generated/LibObjectFile.Dwarf.generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ public static unsafe partial class DwarfNative
public const ushort DW_AT_byte_stride = 81;

/// <summary>
/// DWARF3 (do not use)
/// DWARF2 (do not use)
/// </summary>
public const ushort DW_AT_stride = 81;

Expand Down Expand Up @@ -4183,9 +4183,15 @@ public enum DwarfAttributeKind : ushort
ReturnAddr = DwarfNative.DW_AT_return_addr,

StartScope = DwarfNative.DW_AT_start_scope,


/// <summary>
/// DWARF3 name
/// </summary>
BitStride = DwarfNative.DW_AT_bit_stride,


/// <summary>
/// DWARF2 name
/// </summary>
StrideSize = DwarfNative.DW_AT_stride_size,

UpperBound = DwarfNative.DW_AT_upper_bound,
Expand Down Expand Up @@ -4253,9 +4259,15 @@ public enum DwarfAttributeKind : ushort
Associated = DwarfNative.DW_AT_associated,

DataLocation = DwarfNative.DW_AT_data_location,


/// <summary>
/// DWARF3f
/// </summary>
ByteStride = DwarfNative.DW_AT_byte_stride,


/// <summary>
/// DWARF2
/// </summary>
Stride = DwarfNative.DW_AT_stride,

EntryPC = DwarfNative.DW_AT_entry_pc,
Expand Down
Loading