Skip to content

Commit a406b84

Browse files
committed
Improve roundtrip
1 parent 2f6b6eb commit a406b84

18 files changed

+227
-135
lines changed

src/LibObjectFile.Tests/Elf/ElfSimpleTests.cs

+86-56
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,65 @@ public class ElfSimpleTests : ElfTestBase
2121
[DynamicData(nameof(GetLinuxBins), DynamicDataSourceType.Method)]
2222
public void TestLinuxFile(string file)
2323
{
24-
if (!OperatingSystem.IsLinux())
24+
if (string.IsNullOrEmpty(file))
2525
{
26-
Assert.Inconclusive("This test can only run on Linux");
26+
Assert.Inconclusive("This test can only run on Linux or on Windows with WSL");
2727
return;
2828
}
2929

3030
using var stream = File.OpenRead(file);
3131
if (!ElfFile.IsElf(stream)) return;
32+
3233
var elf = ElfFile.Read(stream);
34+
stream.Position = 0;
35+
var elfOriginal = ElfFile.Read(stream); // elfOriginal is not written back, so it's layout is not updated
3336

34-
// TODO: check for errors
37+
var originalBuffer = File.ReadAllBytes(file);
3538

36-
//var writer = new StringWriter();
37-
//writer.WriteLine("---------------------------------------------------------------------------------------");
38-
//writer.WriteLine($"{file}");
39-
//elf.Print(writer);
40-
//writer.WriteLine();
39+
var copyStream = new MemoryStream();
40+
elf.Write(copyStream);
41+
42+
for (var i = 0; i < elfOriginal.Content.Count; i++)
43+
{
44+
var content = elf.Content[i];
45+
var contentOriginal = elfOriginal.Content[i];
46+
Assert.AreEqual(contentOriginal.Position, content.Position, $"Invalid position for content {content}");
47+
Assert.AreEqual(contentOriginal.Size, content.Size, $"Invalid size for content {content}");
48+
}
49+
50+
for (var i = 0; i < elfOriginal.Segments.Count; i++)
51+
{
52+
var segment = elf.Segments[i];
53+
var segmentOriginal = elfOriginal.Segments[i];
54+
Assert.AreEqual(segmentOriginal.Position, segment.Position, $"Invalid position for segment {segment}");
55+
Assert.AreEqual(segmentOriginal.Size, segment.Size, $"Invalid size for segment {segment}");
56+
}
57+
58+
ByteArrayAssert.AreEqual(originalBuffer, copyStream.ToArray());
4159
}
4260

4361
public static IEnumerable<object[]> GetLinuxBins()
4462
{
63+
var wslDirectory = @"\\wsl$\Ubuntu\usr\bin";
4564
if (OperatingSystem.IsLinux())
4665
{
4766
foreach (var file in Directory.EnumerateFiles(@"/usr/bin"))
4867
{
4968
yield return new object[] { file };
5069
}
5170
}
71+
else if (OperatingSystem.IsWindows() && Directory.Exists(wslDirectory))
72+
{
73+
foreach (var file in Directory.EnumerateFiles(wslDirectory))
74+
{
75+
var fileInfo = new FileInfo(file);
76+
// Skip symbolic links as loading them will fail
77+
if ((fileInfo.Attributes & FileAttributes.ReparsePoint) == 0)
78+
{
79+
yield return new object[] { file };
80+
}
81+
}
82+
}
5283
else
5384
{
5485
yield return new object[] { string.Empty };
@@ -96,7 +127,7 @@ public void TryReadFailed()
96127
public void SimpleEmptyWithDefaultSections()
97128
{
98129
var elf = new ElfFile(ElfArch.X86_64);
99-
elf.Content.Add(new ElfSectionHeaderTable());
130+
elf.Add(new ElfSectionHeaderTable());
100131
AssertReadElf(elf, "empty_default.elf");
101132
}
102133

@@ -121,9 +152,9 @@ public void SimpleCodeSection()
121152
codeStream.Position = 0;
122153

123154
var codeSection = new ElfStreamSection(ElfSectionSpecialType.Text, codeStream);
124-
elf.Content.Add(codeSection);
125-
elf.Content.Add(new ElfSectionHeaderStringTable());
126-
elf.Content.Add(new ElfSectionHeaderTable());
155+
elf.Add(codeSection);
156+
elf.Add(new ElfSectionHeaderStringTable());
157+
elf.Add(new ElfSectionHeaderTable());
127158

128159
AssertReadElf(elf, "test.elf");
129160
}
@@ -136,16 +167,15 @@ public void TestBss()
136167
var stream = new MemoryStream();
137168
stream.Write(new byte[] { 1, 2, 3, 4 });
138169
stream.Position = 0;
139-
var codeSection = new ElfStreamSection(ElfSectionSpecialType.Text, stream);
140-
elf.Content.Add(codeSection);
141-
var bssSection = new ElfStreamSection(ElfSectionSpecialType.Bss)
170+
171+
var codeSection = elf.Add(new ElfStreamSection(ElfSectionSpecialType.Text, stream));
172+
var bssSection = elf.Add(new ElfStreamSection(ElfSectionSpecialType.Bss)
142173
{
143-
Alignment = 1024
144-
};
145-
elf.Content.Add(bssSection);
174+
FileAlignment = 1024
175+
});
146176

