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”.

About Naveen
Write code.

One Response to Exploring undocumented SOS function in Windbg – .NET 4.0

  1. Pingback: Why isn’t the !bpmd in sos / windbg not working? « Naveen's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: