<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Rick Byers : ICorDebug</title><link>http://blogs.msdn.com/rmbyers/archive/tags/ICorDebug/default.aspx</link><description>Tags: ICorDebug</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Getting good dumps when an exception is thrown</title><link>http://blogs.msdn.com/rmbyers/archive/2008/12/22/getting-good-dumps-when-an-exception-is-thrown.aspx</link><pubDate>Tue, 23 Dec 2008 09:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9249385</guid><dc:creator>rmbyers</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/rmbyers/comments/9249385.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rmbyers/commentrss.aspx?PostID=9249385</wfw:commentRss><description>&lt;p&gt;Often, when an unexpected exception occurs in production code, applications want to generate (and potentially report) some sort of diagnostics information.&amp;#160; Sometimes people just want to write to a log file (and perhaps pop some error dialog) for support purposes, but more sophisticated applications will want to have a mechanism to save a minidump of the crash (and perhaps report it back to the author of the software) so their developers can debug the problem.&amp;#160; &lt;a class="" href="http://msdn.microsoft.com/en-us/isv/bb190483.aspx" mce_href="http://msdn.microsoft.com/en-us/isv/bb190483.aspx"&gt;Windows Error Reporting&lt;/a&gt; is usually the best way to do this (the CLR v2 and above &lt;a class="" href="http://msdn.microsoft.com/en-us/library/bb219076.aspx#MicrosoftErrorReporting_ManagedCode" mce_href="http://msdn.microsoft.com/en-us/library/bb219076.aspx#MicrosoftErrorReporting_ManagedCode"&gt;integrates with WER&lt;/a&gt; for all managed apps), but people also like to build their own custom solutions.&amp;#160; By the way, if you want to build your own error-reporting mechanism that captures dump files, I suggest you use a helper process to suspend all your threads and call MiniDumpWriteDump, rather than calling it directly in-process (see &lt;a href="http://www.eggheadcafe.com/software/aspnet/29825284/loader-lock-deadlock-in-m.aspx"&gt;this discussion&lt;/a&gt; for example).&lt;/p&gt;  &lt;p&gt;As a very simple example, you may want to use the FailFast API to say &amp;quot;exceptions should never escape here, if it does present an error to the user and let them report the problem back through WER&amp;quot;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;try
&lt;/span&gt;{
    MyCode();
}
&lt;span style="color: blue"&gt;catch &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Exception &lt;/span&gt;ex)
{
    &lt;span style="color: green"&gt;// We don't expect any exceptions - generate an error-report if we see one
    &lt;/span&gt;System.&lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.FailFast(&lt;span style="color: #a31515"&gt;&amp;quot;Unexpected exception: &amp;quot; &lt;/span&gt;+ ex.Message);
}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Unfortunately, this won’t give you a very useful dump in your error-report.&amp;#160; The problem is that by the time the catch block has been started, the stack frames showing how the exception occurred are no longer available (see below for details).&amp;#160; Managed exceptions are built on &lt;a href="http://www.microsoft.com/msj/0197/exception/exception.aspx"&gt;Windows Structured Exception Handling&lt;/a&gt;, and so have the same two-pass model.&amp;#160; ‘catch’ blocks are executed on the second pass, but really what we want here is to generate our error-report on the first-pass (before EBP gets reset).&amp;#160; You are probably used to seeing this when debugging your code.&amp;#160; If you really want to see what caused an exception, you have to tell Visual Studio to &lt;a href="http://msdn.microsoft.com/en-us/library/h22dk1y6.aspx"&gt;stop on first-chance exceptions&lt;/a&gt; – by the time you stop in the catch block, the code that threw the exception is no longer visible on the callstack:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Gettinggooddumpswhenanexceptionisthrown_141E6/image_2.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="316" alt="image" src="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Gettinggooddumpswhenanexceptionisthrown_141E6/image_thumb.png" width="607" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Luckily the CLR provides a way to do this called managed exception filters.&amp;#160; Unfortunately C# doesn’t expose a way to use them.&amp;#160; The simplest way to use a filter from C# code is to write a simple helper function in VB.Net.&amp;#160; The ‘When’ portion of a ‘Catch’ clause in VB.Net is an exception filter.&amp;#160; Here’s a simple helper I wrote for this that I can easily call from C#:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;ExceptionUtils
    &lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;Filter(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;body &lt;span style="color: blue"&gt;As &lt;/span&gt;Action, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;filter &lt;span style="color: blue"&gt;As &lt;/span&gt;Func(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Exception, &lt;span style="color: blue"&gt;Boolean&lt;/span&gt;), &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;handler &lt;span style="color: blue"&gt;As &lt;/span&gt;Action(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Exception))
        &lt;span style="color: blue"&gt;Try
            &lt;/span&gt;body()
        &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception &lt;span style="color: blue"&gt;When &lt;/span&gt;filter(ex)
            handler(ex)
        &lt;span style="color: blue"&gt;End Try
    End Sub
