.NET应用程序的本机访问冲突

时间:2014-05-22 13:16:42

标签: .net windbg access-violation il memory-dump

我们遇到.NET应用程序的问题。它在关闭时随机产生本机访问冲突(因此不是.NET异常)。

  • Windows Server 2012 x64(在刀片系统上运行的虚拟机)
  • .NET 4.0 Framework(已安装4.5)
  • 我们的应用程序是.NET x86应用程序(不是AnyCPU;不是ASP.NET)
  • 第三方本机模块使用SQL CE 3.5,其他

来自Windows事件日志的错误报告看起来像这样(省略了应用程序和模块名称,我从德语翻译了条目):

Exceptioncode: 0xc0000005
Offset: 0x00006a9e
Process ID: 0xfe8
...

我发现0xc0000005是一种访问冲突。由于.NET NullReferenceException,也可能发生这种情况。当Windows错误报告对话框打开时,我们已经用ProcDump标志-ma创建了一个完整的内存转储。

当我打开这个转储时,我找不到除.exe文件本身以外的任何.NET模块。我不是本地编程方面的专家,只知道一些关于WinDbg的基础知识。

所以我做了什么:

  1. 使用WinDbg打开转储
  2. 使用

    设置符号路径
    .sympath SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols;C:\PathToMatchingPDBs\ForTheProgram
    
  3. 使用

    重新加载所有符号
    .reload /d /f
    
    Reloading current modules
    ...*** ERROR: Symbol file could not be found.  Defaulted to export symbols for sysfer.dll - 
    ...
    
  4. ~* k输出

    .  0  Id: 1560.19a4 Suspend: 0 Teb: ff20e000 Unfrozen
    ChildEBP RetAddr  
    0058f0e8 7744c752 ntdll!ZwWaitForMultipleObjects+0xc
    0058f26c 76d256c0 KERNELBASE!WaitForMultipleObjectsEx+0x10b
    0058f2e0 76d2586a kernel32!WerpReportFaultInternal+0x1c4
    0058f2f4 76cf7828 kernel32!WerpReportFault+0x6d
    0058f300 774d07c4 kernel32!BasepReportFault+0x19
    0058f39c 7762c11c KERNELBASE!UnhandledExceptionFilter+0x1f1
    0058f3a4 775f3334 ntdll!__RtlUserThreadStart+0x57
    0058f3b8 77691fd7 ntdll!_EH4_CallFilterFunc+0x12
    0058f3e0 77693612 ntdll!_except_handler4_common+0x8e
    0058f400 775f30f1 ntdll!_except_handler4+0x20
    0058f424 775f30c3 ntdll!ExecuteHandler2+0x26
    0058f4ec 775f2f2b ntdll!ExecuteHandler+0x24
    0058f4ec 00406a9e ntdll!KiUserExceptionDispatcher+0xf
    0058f844 7760ac69 MyProgram!COM+_Entry_Point <PERF> (MyProgram+0x6a9e)
    0058f888 7760ac3c ntdll!__RtlUserThreadStart+0x72
    0058f8a0 00000000 ntdll!_RtlUserThreadStart+0x1
    
  5. 下一部分我很不确定我做的是否正确。我在某处读到你可以获取RetAddr列的地址并将其传递给uf以查看此时该函数的作用。它是否正确?所以我期待以下命令显示MyProgram + 0x6a9e函数的反汇编,参见上面的调用堆栈。

    >uf 0x00406a9e
    MyProgram!COM+_Entry_Point <PERF> (MyProgram +0x6a9e):
    00406a9e ff2500204000    jmp     dword ptr [MyProgram!COM+_Entry_Point <PERF> (MyProgram+0x2000) (00402000)]
    
    mscoree!_CorExeMain_Exported:
    707f4ddb 8bff            mov     edi,edi
    707f4ddd 56              push    esi
    707f4dde e80c2f0000      call    mscoree!ShellShim__CorExeMain (707f7cef)
    707f4de3 6a00            push    0
    707f4de5 8bf0            mov     esi,eax
    707f4de7 e84bc4ffff      call    mscoree!GetShimImpl (707f1237)
    707f4dec e93a800000      jmp     mscoree!_CorExeMain_Exported+0x11 (707fce2b)
    
    mscoree!_CorExeMain_Exported+0x11:
    707fce2b 83f801          cmp     eax,1
    707fce2e 750a            jne     mscoree!_CorExeMain_Exported+0x20 (707fce3a)
    
    mscoree!_CorExeMain_Exported+0x16:
    707fce30 6858378370      push    offset mscoree!g_wszShimImplDllPath (70833758)
    707fce35 e826350100      call    mscoree!DisplayMessageBoxForNoShimImpl (70810360)
    
    mscoree!_CorExeMain_Exported+0x20:
    707fce3a 8bc6            mov     eax,esi
    707fce3c 5e              pop     esi
    707fce3d c3              ret
    

    我不确定如何解释这一点。由于CoreExeMain Exports,我看起来这真的是应用程序的切入点?那么这里没有那么多有用的信息,或者?只有在本机代码级别出现问题;据我所解释。

  6. 只是为了完整性:

    .loadby sos clr
    Unable to find module ‘clr’
    !pe
    No export pe found.
    

    当我使用Visual Studio打开转储时,也没有发现异常。

    这就是我走了多远。也许有人可以帮我解释这些数据和/或给我一些提示我还能尝试什么?

    我的问题:

    • 使用Reflection.Emit生成IL-Code会导致此类错误吗?
    • 如何进一步分析问题/找到原因?
    • COM + _Entry_Point是什么意思。这是我的应用程序的主要入口点还是与某些外部组件有关?

    修改

    @Jochen Kalmbach

    .ecxr;kP
    
    Minidump doesn't have an exception context
    Unable to get exception context, HRESULT 0x80004002
    ChildEBP RetAddr  
    0058f0e8 7744c752 ntdll!ZwWaitForMultipleObjects+0xc
    0058f26c 76d256c0 KERNELBASE!WaitForMultipleObjectsEx+0x10b
    0058f2e0 76d2586a kernel32!WerpReportFaultInternal+0x1c4
    0058f2f4 76cf7828 kernel32!WerpReportFault+0x6d
    0058f300 774d07c4 kernel32!BasepReportFault+0x19
    0058f39c 7762c11c KERNELBASE!UnhandledExceptionFilter+0x1f1
    0058f3a4 775f3334 ntdll!__RtlUserThreadStart+0x57
    0058f3b8 77691fd7 ntdll!_EH4_CallFilterFunc+0x12
    0058f3e0 77693612 ntdll!_except_handler4_common+0x8e
    0058f400 775f30f1 ntdll!_except_handler4+0x20
    0058f424 775f30c3 ntdll!ExecuteHandler2+0x26
    0058f4ec 775f2f2b ntdll!ExecuteHandler+0x24
    0058f4ec 00406a9e ntdll!KiUserExceptionDispatcher+0xf
    0058f844 7760ac69 MyProgram!COM+_Entry_Point <PERF> 
    0058f888 7760ac3c ntdll!__RtlUserThreadStart+0x72
    0058f8a0 00000000 ntdll!_RtlUserThreadStart+0x1b
    

    为何选择minidump?

    @Thomas W。

    lm
    
    start    end        module name
    00400000 0040c000   MyProgram   (private pdb symbols)  c:\...\release\MyProgram.pdb
    707f0000 7083a000   mscoree    (pdb symbols)          c:\symbols\mscoree.pdb\7608F9FF3C954E429A27D833164E4BEE2\mscoree.pdb
    74b70000 74bdd000   sysfer     (export symbols)       sysfer.dll
    76cc0000 76df0000   kernel32   (pdb symbols)          c:\symbols\wkernel32.pdb\CFACA818EC334A5EAD707CD86C847B4A1\wkernel32.pdb
    77440000 774e6000   KERNELBASE   (pdb symbols)          c:\symbols\wkernelbase.pdb\CAE0056433064B78937D9022B20FA1102\wkernelbase.pdb
    775b0000 77707000   ntdll      (private pdb symbols)  c:\symbols\wntdll.pdb\EC83D8DF555946E0B630133EBD9792662\wntdll.pdb
    

    修改2

    其他信息:

    !heap
    Index   Address  Name      Debugging options enabled
      1:   009c0000                
      2:   006b0000                
      3:   00770000                
      4:   00d00000
    
    
    !heap -a
    Index   Address  Name      Debugging options enabled
      1:   009c0000 
        Segment at 009c0000 to 00abf000 (0000b000 bytes committed)
      2:   006b0000 
        Segment at 006b0000 to 006bf000 (00003000 bytes committed)
        Segment at 00810000 to 0090f000 (00042000 bytes committed)
      3:   00770000 
        Segment at 00770000 to 0077f000 (00003000 bytes committed)
      4:   00d00000 
        Segment at 00d00000 to 00d3f000 (00001000 bytes committed)
    
    
    !heap -l
    Searching the memory for potential unreachable busy blocks.
    Heap 009c0000
    Heap 006b0000
    Heap 00770000
    Heap 00d00000
    Scanning VM ...
    Scanning references from 204 busy blocks (0 MBytes) ...
    Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
    -----------------------------------------------------------------------------
    006b07c0  006b07c8  006b0000  006b0000        88       220         8  busy 
    007707c0  007707c8  00770000  00770000        88       220         8  busy 
    2 potential unreachable blocks were detected.
    

    那是什么意思?

