1010using BenchmarkDotNet . Portability ;
1111using JetBrains . Annotations ;
1212using System . ComponentModel ;
13+ using Microsoft . Diagnostics . NETCore . Client ;
1314
1415namespace BenchmarkDotNet . Disassemblers
1516{
@@ -58,7 +59,7 @@ private static ulong GetMinValidAddress()
5859 {
5960 Environments . Platform . X86 or Environments . Platform . X64 => 4096 ,
6061 Environments . Platform . Arm64 => 0x100000000 ,
61- _ => throw new NotSupportedException ( $ "{ RuntimeInformation . GetCurrentPlatform ( ) } is not supported")
62+ var platform => throw new NotSupportedException ( $ "{ platform } is not supported")
6263 } ;
6364 throw new NotSupportedException ( $ "{ System . Runtime . InteropServices . RuntimeInformation . OSDescription } is not supported") ;
6465 }
@@ -71,14 +72,53 @@ private static bool IsValidAddress(ulong address)
7172 && address != 0
7273 && address >= MinValidAddress ;
7374
75+ private DataTarget Attach ( int processId )
76+ {
77+ bool isSelf = processId == System . Diagnostics . Process . GetCurrentProcess ( ) . Id ;
78+ if ( OsDetector . IsWindows ( ) )
79+ {
80+ // Windows CoreCLR fails to disassemble generic types when using CreateSnapshotAndAttach, and succeeds with AttachToProcess. https://github.com/microsoft/clrmd/issues/1334
81+ return isSelf && ! RuntimeInformation . IsNetCore
82+ ? DataTarget . CreateSnapshotAndAttach ( processId )
83+ : DataTarget . AttachToProcess ( processId , suspend : false ) ;
84+ }
85+ if ( OsDetector . IsLinux ( ) )
86+ {
87+ // Linux crashes when using AttachToProcess in the same process.
88+ return isSelf
89+ ? DataTarget . CreateSnapshotAndAttach ( processId )
90+ : DataTarget . AttachToProcess ( processId , suspend : false ) ;
91+ }
92+ if ( OsDetector . IsMacOS ( ) )
93+ {
94+ // ClrMD does not support CreateSnapshotAndAttach on MacOS, and AttachToProcess is unreliable, so we have to create a dump file and load it.
95+ string ? dumpPath = Path . GetTempFileName ( ) ;
96+ try
97+ {
98+ try
99+ {
100+ new DiagnosticsClient ( processId ) . WriteDump ( DumpType . Full , dumpPath , logDumpGeneration : false ) ;
101+ }
102+ catch ( ServerErrorException sxe )
103+ {
104+ throw new ArgumentException ( $ "Unable to create a snapshot of process { processId : x} .", sxe ) ;
105+ }
106+ return DataTarget . LoadDump ( dumpPath ) ;
107+ }
108+ finally
109+ {
110+ if ( dumpPath != null )
111+ {
112+ File . Delete ( dumpPath ) ;
113+ }
114+ }
115+ }
116+ throw new NotSupportedException ( $ "{ System . Runtime . InteropServices . RuntimeInformation . OSDescription } is not supported") ;
117+ }
118+
74119 internal DisassemblyResult AttachAndDisassemble ( ClrMdArgs settings )
75120 {
76- // Windows CoreCLR fails to disassemble generic types when using CreateSnapshotAndAttach, and succeeds with AttachToProcess. https://github.com/microsoft/clrmd/issues/1334
77- // Non-Windows (Linux) crashes when using AttachToProcess in the same process.
78- bool createSnapshot = ( ! OsDetector . IsWindows ( ) || ! RuntimeInformation . IsNetCore ) && settings . ProcessId == System . Diagnostics . Process . GetCurrentProcess ( ) . Id ;
79- using var dataTarget = createSnapshot
80- ? DataTarget . CreateSnapshotAndAttach ( settings . ProcessId )
81- : DataTarget . AttachToProcess ( settings . ProcessId , suspend : false ) ;
121+ using var dataTarget = Attach ( settings . ProcessId ) ;
82122
83123 var runtime = dataTarget . ClrVersions . Single ( ) . CreateRuntime ( ) ;
84124
0 commit comments