diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3ced890..26cbb00 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,7 +10,7 @@ on: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout diff --git a/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs b/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs index 6a159ab..1793215 100644 --- a/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs +++ b/src/LibObjectFile.Tests/Dwarf/DwarfTests.cs @@ -80,7 +80,7 @@ public void TestDebugLineHelloWorld() { var cppName = "helloworld"; var cppExe = $"{cppName}_debug"; - LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -g -o {cppExe}"); + LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -gdwarf-4 -o {cppExe}"); ElfObjectFile elf; using (var inStream = File.OpenRead(cppExe)) @@ -139,7 +139,7 @@ public void TestDebugLineLibMultipleObjs() { var cppName = "lib"; var libShared = $"{cppName}_debug.so"; - LinuxUtil.RunLinuxExe("gcc", $"{cppName}_a.cpp {cppName}_b.cpp -g -shared -o {libShared}"); + LinuxUtil.RunLinuxExe("gcc", $"{cppName}_a.cpp {cppName}_b.cpp -gdwarf-4 -shared -o {libShared}"); ElfObjectFile elf; using (var inStream = File.OpenRead(libShared)) @@ -198,7 +198,7 @@ public void TestDebugLineSmall() { var cppName = "small"; var cppObj = $"{cppName}_debug.o"; - LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -g -c -o {cppObj}"); + LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -gdwarf-4 -c -o {cppObj}"); ElfObjectFile elf; using (var inStream = File.OpenRead(cppObj)) { @@ -256,7 +256,7 @@ public void TestDebugLineMultipleFunctions() { var cppName = "multiple_functions"; var cppObj = $"{cppName}_debug.o"; - LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -g -c -o {cppObj}"); + LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -gdwarf-4 -c -o {cppObj}"); ElfObjectFile elf; using (var inStream = File.OpenRead(cppObj)) @@ -314,7 +314,7 @@ public void TestDebugInfoSmall() { var cppName = "small"; var cppObj = $"{cppName}_debug.o"; - LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -g -c -o {cppObj}"); + LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -gdwarf-4 -c -o {cppObj}"); ElfObjectFile elf; using (var inStream = File.OpenRead(cppObj)) diff --git a/src/LibObjectFile.Tests/LinuxUtil.cs b/src/LibObjectFile.Tests/LinuxUtil.cs index 070572b..06205fc 100644 --- a/src/LibObjectFile.Tests/LinuxUtil.cs +++ b/src/LibObjectFile.Tests/LinuxUtil.cs @@ -17,7 +17,7 @@ public static string ReadElf(string file, string arguments = "-W -a") return RunLinuxExe("readelf", $"{file} {arguments}"); } - public static string RunLinuxExe(string exe, string arguments, string distribution = "Ubuntu-20.04") + public static string RunLinuxExe(string exe, string arguments, string distribution = "Ubuntu") { if (exe == null) throw new ArgumentNullException(nameof(exe)); if (arguments == null) throw new ArgumentNullException(nameof(arguments)); diff --git a/src/LibObjectFile/Elf/ElfObjectFile.cs b/src/LibObjectFile/Elf/ElfObjectFile.cs index fc0b979..a457826 100644 --- a/src/LibObjectFile/Elf/ElfObjectFile.cs +++ b/src/LibObjectFile/Elf/ElfObjectFile.cs @@ -253,12 +253,23 @@ public unsafe void UpdateLayout(DiagnosticBag diagnostics) shstrTable.Reset(); // Prepare all section names (to calculate the name indices and the size of the SectionNames) - for (var j = 0; j < sections.Count; j++) + // Do it in two passes to generate optimal string table + for (var pass = 0; pass < 2; pass++) { - var otherSection = sections[j]; - if ((j == 0 && otherSection.Type == ElfSectionType.Null)) continue; - if (otherSection.IsShadow) continue; - otherSection.Name = otherSection.Name.WithIndex(shstrTable.GetOrCreateIndex(otherSection.Name)); + for (var j = 0; j < sections.Count; j++) + { + var otherSection = sections[j]; + if ((j == 0 && otherSection.Type == ElfSectionType.Null)) continue; + if (otherSection.IsShadow) continue; + if (pass == 0) + { + shstrTable.ReserveString(otherSection.Name); + } + else + { + otherSection.Name = otherSection.Name.WithIndex(shstrTable.GetOrCreateIndex(otherSection.Name)); + } + } } } @@ -276,9 +287,9 @@ public unsafe void UpdateLayout(DiagnosticBag diagnostics) } // The Section Header Table will be put just after all the sections - Layout.OffsetOfSectionHeaderTable = offset; + Layout.OffsetOfSectionHeaderTable = AlignHelper.AlignToUpper(offset, FileClass == ElfFileClass.Is32 ? 4u : 8u); - Layout.TotalSize = offset + (ulong)VisibleSectionCount * Layout.SizeOfSectionHeaderEntry; + Layout.TotalSize = Layout.OffsetOfSectionHeaderTable + (ulong)VisibleSectionCount * Layout.SizeOfSectionHeaderEntry; } // Update program headers with offsets from auto layout diff --git a/src/LibObjectFile/Elf/ElfPrinter.cs b/src/LibObjectFile/Elf/ElfPrinter.cs index 631b1b2..f6666b3 100644 --- a/src/LibObjectFile/Elf/ElfPrinter.cs +++ b/src/LibObjectFile/Elf/ElfPrinter.cs @@ -68,7 +68,14 @@ public static void PrintElfHeader(ElfObjectFile elf, TextWriter writer) writer.WriteLine($" Size of program headers: {elf.Layout.SizeOfProgramHeaderEntry} (bytes)"); writer.WriteLine($" Number of program headers: {elf.Segments.Count}"); writer.WriteLine($" Size of section headers: {elf.Layout.SizeOfSectionHeaderEntry} (bytes)"); - writer.WriteLine($" Number of section headers: {elf.VisibleSectionCount}"); + if (elf.VisibleSectionCount >= ElfNative.SHN_LORESERVE || elf.VisibleSectionCount == 0) + { + writer.WriteLine($" Number of section headers: 0 ({elf.VisibleSectionCount})"); + } + else + { + writer.WriteLine($" Number of section headers: {elf.VisibleSectionCount}"); + } writer.WriteLine($" Section header string table index: {elf.SectionHeaderStringTable?.SectionIndex ?? 0}"); } @@ -97,7 +104,7 @@ public static void PrintSectionHeaders(ElfObjectFile elf, TextWriter writer) W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), - l (large), p (processor specific)"); + D (mbind), l (large), p (processor specific)"); } public static void PrintSectionGroups(ElfObjectFile elf, TextWriter writer) @@ -105,13 +112,6 @@ public static void PrintSectionGroups(ElfObjectFile elf, TextWriter writer) if (elf == null) throw new ArgumentNullException(nameof(elf)); if (writer == null) throw new ArgumentNullException(nameof(writer)); - if (elf.Sections.Count == 0) - { - writer.WriteLine(); - writer.WriteLine("There are no sections to group in this file."); - return; - } - writer.WriteLine(); writer.WriteLine("There are no section groups in this file."); // TODO @@ -252,8 +252,15 @@ public static void PrintUnwind(ElfObjectFile elf, TextWriter writer) if (elf == null) throw new ArgumentNullException(nameof(elf)); if (writer == null) throw new ArgumentNullException(nameof(writer)); - writer.WriteLine(); - writer.WriteLine($"The decoding of unwind sections for machine type {GetElfArch(elf.Arch)} is not currently supported."); + if (elf.Arch == ElfArchEx.I386 || elf.Arch == ElfArchEx.X86_64) + { + writer.WriteLine("No processor specific unwind information to decode"); + } + else + { + writer.WriteLine(); + writer.WriteLine($"The decoding of unwind sections for machine type {GetElfArch(elf.Arch)} is not currently supported."); + } } diff --git a/src/LibObjectFile/Elf/ElfSegmentRange.cs b/src/LibObjectFile/Elf/ElfSegmentRange.cs index 4ad4805..e33ffb4 100644 --- a/src/LibObjectFile/Elf/ElfSegmentRange.cs +++ b/src/LibObjectFile/Elf/ElfSegmentRange.cs @@ -99,17 +99,7 @@ public ulong Size return 0; } - var parent = BeginSection.Parent; - ulong size = 0; - for (uint i = BeginSection.Index; i < EndSection.Index; i++) - { - var section = parent.Sections[(int)i]; - if (section.HasContent) - { - size += section.Size; - } - } - + ulong size = EndSection.Offset - BeginSection.Offset; size -= BeginOffset; size += EndOffset < 0 ? (ulong)((long)EndSection.Size + EndOffset + 1) : (ulong)(EndOffset + 1); return size; diff --git a/src/LibObjectFile/Elf/ElfWriter{TEncoder}.cs b/src/LibObjectFile/Elf/ElfWriter{TEncoder}.cs index 163adaf..695195d 100644 --- a/src/LibObjectFile/Elf/ElfWriter{TEncoder}.cs +++ b/src/LibObjectFile/Elf/ElfWriter{TEncoder}.cs @@ -227,10 +227,16 @@ private void WriteSections() private void WriteSectionHeaderTable() { var offset = (ulong)Stream.Position - _startOfFile; - if (offset != Layout.OffsetOfSectionHeaderTable) + var diff = Layout.OffsetOfSectionHeaderTable - offset; + if (diff < 0 || diff > 8) { throw new InvalidOperationException("Internal error. Unexpected offset for SectionHeaderTable"); } + else if (diff != 0) + { + // Alignment + Stream.Write(stackalloc byte[(int)diff]); + } // Then write all regular sections var sections = ObjectFile.Sections;