SOS.DLL在windbg里加载错误

sos.dll/mscordacwks.dll

公共语言运行库(CLR)是执行托管代码的Microsoft.NET框架的核心引擎。简单地说,它通过在托管程序集中使用中间语言和元数据,JIT按需编译代码,构建程序集定义和使用的类型的内存表示,并确保生成的代码是安全的、安全的和可验证的,并在需要时执行。这个引擎本身是用本机代码实现的。当我们想使用本机调试器(如CDB或WinDBG)调试.NET应用程序时(如果我们想使用事后内存转储文件调试它,我们目前做了很多工作),我们必须在本机调试器和托管世界之间使用“桥”,因为本机调试器本身并不理解托管代码。它是本机调试器。
为了提供这个桥,CLR附带了一个调试扩展名SOS.DLL。这理解CLR的内部结构,因此允许我们执行诸如输出托管调用堆栈、转储托管堆等操作。
但是,这些内部数据结构和CLR的详细信息会不时发生变化,因此,从使.NET应用程序工作的CLR的实际内部实现中抽象出此调试器扩展所需的CLR接口是非常有用的。输入mscordacwks.dll。这提供了数据访问组件(DAC),该组件允许SOS.DLL调试器扩展解释维护.NET应用程序状态的内存中数据结构。

如果您在框架文件夹中查看,则应始终看到这些dll的匹配集:

  • 32位的
    C:\Windows\Microsoft.NET\Framework\v4.0.30319
  • 64位的
    C:\Windows\Microsoft.NET\Framework64\v4.0.30319

错误表现

很多时候当你这样做的时候你会得到这个错误。

  1. .load sos

    0:080> .load sos

    The call to LoadLibrary(sos) failed, Win32 error 0n2
    "The system cannot find the file specified."
    Please check your debugger configuration and/or network access.
    You can solve this by doing .loadby sos clr, this means you are trying to load sos.dll from the same location you loaded clr.dll from.

    This is a different error
  2. .loadby sos clr

    0:091> .loadby sos clr

    Unable to find module 'clr'
    我问自己的第一个问题是,我是否在用64位调试器调试32位应用程序,如果不是,我要列出所有加载的模块
    在本例中,我看到没有加载clr.dll,但mscorwks是因为我正在调试的应用程序使用的是.net framework 2.0

    0:091> lm

    start             end                 module name

    00000000`1b6d0000 00000000`1b9cf000   System_Data   (deferred)            

    00000000`1e230000 00000000`1e279000   System_Transactions   (deferred)            

    00000000`714b0000 00000000`71556000   System_Core   (deferred)            

    00000000`77610000 00000000`777b9000   ntdll      (private pdb symbols)  d:\symbols\ntdll.pdb\15EB43E23B12409C84E3CC7635BAF5A32\ntdll.pdb

    00000642`ffaf0000 00000642`ffb09000   mscorsec   (deferred)            

    000007fe`dae40000 000007fe`db68b000   System_Data_ni   (deferred)            

    000007fe`e07b0000 000007fe`e0945000   System_DirectoryServices_ni   (deferred)            

    000007fe`e0950000 000007fe`e0a5d000   System_EnterpriseServices_ni   (deferred)            

    000007fe`e0a60000 000007fe`e0b45000   System_Transactions_ni   (deferred)            

    000007fe`eb380000 000007fe`ec25c000   mscorlib_ni   (deferred)            

    000007fe`ec260000 000007fe`ecbfc000   mscorwks   (deferred)           

  3. .loadby sos mscorwks

    Failed to load data access DLL, 0x80004005 
    Verify that

                1) you have a recent build of the debugger (6.2.14 or newer) 

                2) the file mscordacwks.dll that matches your version of mscorwks.dll is 
                    in the version directory 
                3) or, if you are debugging a dump file, verify that the file 
                    mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path. 
                4) you are debugging on the same architecture as the dump file. 
                    For example, an IA64 dump file must be debugged on an IA64 
                    machine.

    You can also run the debugger command .cordll to control the debugger's
    load of mscordacwks.dll.  .cordll -ve -u -l will do a verbose reload.
    If that succeeds, the SOS command should work on retry.

    If you are debugging a minidump, you need to make sure that your executable
    path is pointing to mscorwks.dll as well.

