|
4 | 4 |
|
5 | 5 | using System; |
6 | 6 | using System.Collections.Generic; |
| 7 | +using System.Runtime.CompilerServices; |
| 8 | +using System.Runtime.InteropServices; |
7 | 9 | using LibObjectFile.Diagnostics; |
| 10 | +using LibObjectFile.IO; |
8 | 11 |
|
9 | 12 | namespace LibObjectFile.Elf; |
10 | 13 |
|
@@ -63,95 +66,77 @@ public override void Write(ElfWriter writer) |
63 | 66 | private unsafe void Read32(ElfReader reader) |
64 | 67 | { |
65 | 68 | var numberOfEntries = base.Size / base.TableEntrySize; |
66 | | - _entries.Capacity = (int)numberOfEntries; |
| 69 | + var entries = _entries; |
| 70 | + CollectionsMarshal.SetCount(entries, (int)numberOfEntries); |
| 71 | + var span = CollectionsMarshal.AsSpan(entries); |
| 72 | + |
67 | 73 | if (IsRelocationWithAddends) |
68 | 74 | { |
69 | | - for (ulong i = 0; i < numberOfEntries; i++) |
| 75 | + using var batch = new BatchDataReader<ElfNative.Elf32_Rela>(reader.Stream, (int)numberOfEntries); |
| 76 | + ref var entry = ref MemoryMarshal.GetReference(span); |
| 77 | + while (batch.HasNext()) |
70 | 78 | { |
71 | | - ElfNative.Elf32_Rela rel; |
72 | | - ulong streamOffset = (ulong)reader.Stream.Position; |
73 | | - if (!reader.TryReadData(sizeof(ElfNative.Elf32_Rela), out rel)) |
74 | | - { |
75 | | - reader.Diagnostics.Error(DiagnosticId.ELF_ERR_IncompleteRelocationAddendsEntry32Size, $"Unable to read entirely the relocation entry [{i}] from {Type} section [{Index}]. Not enough data (size: {base.TableEntrySize}) read at offset {streamOffset} from the stream"); |
76 | | - } |
77 | | - |
78 | | - var offset = reader.Decode(rel.r_offset); |
| 79 | + ref var rel = ref batch.ReadNext(); |
| 80 | + entry.Offset = reader.Decode(rel.r_offset); |
79 | 81 | var r_info = reader.Decode(rel.r_info); |
80 | | - var type = new ElfRelocationType(Parent!.Arch, r_info & 0xFF); |
81 | | - var symbolIndex = r_info >> 8; |
82 | | - var addend = reader.Decode(rel.r_addend); |
83 | | - |
84 | | - var entry = new ElfRelocation(offset, type, symbolIndex, addend); |
85 | | - _entries.Add(entry); |
| 82 | + entry.Type = new ElfRelocationType(Parent!.Arch, r_info & 0xFF); |
| 83 | + entry.SymbolIndex = r_info >> 8; |
| 84 | + entry.Addend = reader.Decode(rel.r_addend); |
| 85 | + entry = ref Unsafe.Add(ref entry, 1); |
86 | 86 | } |
87 | 87 | } |
88 | 88 | else |
89 | 89 | { |
90 | | - for (ulong i = 0; i < numberOfEntries; i++) |
| 90 | + using var batch = new BatchDataReader<ElfNative.Elf32_Rel>(reader.Stream, (int)numberOfEntries); |
| 91 | + ref var entry = ref MemoryMarshal.GetReference(span); |
| 92 | + while (batch.HasNext()) |
91 | 93 | { |
92 | | - ElfNative.Elf32_Rel rel; |
93 | | - ulong streamOffset = (ulong)reader.Stream.Position; |
94 | | - if (!reader.TryReadData(sizeof(ElfNative.Elf32_Rel), out rel)) |
95 | | - { |
96 | | - reader.Diagnostics.Error(DiagnosticId.ELF_ERR_IncompleteRelocationEntry32Size, $"Unable to read entirely the relocation entry [{i}] from {Type} section [{Index}]. Not enough data (size: {base.TableEntrySize}) read at offset {streamOffset} from the stream"); |
97 | | - } |
98 | | - |
99 | | - var offset = reader.Decode(rel.r_offset); |
100 | | - |
| 94 | + ref var rel = ref batch.ReadNext(); |
| 95 | + entry.Offset = reader.Decode(rel.r_offset); |
101 | 96 | var r_info = reader.Decode(rel.r_info); |
102 | | - var type = new ElfRelocationType(Parent!.Arch, r_info & 0xFF); |
103 | | - var symbolIndex = r_info >> 8; |
104 | | - |
105 | | - var entry = new ElfRelocation(offset, type, symbolIndex, 0); |
106 | | - _entries.Add(entry); |
| 97 | + entry.Type = new ElfRelocationType(Parent!.Arch, r_info & 0xFF); |
| 98 | + entry.SymbolIndex = r_info >> 8; |
| 99 | + entry.Addend = 0; |
| 100 | + entry = ref Unsafe.Add(ref entry, 1); |
107 | 101 | } |
108 | 102 | } |
109 | 103 | } |
110 | 104 |
|
111 | 105 | private unsafe void Read64(ElfReader reader) |
112 | 106 | { |
113 | 107 | var numberOfEntries = base.Size / base.TableEntrySize; |
| 108 | + var entries = _entries; |
| 109 | + CollectionsMarshal.SetCount(entries, (int)numberOfEntries); |
| 110 | + var span = CollectionsMarshal.AsSpan(entries); |
| 111 | + |
114 | 112 | if (IsRelocationWithAddends) |
115 | 113 | { |
116 | | - for (ulong i = 0; i < numberOfEntries; i++) |
| 114 | + using var batch = new BatchDataReader<ElfNative.Elf64_Rela>(reader.Stream, (int)numberOfEntries); |
| 115 | + ref var entry = ref MemoryMarshal.GetReference(span); |
| 116 | + while (batch.HasNext()) |
117 | 117 | { |
118 | | - ElfNative.Elf64_Rela rel; |
119 | | - ulong streamOffset = (ulong)reader.Stream.Position; |
120 | | - if (!reader.TryReadData(sizeof(ElfNative.Elf64_Rela), out rel)) |
121 | | - { |
122 | | - reader.Diagnostics.Error(DiagnosticId.ELF_ERR_IncompleteRelocationAddendsEntry64Size, $"Unable to read entirely the relocation entry [{i}] from {Type} section [{Index}]. Not enough data (size: {base.TableEntrySize}) read at offset {streamOffset} from the stream"); |
123 | | - } |
124 | | - |
125 | | - var offset = reader.Decode(rel.r_offset); |
126 | | - |
| 118 | + ref var rel = ref batch.ReadNext(); |
| 119 | + entry.Offset = reader.Decode(rel.r_offset); |
127 | 120 | var r_info = reader.Decode(rel.r_info); |
128 | | - var type = new ElfRelocationType(Parent!.Arch, (uint)(r_info & 0xFFFFFFFF)); |
129 | | - var symbolIndex = (uint)(r_info >> 32); |
130 | | - var addend = reader.Decode(rel.r_addend); |
131 | | - |
132 | | - var entry = new ElfRelocation(offset, type, symbolIndex, addend); |
133 | | - _entries.Add(entry); |
| 121 | + entry.Type = new ElfRelocationType(Parent!.Arch, (uint)(r_info & 0xFFFFFFFF)); |
| 122 | + entry.SymbolIndex = (uint)(r_info >> 32); |
| 123 | + entry.Addend = reader.Decode(rel.r_addend); |
| 124 | + entry = ref Unsafe.Add(ref entry, 1); |
134 | 125 | } |
135 | 126 | } |
136 | 127 | else |
137 | 128 | { |
138 | | - for (ulong i = 0; i < numberOfEntries; i++) |
| 129 | + using var batch = new BatchDataReader<ElfNative.Elf64_Rel>(reader.Stream, (int)numberOfEntries); |
| 130 | + ref var entry = ref MemoryMarshal.GetReference(span); |
| 131 | + while (batch.HasNext()) |
139 | 132 | { |
140 | | - ElfNative.Elf64_Rel rel; |
141 | | - ulong streamOffset = (ulong)reader.Stream.Position; |
142 | | - if (!reader.TryReadData(sizeof(ElfNative.Elf64_Rel), out rel)) |
143 | | - { |
144 | | - reader.Diagnostics.Error(DiagnosticId.ELF_ERR_IncompleteRelocationEntry64Size, $"Unable to read entirely the relocation entry [{i}] from {Type} section [{Index}]. Not enough data (size: {base.TableEntrySize}) read at offset {streamOffset} from the stream"); |
145 | | - } |
146 | | - |
147 | | - var offset = reader.Decode(rel.r_offset); |
148 | | - |
| 133 | + ref var rel = ref batch.ReadNext(); |
| 134 | + entry.Offset = reader.Decode(rel.r_offset); |
149 | 135 | var r_info = reader.Decode(rel.r_info); |
150 | | - var type = new ElfRelocationType(Parent!.Arch, (uint)(r_info & 0xFFFFFFFF)); |
151 | | - var symbolIndex = (uint)(r_info >> 32); |
152 | | - |
153 | | - var entry = new ElfRelocation(offset, type, symbolIndex, 0); |
154 | | - _entries.Add(entry); |
| 136 | + entry.Type = new ElfRelocationType(Parent!.Arch, (uint)(r_info & 0xFFFFFFFF)); |
| 137 | + entry.SymbolIndex = (uint)(r_info >> 32); |
| 138 | + entry.Addend = 0; |
| 139 | + entry = ref Unsafe.Add(ref entry, 1); |
155 | 140 | } |
156 | 141 | } |
157 | 142 | } |
|
0 commit comments