dumpstring – windbg


Viewing strings inside the debugger has never been pretty, especially if you are using sos extension.  Here is a sample !dumpobj on a string

0:000> !do 00000000025f2280
Name:        System.String
MethodTable: 000007fef6e26960
EEClass:     000007fef69aeec8
Size:        32(0x20) bytes
String:     Foo
Fields:
MT    Field   Offset                 Type VT     Attr            Value Name
000007fef6e2c848  40000ed        8         System.Int32  1 instance                3 m_stringLength
000007fef6e2b388  40000ee        c          System.Char  1 instance               46 m_firstChar
000007fef6e26960  40000ef       10        System.String  0   shared           static Empty
>> Domain:Value  00000000002ae900:00000000025e1420 <<

Some of the devs like to use the du command

du 00000000025f2280+c

0:000> du 00000000025f2280+c

00000000`025f228c  “Foo”

My choice is to use the .printf command and here is my alias for printing string

as !ds .printf "%mu \n", c+

0:000> !ds 00000000025f2280

Foo

I prefer .printf over du because I am not interested in looking at the memory address often especially dumping strings within a script.

Custom DumpArray – Windbg


The sos has !dumparray for getting contents of the array. But it cannot be used for scripting or automation. Here is an example

using System;
namespace ConsoleApplication
{
 class Program
{
 Test[] arr = new[] { new Test() { ID = 1, Name = "Foo" }, new Test() { ID = 2, Name = "Bar" } };
 static void Main(string[] args)
 {
 var p = new Program();
 Console.WriteLine(p.arr);
 Console.Read();
 }
 }
 class Test
 {
 public int ID;
 public string Name;
 }
}

And here is the output of the arr variable within the debugger

0:000> !da -details 021fbc6c
Name:        ConsoleApplication.Test[]
MethodTable: 64b56c28
EEClass:     648d9698
Size:        24(0x18) bytes
Array:       Rank 1, Number of elements 2, Type CLASS
Element Methodtable: 001938b0
[0] 021fbc84
Name:        ConsoleApplication.Test
MethodTable: 001938b0
EEClass:     00191488
Size:        16(0x10) bytes
File:        C:\Users\naveen\Documents\Visual Studio 2010\Projects\ConsoleApplication9\bin\Debug\ConsoleApplication.exe
Fields:
MT    Field   Offset                 Type VT     Attr    Value Name
64ba2978  4000002        8             System.Int32      1     instance            1     ID
64b9f9ac  4000003        4            System.String      0     instance     021fbc44     Name
[1] 021fbc94
Name:        ConsoleApplication.Test
MethodTable: 001938b0
EEClass:     00191488
Size:        16(0x10) bytes
File:        C:\Users\naveen\Documents\Visual Studio 2010\Projects\ConsoleApplication9\bin\Debug\ConsoleApplication.exe
Fields:
MT    Field   Offset                 Type VT     Attr    Value Name
64ba2978  4000002        8             System.Int32      1     instance            2     ID
64b9f9ac  4000003        4            System.String      0     instance     021fbc58     Name

From the output  we cannot see the values of the  Name variable within the Test class. To get the value we would have manually issue a !dumpobj on each one of these. In this post I will demonstrate how to automate this. In doing so we will also explore the array internals from raw memory perspective.

To start of lets dump the raw memory of the array. The  array address is 021fbc6c

dd 021fbc6c

0:000> dd 021fbc6c
021fbc6c  64b56c28 00000002 001938b0 021fbc84
021fbc7c  021fbc94 00000000 001938b0 021fbc44
021fbc8c  00000001 00000000 001938b0 021fbc58
021fbc9c  00000002 00000000 64ba7490 00000000
021fbcac  00000000 00000000 00000000 00000000
021fbcbc  00000000 64b9f5e8 00000000 40010000
021fbccc  64ba6034 00000007 00000004 00000100
021fbcdc  00000000 64ba6f40 00000000 00000000

Fields

  1. 64b56c28 - Array’s Method table pointer
  2. 00000002 - Array’s length ( this will be used later)
  3. 001938b0 -Array contents method table pointer ( Test class)
  4. 021fbc84, 021fbc94 - Contents of the array( 2 instances of the Test class)

I would be using  $t0, $t1   User-Defined Pseudo-Registers within my script  as local variables to maintain state. Think of them as predefined variables that we can use. Here is the script to get just the Name from the array

.for (r $t0=0; @$t0 < poi(021fbc6c+0x4); r$t0=@$t0+1 ) { r$t1 = 0; .if(@$t0 = 0) { r$t1=10} .else { r$t1= 10+ @$t0*4};.echo ************;!do poi(poi((021fbc6c-0x4)+@$t1)+0x4) }

Here is the explanation for the above script

  1. The .for loop is used to iterate through the contents of the array :  “.for (r $t0=0; @$t0 < poi(021fbc6c+0x4); r$t0=@$t0+1 ) ”
    • The loop variable is $t0, which is initialized to zero  “r $t0=0;”,
    • Next is the loop condition check @$to < poi(021fbc6c+0x4) , the poi(021fbc6c+0x4) is the pointer deference to array length which is 00000002
    • And the last statement is the increment command of the loop variable r$t0=@$t0+1
    • Tip :- I am using “@” before the “$” for increased speed within the debugger when accessing registers.
  2. The next statement is “r$t1 = 0″ is initializing another pseudo register to zero
  3. After which the command “if(@$t0 = 0) { r$t1=10} .else { r$t1= 10+ @$t0*4}” resets the value of $t1 register either “10” or $t0 * 4, where $to is loop variable. I do this because the first instance of the Test class within the array is in the 10th offset and the rest of them would be on the next 4th offset. So for example the first time loop ,$t1 would be 10 , the second time  $t1 would 14 (10 + 1*4).
  4. The “.echo ************” is just for line separation
  5. The last command is the one which does most of the work
    • The command poi((021fbc6c-0x4)+@$t1) would return the pointer of the each element in the array which is instance of Test class . The first time it would be poi((021fbc6c-0x4)+10) which would point 021fbc84 and the next time it would be poi((021fbc6c-0x4)+14) which would be 021fbc94
    • The outermost “poi 0x4” is to get pointer of the member variable Name and dump its content using !do

And here is the output from the script

    0:000> .for (r $t0=0; @$t0 < poi(021fbc6c   +0x4); r$t0=@$t0+1 ) { r$t1 = 0; .if(@$t0 = 0) { r$t1=10} .else { r$t1= 10+ @$t0*4};.echo ************;  !do poi(poi((021fbc6c-0x4)+@$t1)+0x4) }
    ************
    Name:        System.String
    MethodTable: 64b9f9ac
    EEClass:     648d8bb0
    Size:        20(0x14) bytes
    File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
    String:      Foo
    Fields:
    MT    Field   Offset                 Type VT     Attr    Value Name
    64ba2978  40000ed        4         System.Int32  1 instance        3 m_stringLength
    64ba1dc8  40000ee        8          System.Char  1 instance       46 m_firstChar
    64b9f9ac  40000ef        8        System.String  0   shared   static Empty
    >> Domain:Value  00745c28:021f1228 <<
    ************
    Name:        System.String
    MethodTable: 64b9f9ac
    EEClass:     648d8bb0
    Size:        20(0x14) bytes
    File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
    String:      Bar
    Fields:
    MT    Field   Offset                 Type VT     Attr    Value Name
    64ba2978  40000ed        4         System.Int32  1 instance        3 m_stringLength
    64ba1dc8  40000ee        8          System.Char  1 instance       42 m_firstChar
    64b9f9ac  40000ef        8        System.String  0   shared   static Empty
    >> Domain:Value  00745c28:021f1228 <<

Do I have Managed or Native memory leak?


I noticed someone who couldn’t figure out the cause of memory leak in  managed application within the debugger. This person had basic debugging skills and was comfortable with sos.  FYI the leak wasn’t in the managed code, but in the native code. The managed code was using native code via PInvoke.

Here is how I figured out the cause. Every time I have to debug a memory leak in managed code ,the first command I run is !vmstat. The !vmstat is available in psscor2.dll for .net 3.5 and for .net 4.0 it is available in sos. This command provides summary of VM. The output is similar to the VMMap tool and here is the output from the command.

Now that I know there is a memory leak, I always start of with running these commands


.shell -ci "!EEHeap -loader" findstr  "LoaderHeap"

.shell -ci "!EEHeap -gc" findstr /B "Total Size"

!heapstat  - iu

And here is the output from the above commands

0:004> .shell -ci “!EEHeap -loader” findstr  “LoaderHeap”
Total LoaderHeap size: 0x10000(65,536)bytes
.shell: Process exited
0:004> .shell -ci “!EEHeap -gc” findstr /B “Total Size”
Total Size   0x3df74(253,812)
.shell: Process exited
0:004> !heapstat -iu
Heap     Gen0         Gen1         Gen2         LOH
Heap0    8204         182020       54820        8768

Free space:                                                 Percentage
Heap0    12           149212       36           48          SOH: 60% LOH:  0%

Unrooted objects:                                           Percentage
Heap0    1188         0            0            0           SOH:  0% LOH:  0%
0:004>

And from the output I know there isn’t a managed memory leak. The total heap size is only 253,812 bytes and my loader heap is 65,536 bytes, so it has to be native code.  Now I can focus my efforts on the native code debugging.

Customizing Witty Twitter Client Part 1- using C# as Compiler Service


This is going to be a multipart blog post where I am going to be demonstrating how I have customized Witty twitter client for my need. I chose Witty because it is the only OSS .NET twitter client I know of.

One of the reasons for customizing is primarily using C# as compiler service to extend it for my needs dynamically. For example I follow this twitter list http://twitter.com/shanselman/programmers , it’s a cool list that Scott maintains, thanks to him. But there is one person in this list who keeps tweeting about weight loss, which I am least interested and I didn’t have control over it but to ignore, until now. And it is always fun to write  software for your daily needs, which for me saves time.  Thanks to Mono for C# as compiler service. FYI I have shown a simple usage of Mono Csharp compiler service in this post.

Here are things that I could get done by just spending few hours of my weekend time

Here is my the default witty

Filter the list by user name  which I am not interested in


new Func<Tweet, bool>(t => !t.User.Name.Contains("CNN"));

Here is the same without CNN

FYI the filter C# code is in the Filter Text box

The next filter criteria is to look for tweets that have hashtag as fsharp and also at least have one link


new Func<Tweet, bool>(t => t.HashTags.DefaultIfEmpty().Contains("#fsharp") && t.Urls.DefaultIfEmpty().Count() > 0);

And here is the filtered list

Be even crazier look for tweets that have hashtag as fsharp and at least one link and then open the link automatically

new Func<Tweet, bool>(t => {
 if (t.HashTags.DefaultIfEmpty().Contains("#fsharp") && t.Urls.DefaultIfEmpty().Count() > 0)
 System.Diagnostics.Process.Start(t.Urls.First().ToString());
 return t.HashTags.DefaultIfEmpty().Contains("#fsharp") && t.Urls.DefaultIfEmpty().Count() > 0; });

The browser with the link opened automatically.

It’s a hack and I shouldn’t be doing the above, but it does the job.

There is so much more possibilities. I could easily provide a save feature for these search scripts and reuse the same.  At the end of the series I will post the entire code in GitHub. But if you want to try it before that here are the simple changes I started doing to the code.

Extension Method for Compilation


static class Extensions
 {
 public static object Compile(this string code)
 {
 return Mono.CSharp.Evaluator.Evaluate(code);
 }
 public static void Run(this string code)
 {
 Mono.CSharp.Evaluator.Run(code);
 }
 }

The filter code


public bool TweetFilter(object item)
 {
 Tweet tweet = item as Tweet;

 // this will prevent the fade animation from starting when the tweet is filtered
 tweet.IsNew = false;
 try
 {
 Func<Tweet, bool> compare = (Func<Tweet, bool>)FilterTextBox.Text.Compile();
 return compare.Invoke(tweet);
 }
 catch(Exception ex)
 {
 Console.WriteLine(ex);

 }
 return true;
 }

The hashtags and Links weren’t part of the tweet class , but they were part of the UI class. So I had to bring them to the tweet class and populate them.

public IEnumerable<Uri> Urls
 {
 get
 {
 return links;
 }
 set
 {
 links.Clear();
 links.AddRange(value);
 }
 }
 public IEnumerable<string> HashTags
 {
 get
 {
 return hashTags;
 }
 set
 {
 hashTags.Clear();
 hashTags.AddRange(value);
 }
 }

And here is the code to populate the above properties

private IEnumerable<Uri> GetLinks(string text)
 {
 string[] words = Regex.Split(text, @"([ \(\)\{\}\[\]])");
 return (from word in words
 let isUrl = new Func<string, bool>(s => UrlShorteningService.IsUrl(s))
 where isUrl(word)
 select new Uri(word) ).ToList();
 }
 private IEnumerable<string> GetHashTags(string text)
 {
 string[] words = Regex.Split(text, @"([ \(\)\{\}\[\]])");
 return (from word in words
 let ishash = new Func<string, bool>(s => s.StartsWith("#"))
 where ishash(word)
 select word).ToList();
 }

I know for the above 2 functions I could have written a High-Order Function

Using Tuple as Dictionary / Map key


I  recently had to create a dictionary which needed a multipart key like <string,int> . To do this I would have to create a custom class  override equals and gethashcode. That’s when someone told I could use Tuple, but weren’t sure it was possible.  Here was the quick sample to try it in F#

let x = [("naveen",1),1;("naveen",1),2] |> Map.ofList

as expected only one item in the Map

val x : Map<(string * int),int> = map [(("naveen", 1), 2)]

And the same in C#

 Console.WriteLine(Tuple.Create("Naveen",1).Equals( Tuple.Create("Naveen",1)));

The next step was to actually disassemble Tuple in reflector

The code implements IStructuralComparable.CompareTo and does the comparison for each item. This is one of the reasons why generics is cool.

Using Tech-Ed OData to download videos


I wanted to watch the Teched 2010 videos, but the problem I had was going to the site manually to download files for offline viewing.  And I was also interested only in Dev sessions which were level 300 / 400. Thanks to OData for teched http://odata.msteched.com/sessions.svc/ ,I  could write 3 statements in linqpad and had them all downloaded using wget

File.Delete(@"C:\temp\download.txt");

Sessions
.Where (s => (s.Level.StartsWith("400") ||  s.Level.StartsWith("300") ) && s.Code.StartsWith("DEV"))
.Take(10)
.ToList()
.Select (s => @"http://ecn.channel9.msdn.com/o9/te/NorthAmerica/2010/mp4/" + s.Code + ".mp4" )
.Run(s => File.AppendAllText(@"C:\temp\download.txt",s + Environment.NewLine));

Util.Cmd(@"wget.exe -b -i c:\Temp\download.txt",true);

Forgot to mention for the Run extension method is from Reactive Extensions

Debugging base class method with conditional break point in .NET using Windbg


In this post I am going to be demonstrating how to have a conditional break-point on the base class method where it has been used by multiple derived classes. A classic example is Winform UI.

The Control base class has got methods like set_Enabled , set_Visible which could be consumed by multiple derived controls. The goal is to debug only the control instance that we are interested in. Here is the sample code.


using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
 public Form1()
 {
 InitializeComponent();
 button3.Click += (s, b) => button1.Enabled = button1.Enabled ? false : true;
 button4.Click += (s, b) => button2.Enabled = button2.Enabled ? false : true;
 }
 }
}

image

This app that has four buttons. On the click of button3 it toggles button1’s enabled property and the button 4 does the same for button2. The goal is to break only when button1’s enabled property is set.

Launched the app and attached it to windbg and loaded sosex, issued the command

!mbm *Control.set_Enabled

to set a break-point on enabled method. FYI set_Enabled is not available in the button class because it is derived from the base class. The goal is to break only when the button1’s enabled property is changed. With the above command it will break every time and here is the output when the break-point hits

rax=000007fede335c40 rbx=0000000000060b28 rcx=000000000242ed18
rdx=0000000000000000 rsi=0000000000000000 rdi=000000000242ed18
rip=000007fede335c4d rsp=000000000015dde0 rbp=000000000015df80
r8=0000000002464500  r9=0000000000000000 r10=000007fffff10018
r11=000000000015dd20 r12=00000000002f5980 r13=000000000015dea8
r14=000000000015e380 r15=0000000000100000
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
System_Windows_Forms_ni+0x2b5c4d:
000007fe`de335c4d 488bcf          mov     rcx,rdi

