From bc113d557c307e3211e6b6f1d01ab89e42f9f934 Mon Sep 17 00:00:00 2001 From: David Nguyen <87228593+davidnguyen-tech@users.noreply.github.com> Date: Fri, 2 Jan 2026 16:26:12 +0100 Subject: [PATCH 1/2] Skip empty sections when calculating the PE file layout --- .../Compiler/ObjectWriter/PEObjectWriter.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs index 5243d2e214c685..f1eb932f7458c1 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs @@ -445,6 +445,21 @@ private void LayoutSections(bool recordFinalLayout, out ushort numberOfSections, foreach (SectionDefinition s in _sections) { CoffSectionHeader h = s.Header; + + // Skip calculating the layout for empty sections. + // Empty sections remain in _sections for index stability but are assigned zero VA/size + // to avoid wasting virtual address space and inflating the final PE file size. + if (s.Stream.Length == 0 && !h.SectionCharacteristics.HasFlag(SectionCharacteristics.ContainsUninitializedData)) + { + if (recordFinalLayout) + { + // Ensure that we match the section indexes in _sections, even though we omit them in EmitObjectFile. + _outputSectionLayout.Add(new OutputSection(h.Name, 0, 0, 0)); + } + + continue; + } + h.SizeOfRawData = (uint)s.Stream.Length; uint requestedAlignment = GetSectionAlignment(h); uint rawAligned = h.SectionCharacteristics.HasFlag(SectionCharacteristics.ContainsUninitializedData) From d694f86cab9e66ee79abb9b6f9d26de2d770172c Mon Sep 17 00:00:00 2001 From: David Nguyen <87228593+davidnguyen-tech@users.noreply.github.com> Date: Fri, 2 Jan 2026 16:50:24 +0100 Subject: [PATCH 2/2] Update comment --- .../tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs index f1eb932f7458c1..ca9fb97c0e93b1 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/PEObjectWriter.cs @@ -447,13 +447,12 @@ private void LayoutSections(bool recordFinalLayout, out ushort numberOfSections, CoffSectionHeader h = s.Header; // Skip calculating the layout for empty sections. - // Empty sections remain in _sections for index stability but are assigned zero VA/size - // to avoid wasting virtual address space and inflating the final PE file size. if (s.Stream.Length == 0 && !h.SectionCharacteristics.HasFlag(SectionCharacteristics.ContainsUninitializedData)) { if (recordFinalLayout) { - // Ensure that we match the section indexes in _sections, even though we omit them in EmitObjectFile. + // Although we omit the empty sections in EmitObjectFile, we add them to _sections in order to match indexes. + // We assign zero VA/size to avoid wasting virtual address space and inflating the final PE file size. _outputSectionLayout.Add(new OutputSection(h.Name, 0, 0, 0)); } @@ -516,8 +515,6 @@ private void LayoutSections(bool recordFinalLayout, out ushort numberOfSections, if (recordFinalLayout) { // Use the stream length so we don't include any space that's appended just for alignment purposes. - // To ensure that we match the section indexes in _sections, we don't skip empty sections here - // even though we omit them in EmitObjectFile. _outputSectionLayout.Add(new OutputSection(h.Name, h.VirtualAddress, h.PointerToRawData, (uint)s.Stream.Length)); } firstSection = false;