147-
elf.Content.Add(new ElfSectionHeaderStringTable());
148-
elf.Content.Add(new ElfSectionHeaderTable());
177+
elf.Add(new ElfSectionHeaderStringTable());
178+
elf.Add(new ElfSectionHeaderTable());
149179

150180
var diagnostics = new DiagnosticBag();
151181
elf.UpdateLayout(diagnostics);
@@ -166,10 +196,10 @@ public void SimpleCodeSectionAndSymbolSection()
166196
codeStream.Position = 0;
167197

168198
var codeSection = new ElfStreamSection(ElfSectionSpecialType.Text, codeStream);
169-
elf.Content.Add(codeSection);
199+
elf.Add(codeSection);
170200

171201
var stringSection = new ElfStringTable();
172-
elf.Content.Add(stringSection);
202+
elf.Add(stringSection);
173203

174204
var symbolSection = new ElfSymbolTable()
175205
{
@@ -198,9 +228,9 @@ public void SimpleCodeSectionAndSymbolSection()
198228
}
199229
}
200230
};
201-
elf.Content.Add(symbolSection);
202-
elf.Content.Add(new ElfSectionHeaderStringTable());
203-
elf.Content.Add(new ElfSectionHeaderTable());
231+
elf.Add(symbolSection);
232+
elf.Add(new ElfSectionHeaderStringTable());
233+
elf.Add(new ElfSectionHeaderTable());
204234

205235
AssertReadElf(elf, "test2.elf");
206236
}
@@ -216,22 +246,22 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSection()
216246
var codeSection = new ElfStreamSection(ElfSectionSpecialType.Text, codeStream)
217247
{
218248
VirtualAddress = 0x1000,
219-
Alignment = 4096
249+
VirtualAddressAlignment = 4096
220250
};
221-
elf.Content.Add(codeSection);
251+
elf.Add(codeSection);
222252

223253
var dataStream = new MemoryStream();
224254
dataStream.Write(new byte[1024]);
225255

226256
var dataSection = new ElfStreamSection(ElfSectionSpecialType.ReadOnlyData, dataStream)
227257
{
228258
VirtualAddress = 0x2000,
229-
Alignment = 4096
259+
VirtualAddressAlignment = 4096
230260
};
231-
elf.Content.Add(dataSection);
261+
elf.Add(dataSection);
232262

233263
var stringSection = new ElfStringTable();
234-
elf.Content.Add(stringSection);
264+
elf.Add(stringSection);
235265

236266
var symbolSection = new ElfSymbolTable()
237267
{
@@ -260,10 +290,10 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSection()
260290
}
261291
}
262292
};
263-
elf.Content.Add(symbolSection);
293+
elf.Add(symbolSection);
264294

265-
elf.Content.Add(new ElfSectionHeaderStringTable());
266-
elf.Content.Add(new ElfSectionHeaderTable());
295+
elf.Add(new ElfSectionHeaderStringTable());
296+
elf.Add(new ElfSectionHeaderTable());
267297