The rcx register contains the reference of the instance of the class ,  example button1 / button2. And here is the command to get the offset of the button text

.shell -ci "!do @rcx" findstr /E text

and the output of the command is

0:000> .shell -ci”!do @ecx” findstr /E text
000007fef6db6960  40001c2       40        System.String  0 instance 000000000242ec50 text
000007fef6db5ab8  400016d      280        System.Object  0   static 0000000002403d80 EventBindingContext
.shell: Process exited

The reason behind getting the button text offset is to use the text as the property for conditional break-point. The text member is available in the 40 offset of the button class. Now that we have the offset of the text property lets try and reset the break-point with a condition. To do this  get the address of the break-point using the bl command and the output is

0:000> bl
0 e 000007fe`de335c4d     0001 (0001)  0:**** System_Windows_Forms_ni+0x2b5c4d

The address of the set_Enabled function is 000007fe`de335c4d.   Here is the conditional break-point for button1

bp 000007fe`de335c4d "as /mu ${/v:name} (poi(@rcx+40)+c);.block{ .if (0== $scmp( \"${name}\", \"button1\") ) { .echo 'in button1';gc } .else { gc}}"

The “as /mu ${/v:name} (poi(@rcx+40)+c)” will set the value of text property  to the variable “name”. The .block command is used to evaluate the variable  “name” and the rest is a simple .if .else command. Every time the button1 is clicked it would output  “in button1” and continue. Now we have managed to break-in only on the button1 click.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: