diff --git a/debuggees.sln b/debuggees.sln index abffc6dacd..dc3ff8c030 100644 --- a/debuggees.sln +++ b/debuggees.sln @@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SymbolTestDll", "src\SOS\SO EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LineNums", "src\SOS\SOS.UnitTests\Debuggees\LineNums\LineNums.csproj", "{84881FB8-37E1-4D9B-B27E-9831C30DCC04}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GCPOH", "src\SOS\SOS.UnitTests\Debuggees\GCPOH\GCPOH.csproj", "{0A34CA51-8B8C-41A1-BE24-AB2C574EA144}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Checked|Any CPU = Checked|Any CPU @@ -621,6 +623,46 @@ Global {84881FB8-37E1-4D9B-B27E-9831C30DCC04}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {84881FB8-37E1-4D9B-B27E-9831C30DCC04}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU {84881FB8-37E1-4D9B-B27E-9831C30DCC04}.RelWithDebInfo|x86.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|Any CPU.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM64.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|ARM64.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x64.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x64.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x86.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Checked|x86.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|ARM64.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x64.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x64.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x86.ActiveCfg = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Debug|x86.Build.0 = Debug|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|Any CPU.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM64.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|ARM64.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x64.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x64.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x86.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.Release|x86.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM64.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|ARM64.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144}.RelWithDebInfo|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -642,6 +684,7 @@ Global {112FE2A7-3FD2-4496-8A14-171898AD5CF5} = {C3072949-6D24-451B-A308-2F3621F858B0} {8C27904A-47C0-44C7-B191-88FF34580CBE} = {C3072949-6D24-451B-A308-2F3621F858B0} {84881FB8-37E1-4D9B-B27E-9831C30DCC04} = {C3072949-6D24-451B-A308-2F3621F858B0} + {0A34CA51-8B8C-41A1-BE24-AB2C574EA144} = {C3072949-6D24-451B-A308-2F3621F858B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {46465737-C938-44FC-BE1A-4CE139EBB5E0} diff --git a/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.cs b/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.cs new file mode 100644 index 0000000000..a16244e924 --- /dev/null +++ b/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.cs @@ -0,0 +1,23 @@ +using System; +using System.IO; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.InteropServices; + +class GCPOH +{ + static int Main() + { + // Use reflection to get the API because the test is compiled against an older version of netstandard + // that doesn't have the POH APIs + Assembly corlib = typeof(Object).Assembly; + Type gc = corlib.GetType("System.GC"); + MethodInfo method = gc.GetMethod("AllocateArray", BindingFlags.Public | BindingFlags.Static); + MethodInfo generic = method.MakeGenericMethod(typeof(byte)); + // Calls GC.AllocateArray(size: 100, pinned: true) + byte[] myArray = (byte[])generic.Invoke(null, new object[] { 100, true }); + Debugger.Break(); + GC.KeepAlive(myArray); + return 0; + } +} diff --git a/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.csproj b/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.csproj new file mode 100644 index 0000000000..25ce9e1dd2 --- /dev/null +++ b/src/SOS/SOS.UnitTests/Debuggees/GCPOH/GCPOH.csproj @@ -0,0 +1,7 @@ + + + Exe + $(BuildProjectFramework) + netcoreapp2.1;netcoreapp3.1 + + diff --git a/src/SOS/SOS.UnitTests/SOS.cs b/src/SOS/SOS.UnitTests/SOS.cs index 338abcec29..943dd5b909 100644 --- a/src/SOS/SOS.UnitTests/SOS.cs +++ b/src/SOS/SOS.UnitTests/SOS.cs @@ -121,6 +121,17 @@ public async Task GCTests(TestConfiguration config) await RunTest(config, "GCWhere", "GCTests.script", testName: "SOS.GCTests", testDump: false); } + [SkippableTheory, MemberData(nameof(Configurations))] + public async Task GCPOHTests(TestConfiguration config) + { + if (!config.IsNETCore || config.RuntimeFrameworkVersionMajor < 5) + { + throw new SkipTestException("This test validates POH behavior, which was introduced in .net 5"); + } + + await RunTest(config, "GCPOH", "GCPOH.script", testName: "SOS.GCPOHTests", testDump: false); + } + [SkippableTheory, MemberData(nameof(Configurations))] public async Task Overflow(TestConfiguration config) { diff --git a/src/SOS/SOS.UnitTests/Scripts/GCPOH.script b/src/SOS/SOS.UnitTests/Scripts/GCPOH.script new file mode 100644 index 0000000000..182a8a7820 --- /dev/null +++ b/src/SOS/SOS.UnitTests/Scripts/GCPOH.script @@ -0,0 +1,66 @@ +# +# Tests various SOS GC and object based commands on the pinned object heap (POH). +# +# Commands Verified: GCWhere, GCRoot, DumpObj, DumpHeap, DumpStackObjects +# +# 1) Run to the first debug break +# 2) Load sos +# 3) Dump stack objects to get the address of GCWhere!temp +# 4) Run various commands on the address, verify POH +#11) Let the program run to completion + +# Continue to the DebugBreak +CONTINUE +IFDEF:CDB +VERIFY:Break instruction exception - code 80000003 +ENDIF:CDB + +LOADSOS + +SOSCOMMAND:DumpStackObjects +VERIFY:\s+\s+System.Byte\[\]\s+ + +SOSCOMMAND:DumpObj \w+\s+()\s+(System.Byte\[\]!\$0_)*System.Byte\[\]\s+ +VERIFY:\s+Name: System.Byte\[\]\s+ +VERIFY:\s+Array: Rank 1, Number of elements 100, Type Byte\s+ + +SOSCOMMAND:GCWhere +# we care that the Gen is 4 (POH) +VERIFY:\s+4\s+\d\s+\s+\s+\s+0x\s*\(\d+\) + +SOSCOMMAND:GCRoot +VERIFY:.*Thread : +VERIFY:\s+\s+\s+GCPOH\.Main\(\)\s+\[.*[Gg][Cc][Pp][Oo][Hh]\.cs\s+@\s+19\]\s+ + +SOSCOMMAND:GCRoot -all +VERIFY:.*Thread : +VERIFY:\s+\s+\s+GCPOH\.Main\(\)\s+\[.*[Gg][Cc][Pp][Oo][Hh]\.cs\s+@\s+19\]\s+ + +SOSCOMMAND:DumpHeap +VERIFY:\s+\s+\s+\s+ + +SOSCOMMAND:DumpHeap -stat +VERIFY:\s*Statistics:\s+ +VERIFY:\s+MT\s+Count\s+TotalSize\s+Class\s+Name\s+ +VERIFY:\s+\s+\s+\s+System.Byte\[\]\s+ + +SOSCOMMAND:EEHeap +VERIFY:\s*Loader Heap:\s+ +VERIFY:\s+System Domain:\s+\s+ +VERIFY:\s+LowFrequencyHeap:\s+.*bytes.*\s+ +VERIFY:\s+HighFrequencyHeap:\s+.*bytes.*\s+ +VERIFY:\s+Total size:\s+Size:\s+0x\s+\(|lu\)\s+bytes\.\s+ +VERIFY:\s+Jit code heap:\s+ +VERIFY:\s+LoaderCodeHeap:\s+.*bytes\.\s+ +VERIFY:\s+Total LoaderHeap size:\s+Size:\s+0x\s+\(|lu\)\s+bytes\.\s+ +VERIFY:\s+Number of GC Heaps:\s+\s+ +VERIFY:\s+generation\s+\s+starts\s+at\s+0x\s+ +VERIFY:\s+generation\s+\s+starts\s+at\s+0x\s+ +VERIFY:\s+generation\s+\s+starts\s+at\s+0x\s+ +VERIFY:\s+segment\s+begin\s+allocated\s+size\s+ +VERIFY:\s+\s+\s+\s+0x\(\) +VERIFY:\s+Large object heap starts at 0x\s+ +VERIFY:\s+Pinned object heap starts at 0x\s+ + +# Continue to the next DebugBreak +CONTINUE