268298
elf.Segments.Add(new ElfSegment()
269299
{
@@ -274,7 +304,7 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSection()
274304
Flags = ElfSegmentFlagsCore.Readable|ElfSegmentFlagsCore.Executable,
275305
Size = 4096,
276306
SizeInMemory = 4096,
277-
Alignment = 4096,
307+
VirtualAddressAlignment = 4096,
278308
});
279309

280310
elf.Segments.Add(new ElfSegment()
@@ -286,7 +316,7 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSection()
286316
Flags = ElfSegmentFlagsCore.Readable | ElfSegmentFlagsCore.Writable,
287317
Size = 1024,
288318
SizeInMemory = 1024,
289-
Alignment = 4096,
319+
VirtualAddressAlignment = 4096,
290320
});
291321

292322
AssertReadElf(elf, "test3.elf");
@@ -304,22 +334,22 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSectionAndRelocation()
304334
var codeSection = new ElfStreamSection(ElfSectionSpecialType.Text, codeStream)
305335
{
306336
VirtualAddress = 0x1000,
307-
Alignment = 4096
337+
VirtualAddressAlignment = 4096
308338
};
309-
elf.Content.Add(codeSection);
339+
elf.Add(codeSection);
310340

311341
var dataStream = new MemoryStream();
312342
dataStream.Write(new byte[1024]);
313343

314344
var dataSection = new ElfStreamSection(ElfSectionSpecialType.ReadOnlyData, dataStream)
315345
{
316346
VirtualAddress = 0x2000,
317-
Alignment = 4096
347+
VirtualAddressAlignment = 4096
318348
};
319-
elf.Content.Add(dataSection);
349+
elf.Add(dataSection);
320350

321351
var stringSection = new ElfStringTable();
322-
elf.Content.Add(stringSection);
352+
elf.Add(stringSection);
323353

324354
var symbolSection = new ElfSymbolTable()
325355
{
@@ -348,7 +378,7 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSectionAndRelocation()
348378
}
349379
}
350380
};
351-
elf.Content.Add(symbolSection);
381+
elf.Add(symbolSection);
352382

353383
elf.Segments.Add(
354384
new ElfSegment()
@@ -360,7 +390,7 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSectionAndRelocation()
360390
Flags = ElfSegmentFlagsCore.Readable | ElfSegmentFlagsCore.Executable,
361391
Size = 4096,
362392
SizeInMemory = 4096,
363-
Alignment = 4096,
393+
VirtualAddressAlignment = 4096,
364394
}
365395
);
366396

@@ -374,7 +404,7 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSectionAndRelocation()
374404
Flags = ElfSegmentFlagsCore.Readable | ElfSegmentFlagsCore.Writable,
375405
Size = 1024,
376406
SizeInMemory = 1024,
377-
Alignment = 4096,
407+
VirtualAddressAlignment = 4096,
378408
}
379409
);
380410

@@ -399,10 +429,10 @@ public void SimpleProgramHeaderAndCodeSectionAndSymbolSectionAndRelocation()
399429
}
400430
}
401431
};
402-
elf.Content.Add(relocTable);
432+
elf.Add(relocTable);
403433

404-
elf.Content.Add(new ElfSectionHeaderStringTable());
405-
elf.Content.Add(new ElfSectionHeaderTable());
434+
elf.Add(new ElfSectionHeaderStringTable());
435+
elf.Add(new ElfSectionHeaderTable());
406436

407437
AssertReadElf(elf, "test4.elf");
408438
}
@@ -454,12 +484,12 @@ public void TestAlignedSection()
454484

455485
var codeSection = new ElfStreamSection(ElfSectionSpecialType.Text, codeStream)
456486
{
457-
Alignment = 0x1000,
487+
FileAlignment = 0x1000,
458488
};
459-
elf.Content.Add(codeSection);
489+
elf.Add(codeSection);
460490

461-
elf.Content.Add(new ElfSectionHeaderStringTable());
462-
elf.Content.Add(new ElfSectionHeaderTable());
491+
elf.Add(new ElfSectionHeaderStringTable());
492+
elf.Add(new ElfSectionHeaderTable());
463493

