From 221465639cc595dd8cb816d3ed15568c7391c838 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:32:29 +0000 Subject: [PATCH 1/6] Initial plan From 77cc2161c80ece5d72b97d1c0fab02b27bd07d4f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Jul 2025 18:03:17 +0000 Subject: [PATCH 2/6] Add NoSEH flag test case and individual test Co-authored-by: agocke <515774+agocke@users.noreply.github.com> --- .../CommandLine/NoSEHFlagIsSet.cs | 24 +++++++++++++++ .../TestCases/IndividualTests.cs | 29 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs new file mode 100644 index 00000000000000..469a1b64aa2400 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs @@ -0,0 +1,24 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.CommandLine +{ + /// + /// This test case verifies that the NoSEH flag is set in the PE header + /// when running ILLink on a sample application that has been R2R-stripped. + /// + public class NoSEHFlagIsSet + { + public static void Main() + { + // Simple test case - just call a method + TestMethod(); + } + + [Kept] + static void TestMethod() + { + // Simple implementation + } + } +} \ No newline at end of file diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs index e919363365a279..9a877675495a5d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs @@ -8,6 +8,7 @@ using System.Runtime.Serialization.Json; using System.Xml; using Mono.Cecil; +using Mono.Linker.Tests.Cases.CommandLine; using Mono.Linker.Tests.Cases.CommandLine.Mvid; using Mono.Linker.Tests.Cases.Interop.PInvoke.Individual; using Mono.Linker.Tests.Cases.References.Individual; @@ -16,6 +17,8 @@ using Mono.Linker.Tests.Extensions; using Mono.Linker.Tests.TestCasesRunner; using NUnit.Framework; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; namespace Mono.Linker.Tests.TestCases { @@ -269,5 +272,31 @@ protected virtual TrimmedTestCaseResult Run(TestCase testCase, out TestRunner ru runner = new TestRunner(new ObjectFactory()); return runner.Run(testCase); } + + [Test] + public void NoSEHFlagIsSetInPEHeader() + { + var testcase = CreateIndividualCase(typeof(NoSEHFlagIsSet)); + var result = Run(testcase); + + var outputPath = result.OutputAssemblyPath; + if (!outputPath.Exists()) + Assert.Fail($"The linked assembly is missing. Expected it to exist at {outputPath}"); + + // Check PE header for NoSEH flag + using (var fileStream = new FileStream(outputPath, FileMode.Open, FileAccess.Read)) + using (var peReader = new PEReader(fileStream)) + { + var peHeaders = peReader.PEHeaders; + var characteristics = peHeaders.CofHeader.Characteristics; + var dllCharacteristics = peHeaders.PEHeader.DllCharacteristics; + + // IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 + const DllCharacteristics NoSEH = (DllCharacteristics)0x0400; + + Assert.That(dllCharacteristics & NoSEH, Is.EqualTo(NoSEH), + $"NoSEH flag (0x0400) is not set in PE header. DllCharacteristics: 0x{dllCharacteristics:X}"); + } + } } } From 6b74da4bebb01d45ccf17e73af192b8e981e4b85 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Jul 2025 18:17:14 +0000 Subject: [PATCH 3/6] Update NoSEH flag test with corrected PE header property name Co-authored-by: agocke <515774+agocke@users.noreply.github.com> --- .../test/Mono.Linker.Tests/TestCases/IndividualTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs index 9a877675495a5d..75abdf0028a271 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs @@ -288,8 +288,8 @@ public void NoSEHFlagIsSetInPEHeader() using (var peReader = new PEReader(fileStream)) { var peHeaders = peReader.PEHeaders; - var characteristics = peHeaders.CofHeader.Characteristics; - var dllCharacteristics = peHeaders.PEHeader.DllCharacteristics; + var characteristics = peHeaders.CoffHeader.Characteristics; + var dllCharacteristics = peHeaders.PEHeader!.DllCharacteristics; // IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 const DllCharacteristics NoSEH = (DllCharacteristics)0x0400; From 976e82383020189d6f70aaa071d38ebaf872e53a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Jul 2025 19:23:47 +0000 Subject: [PATCH 4/6] Fix ambiguous namespace compiler errors in dotnet-linker-tests Remove broad using statements for System.Reflection.Metadata and System.Reflection.PortableExecutable namespaces that were causing ambiguity with existing Individual test namespaces. Fully qualify the PE types to avoid conflicts. Co-authored-by: agocke <515774+agocke@users.noreply.github.com> --- .../test/Mono.Linker.Tests/TestCases/IndividualTests.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs index 75abdf0028a271..fec9b2a5a3ac92 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs @@ -17,8 +17,6 @@ using Mono.Linker.Tests.Extensions; using Mono.Linker.Tests.TestCasesRunner; using NUnit.Framework; -using System.Reflection.Metadata; -using System.Reflection.PortableExecutable; namespace Mono.Linker.Tests.TestCases { @@ -285,14 +283,14 @@ public void NoSEHFlagIsSetInPEHeader() // Check PE header for NoSEH flag using (var fileStream = new FileStream(outputPath, FileMode.Open, FileAccess.Read)) - using (var peReader = new PEReader(fileStream)) + using (var peReader = new System.Reflection.PortableExecutable.PEReader(fileStream)) { var peHeaders = peReader.PEHeaders; var characteristics = peHeaders.CoffHeader.Characteristics; var dllCharacteristics = peHeaders.PEHeader!.DllCharacteristics; // IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 - const DllCharacteristics NoSEH = (DllCharacteristics)0x0400; + const System.Reflection.PortableExecutable.DllCharacteristics NoSEH = (System.Reflection.PortableExecutable.DllCharacteristics)0x0400; Assert.That(dllCharacteristics & NoSEH, Is.EqualTo(NoSEH), $"NoSEH flag (0x0400) is not set in PE header. DllCharacteristics: 0x{dllCharacteristics:X}"); From 8d3a5d85e796327999e98215bffc17b5d3d1b043 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 6 Aug 2025 02:19:04 +0000 Subject: [PATCH 5/6] Set NoSEH flag for crossgened modules in ILLink output Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com> --- src/tools/illink/src/linker/Linker.Steps/OutputStep.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs b/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs index 5c5b24749f1951..779fbcdc3ec355 100644 --- a/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs @@ -100,6 +100,7 @@ protected virtual void WriteAssembly(AssemblyDefinition assembly, string directo module.Attributes |= ModuleAttributes.ILOnly; module.Attributes ^= ModuleAttributes.ILLibrary; module.Architecture = TargetArchitecture.I386; // I386+ILOnly which ultimately translates to AnyCPU + module.Characteristics |= ModuleCharacteristics.NoSEH; } } From c9fa6e0c072c579f62c3b82c369a07619e2a1594 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 6 Aug 2025 14:49:55 +0000 Subject: [PATCH 6/6] Remove NoSEH flag test as requested Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com> --- .../CommandLine/NoSEHFlagIsSet.cs | 24 ----------------- .../TestCases/IndividualTests.cs | 27 ------------------- 2 files changed, 51 deletions(-) delete mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs deleted file mode 100644 index 469a1b64aa2400..00000000000000 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CommandLine/NoSEHFlagIsSet.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Metadata; - -namespace Mono.Linker.Tests.Cases.CommandLine -{ - /// - /// This test case verifies that the NoSEH flag is set in the PE header - /// when running ILLink on a sample application that has been R2R-stripped. - /// - public class NoSEHFlagIsSet - { - public static void Main() - { - // Simple test case - just call a method - TestMethod(); - } - - [Kept] - static void TestMethod() - { - // Simple implementation - } - } -} \ No newline at end of file diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs index fec9b2a5a3ac92..e919363365a279 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCases/IndividualTests.cs @@ -8,7 +8,6 @@ using System.Runtime.Serialization.Json; using System.Xml; using Mono.Cecil; -using Mono.Linker.Tests.Cases.CommandLine; using Mono.Linker.Tests.Cases.CommandLine.Mvid; using Mono.Linker.Tests.Cases.Interop.PInvoke.Individual; using Mono.Linker.Tests.Cases.References.Individual; @@ -270,31 +269,5 @@ protected virtual TrimmedTestCaseResult Run(TestCase testCase, out TestRunner ru runner = new TestRunner(new ObjectFactory()); return runner.Run(testCase); } - - [Test] - public void NoSEHFlagIsSetInPEHeader() - { - var testcase = CreateIndividualCase(typeof(NoSEHFlagIsSet)); - var result = Run(testcase); - - var outputPath = result.OutputAssemblyPath; - if (!outputPath.Exists()) - Assert.Fail($"The linked assembly is missing. Expected it to exist at {outputPath}"); - - // Check PE header for NoSEH flag - using (var fileStream = new FileStream(outputPath, FileMode.Open, FileAccess.Read)) - using (var peReader = new System.Reflection.PortableExecutable.PEReader(fileStream)) - { - var peHeaders = peReader.PEHeaders; - var characteristics = peHeaders.CoffHeader.Characteristics; - var dllCharacteristics = peHeaders.PEHeader!.DllCharacteristics; - - // IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 - const System.Reflection.PortableExecutable.DllCharacteristics NoSEH = (System.Reflection.PortableExecutable.DllCharacteristics)0x0400; - - Assert.That(dllCharacteristics & NoSEH, Is.EqualTo(NoSEH), - $"NoSEH flag (0x0400) is not set in PE header. DllCharacteristics: 0x{dllCharacteristics:X}"); - } - } } }