Exploring undocumented SOS function in Windbg – .NET 4.0
With the new Microsoft .NET Framework 4.0 ,comes a new sos , which adds bunch of features. In this post I will be exploring one of the undocumented function , which is !HandleCLRN. Brian has also mentioned about these undocumented functions.
I guessed it by the name ,it would have to be something about clr notification exception. I knew these exceptions are raised when there is an assembly load. Here is the simple console application that I am going to be using for exploring this.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
Console.WriteLine("Debugging");
Console.Read();
}
}
}
Started the exe within windbg. Issued the command
sxe ld:clrjit
To load the sos after clr is loaded. Then loaded sos by
.loadby sos clr
Note there is change in the syntax for loading sos in .NET 4.0. Prior to this, clr was part of mscorwks.dll and now it is clr.dll.
Next step is to have a break-point on the Main Method.
!bpmd ConsoleApplication1.exe ConsoleApplication1.Program.Main
And here was the output
0:000> !bpmd ConsoleApplication1.exe ConsoleApplication1.Program.Main
Found 1 methods in module 009b2e8c…
MethodDesc = 009b388c
Adding pending breakpoints…
My assumption was ,sos would have signup with debugger for an exception, for the above command , and I was correct and here is my output from sx command
0:000> sx
ct – Create thread – ignore
et – Exit thread – ignore
cpr – Create process – ignore
epr – Exit process – break
ld – Load module – break
(only break for clrjit)
ud – Unload module – ignore
ser – System error – ignore
ibp – Initial breakpoint – break
iml – Initial module load – ignore
out – Debuggee output – output
av – Access violation – break – not handled
asrt – Assertion failure – break – not handled
aph – Application hang – break – not handled
bpe – Break instruction exception – break
bpec – Break instruction exception continue – handled
eh – C++ EH exception – second-chance break – not handled
clr – CLR exception – break – handled
Command: “”
Second command: “”
clrn – CLR notification exception – break – handled
Command: “!HandleCLRN”
cce – Control-Break exception – break
cc – Control-Break exception continue – handled
cce – Control-C exception – break
cc – Control-C exception continue – handled
dm – Data misaligned – break – not handled
dbce – Debugger command exception – ignore – handled
gp – Guard page violation – break – not handled
ii – Illegal instruction – second-chance break – not handled
ip – In-page I/O error – break – not handled
dz – Integer divide-by-zero – break – not handled
iov – Integer overflow – break – not handled
ch – Invalid handle – break
hc – Invalid handle continue – not handled
lsq – Invalid lock sequence – break – not handled
isc – Invalid system call – break – not handled
3c – Port disconnected – second-chance break – not handled
svh – Service hang – break – not handled
sse – Single step exception – break
ssec – Single step exception continue – handled
sbo – Stack buffer overflow – break – not handled
sov – Stack overflow – break – not handled
vs – Verifier stop – break – not handled
vcpp – Visual C++ exception – ignore – handled
wkd – Wake debugger – break – not handled
wob – WOW64 breakpoint – break – handled
wos – WOW64 single step exception – break – handled
* – Other exception – second-chance break – not handled
Notice that for clrn exception , there is the new command called!HandleCLRN
Changed the sxe for clrn to kb, to get the call stack
sxe -c "kb" clrn
And here is the output from the clrn exception
0:000> g
(5f5b8.5f5bc): CLR notification exception – code e0444143 (first chance)
RetAddr : Args to Child : Call Site
000007fe`e860da53 : 00000000`01ed4c60 000007fe`e81940a9 00000000`001be560 000007fe`e85ea423 : KERNELBASE!RaiseException+0×39
000007fe`e84f08e3 : 00000000`00000000 000007fe`e85fb772 00000000`001be560 00000000`001be7b9 : clr!DACNotifyExceptionHelper+0×43
000007fe`e84f1d2b : 000007ff`000440e0 00000000`004ae620 00000000`001be948 000007ff`00000000 : clr!DACNotify::DoJITNotification+0x2b
000007fe`e824e3ce : 000007ff`000440e0 000007ff`00160120 000007ff`000440e0 00000000`00000001 : clr!DACNotifyCompilationFinished+0x6d
000007fe`e824e164 : 000007ff`000440e0 00000000`00000001 00000000`00000000 00000000`001be800 : clr!MethodDesc::MakeJitWorker+0×256
000007fe`e81cdaf3 : 000007ff`000440e0 00000000`00000000 00000000`00000000 00000000`00000000 : clr!MethodDesc::DoPrestub+0×522
000007fe`e8192547 : 00000000`00000000 00000000`004ae620 00000000`001be948 00000000`001beb20 : clr!PreStubWorker+0x1df
000007fe`e81ccc74 : 00000000`021c2258 00000000`001bebb0 00000000`001bea10 000007fe`e8194ab5 : clr!ThePreStubAMD64+0×87
000007fe`e81ccd89 : 000007ff`000440e0 00000000`00000001 00000000`00000000 00000000`00000000 : clr!CallDescrWorker+0×84
000007fe`e81cce05 : 00000000`001beb18 00000000`00000001 00000000`001beb20 00000000`001bed00 : clr!CallDescrWorkerWithHandler+0xa9
000007fe`e8352820 : 00000000`00000000 00000000`001bed08 00000000`00000001 000007fe`e6f23502 : clr!MethodDesc::CallDescr+0x2a1
000007fe`e8352958 : 00000000`004ae620 00000000`004ae620 00000000`00000000 00000000`00000000 : clr!ClassLoader::RunMain+0×228
000007fe`e8352e0a : 00000000`001bf500 00000000`00000200 00000000`01ebd660 00000000`00000200 : clr!Assembly::ExecuteMainMethod+0xac
000007fe`e8353036 : 00000000`00000000 00000000`002b0000 00000000`00000000 00000000`00000000 : clr!SystemDomain::ExecuteMainMethod+0×452
000007fe`e8352f53 : 00000000`002b0000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!ExecuteEXE+0×43
000007fe`e82cf7c1 : 00000000`004ae620 ffffffff`ffffffff 00000000`00000000 00000000`00000000 : clr!CorExeMainInternal+0xc4
000007fe`f17c4989 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`001bf818 : clr!CorExeMain+0×15
000007fe`fb675b21 : 000007fe`e82cf7ac 000007fe`f17c4940 00000000`00000000 00000000`00000000 : mscoreei!CorExeMain+0×41
00000000`7712f56d : 000007fe`f17c0000 00000000`00000000 00000000`00000000 00000000`00000000 : MSCOREE!CorExeMain_Exported+0×57
00000000`77363281 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0xd
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
KERNELBASE!RaiseException+0×39:
000007fe`fd5faa7d 4881c4c8000000 add rsp,0C8h
Got it ,the !HandleCLRN is used by sos to set break-points on methods that have not yet being jitted.
sos would have to hook with clr for getting JIT notification. Without this, sos will not be able to set break-points on function names using !bpmd ,that have not yet jitted. When clr jits the code, sos is notified because sos has signed for jit callbacks using !HandleCLRN ,after which sos will be able to set “bp”. This is evident from the above call stack.
So my next question was so how sos handling prior to !HandleCLRN. Tried the same in .NET 3.5 and the undocumented parameter it was using is “!bpmd -notification”.
[...] recently noticed another blog post refer to one of my post. The issue was, sos wasn’t enabling the break-points on non-jitted functions. The classic [...]
Why isn’t the !bpmd in sos / windbg not working? « Naveen's Blog
December 5, 2010 at 7:17 pm