<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6290271494008843512</id><updated>2012-02-16T00:57:05.911-08:00</updated><category term='windows software preprocessor'/><category term='sp1'/><category term='visual studio 2008'/><category term='drivers'/><category term='ddk'/><category term='wpp'/><title type='text'>I digress.  D066.</title><subtitle type='html'>Random stuff that falls out of my head (that's short enough to write about in a blog).

Bonus points if you know what the number means.  Bonus points if you knew it was a number ;)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-4212010081447507240</id><published>2009-02-23T09:19:00.000-08:00</published><updated>2009-03-02T16:37:50.311-08:00</updated><title type='text'>Anonymous Types and Regular Expressions</title><content type='html'>Regular Expressions are great, and they aren't bad to program, but .  It is "non-obvious" which field you are supposed to use.  A group is a capture, and has captures, so where is your named capture group to get that simple piece of text?  &lt;br /&gt;&lt;br /&gt;In the spirit of the "pit of success" here's a quick way to use Regex in your program and you only have to remember one call.  We'll do this by casting to an anonymous type.  It looks a tad wierd, but it is super easy to use.  Super easy, the second time.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; RegularExpressions;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; egrep&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="cls"&gt;egrep&lt;/span&gt;&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; &lt;span class="cls"&gt;Main&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] &lt;span class="var"&gt;args&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; &lt;span class="var"&gt;text&lt;/span&gt; = "The the quick brown fox  fox jumped over the lazy dog dog.";&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;var&lt;/span&gt; &lt;span class="var"&gt;matches&lt;/span&gt; = Regex.&lt;span class="cls"&gt;grep&lt;/span&gt;(&lt;span class="var"&gt;text&lt;/span&gt;, @"\b(?&amp;lt;double_word&amp;gt;\w+)\s+(\k&amp;lt;double_word&amp;gt;)\b",&lt;br /&gt;                 &lt;span class="kwrd"&gt;new&lt;/span&gt; { double_word = "" });&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;var&lt;/span&gt; &lt;span class="var"&gt;find&lt;/span&gt; in &lt;span class="var"&gt;matches&lt;/span&gt;)&lt;br /&gt;                Console.&lt;span class="cls"&gt;WriteLine&lt;/span&gt;(&lt;span  class="var"&gt;find&lt;/span&gt;.double_word);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-4212010081447507240?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/4212010081447507240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=4212010081447507240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/4212010081447507240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/4212010081447507240'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2009/02/anonymous-types-and-regular-expressions.html' title='Anonymous Types and Regular Expressions'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-1337806476064970542</id><published>2009-01-29T10:48:00.000-08:00</published><updated>2009-01-31T12:17:29.888-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ddk'/><category scheme='http://www.blogger.com/atom/ns#' term='windows software preprocessor'/><category scheme='http://www.blogger.com/atom/ns#' term='wpp'/><category scheme='http://www.blogger.com/atom/ns#' term='drivers'/><category scheme='http://www.blogger.com/atom/ns#' term='visual studio 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='sp1'/><title type='text'>Building Windows Software Tracing from Visual Studio 2008</title><content type='html'>&lt;a href="http://www.whirlygigventures.com/wpp.rules"&gt;Rule File&lt;/a&gt; to use with Visual Studio 2008 SP1.&lt;br /&gt;&lt;br /&gt;The Windows software trace preprocessor (abbreviated WPP; the preprocessor and related support tools are known as WPP Software Tracing) is a preprocessor that simplifies the use of WMI event tracing to implement efficient software tracing in drivers and applications that target Windows 2000 and later operating systems. WPP was created by Microsoft and is included in the Windows DDK.&lt;br /&gt;&lt;br /&gt;WPP is run prior to compilation (in other words, before even the C preprocessor), and generates a trace message header for each file that it processes (by default this header is filename.tmh, where filename is the name of the processed source file). This header must then be explicitly included into the source file, for example:&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;// File: file.cxx&lt;br /&gt;// This file is an example of using WPP&lt;br /&gt;#include "file.tmh"&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The preprocessing for WPP is normally handled by the DDK compiler.  This rules out using Visual Studio to add this to your project.  After looking around there is a nearly undocumented solution.  The preprocessor also exists as an executable named &lt;strong&gt;tracewpp.exe&lt;/strong&gt; in the bin directory in the DDK. Normally this would be&lt;br /&gt;&lt;div class="csharpcode"&gt;c:\WinDDK\6001.18002\bin\x86\tracewpp.exe&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;To add this to VS 2008 SP1, the easiest way I've found is to create a second project as a dependency to your driver project. Then each C/CPP file can use a custom build rule.&lt;br /&gt;&lt;br /&gt;Here's how to setup the project.&lt;br /&gt;&lt;div&gt;&lt;a href="http://2.bp.blogspot.com/_QvA8PCZOesc/SYIHv3xqquI/AAAAAAAAABk/GLPLhuJksP0/s1600-h/Utility.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://2.bp.blogspot.com/_QvA8PCZOesc/SYIHv3xqquI/AAAAAAAAABk/GLPLhuJksP0/s320/Utility.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5296804630748637922" /&gt;&lt;/a&gt; Create a new project, and change the type to &lt;strong&gt;Utility&lt;/strong&gt;.  This will keep it from compiling the .c files.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_QvA8PCZOesc/SYIHu5nz_bI/AAAAAAAAABU/vGSw1Rj-VTg/s1600-h/Step2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 197px;" src="http://3.bp.blogspot.com/_QvA8PCZOesc/SYIHu5nz_bI/AAAAAAAAABU/vGSw1Rj-VTg/s320/Step2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5296804614064307634" /&gt;&lt;/a&gt;  Right click on the new project to edit the Custom Build Rules.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_QvA8PCZOesc/SYIJ4ZlG47I/AAAAAAAAABs/b6tD9qmDCK0/s1600-h/CustomRuleFiles.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 218px;" src="http://4.bp.blogspot.com/_QvA8PCZOesc/SYIJ4ZlG47I/AAAAAAAAABs/b6tD9qmDCK0/s320/CustomRuleFiles.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5296806976284976050" /&gt;&lt;/a&gt;  Add a custom rule file so that you can reuse it.  I called mine WPP.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_QvA8PCZOesc/SYIHvOx1uNI/AAAAAAAAABc/F1FVUweoHQU/s1600-h/Step3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 218px;" src="http://2.bp.blogspot.com/_QvA8PCZOesc/SYIHvOx1uNI/AAAAAAAAABc/F1FVUweoHQU/s320/Step3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5296804619743508690" /&gt;&lt;/a&gt;  Here are the Build Rule properties you will need.&lt;br&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.whirlygigventures.com/wpp.rules"&gt;Rule file&lt;/a&gt; to use with Visual Studio 2008 SP1.&lt;strong&gt;&lt;/strong&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-1337806476064970542?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/1337806476064970542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=1337806476064970542' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/1337806476064970542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/1337806476064970542'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2009/01/building-windows-software-tracing-from.html' title='Building Windows Software Tracing from Visual Studio 2008'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_QvA8PCZOesc/SYIHv3xqquI/AAAAAAAAABk/GLPLhuJksP0/s72-c/Utility.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-1448796807820993901</id><published>2008-08-27T19:55:00.000-07:00</published><updated>2009-03-15T23:41:36.322-07:00</updated><title type='text'>NTFS 010 Editor Template</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;br /&gt;Here's a NTFS (New Technologies File System) template I have been working on for viewing the NTFS Master File Table (or MFT) using the &lt;a href="http://www.sweetscape.com/"&gt;010 Editor&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;The MFT contains all the information about the files and directories stored on the disk.  In the NTFS, everything is a file. The MFT itself is a list of file records, typically 1k in size, that has all your file entries. The root directory of the file structure starts in entry 5, and it's name is '.'&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bootstrap&lt;/b&gt;&lt;br /&gt;Since the above paragraph is technically correct, but makes no sense, here's is how we start.  The start of the MFT is stored in the NTFS boot sector.  This is the first block of the &lt;b&gt;volume&lt;/b&gt;.  There is a disk boot sector as well, to confuse matters.  The disk boot sector lists all the volumes, such as the NTFS volume we are going to look at.&lt;br /&gt;&lt;br /&gt;From the boot sector we can find the start of the MFT.  The MFT is logically an array of MFT entries on disk. It can be in multiple chunks, which makes sense for expanding and contracting volumes.  When you expand, there is surely little room for another disks worth of file entries (mft entries), so NTFS can put these in different spots on the the drive.&lt;br /&gt;&lt;br /&gt;MFT entry 0, is a file called (drum roll....) $MFT.  It's file attribute called $DATA lists the different runs for the file.  The file in this case being the MFT itself.  The first run starts exactly where MFT 0 starts, which is why it is called self describing.  We just need the boot sector to get things rolling.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Here's a picture of bcd.hive.LOG1 and a picture is worth way more than a few thousand words this time.&lt;br /&gt;&lt;br /&gt;Start at MFT 5, Attribute 4 is the Index_Allocation (Attribute 3 points here).  In the second run of the Allocation, entry 2 has the file properties.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_QvA8PCZOesc/SY5kFJj_JTI/AAAAAAAAACo/2HjQ1hp-yYo/s1600-h/NTFS.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 252px; height: 640px;" src="http://4.bp.blogspot.com/_QvA8PCZOesc/SY5kFJj_JTI/AAAAAAAAACo/2HjQ1hp-yYo/s320/NTFS.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5300283851090634034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="www.whirlygigventures.com/ntfs_defs.bt"&gt;ntfs_defs.bt&lt;/a&gt;&lt;br /&gt;&lt;a href="www.whirlygigventures.com/ntfs.bt"&gt;ntfs.bt&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-1448796807820993901?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/1448796807820993901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=1448796807820993901' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/1448796807820993901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/1448796807820993901'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2008/08/ntfs-010-editor-template.html' title='NTFS 010 Editor Template'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_QvA8PCZOesc/SY5kFJj_JTI/AAAAAAAAACo/2HjQ1hp-yYo/s72-c/NTFS.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-4789794381964367193</id><published>2008-03-29T09:44:00.000-07:00</published><updated>2008-03-29T10:09:47.664-07:00</updated><title type='text'>Design Rules</title><content type='html'>I ran across this on Kevin's blog.  Great stuff I have to add my slant to it.&lt;br /&gt;&lt;br /&gt;Minimize code complexity&lt;br /&gt;Maximize API ease-of-use &lt;br /&gt;Maximize the chance another dev will use an API correctly (see Pit of Success) &lt;br /&gt;Minimize code size &lt;br /&gt;Minimize unnecessary code churn &lt;br /&gt;Maximize code readability &lt;br /&gt;Maximize correctness &lt;br /&gt;Maximize robustness &lt;br /&gt;Maximize flexibility &lt;br /&gt;Maximize code maintainability &lt;br /&gt;Maximize CPU performance characteristics &lt;br /&gt;Maximize Memory performance characteristics &lt;br /&gt;Opt for immutable data structures &lt;br /&gt;Opt for thread-safe data structures and APIs &lt;br /&gt;Verify pre-conditions &lt;br /&gt;Follow design guidelines &lt;br /&gt;Get it done yesterday! &lt;br /&gt;&lt;br /&gt;These are all but the same rule to me.  It's the first goal listed, &lt;strong&gt;Minimize code complexity&lt;/strong&gt;.  Maybe I should say rules 2 through N are how to get to minimal code complexity.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Levels of Complexity&lt;/em&gt;&lt;br /&gt;If you have a component with no interrelations, at most it will take you W^1 units of work.  Put your slowest or fastest dev on the component, it won't change you project completion date.&lt;br /&gt;&lt;br /&gt;Now, if you have a component that rely's on something else.  This is pretty much going to take you 4 times as long.  W^2&lt;br /&gt;&lt;br /&gt;W^3?  That's right.... 9 times as long.&lt;br /&gt;&lt;br /&gt;On the way to reaching you minimal code complexity, item's 2 and 3 are super important.  Maybe we should change it to &lt;strong&gt;minimal api complexity&lt;/strong&gt;.  I will take tons of code in a class with a super easy api.  That all but takes you from 9 work units down to 4.&lt;br /&gt;&lt;br /&gt;Either way, a great list to use as talking points.&lt;br /&gt;&lt;br /&gt;Some crazy extreme's come to mind.  boost's Spirit (www.boost.org).  A very neat parsing library.  Almost nothing in the classes is directly tied to any other class.&lt;br /&gt;&lt;br /&gt;The use of templates and the fact that every compiler error and call stack is a good 20 lines long makes it just impossible to use.  Impossible unless you know about all the classes that exist to help everything compile.  If VC9.0 would just let you turn off namespaces, and even template parameters in the debugger it'd be 100 times easier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-4789794381964367193?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/4789794381964367193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=4789794381964367193' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/4789794381964367193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/4789794381964367193'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2008/03/design-rules.html' title='Design Rules'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-2582815021943526077</id><published>2008-03-26T14:11:00.000-07:00</published><updated>2008-03-26T14:13:26.354-07:00</updated><title type='text'>Great keyboard</title><content type='html'>This get's an "epic" rating.&lt;br /&gt;&lt;a href="http://www.daskeyboard.com"&gt;Das Keyboard II&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Of course, there are some nice $600 keyboards with mechanical keys, but this one is a whole $80.  A no brainer if you type all day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-2582815021943526077?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/2582815021943526077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=2582815021943526077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/2582815021943526077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/2582815021943526077'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2008/03/great-keyboard.html' title='Great keyboard'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-4553758394996544652</id><published>2008-03-26T14:07:00.000-07:00</published><updated>2008-03-26T14:11:30.244-07:00</updated><title type='text'>IL IDA tool</title><content type='html'>A little interactive disassembly for you from the Reflector addins.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sourceforge.net/projects/reflexil/"&gt;Reflexil on SourceForge.net&lt;/a&gt;&lt;br&gt;&lt;br /&gt;Reflexil is an assembly editor and runs as a plug-in for Reflector. Using Mono.Cecil, Reflexil is able to manipulate IL code and save the modified assemblies to disk. Reflexil also supports 'on the fly' C# and VB.NET code injection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-4553758394996544652?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/4553758394996544652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=4553758394996544652' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/4553758394996544652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/4553758394996544652'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2008/03/il-ida-tool.html' title='IL IDA tool'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-1434827222320779889</id><published>2008-01-15T07:23:00.000-08:00</published><updated>2008-01-15T07:58:36.165-08:00</updated><title type='text'>Visual Studio 2008 CRT bug</title><content type='html'>I run into this "issue" alot compiling this open source project or that open source project.  It's a fun MACRO problem.  I love MACROs.  &lt;/sarc&gt;&lt;br /&gt;&lt;br /&gt;Here's what your compiler will give you.&lt;br /&gt;&lt;br /&gt; 12&gt;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\stdio.h(358) : error C3163: '_vsnprintf': attributes inconsistent with previous declaration&lt;br /&gt; 12&gt;        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\stdio.h(350) : see declaration of '_vsnprintf'&lt;br /&gt; 12&gt;Generating Code...&lt;br /&gt;&lt;br /&gt;Now this looks like a no brainer, I mean the two declarations are 8 lines apart!  So I stare for a while.  (Looks the same to me).   Hmmmm.  Then I try following a few MACRO's, often futile if you don't have browser symbols built yet.  Perhaps I have some crazy path with my includes!?  I only have 12 SDKs or something installed.  So I turn on /showIncludes (how did it take 20yrs to add this option?)  Looks good again.....&lt;br /&gt;&lt;br /&gt;Crap time for the Big Guns --  If you love MACRO programming you know what's next.  Turn on the C++ listing output.  The listing output is what the compiler really compiles are the preprocessor has had it's merry way with the code.  2MB of the finest night time reading you'll ever find.  Per source file of course.  I was kinda dreading trying to find the function after all it's beautification had been stripped.&lt;br /&gt;&lt;br /&gt;I've read a lot of code over the years, and I'm not even sure what this would preprocess out to.&lt;br /&gt;&lt;br /&gt;__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_ARGLIST_EX(int, __RETURN_POLICY_SAME, _CRTIMP, _snprintf, _vsnprintf, _Pre_notnull_ _Post_maybez_ char, _Out_cap_(_Count) _Post_maybez_, char, _Dest, _In_ size_t, _Count, _In_z_ _Printf_format_string_ const char *, _Format)&lt;br /&gt;&lt;br /&gt;I digress...&lt;br /&gt;&lt;br /&gt;It just compiles when you turn on the listing output.&lt;br /&gt;&lt;br /&gt;I'll type it more slowly this time, in case that didn't sink in.  The compiler switch, that just spits out more information, changed things just enough to have everything compile.  Neato, unless that sort of thing keeps you up at night.&lt;br /&gt;&lt;br /&gt;btw, the fix, if you've been reading this far is to not #define vsnprintf in _your_ project.  The CRT must redefine it once or thrice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-1434827222320779889?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/1434827222320779889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=1434827222320779889' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/1434827222320779889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/1434827222320779889'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2008/01/visual-studio-2008-crt-bug.html' title='Visual Studio 2008 CRT bug'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-7993136568261094616</id><published>2007-02-22T09:14:00.000-08:00</published><updated>2007-02-22T15:23:11.267-08:00</updated><title type='text'>Need to call System.dll internal functions?</title><content type='html'>Occasionally you will discover a nice class or function you would like to use.  I stumbled across [mscorcfg]Microsoft.CLRAdmin.Fusion.AddAssemblytoGac(string strAssembly).  Oddly enough there's no way to add an assembly to the gac from .Net code.  This would be just great for MSBuild tasks, or even just installing.&lt;br /&gt;&lt;br /&gt;If you try and use this class or function you get this result.&lt;br /&gt;&lt;br /&gt;&lt;div width=100% class="csharpcode"&gt;&lt;pre&gt;&lt;br /&gt;c:\dev\test\private test.cs(10,9) : error CS0122: 'Microsoft.CLRAdmin.Fusion' is inaccessible due to its protection level&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Turns out using this function is pretty easy in theory.  .Net only checks permissions at link time.  You could do get around this the hard way by using ILAsm, or Reflection in C#.&lt;br /&gt;&lt;br /&gt;Here's how you would do this using Reflection.&lt;br /&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Int32 AddAssemblyToGac(&lt;span class="kwrd"&gt;string&lt;/span&gt; strAssembly)&lt;br /&gt;{&lt;br /&gt;  &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args = &lt;span class="kwrd"&gt;new&lt;/span&gt;&lt;span class="kwrd"&gt;object&lt;/span&gt;[] { strAssembly };&lt;br /&gt;  BindingFlags bindingFlags = (BindingFlags)314;&lt;br /&gt;  &lt;span class="kwrd"&gt;return&lt;/span&gt; ((Int32)(FusionType.InvokeMember(&lt;span class="str"&gt;"AddAssemblytoGac"&lt;/span&gt;, bindingFlags, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, args)));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Well that just opens up about a million possibilities.  Just try and "fix" one class from the ASP.NET framework and you have to drag in 12 million interfaces.  Now you are set, just use the same one's that it was using.  This is going to save me tons of time.  There's no way I'm writing a million Reflection proxy interfaces.  Nevermind the fact that you can just call the interface using IL.  There just &lt;u&gt;has&lt;/u&gt; to be a good way to do this from C#.  Worse case we could lie/cheat to the compiler.&lt;br /&gt;&lt;br /&gt;The C# team has added a nice Attribute for us to do this.&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;[InternalsVisibleTo(&lt;span class="str"&gt;"AndrewsAssembly, PublicKeyToken=0b00fde735121dcc"&lt;/span&gt;)]&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;You can read up on it viewing &lt;a href="http://msdn2.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx"&gt;InternalsVisibleToAttribute&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So ILDasm System.Web.dll, or your favorite assembly, and recompile adding this CustomAttribute.  Compile your assembly and you are off and running.&lt;br /&gt;&lt;br /&gt;Here's a view from Lutz Roeder's Reflector of my test app using an internal System.Web enum.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_QvA8PCZOesc/Rd3TILXksmI/AAAAAAAAAAM/sXw5k1BlREY/s1600-h/test.GIF"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_QvA8PCZOesc/Rd3TILXksmI/AAAAAAAAAAM/sXw5k1BlREY/s320/test.GIF" border="0" alt=""id="BLOGGER_PHOTO_ID_5034412095914160738" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-7993136568261094616?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/7993136568261094616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=7993136568261094616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/7993136568261094616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/7993136568261094616'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2007/02/need-to-call-systemdll-internal.html' title='Need to call System.dll internal functions?'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_QvA8PCZOesc/Rd3TILXksmI/AAAAAAAAAAM/sXw5k1BlREY/s72-c/test.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-8883183448738256672</id><published>2007-02-20T11:36:00.000-08:00</published><updated>2007-02-22T15:27:50.198-08:00</updated><title type='text'>CustomAttributes with ILASM 2.0</title><content type='html'>There are some great debugging attributes you can add to your .Net project.  Sadly I have not found a good way yet to get the debugger to use them on "system" assemblies that have private or internal classes.  You can view all this information in the debugger, so I can't say it makes a lot of sense.&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;br /&gt;[assembly: DebuggerDisplay(&lt;span class="str"&gt;"{{_completionCallback.Method}}"&lt;/span&gt;, Target=&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(System.Web.HttpApplication.SyncEventExecutionStep))]&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This fine code gets you this error message.&lt;br&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;autoexp.cs(18,103): error CS0122: 'System.Web.HttpApplication.SyncEventExecutionStep' is inaccessible due to its protection level&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Lame, very lame.&lt;br /&gt;&lt;br /&gt;You can work around this by using ILASM.  I mean we just need the type after all, can't be that hard.  Here's a working ILDasm of a custom attribute.&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;.custom instance void [mscorlib]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 0C 5C 7B 7B 4D 65 73 73 61 67 65 7D 7D 01   // ...\{{Message}}.&lt;br /&gt;                                                                                                 00 54 50 06 54 61 72 67 65 74 7A 53 79 73 74 65   // .TP.TargetzSyste&lt;br /&gt;                                                                                                 6D 2E 52 65 66 6C 65 63 74 69 6F 6E 2E 52 65 66   // m.Reflection.Ref&lt;br /&gt;                                                                                                 6C 65 63 74 69 6F 6E 54 79 70 65 4C 6F 61 64 45   // lectionTypeLoadE&lt;br /&gt;                                                                                                 78 63 65 70 74 69 6F 6E 2C 20 6D 73 63 6F 72 6C   // xception, mscorl&lt;br /&gt;                                                                                                 69 62 2C 20 56 65 72 73 69 6F 6E 3D 32 2E 30 2E   // ib, Version=2.0.&lt;br /&gt;                                                                                                 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65 75   // 0.0, Culture=neu&lt;br /&gt;                                                                                                 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79 54   // tral, PublicKeyT&lt;br /&gt;                                                                                                 6F 6B 65 6E 3D 62 37 37 61 35 63 35 36 31 39 33   // oken=b77a5c56193&lt;br /&gt;                                                                                                 34 65 30 38 39 )                                  // 4e089&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is just a joy to edit and try and use.  Luckily with v2.0 it's much better.&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;.custom instance &lt;span class="kwrd"&gt;void&lt;/span&gt; [mscorlib]&lt;span class="preproc"&gt;System&lt;/span&gt;.&lt;span class="preproc"&gt;Diagnostics&lt;/span&gt;.&lt;span class="preproc"&gt;DebuggerDisplayAttribute&lt;/span&gt;::.ctor(&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;br /&gt;= {&lt;span class="kwrd"&gt;string&lt;/span&gt;(&lt;span class="str"&gt;'\\{{_completionCallback.Method}}'&lt;/span&gt;)property type &lt;span class="str"&gt;'Target'&lt;/span&gt; = type(&lt;span class="kwrd"&gt;class&lt;/span&gt; &lt;span class="str"&gt;'System.Web.HttpApplication.SyncEventExecutionStep, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'&lt;/span&gt;)}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;There you go, now it's editable, you just have build into your DLL of choice and you can almost tell what's happening.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-8883183448738256672?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/8883183448738256672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=8883183448738256672' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/8883183448738256672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/8883183448738256672'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2007/02/customattributes-with-ilasm-20.html' title='CustomAttributes with ILASM 2.0'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6290271494008843512.post-3876653851138073126</id><published>2007-02-12T08:09:00.000-08:00</published><updated>2009-01-29T15:16:14.923-08:00</updated><title type='text'>Some good .Net debugging info</title><content type='html'>&lt;a href="http://blogs.msdn.com/vancem/archive/2006/09/05/742062.aspx"&gt;http://blogs.msdn.com/vancem/archive/2006/09/05/742062.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;    &lt;h2 class="CommonTitle" minmax_bound="true"&gt;&lt;br /&gt;        &lt;a id="ctl00___ctl00___ctl00_ctl00_bcr_bth___BlogTitle" class="headermaintitle" href="/vancem/default.aspx" minmax_bound="true"&gt;Vance Morrison's Weblog&lt;/a&gt;&lt;/h2&gt;&lt;br /&gt;    &lt;div class="CommonContent" minmax_bound="true"&gt;&lt;br /&gt;        Vance Morrison is currently an Architect on the .NET Runtime Team, specializing in performance issues with the runtime or managed code in general.&lt;br /&gt;    &lt;/div&gt;&lt;br /&gt;I have let my blog laps for too long. &amp;nbsp;&amp;nbsp; I am back to blogging. &amp;nbsp; I realized reciently that we have simply not written down many interesting facts about how the runtime actually works.&amp;nbsp; I want to fix this. &amp;nbsp; Coming up in future blogs I am going to be doing a bit of a 'architectural overview' which describe the differences between managed and unmanaged code, but before I do that I realized that I have not even finished a blog entry I started in March.&lt;br /&gt;&lt;br /&gt;In my blog &lt;a href="http://blogs.msdn.com/vancem/archive/2006/02/20/535807.aspx" minmax_bound="true"&gt;How to use Visual Studio to investigate code generation questions in managed code&lt;/a&gt;, I talk about the how to configure Visual Studio so that you can actually look at optimized code in the debugger (which sadly is not as trivial as you would like), and showed how to look at the disassembly of managed code. &amp;nbsp; &amp;nbsp;Unfortunately manage code is hard to read without a guide, and so in this blog I will show you some very useful tips for reading managed assembly code.&lt;br /&gt;&lt;br /&gt;In this blog entry I will show you the instructions ACTUALLY need to get executed to do something as simple as assigning a string to field of a class.  Note that I am assuming a familiarity with X86 assembly code. If you are the type who never wants to read assembly code, you should stop reading now, because most of this blog is a step-by-step explanation of it.&lt;br /&gt;&lt;br /&gt;I have attached the file InspectingManageCode.zip, which contains a (trivial), project that I used for this example.&amp;nbsp; You are STRONLY encouraged to open it (you can browse it the main file is Program.cs).&amp;nbsp; Copy the files (simply drag the 'InspectingManagedCode directory inside the ZIP to a directory of your choosing), launch the InspecingManagedCode.sln file and run the example.&amp;nbsp;  &amp;nbsp;While the project is already set to build and run optimized code, you will still need to turn off ‘just my code’ and turn on JIT optimization as described in my previous blog to follow along.&lt;br /&gt;&lt;br /&gt;The code in the attached example is pretty trivial.&lt;br /&gt;class Program&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; string myString;&lt;br /&gt;&amp;nbsp; &amp;nbsp; private Program()&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; myString = "foo";&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; static void Main(string[] args)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Program p = new Program();&lt;br /&gt;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;If you were to follow the instructions in the &lt;a  href="http://blogs.msdn.com/vancem/archive/2006/02/20/535807.aspx" minmax_bound="true"&gt;previous blog &lt;/a&gt;to see what code was generated for the body of ‘Main’ you would find the following code.&lt;br /&gt;                    &lt;br /&gt;00000000&amp;nbsp; push &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;esi&lt;br /&gt;00000001&amp;nbsp; mov &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; ecx,9181F4h&lt;br /&gt;00000006&amp;nbsp; call &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;FFCB1264&lt;br /&gt;0000000b&amp;nbsp; mov &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; esi,eax&lt;br /&gt;0000000d&amp;nbsp; mov &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eax,dword ptr ds:[0227307Ch]&lt;br /&gt;00000013&amp;nbsp; lea &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; edx,[esi+4]&lt;br /&gt;00000016&amp;nbsp; call &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; 79222B78&lt;br /&gt;0000001b&amp;nbsp; pop &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; esi&lt;br /&gt;0000001c&amp;nbsp; ret&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;At first glance this code has little similarity to the source code: the original source has a call the constructor ‘Program’ and the assembly code has two calls to strange hex addresses.&amp;nbsp; There are also references to magical numbers like 9181F4H and 0227307CH. &amp;nbsp; In this case the disassembly has not proven to be very valuable. &amp;nbsp;&amp;nbsp; What can we do? &amp;nbsp;&amp;nbsp; &lt;br /&gt; &lt;br /&gt;Sadly if we try to peer into these CALL instructions we cannot, the debugger comes back with the very unhelpful message ‘There is no code at the specified  location’. &amp;nbsp; Actually Visual Studio is LIEING to you. There really is code there, but it simply will not show you.  I will show you techniques to get around this.&lt;br /&gt;&lt;br /&gt;The key to unlocking mysteries of managed code, is a debug helper called SOS.DLL (it is a dll that is shipped with the runtime).  The DLL is what is called a ‘debugger extension’.  Basically it implements functionality that is useful in a debugger implementing functions that are useful for debugging code associated with it (in this case the runtime).&amp;nbsp; &amp;nbsp;Other bloggers have also commented on the use of this DLL (do a web search of SOS.DLL for more).&lt;br /&gt;                                &lt;br /&gt;In Visual Studio, you load SOS.DLL by opening the immediate window (Ctrl-D I) and typing&lt;br /&gt;                &lt;br /&gt;&lt;div class="csharpcode"&gt;.load SOS.dll&lt;/div&gt;&lt;br /&gt;If you do this you may get the message&lt;br /&gt;&lt;div class="csharpcode"&gt;SOS not available while Managed only debugging.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;To load SOS, enable unmanaged debugging in your project properties.&lt;br /&gt;This message is actually reasonably helpful.  By stopping the debugger (Shift F5) going to Solution Explorer (Right hand pane), right clicking on the InspectingManagedCode project file, and selecting Properties, you will get the properties pane for the project.  If you select the ‘Debug’ tab on the left side you will find 3 check boxes at the bottom, one of which is labeled ‘Enable unmanaged code debugging'  If you check this, you put the debugger into a mode where it can debug both mananged and unmanaged code, (which means you can then use SOS.DLL). &lt;br /&gt;&lt;br /&gt;I have already done this on the InspectingManagedCode project, but you will have to repeat this any time you need to use SOS.(Sadly the instructions for setting the debugger mode are different for C++).&lt;br /&gt;&lt;br /&gt;Note that running the debugger to debug both managed and unmanaged code will slow the debugger down a bit (it loads the symbols for all the unmanaged DLLS), so you probably only want do this on projects like this one where you want to use SOS.DLL.&lt;br /&gt;&lt;br /&gt;Now you should be able to set a breakpoint in Main(), run the program (F5), and go to the immediate window (CTRL-D I) and type&lt;br /&gt;&lt;div class="csharpcode"&gt;.load SOS.dll&lt;br&gt;&lt;br /&gt;extension C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll loaded.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;If you are curious the SOS.DLL has reasonably good help, if you type the command &lt;br /&gt;&lt;div class="csharpcode"&gt; !Help&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It will give you a list of commands, and you can get help on individual commands by specifying the name eg.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Help u&lt;br /&gt;&lt;/pre&gt;                        &lt;br /&gt;It will give you help on the ‘u’ (unassembled) command. &amp;nbsp;&amp;nbsp; All SOS commands need to be prefixed by a ! character so that the Visual Studio Debugger knows that it is an SOS command and not an immediate value to be interpreted (the normal meaning of text typed in the immediate window).&lt;br /&gt;                        &lt;br /&gt;The unassemble SOS command is the command we are interested in. &amp;nbsp; It will disassemble a managed routine, but do a much better job than Visual Studio presently does. &amp;nbsp; Unfortunately, we need the address of the routine we want disassemble, and Visual Studio goes to some length to hide this information.&amp;nbsp;If you look at the disassembly for the code (CTRL-ALT-D), you will see that the address of the routine is never given, only the offset from the beginning of the method.&amp;nbsp; &lt;br /&gt;                &lt;br /&gt;The way around this is to use the ‘Registers window’ (Ctrl-D R).&amp;nbsp; &lt;br /&gt;I happen to like to put this window just above the immediate window and shrink it so that only the two lines that actually show values are showing.&amp;nbsp; &amp;nbsp;One of the registers is ‘EIP’ which stands for Extended Instruction Pointer’.&amp;nbsp; It is the address of the current instruction pointer. &amp;nbsp; In my particular invokaction EIP has the value of 00DE0071, so I can do the command&lt;pre&gt;&lt;br /&gt;!u 00DE0071&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Which will disassemble the ENTIRE routine that the address 00DE0071 lives in.&amp;nbsp; I like to right click in the immediate window and select ‘Clear All’ before I do this so the only thing in that window is the disassembly. &amp;nbsp; On my machine I get the result &lt;br /&gt;                    &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Normal JIT generated code&lt;br /&gt;Program.Main(System.String[])&lt;br /&gt;Begin 00de0070, size 1d&lt;br /&gt;00DE0070 56           push esi &lt;br /&gt;00DE0071 B904309100   mov  ecx,913004h&lt;br /&gt;00DE0076 E8A11FB2FF   call 0090201C (JitHelp: CORINFO_HELP_NEWSFAST)&lt;br /&gt;00DE007B 8BF0         mov  esi,eax&lt;br /&gt;00DE007D 8B053C302B02 mov  eax,dword ptr ds:[022B303Ch]&lt;br /&gt;00DE0083 8D5604       lea  edx,[esi+4]&lt;br /&gt;00DE0086 E8A5380979   call 79E73930&lt;br /&gt;00DE008B 5E           pop  esi&lt;br /&gt;00DE008C C3           ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It is not unlike the version the Visual Studio produced, but there are differences&lt;br /&gt;&lt;br /&gt;    1.  You will note that the ‘call instruction is annoted with ‘JitHelp: CORINFO_HELP_NEWFAST’, which makes it at least a bit clearer that this helper is used to create a New object (and is the fast version, we have many variations).&lt;br /&gt;        &lt;br /&gt;    2.  It printed the whole routine that 00DE0071 lives in and prints a &amp;gt;&amp;gt;&amp;gt; on the instruction corresponding to the 00DE0071 address. &lt;br /&gt;        &lt;br /&gt;    3.  While it did not print the name for the ‘call 79E73930’, notice that the HEX value is different than the value in the Visual Studio Disassembly (79222B78). The value in the VS disassembly is simply WRONG (it is bug no one bothered to fix). &lt;br /&gt;        &lt;br /&gt;So let’s take a look at the first two instructions.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00DE0071 B904309100  mov  ecx,913004h&lt;br /&gt;00DE0076 E8A11FB2FF  call 0090201C (JitHelp: CORINFO_HELP_NEWSFAST)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I mentioned that this helper call creates a new object from the GC heap. To do so it needs to know that type of the object to be created. This is what the magic number 913004 does.&amp;nbsp; Internally in the runtime types are described by a structure called a MethodTable, and 913004 is the address of the MethodTable to create.&amp;nbsp; We can find out what type 913004 corresponds to by using the !DumpMT (dump Method Table) SOS command.&amp;nbsp; &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;DumpMT 913004h&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Produces the output&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; EClass:    00911254&lt;br /&gt; Module:    00912c14&lt;br /&gt; Name:      Program&lt;br /&gt; mdToken:   02000002&amp;nbsp; (C:\Documents and Settings\vancem\My Documents\Visual Studio 2005\Projects\InspectingManagedCode\bin\Release\InspectingManagedCode.exe)&lt;br /&gt; BaseSize:  0xc&lt;br /&gt; ComponentSize: 0x0&lt;br /&gt; Number of IFaces in IFaceMap: 0&lt;br /&gt; Slots in VTable: 6&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The only output of this that is interesting at this point is the ‘Name’ field, which as you can see, indicates that 913004 cooresponds to the ‘Program’ type. &amp;nbsp; Thus these first two instructions create a program object. &amp;nbsp; This program object comes back from the helper with all its fields zeroed, so the next instructions in the program are the body of the constructor (the Program() constructor has been inlined into the body of Main().&amp;nbsp; &lt;br /&gt;                        &lt;br /&gt;The next instructions&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00DE007B 8BF0 mov esi,eax&lt;br /&gt;00DE007D 8B053C302B02 mov eax,dword ptr ds:[022B303Ch]&lt;br /&gt;00DE0083 8D5604 lea edx,[esi+4]&lt;br /&gt;00DE0086 E8A5380979 call 79E73930&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Basically implement the statement ‘myString = "foo"’ The helper returns a pointer into the uninitialized object in the EAX register.&amp;nbsp; The mov saves this into the ESI register.&amp;nbsp; EAX is then loaded with what is at the address 022B303Ch.&amp;nbsp; This happens to be the string “foo” (more on how it go there in a later blog). &amp;nbsp; You can confirm this by going to the disassembly code, setting a breakpoing right after the eax,dword ptr ds:[022B303Ch] instruction and looking at the value of the EAX register in the ‘registers’ window.&amp;nbsp; &amp;nbsp;In my example it happens to be the value 012B1D44. &amp;nbsp; You can then use the command                &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;!DumpObj 012B1D44&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Which will dump the managed object at this address.&amp;nbsp; This will print .&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;DumpObj 012B1D44&lt;br /&gt;Name: System.String&lt;br /&gt;MethodTable: 790fa3e0&lt;br /&gt;EEClass: 790fa340&lt;br /&gt;Size: 24(0x18) bytes&lt;br /&gt;(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)&lt;br /&gt;String: foo&lt;br /&gt;Fields:&lt;br /&gt;&lt;br /&gt;MT  Field           Offset Type         VT Attr      Value Name&lt;br /&gt;&lt;br /&gt;790fed1c 4000096    4      System.Int32  0 instance   4   m_arrayLength&lt;br /&gt;790fed1c 4000097    8      System.Int32  0 instance   3   m_stringLength&lt;br /&gt;790fbefc 4000098    c      System.Char   0 instance   66  m_firstChar&lt;br /&gt;790fa3e0 4000099    10     System.String 0 shared static  Empty &amp;gt;&amp;gt;  Domain:Value 0014c550:790d6584 &amp;lt;&amp;lt;&lt;br /&gt;79124670 400009a    14     System.Char[] 0 shared static  WhitespaceChars &amp;gt;&amp;gt; Domain:Value 0014c550:012b186c &amp;lt;&amp;lt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Again, most of the output is uninteresting at this point, except the Name field (which says its a string), and the ‘String’ field (which shows the string value is ‘foo’).&amp;nbsp; So we have confirmed that this instruction loads up the address of the ‘foo’ string into the EAX register.&amp;nbsp; What is left is&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00DE0083 8D5604      lea   edx,[esi+4]&lt;br /&gt;00DE0086 E8A5380979  call  79E73930&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The first instruction ‘LEA’ may not be familiar to you.&amp;nbsp; It is Load Effective Address (LEA).&amp;nbsp; Basically it works just like a MOV instruction, but instead of moving what was AT the memory specified, it loads the ADDRESS of the memory. &amp;nbsp; Another way of looking at this is to imagine a MOV instruction with the [] dropped (which represent memory fetching).&amp;nbsp; Thus&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00DE0083 8D5604   lea  edx,[esi+4]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Can be thought of as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00DE0083 8D5604   mov  edx, esi+4&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That is it adds 4 to ESI and places it in EDX. &amp;nbsp; Now remember ESI points at our newly created ‘Program’ object. &amp;nbsp; We could find out all the fields of this object by dumping it,&amp;nbsp; In my debugger ESI has the value of 012B1D5C so I can do&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;!DumpObj 012B1D5C&lt;br /&gt;&lt;br /&gt;And get&lt;br /&gt;Name: Program&lt;br /&gt;MethodTable: 00913004&lt;br /&gt;EEClass: 00911254&lt;br /&gt;Size: 12(0xc) bytes&lt;br /&gt;(C:\Documents and&lt;br /&gt;Settings\vancem\My Documents\Visual Studio 2005\Projects\InspectingManagedCode\bin\Release\InspectingManagedCode.exe)&lt;br /&gt;Fields:&lt;br /&gt;MT Field  Offset        Type VT   Attr  Value Name&lt;br /&gt;790fa3e0 4000001    4  System.String 0 instance 00000000 myString&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Which tells us that ESI points at a ‘Program’ object and that the total size of the object is 12 (more on that in a later blog), and that at offset 4 there is a field calls ‘myString’ of type System.String that currently has the value of 0 (null). So now we can make a pretty good guess that the LEA instruction is setting EDX to the address of the ‘myString’ field of the program object. EAX has been set to the ‘Foo’ String, and next comes the mysterious&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00DE0086 E8A5380979  call  79E73930&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ideally SOS would have annotated this helper. &amp;nbsp; It is what we call a ‘WriteBarrier’. &amp;nbsp;More on exactly what a write barrier is later, &amp;nbsp;but for now the important thing to know is that ALL updates to OBJECT REFERENCES that live in the GC heap need to be done by calling a write barrier helper. &amp;nbsp;&amp;nbsp; Since the Program object lives in the heap, and we are updating a object reference pointer inside it we need to use the write barrier.&lt;br /&gt;&lt;br /&gt;The runtime actually has many write barriers.&amp;nbsp; All the write barriers have an unusual calling convention.&amp;nbsp;They all take the address to be updated in the EDX register. &amp;nbsp; Then depending on the write barrier, they take the value to update in some other register (this particular write barrier is the most commonly used, and takes its argument in the EAX register). &amp;nbsp;&amp;nbsp; Logically all the write barrier does is do (*EDX = EAX)&amp;nbsp; (that is update what EDX points at to be the value in EAX).&lt;br /&gt;                        &lt;br /&gt;That is about it for this example&amp;nbsp; The only instructions we did not cover are the PUSH ESI, and POP ESI at the beginning and end of the routine.&amp;nbsp; As anyone who deals with assembly code this is simply saving and restoring ESI since we used it in the routine itself.&amp;nbsp; &lt;br /&gt;                                &lt;br /&gt;To recap here are the instructions that actually got executed in the ‘Main’ program and what they do.&amp;nbsp; &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;push    esi   &lt;br /&gt;&lt;br /&gt;// save ESI&lt;br /&gt;mov     ecx,913004h&lt;br /&gt;&lt;br /&gt;// ECX = MethodTable(Program)&lt;br /&gt;call    0090201C &lt;br /&gt;&lt;br /&gt;// EAX = New Object (Program)&lt;br /&gt;mov     esi,eax&lt;br /&gt;&lt;br /&gt;// ESI = this (new object)&lt;br /&gt;mov     eax,dword ptr ds:[022B303Ch]   // EAX = “foo”&lt;br /&gt;lea     edx,[esi+4]&lt;br /&gt;&lt;br /&gt;// EDX = &amp;amp;this.myString&lt;br /&gt;call    79E73930&lt;br /&gt;&lt;br /&gt;// this.myString = EAX (“foo”)&lt;br /&gt;pop     esi&lt;br /&gt;&lt;br /&gt;// restore ESI&lt;br /&gt;ret     &lt;br /&gt;// return.&lt;br /&gt;&lt;/pre&gt;                        &lt;br /&gt;We just understood very deaply EXACTLY what happens when a particular piece of managed code executes.  Hopefully that wasn’t so bad. Next time we will dig a bit into this WriteBarrier is and exactly what it does (how expensive is it?).  We will also dig into exactly what went on inside the ‘New’ helper.  In later blogs I will go into how exactly other run time features get converted to native code. &lt;br /&gt;                        &lt;br /&gt;I hope you are enjoying this peek under the hood of the .NET Runtime.&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6290271494008843512-3876653851138073126?l=andrew-dev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrew-dev.blogspot.com/feeds/3876653851138073126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6290271494008843512&amp;postID=3876653851138073126' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/3876653851138073126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6290271494008843512/posts/default/3876653851138073126'/><link rel='alternate' type='text/html' href='http://andrew-dev.blogspot.com/2007/02/some-good-net-debugging-info.html' title='Some good .Net debugging info'/><author><name>Andrew Bradnan</name><uri>http://www.blogger.com/profile/10083339690866873141</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_QvA8PCZOesc/SYPh5lmA56I/AAAAAAAAACA/ClZE9Jwwex8/S220/Andrew.JPG'/></author><thr:total>1</thr:total></entry></feed>
