SmidgeonSoft Logo

PEBrowse Professional
Interactive Debugger

Initializing CLR

Initializing the CLR Environment and the First JITted Method

The normal action of a Windows program would now be to call the loaded DLLs' entry-points in an order determined by the operating system and then your main executable's entry-point, e.g., mainCRTStartup.  But the activity of LdrpCorReplaceStartContext has altered the normal course of events -- press F5 and the debugger will now stop Wilderland.EXE in MSCOREE.DLL!__CorExeMain.  If you have the debug symbols for MSCOREE loaded, you should see the following instruction somewhere in the listing:

0x7917D099: CALL     long __stdcall GetInstallation(int,struct HINSTANCE__ * *,int); (0x79178DC5)

[for SP2:]
0x788110AE: CALL     0x78803216

Step over this call and refresh the Index.  Wow!  The Index has gained a large number of new nodes!  More memory has been allocated and new DLLs have been loaded.  A little further along you will find a call through the contents of EAX; run to this now.  The popup bubble is displaying what appears to be a substantial amount of code.  Double-clicking on the line opens up a new disassembly window for MSCORWKS.DLL!__CorExeMain -- this is the entry-point for the main engine of the Common Language Runtime or CLR.  If you are interested in how the .NET environment is loaded and initialized, step through this code!  There is a lot of activity going on!  In fact, make a mental note of the appearance of the Index now, step over the call to this CorExeMain and refresh the Index.  WOW!!!  The Wilderland.EXE process has grown quite a bit.  There also now appears another disassembly window, this one containing the code for the managed routine, System.AppDomain::SetupDomain.  A few more View menu commands have been enabled as well, e.g., View/JIT Events.  Try this command now.  Now we see the results of selecting the option from the CLR Debug tab sheet, "Break on first JIT event?"  There is only one JIT event displayed.  With this window activated, select Edit/MSIL Disassemble and a new window is created, the Intermediate Language (IL) display for the method, System.AppDomain::SetupDomain.  Single-step through the x86 code and observe what is going on in the IL disassembly window.  You will see the current IL instruction pointer jumping and advancing as well.  If this display is a little confusing, we can fix that.  Close the IL window and in the Index find and select the node for MSCORLIB.DLL (This action will load the .NET symbols.).  Now, go back to x86 disassembly window and toggle the Edit menu command, Include MSIL.  (You may need to toggle the command twice -- one of the quirks in PEBrowse Interactive's interface.)  You should now see the IL disassembly marbled through the x86 instructions that were generated by the JIT compiler.

While we are sitting in the first managed breakpoint, let's add a few more breakpoints to the list.  Find the Wilderland.EXE node in the Index and expand it.  You will see two nodes with very similar text, ".NET MetaData" and ".NET Methods".  Expanding the former will display all of the metadata grouped by major categories, e.g., TypeDefs, ModuleRefs, AssemblyRefs, etc., while the latter, only the .NET methods themselves.  Expand the ".NET Methods" node followed by the "Wilderland.WilderlandForm" node.  Using the popup menu, set breakpoints on the "Main" node and the "Hobbiton_Button_Click" nodes and bring up the breakpoints display to check your effort.  You should now be viewing two pending breakpoints that have been marked "Not JITted" in the bottom half of the display.  Press F5 to continue the program.  The contents of the disassembly window will now be replaced by the JITted code for the Wilderland.WilderlandForm::Main method, the first instruction of the sample program.  Finally!  Since we wish to celebrate the appearance of our first bit of code and having so much fun adding managed breakpoints, let us add one more after a point where the System.Windows.Forms.Application::Run method will return:

; IL_0005: call  System.Windows.Forms.Application::Run()
0x6E51117: MOV      ECX,0x6ED7BFC           
0x6E5111C: CALL     class Object * __fastcall JIT_NewCrossContext(struct CORINFO_CLASS_STRUCT_ *) ; (0x791B2303)
0x6E51121: MOV      ESI,EAX                 
0x6E51123: MOV      ECX,ESI                 
0x6E51125: CALL     DWORD PTR [0x6ED8198]   
0x6E5112B: MOV      ECX,ESI                 
0x6E5112D: CALL     DWORD PTR [0x6ED8794]     ; IL_000A: ldc.i4.0 
; IL_000B: newobj  System.IntPtr::.ctor()
; IL_0010: ldstr "The adventure is ending."
; IL_0015: ldstr "Farewell"
; IL_001A: ldc.i4.0 
; IL_001B: call  Wilderland.WilderlandForm::MessageBox()
; IL_0020: pop 
0x6E51133: LEA      ECX,DWORD PTR [EBP-0x4] ; VAR:0x4                <<<<<<<<<< Add a breakpoint here.
0x6E51136: XOR      EDX,EDX                 
0x6E51138: CALL     DWORD PTR [0x6E6294C]   
0x6E5113E: PUSH     DWORD PTR [0x5B710B0]   
0x6E51144: PUSH     0x0                     
0x6E51146: MOV      EDX,DWORD PTR [0x5B710AC]
0x6E5114C: MOV      ECX,DWORD PTR [EBP-0x4] ; VAR:0x4
0x6E5114F: CALL     DWORD PTR [0x6ED8194]   
; IL_0021: ret 
0x6E51155: NOP

One more View menu item will become enabled here -- View/.NET GC Heap; select it and you will be presented with a dialog box (see Figure 9).

Figure 9

You may notice that a value has already been entered in the edit field; this represents the results of a heuristic inside of PEBrowse Interactive to locate the start of the .NET small object garbage-collected heap.  It may be incorrect, and you are given a chance to override it.  The Index display based on this algorithm also labels nodes with the text, ".NET GC Heap (Small Object)" and ".NET GC Heap (Large Object)".  Press "OK" if you are satisfied with the guess, after a short pause you will open a new window for the .NET GC heap.  (This operation and the following might be unavailable if you are using v2.0 of the framework.  There is a lot of sanity checking in PEBrowse Interactive's heuristic that can cause it to fail in searching for the GC heap starting address.)  For the moment try to resist the temptation to start expanding and exploring the nodes in the tree view display (it will figure prominently a little later in this tutorial).  Instead, try to remember that this is a snapshot of the small object heap at this point in the program's execution and that you will need to refresh it (or close and reopen it again) in order to gain an accurate picture of the managed objects.  You also might want to revisit the JIT events display to learn more about the activity that takes place before your program is even started.  Let the program continue.

prev page 1st page next page
Home | FAQ | News | Software | Documentation | SiteSearch | Licensing | Links | SiteIndex | AboutUs | ContactUs
Page best viewed at 1024x768.   Page last updated 2006-11-19.   This site is PIKT® powered.
Copyright © 1998-2006 Russell Osterlund.  All rights reserved.  SmidgeonSoft is a wholly-owned division of SmidgeonSoft, LLC.
Home FAQ News Software Documentation SiteSearch