CLR Exception 0xE0434F4D和0xE0434352的区别

《根据《CLR Exception---E0434352》和《CLR Exception---E0434F4D》这两篇随笔,我们会发现,这两个异常太相似了,除了代码值不一样,其他几乎都一样。在windbg里调试dmp时,也会看到都叫它们CLR Exception。那他们有什么区别呢?这个问题值得研究研究。

我查了很多资料都没查明白。但是黄天不负有心人。在我搞其他问题时,让我窥得一线道道儿来。

首先上个实际的例子,在VS2013里新建一个c#控制台工程ConsoleApplication1,代码如下:

static void Main(string[] args)
{
            throw new System.Exception();
            return;
}

工程配置如下:

编译好后,用Windbg加载运行

 

 

输入g运行,接着会抛出异常中断

我们可以看到

此时抛出的异常是CLR exception---code e0434352

输入kv,观察下栈

0:000> kv
 # ChildEBP RetAddr  Args to Child              
00 00bcf214 7234ea5c e0434352 00000001 00000005 KERNELBASE!RaiseException+0x62 (FPO: [4,22,0])
01 00bcf2b0 7234f626 00000000 a4329156 00bcf3a0 clr!RaiseTheExceptionInternalOnly+0x230 (FPO: [SEH])
02 00bcf378 07550882 076023ac 076023a0 00bcf394 clr!IL_Throw+0x146 (FPO: [Non-Fpo])
WARNING: Frame IP not in any known module. Following frames may be wrong.
03 00bcf388 721af066 010184c0 00bcf3e8 721b2375 0x7550882
04 00bcf394 721b2375 00bcf430 00bcf3d8 7234e800 clr!CallDescrWorkerInternal+0x34
05 00bcf3e8 721bb3f5 00000000 076023a0 00bcf444 clr!CallDescrWorkerWithHandler+0x6b (FPO: [Non-Fpo])
06 00bcf45c 722c6d3f 00bcf538 a43297ae 071d4d5c clr!MethodDescCallSite::CallTargetWorker+0x16a (FPO: [Non-Fpo])
07 00bcf580 722c741a 00bcf5c4 00000000 a43295c2 clr!RunMain+0x1b3 (FPO: [Non-Fpo])
08 00bcf7ec 722c7347 00000000 a4329efe 00a30000 clr!Assembly::ExecuteMainMethod+0xf7 (FPO: [Non-Fpo])
09 00bcfcd0 722c74c8 a4329f06 00000000 00000000 clr!SystemDomain::ExecuteMainMethod+0x5ef (FPO: [Non-Fpo])
0a 00bcfd28 722c75ee a4329f46 00000000 723117c0 clr!ExecuteEXE+0x4c (FPO: [Non-Fpo])
0b 00bcfd68 723117e5 a4329f8a 00000000 723117c0 clr!_CorExeMainInternal+0xdc (FPO: [Non-Fpo])
0c 00bcfda4 7295fa84 047a2010 729f43f0 7295fa20 clr!_CorExeMain+0x4d (FPO: [Non-Fpo])
0d 00bcfddc 729ee80e 729f43f0 72950000 00bcfe04 mscoreei!_CorExeMain+0xd6 (FPO: [Non-Fpo])
0e 00bcfdec 729f43f8 729f43f0 74c00419 00db6000 MSCOREE!ShellShim__CorExeMain+0x9e (FPO: [Non-Fpo])
0f 00bcfdf4 74c00419 00db6000 74c00400 00bcfe60 MSCOREE!_CorExeMain_Exported+0x8 (FPO: [0,0,4])
10 00bcfe04 76f2662d 00db6000 ba7d08ea 00000000 KERNEL32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
11 00bcfe60 76f265fd ffffffff 76f451e3 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
12 00bcfe70 00000000 729f43f0 00db6000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

可以看到,当我们的代码throw异常时,调用了clr!IL_Throw--->clr!RaiseTheExceptionInternalOnly--->KERNELBASE!RaiseException

输入 uf clr!RaiseTheExceptionInternalOnly观察下RaiseException的调用过程和参数传递

0:000> uf clr!RaiseTheExceptionInternalOnly

...

7234e9f4 c785bcffffff524343e0 mov dword ptr [ebp-44h],0E0434352h

clr!RaiseTheExceptionInternalOnly+0x19c:
7234e9fe 8b85e0ffffff    mov     eax,dword ptr [ebp-20h]
7234ea04 8b4004          mov     eax,dword ptr [eax+4]
7234ea07 a900000010      test    eax,10000000h
7234ea0c 0f8556931600    jne     clr!RaiseTheExceptionInternalOnly+0x1a9 (724b7d68)  Branch

clr!RaiseTheExceptionInternalOnly+0x1db:
7234ea12 8d95c4ffffff    lea     edx,[ebp-3Ch]
7234ea18 6a3e            push    3Eh
7234ea1a 59              pop     ecx
7234ea1b e873feffff      call    clr!IsExceptionOfType (7234e893)
7234ea20 85c0            test    eax,eax
7234ea22 0f858b931600    jne     clr!RaiseTheExceptionInternalOnly+0x1ef (724b7db3)  Branch