464494
var diagnostics = elf.Verify();
465495
Assert.IsFalse(diagnostics.HasErrors);
@@ -482,20 +512,20 @@ public void TestManySections()
482512
for (int i = 0; i < ushort.MaxValue; i++)
483513
{
484514
var section = new ElfStreamSection(ElfSectionSpecialType.Data) { Name = $".section{i}" };
485-
elf.Content.Add(section);
515+
elf.Add(section);
486516
symbolTable.Entries.Add(new ElfSymbol { Type = ElfSymbolType.Section, SectionLink = section });
487517
}
488518

489-
elf.Content.Add(stringTable);
490-
elf.Content.Add(symbolTable);
491-
elf.Content.Add(new ElfSectionHeaderStringTable());
492-
elf.Content.Add(new ElfSectionHeaderTable());
519+
elf.Add(stringTable);
520+
elf.Add(symbolTable);
521+
elf.Add(new ElfSectionHeaderStringTable());
522+
elf.Add(new ElfSectionHeaderTable());
493523

494524
var diagnostics = elf.Verify();
495525
Assert.IsTrue(diagnostics.HasErrors);
496526
Assert.AreEqual(DiagnosticId.ELF_ERR_MissingSectionHeaderIndices, diagnostics.Messages[0].Id);
497527

498-
elf.Content.Add(new ElfSymbolTableSectionHeaderIndices { Link = symbolTable });
528+
elf.Add(new ElfSymbolTableSectionHeaderIndices { Link = symbolTable });
499529
diagnostics = elf.Verify();
500530
Assert.IsFalse(diagnostics.HasErrors);
501531

src/LibObjectFile/Diagnostics/DiagnosticId.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ public enum DiagnosticId
7878
ELF_ERR_SectionHeaderStringTableNotFound = 165,
7979
ELF_ERR_InvalidSectionEntrySize = 166,
8080
ELF_ERR_MissingSectionHeaderTable = 167,
81-
81+
ELF_ERR_MissingSectionHeaderTableSection = 168,
82+
8283
AR_ERR_InvalidMagicLength = 1000,
8384
AR_ERR_MagicNotFound = 1001,
8485
AR_ERR_ExpectingNewLineCharacter = 1002,

src/LibObjectFile/Dwarf/DwarfElfContext.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ private ElfStreamSection GetOrCreateDebugSection(string name, bool createSymbol,
303303
var newSection = new ElfStreamSection(ElfSectionType.ProgBits)
304304
{
305305
Name = name,
306-
Alignment = 1,
306+
VirtualAddressAlignment = 1,
307307
Stream = new MemoryStream(),
308308
};
309309

@@ -328,7 +328,7 @@ private ElfRelocationTable GetOrCreateRelocationTable(ElfStreamSection section)
328328
var newSection = new ElfRelocationTable(true)
329329
{
330330
Name = $".rela{section.Name}",
331-
Alignment = (ulong)AddressSize,
331+
VirtualAddressAlignment = (ulong)AddressSize,
332332
Flags = ElfSectionFlags.InfoLink,
333333
Info = section,
334334
Link = _symbolTable,

src/LibObjectFile/Elf/ElfContent.cs

+6-9
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ public abstract class ElfContent : ElfObject
1818
{
1919
protected ElfContent()
2020
{
21-
Alignment = 0;
21+
FileAlignment = 1;
2222
}
2323

24+
/// <summary>
25+
/// Gets or sets the alignment requirement of this content in the file.
26+
/// </summary>
27+
public uint FileAlignment { get; set; }
28+
2429
protected override void ValidateParent(ObjectElement parent)
2530
{
2631
if (!(parent is ElfFile))
@@ -42,14 +47,6 @@ protected void ValidateParent(ObjectElement parent, ElfFileClass fileClass)
4247
}
4348
}
4449

45-
/// <summary>
46-
/// Gets or sets the alignment requirement of this section.
47-
/// </summary>
48-
/// <remarks>
49-
/// An alignment of zero or 1 means that the section or segment has no alignment constraints.
50-
/// </remarks>
51-
public ulong Alignment { get; set; }
52-
5350
/// <summary>
5451
/// Gets the containing <see cref="ElfFile"/>. Might be null if this section or segment
5552
/// does not belong to an existing <see cref="ElfFile"/>.

0 commit comments

Comments
 (0)