2 个答案:

答案 0 :(得分:5)

这还不是答案,但评论太长了。按照出现的顺序:

  

“当Windows错误报告对话框打开时。”

在Windows错误报告已经使用该进程时进行崩溃转储不能很好地工作。 而是直接使用ProcDump运行应用程序:

procdump -e -ma -x c:\MyDump.dmp C:\PathTo\MyApplication.exe Arguments

ProcDeump将在发生异常时生成故障转储。 如果这对您不起作用,请让Windows错误报告将转储保存在磁盘上。有关注册表设置,请参阅Collecting User Mode dumps。对于.NET,请务必将DumpType设置为2.

  

“我找不到任何加载的.NET模块”

您是如何检查.NET模块的?您可以使用lm列出所有模块,看看是否找到了一些您知道的DLL。

  

“使用...设置符号路径”

没关系。如果您不想键入所有HTTP内容,也可以使用

.symfix C:\Symbols
.sympath+ C:\PathToMatchingPDBs\ForTheProgram
  

“〜* k输出KERNELBASE!UnhandledExceptionFilter + 0x1f1”

这可能是您没有获得有关原始异常的大量信息的原因:异常只是由Windows错误报告处理。

  

“无法找到模块'clr'”

您确定它是.NET 4应用程序吗?尝试.loadby sos mscorwks查看它是否是.NET 2.如果这也无济于事,请检查lm m ms*以查找其他类似.NET的程序集。

答案 1 :(得分:0)

在windbg中加载转储并执行!analyze -v如果符号是好的,你应该得到一个
准确的结果,包括源代码行

获取返回地址并将其提供给uf将无法获得任何有用的信息

uf执行控制流,如果某个随机dll中return address points to a jmp to some random function uf will simply dump the random function

return address is pushed into the stack by the callee

如果您ub <return address>,则可以找到callee

应该是call blah <0x.......>

现在执行uf on the callee uf <0x........>查看通话的内容 最有可能看起来它正在执行未处理的异常