End Class&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now I can re-write my code that triggers error-reporting on exceptions as follows (referencing the VB assembly with the above code):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;ExceptionUtils&lt;/span&gt;.Filter(() =&amp;gt;
{
    &lt;span style="color: green"&gt;// This is the body of the 'try'
    &lt;/span&gt;MyCode();
}, (ex) =&amp;gt;
{
    &lt;span style="color: green"&gt;// This is the body of the filter
    &lt;/span&gt;System.&lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.FailFast(&lt;span style="color: #a31515"&gt;&amp;quot;Unexpected exception: &amp;quot; &lt;/span&gt;+ ex.Message);
    &lt;span style="color: blue"&gt;return false&lt;/span&gt;; &lt;span style="color: green"&gt;// don't catch - this code isn't reached
&lt;/span&gt;}, &lt;span style="color: blue"&gt;null&lt;/span&gt;); &lt;span style="color: green"&gt;// no catch block needed&lt;/span&gt;&lt;/pre&gt;
  &lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;Now, running under the debugger I can see the original call-stack, and even inspect locals/args on it (note the ‘Throw’ frame in the callstack, and the visible arg value for a – I can also click on this frame and poke around as normal):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Gettinggooddumpswhenanexceptionisthrown_141E6/image_4.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="470" alt="image" src="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Gettinggooddumpswhenanexceptionisthrown_141E6/image_thumb_1.png" width="783" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So that’s basically it.&amp;#160; Now debugging at the point of the FailFast (whether live, or with a dump file) will let you see all the data on the stack leading up to the cause of the exception.&amp;#160; Note that if exceptions are thrown and &lt;em&gt;caught within&lt;/em&gt; the body they don’t trigger the filter, the filter is just like a catch block in that it cares about exceptions that “reach” it – which is usually what you want (eg. it’s not normally any of your concern if the implementation of some external API you call happens to throw and catch an exception – as long as it doesn’t propagate back to your code).&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;

&lt;h2&gt;Additional Details&lt;/h2&gt;

&lt;p&gt;It might be a bit of a pain to have to deploy this extra assembly with your application, but there are other options for using an exception filter in your C# app:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Statically link the C# and VB code together into a single (single-file) assembly (eg. using &lt;a href="http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx"&gt;ILMerge&lt;/a&gt;, Link.EXE, or a &lt;a href="http://blogs.msdn.com/greggm/archive/2006/03/23/559155.aspx"&gt;ILDasm/ILAsm round-trip&lt;/a&gt;)&lt;/li&gt;

  &lt;li&gt;Use a tool to re-write your assembly after it’s built to inject the filter.&amp;#160; Gregg on the VS debugger team &lt;a href="http://blogs.msdn.com/greggm/archive/2008/04/21/exception-filter-inject.aspx"&gt;posted such a tool awhile back&lt;/a&gt;.&lt;/li&gt;

  &lt;li&gt;Use Reflection.Emit to dynamically generate the IL code for the filter at run-time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also, one note about using FailFast with managed error-reporting.&amp;#160; Error-reports are grouped by their ‘bucket parameters’.&amp;#160; The buckets generated for System.Environment.FailFast(string) are always the same for any given call-site (basically just the address of the call, and a the string ‘FatalError’ for the exception type.&amp;#160; Ideally what you’d like to do here is use the buckets for the original exception (so that two different exceptions that trigger the same call to FailFast will show up as two different problems).&amp;#160; We’ve added a FailFast overload that takes an Exception object in .NET 4.0 that does this.&lt;/p&gt;

&lt;p&gt;All I’ve talked about so far are simple single exceptions.&amp;#160; Exceptions can also be caught and re-thrown ('”throw;” in C#) or wrapped in an outer exception which is thrown (“nested exceptions”).&amp;#160; Unfortunately if that happens within the body you pass to ExceptionUtils.Filter, by the time the filter is invoked, the first exception has already been thrown and caught and so the stack you see is at the point of rethrow.&amp;#160; There’s no good way that I’m aware of to get the stack from the original throw point in this case (although it’s something I’d like to get added to the CLR in a future version).&amp;#160; This is particularly troublesome when using .NET APIs that catch-and-rethrow like Reflection (which wraps all exceptions in a TargetInvocationException).&amp;#160; The best thing I can suggest is to put filters inside any such point, so you filter sees the exception before it’s caught.&amp;#160; &lt;/p&gt;