这些错误消息通常是人们在尝试使用WinDBG/CDB使用SOS调试器扩展调试.NET/CLR应用程序转储时遇到的问题,这意味着SOS.DLL调试器扩展无法找到匹配的mscordacwks.DLL,它需要能够调试您尝试调试的转储文件。如果调试的是实时应用程序,调试器扩展将自动从框架目录中查找并加载mscordacwks.dll。

如果您正在调试一个转储文件,该文件从使用不同版本(例如,不同安装的服务包或修补程序)的CLR应用程序到本地系统上安装的应用程序,或者.NET框架安装在系统上与其安装位置不同的位置,并且调试器无法通过其他方式找到正确的mscordacwks.dll。因为拥有匹配的mscordacwks.dll对于SOS.dll的正常工作非常重要,所以SOS有很多技巧可以找到它。特别是,如果对符号服务器进行了正确的索引,调试器将从那里加载它。调试器还将在调试器目录中查找它,前提是它已以特殊方式重命名

怎么解决

大多数情况下,如果已正确设置了符号路径(无论如何,在调试任何内容时都需要设置该路径,更不用说托管应用程序),则调试器应能够自动从符号服务器获取正确的mscordacwks.dll,执行下面的指令系列:

  1. !sym noisy
  2. .symfix 路径
  3. .cordll -ve -u -l

如果做了上述工作,还不起作用,我们还可以这样做:

最简单的方法是让给您转储文件的人给您mscordacwks.dll的副本。一旦你有了它,检查它的文件属性的版本号。应该是2.0.50727.xxxx。然后将其重命名为mscordacwks_AAA_AAA_2.0.50727.xxxx.dll。其中,xxxx是版本号的适当位,AAA是x86还是AMD64,这取决于您处理的是32位还是64位应用程序转储。(在我们提到x64之前,AMD64是一个遗留的东西)。然后将这个重命名的副本放入调试器目录(安装WinDBG的目录)。然后,根据错误消息,告诉调试器重试:.cordll -ve -u -l
尽管我们试图确保发布的每个CLR版本(作为服务包、修补程序或其他版本)在公共符号服务器上都有其mscordacwks.dll索引,但不幸的是,有时不会发生这种情况。但由于它总是作为CLR的一部分发布,所以您总是可以选择从转储的机器获取它。

如果你按上面指示跑了.cordll -ve -u -l收到了这样的信息:
CLR DLL status: ERROR: Unable to load DLL mscordacwks_AMD64_x86_2.0.50727.3053.dll, Win32 error 0n87

这意味着您很可能使用64位调试器在64位系统上转储32位进程(在WoW64下运行),现在您正尝试使用64位调试器分析转储。这就是消息引用AMD64和x86的原因。这是行不通的。因为SOS.DLL扩展实际上在调试需要匹配的位时使用了框架。我强烈建议始终使用与进程相同位的调试器生成转储(因此,即使系统是x64系统,也要为WoW64进程生成x86调试器),并使用生成转储的调试器的相同位分析转储。当然,这意味着您不能在32位系统上调试64位转储。这还意味着您必须安装框架来调试托管应用程序转储。

你还可能看到下面的信息输出:

0:018> .cordll -ve -u -l
CLRDLL: ERROR: DLL C:WindowsMicrosoft.NETFrameworkv2.0.50727mscordacwks.dll init failure, Win32 error 0n87
CLR DLL status: ERROR: DLL C:WindowsMicrosoft.NETFrameworkv2.0.50727mscordacwks.dll init failure, Win32 error 0n87

这也意味着有点混乱。我在使用32位调试器分析使用64位调试器生成的WoW64进程的转储时看到了这一点。

posted on 2019-11-18 17:11  活着的虫子  阅读(1889)  评论(2编辑  收藏  举报

导航