<?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>Bug! Inspecting Value-Type Returns Workaround #2</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx</link><description>12/6/2007 Update: The bug described below has been fixed in CLR 2.0 SP1.&amp;#160; (See this post for more info.)&amp;#160; However, you may still find this info useful as a tutorial on performing IL rewriting. Previously, I posted about a bug with using the</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: Bug!  Inspecting Value-Type Returns Workaround #2</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#621209</link><pubDate>Thu, 08 Jun 2006 00:46:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:621209</guid><dc:creator>Marc Brooks</dc:creator><description>Couldn't you avoid all that signature rewriting by calling into a stub function that _itself_ does a local store to it's (0-indexed always!) local, then call-out to the inspection method? That gives:&lt;br&gt;&lt;br&gt;// original&lt;br&gt;ret&lt;br&gt;&lt;br&gt;// injected&lt;br&gt;call inspect // dynamic stub&lt;br&gt;ret&lt;br&gt;&lt;br&gt;// inspect dynamic stub's body (signature left as exercise to you).&lt;br&gt; &amp;nbsp; &amp;nbsp;dup&lt;br&gt; &amp;nbsp; &amp;nbsp;stloc.0 &amp;nbsp; &amp;nbsp; &amp;nbsp;// Copy return value into local&lt;br&gt; &amp;nbsp; &amp;nbsp;ldloca.0 &amp;nbsp; &amp;nbsp; // Push address to local onto stack&lt;br&gt; &amp;nbsp; &amp;nbsp;ldc.i4(8) UnmanagedInspectValue (fcn pointer)&lt;br&gt; &amp;nbsp; &amp;nbsp;calli callsitedescr&lt;br&gt; &amp;nbsp; &amp;nbsp;ret&lt;br&gt;</description></item><item><title>re: Bug!  Inspecting Value-Type Returns Workaround #2</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#621433</link><pubDate>Thu, 08 Jun 2006 04:51:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:621433</guid><dc:creator>davbr</dc:creator><description>I think something like what you propose could work, though it may need some refinement and would probably have worse perf. &amp;nbsp;This is still an interesting idea to explore. &amp;nbsp;Now I haven't tried any of this out, but I suspect the JIT will be unhappy with the IL exactly as you wrote it, due to the IL stack being used in an unbalanced way across the function call. &amp;nbsp;Your &amp;quot;inspect&amp;quot; stub has a dup at the top, but no one explicitly loaded anything onto the stack, so the stack is empty as far as the JIT can tell. &amp;nbsp;Of course, we all know better because we know we'll be good citizens and only call &amp;quot;inspect&amp;quot; right before your rewritten (what you labeled &amp;quot;injected&amp;quot;) function returns (so its return value is on the stack). &amp;nbsp;But we're not allowed to be smarter than the JIT--we've got to follow the rules.&lt;br&gt;&lt;br&gt;Perhaps you wanted &amp;quot;inspect&amp;quot; to take a param, in which case you'd do a &amp;quot;ldarg&amp;quot; just before your &amp;quot;dup&amp;quot;. &amp;nbsp;In that case, &amp;quot;call inspect&amp;quot; will expect that param will be on the stack (for &amp;quot;inspect&amp;quot; to use), and it will therefore be popped for you. &amp;nbsp;So by the time you return out of &amp;quot;inspect&amp;quot; back to &amp;quot;injected&amp;quot;, the JIT will expect your stack is empty and you have nothing to return.&lt;br&gt;&lt;br&gt;If you move your &amp;quot;dup&amp;quot; out of &amp;quot;inspect&amp;quot; and into your injected function, and add the missing IL to push the arg back onto the stack, you have this:&lt;br&gt;&lt;br&gt;// original &lt;br&gt;ret &lt;br&gt;&lt;br&gt;// injected &lt;br&gt;dup&lt;br&gt;call inspect // dynamic stub &lt;br&gt;ret &lt;br&gt;&lt;br&gt;// inspect dynamic stub's body (signature left as exercise to you). &lt;br&gt; &amp;nbsp; ldarg.0 &amp;nbsp; &amp;nbsp; &amp;nbsp;// Push arg back on stack&lt;br&gt; &amp;nbsp; stloc.0 &amp;nbsp; &amp;nbsp; &amp;nbsp;// Copy arg into local &lt;br&gt; &amp;nbsp; ldloca.0 &amp;nbsp; &amp;nbsp; // Push address to local onto stack &lt;br&gt; &amp;nbsp; ldc.i4(8) UnmanagedInspectValue (fcn pointer) &lt;br&gt; &amp;nbsp; calli callsitedescr &lt;br&gt; &amp;nbsp; ret &lt;br&gt;&lt;br&gt;You could simplify even further by using &amp;quot;ldarga&amp;quot; to load the arg's address onto the stack directly, without needing a local at all:&lt;br&gt;&lt;br&gt;// inspect dynamic stub's body (signature left as exercise to you). &lt;br&gt; &amp;nbsp; ldarga.0 &amp;nbsp;// Push address of arg&lt;br&gt; &amp;nbsp; ldc.i4(8) UnmanagedInspectValue (fcn pointer) &lt;br&gt; &amp;nbsp; calli callsitedescr &lt;br&gt; &amp;nbsp; ret &lt;br&gt;&lt;br&gt;Looks cool, right? &amp;nbsp;But that brings me to this part: &amp;quot;signature left as exercise to you&amp;quot;. &amp;nbsp;What exactly is the type of parameter that &amp;quot;inspect&amp;quot; takes? &amp;nbsp;That's quite important to declare to the JIT via metadata. &amp;nbsp;In fact, for every possible value type that can be passed to &amp;quot;inspect&amp;quot;, you'll need another override of &amp;quot;inspect&amp;quot; that takes a parameter of that type. &amp;nbsp;This can be prohibitively time-consuming at run-time to create every possible override you need.&lt;br&gt;&lt;br&gt;That said, maybe this can be worked around by making a single &amp;quot;inspect&amp;quot; function that's vararg? &amp;nbsp;Then again, the extra time it takes to initialize System.ArgIterator so it can fish out the type could again be prohibitive.</description></item><item><title>re: Bug!  Inspecting Value-Type Returns Workaround #2</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#622486</link><pubDate>Thu, 08 Jun 2006 20:37:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:622486</guid><dc:creator>johnls</dc:creator><description>It's also important to point out to folks that calli is an unverifiable instruction that requires the UnverifiableCode access permission. &amp;nbsp;Any attempt to use this technique in an assembly that doesn't have FullTrust will fail.</description></item><item><title>Creating an IL-rewriting profiler</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#1823934</link><pubDate>Wed, 07 Mar 2007 06:13:22 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1823934</guid><dc:creator>David Broman's CLR Profiling API Blog</dc:creator><description>&lt;p&gt;A frequent topic of discussion between those of us on the CLR Profiling API team at Microsoft and our&lt;/p&gt;
</description></item><item><title>Versions of Microsoft .NET Framework, CLR, and Your Profiler</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#6682526</link><pubDate>Thu, 06 Dec 2007 20:47:44 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6682526</guid><dc:creator>David Broman's CLR Profiling API Blog</dc:creator><description>&lt;p&gt;With the recent release of the Microsoft .NET Framework 3.5, not to mention prior versions like Microsoft&lt;/p&gt;
</description></item><item><title>Versions of Microsoft .NET Framework, CLR, and Your Profiler</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#6682593</link><pubDate>Thu, 06 Dec 2007 20:51:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6682593</guid><dc:creator>Noticias externas</dc:creator><description>&lt;p&gt;With the recent release of the Microsoft .NET Framework 3.5, not to mention prior versions like Microsoft&lt;/p&gt;</description></item><item><title>.NET to C++ Bridge</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#7741002</link><pubDate>Sun, 17 Feb 2008 00:04:50 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7741002</guid><dc:creator>All Your Base Are Belong To Us</dc:creator><description>&lt;p&gt;Most people have encountered the need for interoperability between managed and unmanaged code. There&lt;/p&gt;
</description></item><item><title>re: Bug! Inspecting Value-Type Returns Workaround #2</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#9029441</link><pubDate>Sun, 02 Nov 2008 21:37:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9029441</guid><dc:creator>Tanveer Badar</dc:creator><description>&lt;p&gt;&amp;quot;However, since in my case I only have one parameter anyway, I can cheat and just call it __fastcall, and the compiler is none the wiser. Just so long as I remember that, once I add a third parameter to my function, the gig is up!&amp;quot;&lt;/p&gt;
&lt;p&gt;Perhaps I did wrong math in this case, but it should be the fourth parameter when order starts being significant.&lt;/p&gt;
&lt;p&gt;First two parameters are passed in ECX/EDX. Next parameter is on stack. Order doesn't matter. Its when you add fourth parameter you really need to care about C, D or D, C.&lt;/p&gt;</description></item><item><title>re: Bug! Inspecting Value-Type Returns Workaround #2</title><link>http://blogs.msdn.com/davbr/archive/2006/06/07/bug-inspecting-value-type-returns-workaround-2.aspx#9029779</link><pubDate>Mon, 03 Nov 2008 01:34:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9029779</guid><dc:creator>davbr</dc:creator><description>&lt;p&gt;Hello, Tanveer. &amp;nbsp;Great point! &amp;nbsp;Yes, if there's only 3 parameters, then there's only 1 stack parameter, and therefore there would be no issue with stack parameter ordering in that case. &amp;nbsp;You are correct that, when one moves up to FOUR parameters total, only then does stack ordering become an issue. &amp;nbsp;Thanks for catching that!&lt;/p&gt;
</description></item></channel></rss>