&lt;p&gt;If you want to be really hard-core about exceptions, you could use some sort of exception monitoring solution that notices as soon as an exception is thrown.&amp;#160; For example, you could generate a dump from a &lt;a href="http://msdn.microsoft.com/en-us/library/ms679274.aspx"&gt;vectored exception handler&lt;/a&gt;, but you won’t have access to the managed System.Exception object here.&amp;#160; Better yet, you could write a tool that uses the debugging APIs to watch for first-chance exceptions and log details about them (perhaps including dump files) such as &lt;a href="http://blogs.msdn.com/jmstall/archive/2005/07/28/print_exceptions.aspx"&gt;Mike Stall’s MDbg exception harness&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Above I said that in a catch block the frames leading up to the throw are no longer available on the stack.&amp;#160; Technically, they’re still on the stack (the stack isn’t really “unwound” until you leave the catch block), but &lt;a href="http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx"&gt;the frame pointer has been reset&lt;/a&gt; to point to the frame of the catch block (so that locals are available, etc.).&amp;#160; This is true for native code as well, but powerful low-level debuggers like WinDbg allow you to switch the current context to that where an exception was thrown (.cxr command in windbg) if you have the CONTEXT pointer (which might even be saved into the dump for you – which you can access with .ecxr).&amp;#160; An additional complication with managed code is that once the frame pointer has been reset, we no longer report any “roots”on the stack to the GC, so if a collection occurs there may actually be garbage pointers on (or available from) that masked portion of the stack.&amp;#160; So it’s not a simple feature to expose some way to see the callstack starting from the throw site (unless we disabled inspection all locals and arguments, or allowed it to fail unpredictably).&amp;#160; We’ve toyed with ideas for relaxing this in the CLR, but there won’t be any improvements here in CLR v4.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;At the PDC this year I learned that this general class of problems (error reporting / logging in the face of exceptions) is something that many customers are very interested in.&amp;#160; I don’t think we’ve got a ton of great documentation on this today.&amp;#160; Going forward, you should expect to see more documentation, blog entries and new features from the CLR team in this area.&amp;#160; Feel free to let me know if there’s anything in particular you’d like to know more about.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9249385" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rmbyers/archive/tags/CLR/default.aspx">CLR</category><category domain="http://blogs.msdn.com/rmbyers/archive/tags/ICorDebug/default.aspx">ICorDebug</category></item><item><title>CLR 4.0 advancements in diagnostics</title><link>http://blogs.msdn.com/rmbyers/archive/2008/10/30/clr-4-0-advancements-in-diagnostics.aspx</link><pubDate>Fri, 31 Oct 2008 00:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9016854</guid><dc:creator>rmbyers</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/rmbyers/comments/9016854.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rmbyers/commentrss.aspx?PostID=9016854</wfw:commentRss><description>&lt;P&gt;We announced at PDC today that we're making some significant advances in diagnostics tool support for CLR v4!&amp;nbsp; In particular, we've been investing heavily in improving our support for production diagnostics scenarios over the past couple years.&amp;nbsp; I'm excited that we're finally able to&amp;nbsp;start talking about it!&lt;/P&gt;
&lt;P&gt;Here's a quick list of some of the things we're doing - stay tuned here,&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/davbr/" mce_href="http://blogs.msdn.com/davbr/"&gt;Dave's blog&lt;/A&gt; and &lt;A class="" href="http://blogs.msdn.com/jmstall" mce_href="http://blogs.msdn.com/jmstall"&gt;Mike's blog&lt;/A&gt; for more details.&amp;nbsp; Also feel free to ask questions about our strategy and specific plans for new features on &lt;A class="" href="http://social.msdn.microsoft.com/Forums/en-US/netfxtoolsdev/threads/" mce_href="http://social.msdn.microsoft.com/Forums/en-US/netfxtoolsdev/threads/"&gt;our forum&lt;/A&gt;&amp;nbsp;(of course we still have a few things we're not ready to talk about yet).&amp;nbsp; Of course, all of the features below are only available when targetting a process that is running inside version 4 of the CLR.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Managed dump debugging&lt;BR&gt;&lt;/STRONG&gt;Finally you'll be able to open crash dump files in Visual Studio and see managed state (stacks, locals, etc.) without using SOS.&amp;nbsp; The key scenario we want to enable here is taking a dump of an app/server in production (perhaps in an automated way like Windows Error Reporting) and opening that dump in Visual Studio on another machine at some point in the future.&amp;nbsp;&amp;nbsp;We have a big piece of this working in the VS 2010 CTP, but we still have some work to do before beta (eg. the CTP supports&amp;nbsp;dumps with full heap memory).&amp;nbsp; The experience in VS is very much like being stopped at a breakpoint in a live process, except you can't say "go".&amp;nbsp; Of course production code tends to&amp;nbsp;have JIT-optimizations enabled, so the normal caveats about debugging optimized code&amp;nbsp;apply here too (eg. may not see all locals).&amp;nbsp;&amp;nbsp;Also, you can't evaluate arbitrary expressions since there is no target process to call functions in (but we have some ideas for how we might compensate for this).&amp;nbsp; But despite the caveats, this is still a huge feature that should really help improve production diagnostics scenarios.&amp;nbsp; This work is actually the main visible piece of a much larger "out-of-process debugging" re-architecture we've been working on for years.&amp;nbsp; This re-arch deserves a post of it's own so stay tuned.&lt;BR&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Profiler attach (and detach) for memory diagnostics and sampling&lt;BR&gt;&lt;/STRONG&gt;One of the most common feature requests we hear from profiling tools is to be able to attach to a target process (today you have to set some environment variables at process start which cause your profiler to be loaded).&amp;nbsp; Before you get too excited - this doesn't have everything you want.&amp;nbsp; In particular, the CLR still doesn't have the ability to change the code of a method once it's been JIT-compiled (EnC is a &lt;EM&gt;very&lt;/EM&gt; special case - not really applicable here).&amp;nbsp; This means that IL instrumentation isn't available on attach, as well as a few other features (like object allocated callbacks).&amp;nbsp; But basic memory diagnostics scenarios where the profiler inspects the heap, and simple sampling-based CPU profiling&amp;nbsp;will now work on attach.&amp;nbsp; We anticipate this will be useful in production scenarios - you can walk up to a server behaving badly and attach a profiler, collect some data, and detach - leaving the process in basically the same state it was before you attached.&lt;BR&gt;[Update: See Dave's blog entry &lt;A class="" href="http://blogs.msdn.com/davbr/archive/2008/11/10/new-stuff-in-profiling-api-for-upcoming-clr-4-0.aspx" mce_href="http://blogs.msdn.com/davbr/archive/2008/11/10/new-stuff-in-profiling-api-for-upcoming-clr-4-0.aspx"&gt;here&lt;/A&gt; for additional details on profiling API improvements]&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Registry-free profiler activation&lt;BR&gt;&lt;/STRONG&gt;One major impediment to the sort of production scenario I described above is that today you have to register your profiler in the registry.&amp;nbsp; In many production scenarios, making some change to the machine-wide system registry is very unappealing (will the dev remember to undo the change when he's done with the server, etc?).&amp;nbsp; So to really enable production scenarios, we've also supplied a mechanism for running a process under a managed profiler (or attaching) without having to make any changes to the registry.&lt;BR&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;x64 mixed-mode debugging&lt;BR&gt;&lt;/STRONG&gt;This isn't really a production diagnostics scenario (although you can do x64 mixed-mode dump debugging), but is one of the main debugging feature requests we've gotten.&amp;nbsp; With this feature, "mixed-mode" (native+managed) debugging will work for x64 processes in basically the same way&amp;nbsp;it works for&amp;nbsp;x86 today.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;lock inspection&lt;/STRONG&gt;&lt;BR&gt;We're adding some simple APIs to ICorDebug which allow you to explore managed locks (Monitors).&amp;nbsp; For example, if a thread is blocked waiting for a lock, you can find what other thread is currently holding the lock (and if there is a time-out).&lt;BR&gt;&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Corrupted-state exceptions&lt;BR&gt;&lt;/STRONG&gt;This feature doesn't come from our team (it's part of the core exception-handling sub-system in the CLR), but in my opinion it's a huge improvement for diagnostics scenarios.&amp;nbsp; Basically it means that "bad" exceptions (like access violations) that propagate up the stack into manage code no longer (by default) get converted into normal .NET exceptions (System.AccessViolation) which you can accidentally catch in a "catch(Exception)" clause.&amp;nbsp; Basically, haivng a catch(Exception) which swallows AVs coming from native code is a bad thing because you're unlikely to be able to reason about the consistency of your process after the AV.&amp;nbsp; The default behavior for such "corrupted-state exceptions" is now to fail-fast and send an error-report (just like in normal C++ programming).&amp;nbsp; Of course, you can override this if you REALLY need to catch such an exception.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;That's the overview of the main CLR v4 features that affect diagnostics.&amp;nbsp; Of course there are also lots of other great things coming in CLR v4 and the rest of .NET Fx 4.0.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9016854" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rmbyers/archive/tags/CLR/default.aspx">CLR</category><category domain="http://blogs.msdn.com/rmbyers/archive/tags/ICorDebug/default.aspx">ICorDebug</category><category domain="http://blogs.msdn.com/rmbyers/archive/tags/ICorProfile/default.aspx">ICorProfile</category></item><item><title>ICorDebug re-architecture in CLR 4.0</title><link>http://blogs.msdn.com/rmbyers/archive/2008/10/27/icordebug-re-architecture-in-clr-4-0.aspx</link><pubDate>Mon, 27 Oct 2008 22:08:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9018831</guid><dc:creator>rmbyers</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/rmbyers/comments/9018831.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rmbyers/commentrss.aspx?PostID=9018831</wfw:commentRss><description>&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;In &lt;A class="" href="http://blogs.msdn.com/rmbyers/archive/2008/10/26/clr-4-0-advancements-in-diagnostics.aspx" mce_href="http://blogs.msdn.com/rmbyers/archive/2008/10/26/clr-4-0-advancements-in-diagnostics.aspx"&gt;my previous post&lt;/A&gt; I mentioned that CLR 4.0 will support managed dump debugging through ICorDebug, and that to do this we had to re-architect the debugging support in the CLR.&amp;nbsp; I want to give you a little more detail about what we've been doing here.&amp;nbsp; I'm sure I (and others) will be discussing more details in the time leading up to CLR 4.0 RTM, so stay tuned and also feel free to ask questions on this in our forum.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;History and background&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;BR&gt;First, if you haven't already, read &lt;A href="http://blogs.msdn.com/jmstall/archive/2005/02/09/370178.aspx"&gt;Mike's blog entry&lt;/A&gt; describing the difference between "hard-mode" and "soft-mode" debugging, and his &lt;A href="http://blogs.msdn.com/jmstall/archive/2004/10/13/241828.aspx"&gt;&lt;FONT color=#0000ff&gt;related entry&lt;/FONT&gt;&lt;/A&gt; describing the implication of relying on a helper thread. Mike has clearly been thinking about this for a long time, and the successes we announced at PDC are due in large part to Mike's dedication, vision, and hard-work on this project for the past several years.&amp;nbsp; In fact, after reading this post, if you go back and read other ICorDebug-related entries on Mike’s blog you’ll find a lot of great details on the thinking that lead to the design points I discuss below.&amp;nbsp; Drew Bliss (while he was on the WinDbg team)&amp;nbsp;was also instrumental to the early vision, design and implementation of our re-architecture.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;As you know from Mike's blog, there are clearly a number of advantages to being able to debug from out-of-process (not the least of which is support for dump debugging).&amp;nbsp; The big challenge is how to implement this in a maintainable way for a complex system with lots of fancy data structures and algorithms for accessing them.&amp;nbsp; We've actually been experimenting with prototypes for doing this for many years (since nearly the start of the CLR), and this is exactly what &lt;A href="http://msdn.microsoft.com/en-us/magazine/cc164138.aspx"&gt;&lt;FONT color=#0000ff&gt;SOS&lt;/FONT&gt;&lt;/A&gt; relies on.&amp;nbsp; But it's really only been in the past few years that we've developed the confidence to move ALL managed debugging towards an out-of-process model.&amp;nbsp; A power-user tool like SOS has somewhat different requirements&amp;nbsp;from a production-grade API used by millions of developers every day in their Visual Studio debugging sessions.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The way we attempt to address the maintenance issue is to build both the normal in-process CLR code (mscorwks.dll) and the out-of-process code (mscordacwks.dll) from the same code base.&amp;nbsp; We use some fancy C++ templates to instrument all pointer dereferences so that we can read memory from the target process instead of the process in which the code is executing ("host process").&amp;nbsp; We call this, and it's related infrastructure, our "DAC" (data access component) technology.&amp;nbsp; There are still a lot of challenges associated with DAC (eg. trying to help CLR developers reason about their code when there are two separate address spaces involved), but we've taken it far enough that we're willing to trust the approach.&amp;nbsp; If people are interested, I'd be happy to go into more detail on this in the future, but let's move on now to what we're actually delivering in CLR v4.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;Design points for ICorDebug v4.0&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;Here's a list of principles we followed in the design for debugging in CLR v4.0.&amp;nbsp; There’s a lot of overlap here since these design points are all part of a single coherent vision.&amp;nbsp; Just skimming this list should give you a pretty good idea of what our new architecture is all about.&amp;nbsp; I’ll save going into the concrete details of the new API here (although you can grab the new cordebug.idl from the CTP VPC image and explore it yourself if you're really curious).&lt;/P&gt;
&lt;OL type=1&gt;
&lt;LI&gt;Debugging a 4.0 managed app requires a 4.0-aware debugger (i.e. we &lt;EM&gt;are&lt;/EM&gt; making breaking changes)&lt;BR&gt;It has always been our policy that a debugger needs to be designed to understand the&amp;nbsp;major features of the run-time, and so with a major new release of the runtime (like 4.0) we will require updates to the debugger.&amp;nbsp;&amp;nbsp;This means that VS 2008 will not be able to debug code running in the V4 CLR (exaclty like VS 2003 couldn't debug code running in CLR v2) - but see below.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Migrating a 2.0 debugger to support 4.0 should be very easy&lt;BR&gt;Although we want to hold a hard line on our compat policy above, we are working very hard to make it easy for debuggers to update their code to support CLR v4.&amp;nbsp; In almost all cases, we're not removing / disabling or drastically changing the semantics of any existing APIs.&amp;nbsp;&amp;nbsp; We are adding a bunch of new APIs and re-implementing the existing APIs on top of them, thus giving you the choice of which to use (the new APIs tend to have a lower level of abstraction).&amp;nbsp; In fact, you could install VS 2008 on the &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=922B4655-93D0-4476-BDA4-94CF5F8D4814&amp;amp;displaylang=en"&gt;.NET 4.0 CTP image&lt;/A&gt; and debug code running in the 4.0 CLR.&amp;nbsp; In adition to wanting to make it easy for debugger writers to migrate, we also didn't want to force everyone inside Microsoft using early CLR v4 builds to also use VS 2010 as their debugger until it reaches beta quality.&amp;nbsp; By the time we ship the beta, we'll explicitly break this to ensure we're not setting any unrealistic expectations.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Re-architecture is incremental instead of a complete rewrite&lt;BR&gt;We (mainly, to his credit, Mike) decided early on that we should transition to this new architecture incrementally while keeping our system working throughout.&amp;nbsp; This was done partly for pragmatic reasons, for example that we wanted to always have a working Visual Studio without having to wait for them to update to our new architecture in lock-step with us.&amp;nbsp; This also enabled us to react to changes in the business plan.&amp;nbsp; For example, when we decided to ship Silverlight 2 based on the latest CLR code base (i.e. the V4 branch) rather than based on the CLR v2 codebase, we were pretty-much prepared to ship the current state of our re-architecture even though we weren't yet "done" (we did have to spend a month or so adding Mac support to our new architecture - but that was a relatively isolated new feature, as opposed to a race to productize an unfinished codebase).&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Maintain a single, self-consistent debugging API based on ICorDebug&lt;BR&gt;Despite the huge fundamental changes we needed to make, we decided we needed to maintain consistency with the existing ICorDebug APis as much as possible.&amp;nbsp; Again, this helps ensure that existing managed debuggers can take advantage of our new functionality as easily as possible.&amp;nbsp; In fact, the VS debugger team spent only a few weeks adding the initial dump debugging support to VS 2010 because we made all the inspection operations behave exactly the same as for live debugging (we even had a hacked-up demo of dump-debugging working with VS 2008 without ANY VS changes at all!).&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;All access to the target is abstracted through a callback interface&lt;BR&gt;In V2, ICorDebug used a number of different Win32 APIs to interact with the target process (eg. using ReadProcessMemory, GetThreadContext, shared-memory blocks, and named events).&amp;nbsp; In V4, the core of ICorDebug uses a simple abstraction we call the "data target" (ICorDebugDataTarget) that a debugger implements.&amp;nbsp; This basically just has methods like 'ReadVirtual' (read some memory) and 'GetThreadContext' (get CPU state).&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;ICorDebug can operate in two difference modes - "pure out-of-process v4" and "v2 compatibility" &lt;BR&gt;Again, this is related to everything we've been discussing above.&amp;nbsp; In v2 compat mode, you create an ICorDebug instance in a similar way to V2, and use that to, for example, attach to a process given a PID to get an ICorDebugProcess that can do everything the one in V2 could do.&amp;nbsp; In this case, we implement the ICDDataTarget object ourselves.&amp;nbsp; In pure v4 mode, you use an alternate "open virtual process" creation API that basically just takes an ICDDataTarget and returns an ICorDebugProcess whose connection to the target is completely abstracted.&amp;nbsp; Today, a pure v4 ICDProcess only has the ability to do inspection operations (i.e. mainly just dump debugging), but we'll be enabling more out-of-process functionality (like stepping) in future releases.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;In v4-mode, ICorDebug acts just as a utility library for existing native debuggers&lt;BR&gt;In V2 and before, ICorDebug really behaves as if it owns the target process.&amp;nbsp; This has a lot of negative implications, most significantly that it makes mixed-mode debugging &lt;A href="http://blogs.msdn.com/jmstall/archive/2007/01/10/dont-write-an-interop-debugger.aspx"&gt;extremely difficult&lt;/A&gt; and brittle.&amp;nbsp; It also means that when debuggers want to add features, they often need to come to us (this is especially problematic for us given that the Visual Studio debugger team has a lot more people than the CLR debugger team &amp;lt;grin&amp;gt;).&amp;nbsp; Really we want to enable debuggers to implement their own policy and control of the target process rather than imposing a lot of policy ourselves.&amp;nbsp; This means we're lowering the level of abstraction of ICorDebug in some places.&amp;nbsp; SOS, as an extension that runs on top of a native debugger like WinDbg, &amp;nbsp;clearly already follows this principle.&amp;nbsp; An example benefit is that native debuggers like Visual Studio and WinDbg already have some policy and mechanism for skipping over breakpoints, and now in v4-mode we no longer have to have a completely different policy and mechanism for managed breakpoints.&amp;nbsp; This principle leads directly to the following design decision.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Under the hood we're built on the native debugging pipeline&lt;BR&gt;In v2-compat mode, ICD continues to own the pipeline to the target process (since that was the V2 model), but that pipeline is no longer a collection of shared IPC objects with the target process, but is instead the same pipeline a native debugger uses.&amp;nbsp; Specifically, we attach to a process by calling kernel32!DebugActiveProcess, and get our managed events (things that result in calls to ICorDebugManagedCallback) using kernel32!WaitForDebugEvent.&amp;nbsp; This also means that kernel32!IsDebuggerPresent now returns true when doing managed-only debugging.&amp;nbsp; This also has the nice side-effect of avoiding the problem with doing managed-only debugging when a kernel debugger is enabled (the OS assumes any breakpoint instructions that occur when a debugger isn't attached should cause a break in the kernel debugger).&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;Ok, I think those are the most important design points.&amp;nbsp; Sometime later I'll start going into more of the concrete details. &amp;nbsp;&amp;nbsp;Post a comment if you have any specific things you'd like to hear about.&lt;/P&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9018831" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rmbyers/archive/tags/ICorDebug/default.aspx">ICorDebug</category></item><item><title>Func-eval can fail while stopped in a non-optimized managed method that pushes more than 256 argument bytes </title><link>http://blogs.msdn.com/rmbyers/archive/2008/08/16/Func_2D00_eval-can-fail-while-stopped-in-a-non_2D00_optimized-managed-method-that-pushes-more-than-256-argument-bytes-.aspx</link><pubDate>Sun, 17 Aug 2008 02:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8872792</guid><dc:creator>rmbyers</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/rmbyers/comments/8872792.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rmbyers/commentrss.aspx?PostID=8872792</wfw:commentRss><description>&lt;P&gt;In &lt;A href="http://blogs.msdn.com/jmstall/archive/2005/11/15/funceval-rules.aspx" mce_href="http://blogs.msdn.com/jmstall/archive/2005/11/15/funceval-rules.aspx"&gt;this blog entry&lt;/A&gt;, Mike describes that func-eval will fail when not a GC-safe point.&amp;nbsp; In VS this results in the error "Cannot evaluate expression because a thread is stopped at a point where garbage collection is impossible, possibly because the code is optimized".&amp;nbsp; Typically non-optimized (debuggable) managed code is compiled as "fully-interruptible" which means every point is a GC-safe point.&amp;nbsp; However, occasionally I hear complaints that VS is giving the error even when in non-optimized code.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In CLR 2.0, the x86 JIT has a limitiation where it will fall back to partially-interruptible code if more than 256 bytes of arguments are pushed onto the stack (which is normally very rare).&amp;nbsp; [Update: corrected claim that the limitation was introduced in 2.0, .NET 1.1 actually had an even smaller&amp;nbsp;limit of 128 bytes].&amp;nbsp; For example, the code below passes two 128 byte structures by-value to the function 'BigFunc', and so is compiled as partially-interruptible which means FuncEval isn't necessarily possible at all points in the method.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Funcevalfailswhilestoppedinnonoptimizedm_EDF2/image_6.png" mce_href="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Funcevalfailswhilestoppedinnonoptimizedm_EDF2/image_6.png"&gt;&lt;IMG style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=600 alt=image src="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Funcevalfailswhilestoppedinnonoptimizedm_EDF2/image_thumb_2.png" width=848 border=0 mce_src="http://blogs.msdn.com/blogfiles/rmbyers/WindowsLiveWriter/Funcevalfailswhilestoppedinnonoptimizedm_EDF2/image_thumb_2.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;In the above case, we can verify that the method Main is not fully-interruptible by using the GCInfo command in SOS:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;.load sos &lt;BR&gt;extension C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll loaded&lt;/P&gt;
&lt;P&gt;!GCInfo 003A00A4 &lt;BR&gt;entry point 003a0070 &lt;BR&gt;Normal JIT generated code &lt;BR&gt;GC info 11e8a09800121a98 &lt;BR&gt;Method info block: &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; method&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size&amp;nbsp;&amp;nbsp; = 0167 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; prolog&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size&amp;nbsp;&amp;nbsp; = 32 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; epilog&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size&amp;nbsp;&amp;nbsp; =&amp;nbsp; 8 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; epilog&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; count&amp;nbsp;&amp;nbsp; =&amp;nbsp; 1 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; epilog&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end&amp;nbsp;&amp;nbsp;&amp;nbsp; = yes&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callee-saved regs&amp;nbsp; = EDI ESI EBX EBP &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ebp frame&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = yes&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;fully interruptible= no&amp;nbsp; &lt;BR&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; double align&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = no&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; arguments size&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; =&amp;nbsp; 0 DWORDs &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack frame size&amp;nbsp;&amp;nbsp; = 44 DWORDs &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; untracked count&amp;nbsp;&amp;nbsp;&amp;nbsp; =&amp;nbsp; 1 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var ptr tab count&amp;nbsp; =&amp;nbsp; 1 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; security check obj = yes &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exception handlers = yes &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; edit &amp;amp; continue&amp;nbsp;&amp;nbsp;&amp;nbsp; = yes &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; epilog&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at&amp;nbsp;&amp;nbsp; 015F &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; argTabOffset = 5&amp;nbsp; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;H6&gt;&lt;/H6&gt;
&lt;P&gt;First we load sos in the immediate window, then get an address in the method of interest (eg. by looking at the value of the EIP register while we're stopped there) and pass it to the !GCInfo command.&amp;nbsp; The "fully intteruptible=no" line is unusual for debuggable code (one way you can tell it's indeed debuggable is the "edit &amp;amp; continue = yes" which isn't normally the case in optimized code).&lt;/P&gt;
&lt;P&gt;The other, more common, case where this happens is when calling a method with at least 64 arguments (each of 4 bytes).&amp;nbsp; Having a method that takes 64 arguments seems poor style to me (hard to read), but I've seen such code from code-generation tools.&amp;nbsp; Either way, passing 256 bytes by-value on the stack is generally a bad idea from a performance perspective anyway (it's a fair amount of copying of data).&amp;nbsp; It's usually better to group the data into a class and pass that, and/or pass large value-types by reference (eg. with the 'ref' keyword in C#).&lt;/P&gt;
&lt;P&gt;We're looking into relaxing this restriction in a future version of the CLR, but in the meantime if you run into problems with this, I suggest you refactor your code to avoid having methods that take 256 bytes or more in arguments.&amp;nbsp; Perhaps somebody should write an FxCop rule for this.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8872792" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rmbyers/archive/tags/CLR/default.aspx">CLR</category><category domain="http://blogs.msdn.com/rmbyers/archive/tags/ICorDebug/default.aspx">ICorDebug</category></item><item><title>Invoking a virtual method non-virtually</title><link>http://blogs.msdn.com/rmbyers/archive/2008/08/16/invoking-a-virtual-method-non-virtually.aspx</link><pubDate>Sun, 17 Aug 2008 02:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8872728</guid><dc:creator>rmbyers</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/rmbyers/comments/8872728.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rmbyers/commentrss.aspx?PostID=8872728</wfw:commentRss><description>&lt;P&gt;Method calls using the C# ‘&lt;A href="http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx" mce_href="http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx"&gt;base&lt;/A&gt;’ keyword get compiled to an IL ‘&lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.call.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.call.aspx"&gt;call&lt;/A&gt;’ instruction, rather than the ‘&lt;A href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.callvirt.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.callvirt.aspx"&gt;callvirt&lt;/A&gt;’ &lt;A href="http://blogs.msdn.com/ericgu/archive/2008/07/02/why-does-c-always-use-callvirt.aspx" mce_href="http://blogs.msdn.com/ericgu/archive/2008/07/02/why-does-c-always-use-callvirt.aspx"&gt;that is normally used&lt;/A&gt;. This is the one case in C# where a virtual method can be invoked without virtual dispatch. The CLR allows it to be used generally for non-virtual calls, but it’s unverifiable in other cases (see section 3.19 of the &lt;A href="http://download.microsoft.com/download/7/3/3/733AD403-90B2-4064-A81E-01035A7FE13C/MS%20Partition%20III.pdf" mce_href="http://download.microsoft.com/download/7/3/3/733AD403-90B2-4064-A81E-01035A7FE13C/MS%20Partition%20III.pdf"&gt;CLI specification partition III&lt;/A&gt; for the full definition). &lt;/P&gt;
&lt;P&gt;One place this causes some pain is with &lt;A href="http://blogs.msdn.com/jmstall/archive/category/11475.aspx" mce_href="http://blogs.msdn.com/jmstall/archive/category/11475.aspx"&gt;func-eval&lt;/A&gt;. Func-Eval always does a virtual dispatch on virtual methods, which is why the ‘base’ keyword doesn’t work properly in the watch/immediate window in VS 2008. Mike Stall has a blog entry on this topic here: &lt;A href="http://blogs.msdn.com/jmstall/archive/2006/06/29/funceval-does-virtual-dispatch.aspx" mce_href="http://blogs.msdn.com/jmstall/archive/2006/06/29/funceval-does-virtual-dispatch.aspx"&gt;http://blogs.msdn.com/jmstall/archive/2006/06/29/funceval-does-virtual-dispatch.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;What Mike doesn’t mention is there is actually a work-around for this. First we need some mechanism to invoke a virtual method non-virtually, and the only one I could find was using Reflection.Emit / lightweight-codegen to emit a ‘call’ instruction. For example, the following method can be used to invoke any virtual method non-virtually:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;summary&amp;gt;
/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;Call a virtual method non-virtually - like Reflection's MethodInfo.Invoke, 
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;but doesn't do virtual dispatch.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="method"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;The method to invoke&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="args"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;The arguments to pass (including 'this')&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;The return value from the call&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;/returns&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;static object &lt;/SPAN&gt;InvokeNonVirtual(&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;method, &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[] args)
{
    &lt;SPAN style="COLOR: green"&gt;// Reflection doesn't seem to have a way directly (eg. custom binders are 
    // only used for ambiguities).  Using a delegate also always seems to do 
    // virtual dispatch.

    // Use LCG to generate a temporary method that uses a 'call' instruction to
    // invoke the supplied method non-virtually.
    // Doing a non-virtual call on a virtual method outside the class that 
    // defines it will normally generate a VerificationException (PEVerify 
    // says "The 'this' parameter to the call must be the callng method's 
    // 'this' parameter.").  By associating the method with a type ("Program") 
    // in a full-trust assembly, we tell the JIT to skip this verification step.
    // Alternately we might want to associate it with method.DeclaringType - the
    // verification might then pass even if it's not skipped (eg. partial trust).
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;paramTypes = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Type&lt;/SPAN&gt;&amp;gt;();
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(!method.IsStatic)
        paramTypes.Add(method.DeclaringType);
    paramTypes.AddRange(method.GetParameters().Select(p =&amp;gt; p.ParameterType));
    &lt;SPAN style="COLOR: #2b91af"&gt;DynamicMethod &lt;/SPAN&gt;dm = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicMethod&lt;/SPAN&gt;(
        &lt;SPAN style="COLOR: #a31515"&gt;"NonVirtualInvoker"&lt;/SPAN&gt;,    &lt;SPAN style="COLOR: green"&gt;// name
        &lt;/SPAN&gt;method.ReturnType,      &lt;SPAN style="COLOR: green"&gt;// same return type as method we're calling 
        &lt;/SPAN&gt;paramTypes.ToArray(),   &lt;SPAN style="COLOR: green"&gt;// same parameter types as method we're calling
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Program&lt;/SPAN&gt;));       &lt;SPAN style="COLOR: green"&gt;// associates with this full-trust code
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ILGenerator &lt;/SPAN&gt;il = dm.GetILGenerator();
    &lt;SPAN style="COLOR: blue"&gt;for &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;i = 0; i &amp;lt; paramTypes.Count; i++)
        il.Emit(&lt;SPAN style="COLOR: #2b91af"&gt;OpCodes&lt;/SPAN&gt;.Ldarg, i);             &lt;SPAN style="COLOR: green"&gt;// load all args
    &lt;/SPAN&gt;il.EmitCall(&lt;SPAN style="COLOR: #2b91af"&gt;OpCodes&lt;/SPAN&gt;.Call, method, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);   &lt;SPAN style="COLOR: green"&gt;// call the method non-virtually
    &lt;/SPAN&gt;il.Emit(&lt;SPAN style="COLOR: #2b91af"&gt;OpCodes&lt;/SPAN&gt;.Ret);                      &lt;SPAN style="COLOR: green"&gt;// return what the call returned

    // Call the emitted method, which in turn will call the method requested
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;dm.Invoke(&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, args);
}&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;With a method like the above available, we can use statements like the following (in the program or in the immediate window) to invoke a method non-virtually (i.e. to simulate the ‘base’ keyword):&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// Foo is some class that overrides ToString
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Foo &lt;/SPAN&gt;f = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Foo&lt;/SPAN&gt;();
&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;m = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;).GetMethod(&lt;SPAN style="COLOR: #a31515"&gt;"ToString"&lt;/SPAN&gt;, 
    &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Public);