clr!RaiseTheExceptionInternalOnly+0x1ea:
7234ea28 3985c8ffffff    cmp     dword ptr [ebp-38h],eax
7234ea2e 0f857f931600    jne     clr!RaiseTheExceptionInternalOnly+0x1ef (724b7db3)  Branch

clr!RaiseTheExceptionInternalOnly+0x1fb:
7234ea34 803d34208e7200  cmp     byte ptr [clr!g_StackProbingEnabled (728e2034)],0
7234ea3b 0f8586931600    jne     clr!RaiseTheExceptionInternalOnly+0x204 (724b7dc7)  Branch

clr!RaiseTheExceptionInternalOnly+0x218:
7234ea41 6a01            push    1
7234ea43 8d8d8cffffff    lea     ecx,[ebp-74h]
7234ea49 e8e736e6ff      call    clr!GCPreempNoDtor::Enter (721b2135)
7234ea4e 56              push    esi
7234ea4f 53              push    ebx
7234ea50 57              push    edi
7234ea51 ffb5bcffffff    push    dword ptr [ebp-44h]
7234ea57 ff15e4628f72    call    dword ptr [clr!_imp__RaiseException (728f62e4)]
...

可以看到clr!RaiseTheExceptionInternalOnly函数传给RaiseException的参数确实是0xE0434352。

现在,我们修改下工程配置,将Framework版本改为3.5,如下

然后编译,在Windbg加载运行,最后程序抛出异常中断

可以看到此时抛出了CLR exception---code e0434f4d

输入kv,看下栈

0:000> kv
 # ChildEBP RetAddr  Args to Child              
00 006feb3c 791f7e04 e0434f4d 00000001 00000001 KERNELBASE!RaiseException+0x62 (FPO: [4,22,0])
01 006feb9c 792595d0 06d02cb0 00000000 00000000 mscorwks!RaiseTheExceptionInternalOnly+0x2a8 (FPO: [Non-Fpo])
02 006fec60 08fc00a5 06d02cb0 06d02ca0 006fec80 mscorwks!JIT_Throw+0xfc (FPO: [Non-Fpo])
WARNING: Frame IP not in any known module. Following frames may be wrong.
03 006fec70 79181b6c 00000003 006fec84 006fed00 0x8fc00a5
04 006fec80 79198603 006fed50 00000000 006fed20 mscorwks!CallDescrWorker+0x33
05 006fed00 791a06a3 006fed50 00000000 006fed20 mscorwks!CallDescrWorkerWithHandler+0xa3 (FPO: [Non-Fpo])
06 006fee40 791a06d6 06abc030 006fef0c 006feed8 mscorwks!MethodDesc::CallDescr+0x19c (FPO: [Non-Fpo])
07 006fee5c 791a06f4 06abc030 006fef0c 006feed8 mscorwks!MethodDesc::CallTargetWorker+0x1f (FPO: [Non-Fpo])
08 006fee74 7926090d 006feed8 1c0b468b 00000000 mscorwks!MethodDescCallSite::Call_RetArgSlot+0x1a (FPO: [Non-Fpo])
09 006fefd8 7926082d 06ab301c 00000001 006ff014 mscorwks!ClassLoader::RunMain+0x223 (FPO: [Non-Fpo])
0a 006ff240 79260d4a 00000000 1c0b5e43 00000001 mscorwks!Assembly::ExecuteMainMethod+0xa6 (FPO: [Non-Fpo])
0b 006ff710 79260f34 002f0000 00000000 1c0b5e33 mscorwks!SystemDomain::ExecuteMainMethod+0x45e (FPO: [Non-Fpo])
0c 006ff760 79260e64 002f0000 1c0b5efb 00000000 mscorwks!ExecuteEXE+0x59 (FPO: [Non-Fpo])
0d 006ff7a8 7295fa84 4635529f 729f43f0 7295fa20 mscorwks!_CorExeMain+0x15c (FPO: [Non-Fpo])
0e 006ff7e0 729ee80e 729f43f0 72950000 006ff808 mscoreei!_CorExeMain+0xd6 (FPO: [Non-Fpo])
0f 006ff7f0 729f43f8 729f43f0 74c00419 00438000 MSCOREE!ShellShim__CorExeMain+0x9e (FPO: [Non-Fpo])
10 006ff7f8 74c00419 00438000 74c00400 006ff864 MSCOREE!_CorExeMain_Exported+0x8 (FPO: [0,0,4])
11 006ff808 76f2662d 00438000 589054b8 00000000 KERNEL32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
12 006ff864 76f265fd ffffffff 76f451d5 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
13 006ff874 00000000 729f43f0 00438000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])
可以看到,当我们的代码throw异常时,调用了mscorwks!JIT_Throw-->mscorwks!RaiseTheExceptionInternalOnly--->KERNELBASE!RaiseException

