|
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