&lt;SPAN style="COLOR: green"&gt;// s1 will be the same as f.ToString - whatever Foo.ToString returns
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;s1 = (&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;)m.Invoke(f, 
    &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.InvokeMethod, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);

&lt;SPAN style="COLOR: green"&gt;// s2 will be the return value from Object.ToString
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;s2 = (&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;)InvokeNonVirtual(m, &lt;SPAN style="COLOR: blue"&gt;new object&lt;/SPAN&gt;[] {f});&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;We can also avoid having to get the ‘InvokeNonVirtual’ method into the target program at all by entering code like the following into the immediate window (depending on what method you want to invoke, eg. this invokes 'ToString' non-virtually on object 'o').:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;m1 = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;).GetMethod(&lt;SPAN style="COLOR: #a31515"&gt;"ToString"&lt;/SPAN&gt;, 
    &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Public);
&lt;SPAN style="COLOR: #2b91af"&gt;DynamicMethod &lt;/SPAN&gt;dm = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DynamicMethod&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"ToStringInvoker"&lt;/SPAN&gt;, 
    &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;), &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Type&lt;/SPAN&gt;[] { &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;) }, &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Program&lt;/SPAN&gt;));
&lt;SPAN style="COLOR: #2b91af"&gt;ILGenerator &lt;/SPAN&gt;il = dm.GetILGenerator();
il.Emit(&lt;SPAN style="COLOR: #2b91af"&gt;OpCodes&lt;/SPAN&gt;.Ldarg_0);
il.EmitCall(&lt;SPAN style="COLOR: #2b91af"&gt;OpCodes&lt;/SPAN&gt;.Call, m1, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);
il.Emit(&lt;SPAN style="COLOR: #2b91af"&gt;OpCodes&lt;/SPAN&gt;.Ret);
&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;s3 = (&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;)dm.Invoke(&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;new object&lt;/SPAN&gt;[] { o });&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Yes, I realize typing this into the immediate window whenever you want to say ‘base’ is kind of a pain (perhaps completely impractical). But the interesting thing here is that it means a debugger could build support for the ‘base’ keyword without any additional work from ICorDebug or the CLR! Of course, I still agree with Mike that it’s a reasonable feature-request to have func-eval support an option for non-virtual dispatch. I just don’t see it making its way to the top of our wish-list anytime soon (unless we get strong customer feedback of course).&lt;/P&gt;
&lt;P&gt;This also raises an interesting question about the design of func-eval. Should we have just supported calling a few key reflection APIs and made all evals go through reflection? This certainly would have been simpler and more reliable for the CLR – otherwise we have to duplicate a lot of the logic about how to marshal values and call methods that Reflection already needs to have. Then again, there’s always going to be the challenge of marshalling between ICorDebugValue instances and objects in the target, and that’s a pretty big chunk of what’s required to make func-eval work.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8872728" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rmbyers/archive/tags/CLR/default.aspx">CLR</category><category domain="http://blogs.msdn.com/rmbyers/archive/tags/ICorDebug/default.aspx">ICorDebug</category></item></channel></rss>