Skip to content

Commit 18ba926

Browse files
Fixed crash when reading DWARF V2.
Fix _mapKeyToItem when on duplicate key exist. Remove _items list. It is useless with __mapItems.Values. Rename _mapItems to _mapUlongToItems. Add TryFindByKey to be symmetric with TryFindByCode. Good reason to keep mapKeyToItem.
1 parent 09365c1 commit 18ba926

1 file changed

Lines changed: 35 additions & 117 deletions

File tree

src/LibObjectFile/Dwarf/DwarfAbbreviation.cs

Lines changed: 35 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -6,77 +6,53 @@
66
using System.Collections.Generic;
77
using System.Diagnostics;
88
using System.Diagnostics.CodeAnalysis;
9+
using System.Linq;
910
using LibObjectFile.Diagnostics;
1011

1112
namespace LibObjectFile.Dwarf;
1213

1314
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
1415
public sealed class DwarfAbbreviation : DwarfObject<DwarfAbbreviationTable>
1516
{
16-
private readonly List<DwarfAbbreviationItem> _items;
17-
private readonly Dictionary<ulong, DwarfAbbreviationItem> _mapItems; // Only used if code are non contiguous
17+
private readonly Dictionary<ulong, DwarfAbbreviationItem> _mapUlongToItems;
18+
1819
private readonly Dictionary<DwarfAbbreviationItemKey, DwarfAbbreviationItem> _mapKeyToItem;
1920
private ulong _nextCode;
2021

2122
public DwarfAbbreviation()
2223
{
23-
_items = new List<DwarfAbbreviationItem>();
24-
_mapItems = new Dictionary<ulong, DwarfAbbreviationItem>();
24+
_mapUlongToItems = new Dictionary<ulong, DwarfAbbreviationItem>();
2525
_mapKeyToItem = new Dictionary<DwarfAbbreviationItemKey, DwarfAbbreviationItem>();
2626
_nextCode = 1;
2727
}
2828

2929
public void Reset()
3030
{
3131
// Reset parent dependency
32-
foreach (var dwarfAbbreviationItem in _items)
33-
{
34-
dwarfAbbreviationItem.Parent = null;
35-
}
36-
37-
if (_mapItems.Count > 0)
32+
foreach (var keyPair in _mapUlongToItems.Values)
3833
{
39-
foreach (var keyPair in _mapItems)
40-
{
41-
keyPair.Value.Parent = null;
42-
}
34+
keyPair.Parent = null;
4335
}
44-
45-
_items.Clear();
46-
_mapItems.Clear();
36+
_mapUlongToItems.Clear();
4737
_mapKeyToItem.Clear();
4838
_nextCode = 1;
4939
}
5040

51-
public IEnumerable<DwarfAbbreviationItem> Items => _mapItems.Count > 0 ? GetMapItems() : _items;
41+
public IEnumerable<DwarfAbbreviationItem> Items => _mapUlongToItems.Values;
5242

53-
private IEnumerable<DwarfAbbreviationItem> GetMapItems()
54-
{
55-
foreach (var item in _mapItems.Values)
56-
{
57-
yield return item;
58-
}
59-
}
60-
6143
public DwarfAbbreviationItem GetOrCreate(DwarfAbbreviationItemKey itemKey)
6244
{
63-
if (!_mapKeyToItem.TryGetValue(itemKey, out var item))
45+
if (!TryFindByKey(itemKey, out var item))
6446
{
6547
item = new DwarfAbbreviationItem(_nextCode, itemKey.Tag, itemKey.HasChildren, itemKey.Descriptors)
6648
{
6749
Parent = this
6850
};
6951

70-
if (_mapItems.Count > 0)
71-
{
72-
73-
_mapItems[_nextCode] = item;
74-
}
75-
else
76-
{
77-
_items.Add(item);
78-
}
52+
// insert or update new item
53+
_mapUlongToItems[_nextCode] = item;
7954

55+
// not found insert new item
8056
_mapKeyToItem[itemKey] = item;
8157

8258
_nextCode++;
@@ -93,24 +69,16 @@ public bool TryFindByCode(ulong code, [NotNullWhen(true)] out DwarfAbbreviationI
9369
return false;
9470
}
9571

96-
code--;
97-
98-
if (_mapItems.Count > 0)
99-
{
100-
return _mapItems.TryGetValue(code, out item);
101-
}
102-
103-
if (code < int.MaxValue && (int)code < _items.Count)
104-
{
105-
item = _items[(int) code];
106-
return true;
107-
}
72+
return _mapUlongToItems.TryGetValue(code, out item);
73+
}
10874

75+
public bool TryFindByKey(DwarfAbbreviationItemKey key, [NotNullWhen(true)] out DwarfAbbreviationItem? item)
76+
{
10977
item = null;
110-
return false;
78+
return _mapKeyToItem.TryGetValue(key, out item);
11179
}
11280

113-
private string DebuggerDisplay => $"Count = {(_mapItems.Count > 0 ? _mapItems.Count : _items.Count)}";
81+
private string DebuggerDisplay => $"Count = {_mapUlongToItems.Count}";
11482

11583
private bool TryReadNext(DwarfReader reader)
11684
{
@@ -123,45 +91,27 @@ private bool TryReadNext(DwarfReader reader)
12391

12492
var item = new DwarfAbbreviationItem
12593
{
126-
Position = startOffset,
94+
Position = startOffset,
12795
Code = code
12896
};
12997

130-
var index = code - 1;
131-
bool canAddToList = _mapItems.Count == 0 && index < int.MaxValue && _items.Count == (int)index;
132-
13398
item.Read(reader);
13499

135-
if (canAddToList)
100+
if (_mapUlongToItems.ContainsKey(code))
136101
{
137-
_items.Add(item);
138-
_nextCode++;
102+
reader.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"Invalid code {code} found while another code already exists in this abbreviation.");
103+
return false;
139104
}
140-
else
141-
{
142-
if (_mapItems.Count == 0)
143-
{
144-
for (var i = 0; i < _items.Count; i++)
145-
{
146-
var previousItem = _items[i];
147-
_mapItems.Add((ulong)i + 1, previousItem);
148-
}
149-
_items.Clear();
150-
}
151-
152-
// TODO: check collisions
153-
if (_mapItems.ContainsKey(code))
154-
{
155-
reader.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"Invalid code {code} found while another code already exists in this abbreviation.");
156-
return false;
157-
}
158-
_mapItems.Add(code, item);
159105

160-
_nextCode = Math.Max(code, _nextCode) + 1;
161-
}
106+
_mapUlongToItems.Add(code, item);
107+
_nextCode = Math.Max(code, _nextCode) + 1;
162108

163109
var key = new DwarfAbbreviationItemKey(item.Tag, item.HasChildren, item.Descriptors);
164-
_mapKeyToItem.Add(key, item);
110+
111+
if (!_mapKeyToItem.ContainsKey(key))
112+
{
113+
_mapKeyToItem.Add(key, item);
114+
}
165115

166116
return true;
167117
}
@@ -180,24 +130,9 @@ public override void Write(DwarfWriter writer)
180130
{
181131
var startOffset = writer.Position;
182132
Debug.Assert(startOffset == Position);
183-
if (_mapItems.Count > 0)
133+
foreach (var item in _mapUlongToItems.Values)
184134
{
185-
foreach (var itemPair in _mapItems)
186-
{
187-
var item = itemPair.Value;
188-
item.Write(writer);
189-
}
190-
191-
}
192-
else
193-
{
194-
if (_items.Count > 0)
195-
{
196-
foreach (var item in _items)
197-
{
198-
item.Write(writer);
199-
}
200-
}
135+
item.Write(writer);
201136
}
202137

203138
// End of abbreviation item
@@ -210,28 +145,11 @@ protected override void UpdateLayoutCore(DwarfLayoutContext context)
210145
{
211146
var endOffset = Position;
212147

213-
if (_mapItems.Count > 0)
148+
foreach (var item in _mapUlongToItems.Values)
214149
{
215-
foreach (var itemPair in _mapItems)
216-
{
217-
var item = itemPair.Value;
218-
item.Position = endOffset;
219-
item.UpdateLayout(context);
220-
endOffset += item.Size;
221-
}
222-
223-
}
224-
else
225-
{
226-
if (_items.Count > 0)
227-
{
228-
foreach (var item in _items)
229-
{
230-
item.Position = endOffset;
231-
item.UpdateLayout(context);
232-
endOffset += item.Size;
233-
}
234-
}
150+
item.Position = endOffset;
151+
item.UpdateLayout(context);
152+
endOffset += item.Size;
235153
}
236154

237155
endOffset += DwarfHelper.SizeOfULEB128(0);

0 commit comments

Comments
 (0)