输入 uf mscorwks!RaiseTheExceptionInternalOnly观察下RaiseException的调用过程和参数传递

0:000> uf mscorwks!RaiseTheExceptionInternalOnly

...

791f7d7c bb4d4f43e0      mov     ebx,0E0434F4Dh

mscorwks!RaiseTheExceptionInternalOnly+0x1db:
791f7d81 8b4704          mov     eax,dword ptr [edi+4]
791f7d84 a900000010      test    eax,10000000h
791f7d89 7425            je      mscorwks!RaiseTheExceptionInternalOnly+0x210 (791f7db0)  Branch

mscorwks!RaiseTheExceptionInternalOnly+0x1e5:
791f7d8b 8d4508          lea     eax,[ebp+8]
791f7d8e 50              push    eax
791f7d8f 6a43            push    43h
791f7d91 e8c5feffff      call    mscorwks!IsExceptionOfType (791f7c5b)
791f7d96 85c0            test    eax,eax
791f7d98 7416            je      mscorwks!RaiseTheExceptionInternalOnly+0x210 (791f7db0)  Branch

mscorwks!RaiseTheExceptionInternalOnly+0x1f4:
791f7d9a 81677cfff7ffff  and     dword ptr [edi+7Ch],0FFFFF7FFh
791f7da1 8b470c          mov     eax,dword ptr [edi+0Ch]
791f7da4 8945cc          mov     dword ptr [ebp-34h],eax
791f7da7 83f8ff          cmp     eax,0FFFFFFFFh
791f7daa 0f8476851d00    je      mscorwks!RaiseTheExceptionInternalOnly+0x206 (793d0326)  Branch

mscorwks!RaiseTheExceptionInternalOnly+0x210:
791f7db0 8d4508          lea     eax,[ebp+8]
791f7db3 50              push    eax
791f7db4 6a3d            push    3Dh
791f7db6 e8a0feffff      call    mscorwks!IsExceptionOfType (791f7c5b)
791f7dbb 85c0            test    eax,eax
791f7dbd 0f8572851d00    jne     mscorwks!RaiseTheExceptionInternalOnly+0x224 (793d0335)  Branch

mscorwks!RaiseTheExceptionInternalOnly+0x21f:
791f7dc3 394510          cmp     dword ptr [ebp+10h],eax
791f7dc6 0f8569851d00    jne     mscorwks!RaiseTheExceptionInternalOnly+0x224 (793d0335)  Branch

mscorwks!RaiseTheExceptionInternalOnly+0x232:
791f7dcc 897dd4          mov     dword ptr [ebp-2Ch],edi
791f7dcf 8d45d4          lea     eax,[ebp-2Ch]
791f7dd2 2d00c00000      sub     eax,0C000h
791f7dd7 8b8ff4010000    mov     ecx,dword ptr [edi+1F4h]
791f7ddd 894dc8          mov     dword ptr [ebp-38h],ecx
791f7de0 3bc1            cmp     eax,ecx
791f7de2 0f8260851d00    jb      mscorwks!RaiseTheExceptionInternalOnly+0x24a (793d0348)  Branch

mscorwks!RaiseTheExceptionInternalOnly+0x26b:
791f7de8 c745d001000000  mov     dword ptr [ebp-30h],1

mscorwks!RaiseTheExceptionInternalOnly+0x254:
791f7def 8bcf            mov     ecx,edi
791f7df1 e80f20f9ff      call    mscorwks!Thread::EnablePreemptiveGC (79189e05)
791f7df6 56              push    esi
791f7df7 ff75e4          push    dword ptr [ebp-1Ch]
791f7dfa ff75e0          push    dword ptr [ebp-20h]
791f7dfd 53              push    ebx
791f7dfe ff1554121879    call    dword ptr [mscorwks!_imp__RaiseException (79181254)]
...

可以看到mscorwks!RaiseTheExceptionInternalOnly函数传给RaiseException的参数确实是0xE0434F4D

通过这两个对比,我们可以发现视乎CLR异常跟.net Framework版本有关,我又做了.net Framework 3.0/2.0,发现CLR异常是0xE0434F4D,而.net Framework 4.0/4.6/4.7/4.8版本的CLR异常是0xE0434352,同时我们发现0xE0434F4D是在mscorwks模块抛出,而0xE0434352是在clr模块抛出,结合《CLR调试时的sos.dll/clr.dll/mscorwks.dll/mscordacwks.dll等动态库的版本对应》一文,我们可以总结如下:

CLR Exception 0xE0434F4D和0xE0434352它们有一点区别是"CLR2.0版本是0xE0434F4D代码而在CLR4.0就已经改为0xE0434352"。

至于为什么会变,还待研究,也希望其他同好告知。同时也希望告知还有没有其他区别。

posted on 2019-12-18 10:28  活着的虫子  阅读(1978)  评论(1编辑  收藏  举报

导航