当一个进程中加载多个.NET Runtime的时候如何在托管调试中加载指定的mscordacwks.dll

当多个.NETRuntime加载在一个目标进程或一个dump文件中,例如:

 0:030> lm

 start end module name

 00000000'1b6d0000 00000000'1b9ba000 System_Data (deferred)

...

 000007fe'f3e60000 000007fe'f47c5000 clr (deferred)

...

 000007fe'f9880000 000007fe'fa230000 mscorwks (deferred)

...

0:030> lmvm clr

 start end module name

 000007fe'f3e60000 000007fe'f47c5000 clr (deferred)

Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll

 Image name: clr.dll

  ......

 CompanyName: Microsoft Corporation

 ProductName: Microsoft® .NET Framework

 InternalName: clr.dll

 OriginalFilename: clr.dll

 ProductVersion: 4.0.30319.1

 FileVersion: 4.0.30319.1 (RTMRel.030319-0100)

 PrivateBuild: DDBLD431

 FileDescription: Microsoft .NET Runtime Common Language Runtime - WorkStation

 LegalCopyright: © Microsoft Corporation. All rights reserved.

 Comments: Flavor=Retail

0:030> lmvm mscorwks

 start end module name

 000007fe'f9880000 000007fe'fa230000 mscorwks (deferred)

Image path: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll

 Image name: mscorwks.dll

  .......

 CompanyName: Microsoft Corporation

 ProductName: Microsoft® .NET Framework

 InternalName: mscorwks.dll

 OriginalFilename: mscorwks.dll

 ProductVersion: 2.0.50727.4206

 FileVersion: 2.0.50727.4206 (VistaSP2GDR.050727-4200)

 FileDescription: Microsoft .NET Runtime Common Language Runtime - WorkStation

 LegalCopyright: © Microsoft Corporation. All rights reserved.

 Comments: Flavor=Retail

 .NET runtime 4.0中的clr.dll 和.NET runtime 2.0中的mscorwks.dll加载在一个进程中,托管调试可能会为错误的结果,如下面所示:

 0:030> .loadby sos mscorwks

0:030> !clrstack

OS Thread Id: 0x2674 (30)

Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in the process

其实线程30是一个托管线程,是.NET 2.0 的托管线程 ,但不是.NET 4.0的托管线程。

如果通过使用.cordll 来加载托管调试模块 mscordacwks.dll,如下所示,可以看到调试器总是会默认尝试为最新的.NET runtime加载mscordacwks.dll,在我们的示例里面是.NET runtime 4.0 运行库,这就是解释了为什么.NET runtime 2.0托管线程不能被正常调试。

 0:030> .cordll -ve -u -l

CLRDLL: Loaded DLL C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll

CLR DLL status: Loaded DLL

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll

在这种情况下如何加载指定的 mscordacwks.dll来进行托管调试?例如,加载托管调试模块.NET runtime 2.0的 mscorwks.dll 吗?假定匹配的 mscordacwks.dll 复制到文件夹 c:\tempzhong ,下列两个命令可以用来加载模块的托管调试:

  .cordll -ve -se -u -I <Start address of the target .NET runtime module> -N

或者

  .cordll -ve -se -u -I <Start address of the target .NET runtime module> -lp <path of the managed debugging module>

在我们的示例中,该命令为:

  *note* -N switch causes the debugger to search the matched mscordacwks.dll in the configured symbol path. -lp switch causes the debugger to load the matched mscordacwks.dll from the specified path.

0:030> .cordll -ve -se -u -I 000007fe'f9880000 -N

CLRDLL: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscordacwks.dll:2.0.50727.4952 f:0

doesn't match desired version 2.0.50727.4206 f:0

CLRDLL: Loaded DLL

\\SymbolShare\websymbols\mscordacwks_AMD64_AMD64_2.0.50727.4206.dll\4BF4C1819b0000\mscordacwks_AMD64_AMD64_2.0.50727.4206.dll

CLR DLL status: Loaded DLL

\\SymbolShare\websymbols\mscordacwks_AMD64_AMD64_2.0.50727.4206.dll\4BF4C1819b0000\mscordacwks_AMD64_AMD64_2.0.50727.4206.dll

....

或者

0:030> .cordll -ve -se -u -I 000007fe'f9880000 -lp c:\temp

CLRDLL: Loaded DLL c:\temp\mscordacwks.dll

CLR DLL status: Loaded DLL c:\temp\mscordacwks.dll

现在,通过执行托管调试命令可以得到正确结果。

0:030>.loadby sos mscorwks

0:030> !clrstack

OS Thread Id: 0x2674 (30)

(!clrstack processes a max of 1000 stack frames)

Child-SP RetAddr Call Site

0000000005fb71a0 000007fef6fc79b5 System.Net.Sockets.Socket.MultipleSend(System.Net.BufferOffsetSize[], System.Net.Sockets.SocketFlags)

0000000005fb7290 000007fef6fc747b System.Net.Sockets.NetworkStream.MultipleWrite(System.Net.BufferOffsetSize[])

0000000005fb7310 000007fef6fc7381 System.Net.ConnectStream.ResubmitWrite(System.Net.ConnectStream, Boolean)

0000000005fb73c0 000007fef6fc7240 System.Net.HttpWebRequest.EndWriteHeaders_Part2()

......