The last week was really an interesting one with debugging production code. I was debugging a Winforms application which was using .NET framework 3.5 version. The real problem was with the latest release of the code, there was bug which caused certain elements on the UI not to be displayed. This is was High priority bug and very important to the business.

The code that was causing this bug was an integer variable inside a class.

using System;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public int Foo;
        public Form1()
        {
            InitializeComponent();
        }
        private void Button1Click(object sender, EventArgs e)
        {
            if (Foo == 100) 
                this.label1.Visible = true;
        }
    }
}

[]11

The code was something like this. If Foo was equal 100 then the label was set to be visible. Reflector came in handy to disassemble  the code.With the latest code release the  “if (Foo == 100) “ condition was introduced.

The next step was to verify and validate that this condition was the reason for this bug. Though this looks very simple because i have shown a very contrived example which does not involve all the dependencies of the real world business application.

Fired up windbg looked up the heap for object type Form1 using dumpheap.

0:004> !dumpheap -type Form1

         Address               MT     Size

0000000002cb2548 000007ff004b7b68      480    
total 1 objects

Statistics:

              MT    Count    TotalSize Class Name

000007ff004b7b68        1          480 WindowsFormsApplication2.Form1

Total 1 objects

The next was figure of the offset of Foo. So used the !do command on Form1 instance. !do 0000000002cb2548 and here is the partial output of the command   

000007ff00107050  4001e9b     1780        System.Object  0   static 0000000002cb2d48 EVENT_MAXIMIZEDBOUNDSCHANGED

0000000000000000  4000002      1b8                       0 instance 0000000000000000 components

000007ff00694f40  4000003      1c0 …dows.Forms.Button  0 instance 0000000002cdc040 button1

000007ff006962c8  4000004      1c8 …ndows.Forms.Label  0 instance 0000000002cdc2f8 label1

000007ff002683d8  4000005      1d0         System.Int32  1 instance                0 Foo

So from the result i could identify that the Foo variable was on the 1d0 offset of the Form1 object.

After couple of test case runs i dumped the object and here was the output

000007ff00694f40  4000003      1c0 …dows.Forms.Button  0 instance 0000000002cdc040 button1

000007ff006962c8  4000004      1c8 …ndows.Forms.Label  0 instance 0000000002cdc2f8 label1

000007ff002683d8  4000005      1d0         System.Int32  1 instance               23 Foo

So the Foo’s value was now 23. I am sure most of us are used to updating the variable’s value in VS.NET using immediate window. I did something similar to that but instead used windbg.

In Windbg numbers are hex values, so to set the value as 100 it would have to be 64. You can fire up calc to figure this out or you use the command in windbg ?64

Evaluate expression: 100 = 00000000`00000064

FYI “?” expression evaluator in windbg. Now the final step of updating the Foo in memory. The command to do that is

ed 0000000002cb2548+1d0 64

“e” command is enter values in memory. “e” has many flavors like eu,ed,ea. And ed command is for updating  Double-word values. So ed is to update double-word value and the memory location is 0000000002cb2548+1d0 which is the Form1 memory location  along with Foo is offset. 

Voila here is the output of !dumpobj after updating the memory

000007ff002683d8  4000005      1d0         System.Int32  1 instance              100 Foo

Now we could make an emergency patch and be certain the patch would work with the fix already tested in production using the debugger. Having windbg in your toolbox is always saves a lot of time.