Decoding clr20r3 .NET exception – using mono cecil


I have often seen Devs trying to figure out the cause of the app crash without a memory dump. The only information that is available to analyze is the Windows Error Reporting message in the event viewer which would have “Event Name: CLR20r3″ along with Watson bucket information like this.

Fault bucket , type 0
Event Name: CLR20r3
Response: Not available
Cab Id: 0

Problem signature:
P1: unhandledexception.exe
P2: 1.0.0.0
P3: 4ce1e0f1
P4: LibraryCode
P5: 1.0.0.0
P6: 4ce1e0f1
P7: 7
P8: 1f
P9: System.NullReferenceException
P10:

I will demonstrate the steps in identifying the code that caused the app to crash with the above information.Here is the explanation on the Watson Bucket items

  1. P1: unhandledexception.exe – is the Exe File Name
  2. P2:1.0.0.0 – is the Exe File assembly version number
  3. P3:4ce1e0f1- is the Exe File Stamp
  4. P4:LibraryCode- is the Faulting full assembly name
  5. P5:1.0.0.0- is the Faulting assembly version
  6. P6:4ce1e0f1- is the Faulting assembly timestamp
  7. P7:7- is the Faulting assembly method def
  8. P8:1f-  is Faulting method IL Offset within the faulting method
  9. P9:System.NullReferenceException- is Exception type that was thrown

 

Here is the LibraryCode that is mentioned in P4 of the watson bucket

using System;

namespace LibraryCode
{
    public class Foo
    {
        public Foo()
        {
            Console.WriteLine("Constructor");
        }
        public void Test()
        {
            Console.WriteLine("Test");
        }
        public string Bar(string test)
        {
            var x = test;
            return x.ToUpper();
        }
        public string Bar1(string test)
        {
            var x = test;
            return x.ToUpper();
        }
        public string Bar2(string test)
        {
            var x = test;
            return x.ToUpper();
        }
        public string Bar3(string test)
        {
            var x = test;
            return x.ToUpper();
        }
        public string Bar4(string test)
        {
            int j = 10;
            for (int i = 0; i < 10; i++)
            {
                j += i;
            }
            var x = test;
            return x.ToUpper();
        }
    }
}


And here is the code for the Main method calling the LibraryCode

  static void Main(string[] args)
        {
            var f = new Foo();
            var x = Console.ReadKey();
            f.Bar4(null);
        }

The most important items in the above watson bucket are 4,7 ,8 and 9. The item 4 is the assembly that was responsible for the crash which is “LibraryCode”. The item 7 is methoddef that threw the exception which is “7”. To identify the method we would have to dump the IL and here is the command to do that.

ildasm /tokens "C:\temp\LibraryCode.dll" /out=libcode.il

Open the libcode.il in a text editor and look for 06000007. The methoddef starts with 06 and 7 is the hex value and when converted to decimal it is still 7 and that’s how we ended with 06000007. The IL content for the corresponding method def

.method /*06000007*/ public hidebysig instance string
Bar4(string test) cil managed
{
// Code size       42 (0x2a)

With this we know the method that caused the app to crash.

The next step is to identify the faulting IL code within the method. The IL offset that caused the exception to be thrown is 1f (decimal value is 31), and here is the IL Code

IL_001d:  ldarg.1
IL_001e:  stloc.2
IL_001f:  ldloc.2
IL_0020:  callvirt   instance string [mscorlib/*23000001*/]System.String/*01000013*/::ToUpper() /* 0A000012 */
IL_0025:  stloc.3
IL_0026:  br.s       IL_0028

Now mapping the IL code back to C# shouldn’t be hard.

And If you are like me then you would probably want to automate things , so here is doing the same using Mono Cecil

AssemblyFactory.GetAssembly(@"C:\Temp\LibraryCode.dll")
		.MainModule.Types.Cast<TypeDefinition>()
		.ElementAt(1)
		.Methods.Cast<MethodDefinition>().First(md => md.MetadataToken.RID == 7)
		.Body.Instructions.Cast<Instruction>()
		.Select (i => 
			new {Offset = i.Offset, 
			OpCode = i.OpCode.ToString() , 
			Operand = i.Operand != null ? i.Operand.ToString() : string.Empty} )
		.Dump();

Notice the above code looks for methoddef “7” which is the P7 item in the Watson bucket.The code could have just dumped 31st IL offset which is “ldloc.2″ but that would not help , I like to see the entire method to figure out the cause of the exception.

And here is the output from above code.

We cannot get the call-stack for the crash with just watson buckets.

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 Mono Cecil Decompiler within Windbg to decompile


I have been hacking Mono lately and one of the coolest projects I have seen is the Mono Decompiler. It’s like Reflector but no UI and an API to decompile. Guess what, even reflector is built on top of Mono Cecil.  Most of times when I have to debug I would end up using  !dumpil  sos command to get  the IL  of the method desc.  I am not an IL guru, I am much comfortable reading C# than IL. I could have used reflector to do the same thing, but here are couple of reasons for doing this.

  • I don’t have to open another application and I am comfortable with cdb.exe
  • I like to understand this library , which I could use in the future.

Here is a simple app that would return C# code.  I could have written a windbg extension, but I am lazy


using System;
using System.IO;
using System.Linq;
using System.Text;
using Mono.Cecil;
using Cecil.Decompiler.Languages;

namespace Conosole
{
 class Decompiler
 {
 static void Main(string[] args)
 {
 var function = args[1].Split(new[] { '.' });
 //MethodName
 var methodName = function.Last();
 //Typename
 var typeName = function.ElementAt(function.Length - 2);
 //Namespace
 var ns = function.TakeWhile((c, i) => i < function.Length - 2).Aggregate(new StringBuilder(),(sb,s) => sb.Append(s+".")).ToString().Trim(new [] {'.'}) ;

 Console.WriteLine((from module in AssemblyFactory.GetAssembly(args[0]).Modules.Cast<ModuleDefinition>()
 from type in module.Types.Cast<TypeDefinition>()
 from method in type.Methods.Cast<MethodDefinition>()
 where type.Namespace == ns && type.Name == typeName && method.Name == methodName
 select method.SourceCode()).First());
 }
 }
 public static class Extensions
 {
 public static string SourceCode(this MethodDefinition methodName)
 {
 var writer = new StringWriter();
 CSharp.GetLanguage(CSharpVersion.V3).GetWriter(new PlainTextFormatter(writer)).Write(methodName);
 return writer.ToString();
 }
 }
}

And here is the usage within windbg. I am using LinqPad as an example. Here is the !clrstack output

0:000> !CLRStack
OS Thread Id: 0x16e0 (0)
Child SP IP       Call Site
001ae758 7695438d [InlinedCallFrame: 001ae758] System.Windows.Forms.UnsafeNativeMethods.WaitMessage()
001ae754 61fc737a System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32) [f:\dd\ndp\fx\src\WinForms\Managed\System\WinForms\Application.cs @ 2198]
001ae7f0 61fc6e2c System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext) [f:\dd\ndp\fx\src\WinForms\Managed\System\WinForms\Application.cs @ 3422]
001ae848 61fc6c81 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext) [f:\dd\ndp\fx\src\WinForms\Managed\System\WinForms\Application.cs @ 3306]
001ae878 61f5366d System.Windows.Forms.Application.Run(System.Windows.Forms.Form) [f:\dd\ndp\fx\src\WinForms\Managed\System\WinForms\Application.cs @ 1496]
001ae88c 0038316b LINQPad.Program.Run(System.String, Boolean, Boolean, Boolean, System.String)
001ae96c 003813f1 LINQPad.Program.Go(System.String[])
001aeb84 00380554 LINQPad.Program.Start(System.String[])
001aebc4 0038034f LINQPad.ProgramStarter.Run(System.String[])
001aebd0 003800f5 LINQPad.Loader.Main(System.String[])
001aee18 6d7e21db [GCFrame: 001aee18]

I am going to try and decompile this method “003813f1 LINQPad.Program.Go”  into c#

Here is the output from !ip2md 003813f1 to get the method name and class address

0:000> !ip2md 003813f1
MethodDesc:   002c9024
Method Name:  LINQPad.Program.Go(System.String[])
Class:        0036f404
MethodTable:  002c9230
mdToken:      0600025e
Module:       002c2e9c
IsJitted:     yes
CodeAddr:     00380590
Transparency: Critical

The next command is to get the location of the assembly and here I am using the class address from the above command


.shell -ci "!dumpclass  0036f404" findstr File:

And then issued the following commands


.shell

d:\tools\Decompiler “D:\tools\LINQPad.exe” “LINQPad.Program.Go”

Here is the C# code within windbg

So next time, I might not be looking at IL Code inside the debugger.

Using C# Compiler as a Service in F#, PoshConsole (Powershell)


I saw this amazing video from Anders Hejlsberg on C# as Compiler service and after which, Miguel de lcaza from the Mono posted about their implementation of C# Compiler service. Thanks Miguel .The best part is ,it works out of the box in Windows on the Microsoft .NET code base. So here I am using Mono’s C# compiler code  (Mono.CSharp.dll) within Microsoft .NET Code

This is cool because we could use C# more like python. And what if VS.NET can be customized using C# based scripting ,like Lisp for Emacs.

I figured out from Miguel’s post the only class we should be consuming is Evaluator. And here is a simple extension method for string class to compile and run.

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

And here is a code that uses the above extension, which creates a Func dynamically and passes it back to static code.

static void Main()
{

 var people = new List<Person>() { { new Person() { Name = "Bush", Age = 63, Sex = 'M' } },
 { new Person() { Name = "Obama", Age = 53, Sex = 'M' } }, { new Person() { Name = "Gordon", Age = 57, Sex = 'F' } } };
 Evaluator.Init(new string[0]);
 Evaluator.ReferenceAssembly(typeof(Person).Assembly);
 "using System;".Run();
 "using System.Linq;".Run();
 "using TestPerson;".Run();
 var whereexpression = (Func<Person,bool>)"new Func<Person,bool>( (p) => p.Age < 60);".Compile();
 people.Where(whereexpression).Dump();
}
class Person
{
 public string Name { get; set; }
 public int Age { get; set; }
 public char Sex { get; set; }
}

Here is a code that uses C# within F#

open System
open System.Collections.Generic
open Microsoft.FSharp.Core
open Mono.CSharp

Evaluator.Run("using System;") |> ignore
Evaluator.Run("using System.Linq;") |> ignore

let eval code =  Evaluator.Evaluate code

let list = ["FSharp";"CSharp"]
let code =  eval "new Func<string,bool>( (s) => s == \"CSharp\") ;" : ?> Func<string,bool>
printfn "Does list contain Foo? %b" (code.Invoke("Foo"))
printfn "Does list contain CSharp? %b" (List.exists (FuncConvertExtensions.ToFSharpFunc (code)) list)

let seqCast : seq<char> = Seq.cast (eval("from x in \"Bar\" select x;") : ?> IEnumerable<char>)
printfn "Sequence result:  %b" (Seq.exists(fun x -> x = 'c') seqCast)

I know there is F# powerpack for Linq. One of the reasons we would probably extend this is, if an application is developed in F# (targeted at Devs) and it could possibly allow extensions in C#.  Here is an example ,Seesmic has platform for building extension and how would it be If I could write a “ Func<Tweet,bool>( tweet => tweet.Language == “English” && tweet.HasLink == true)”  in the search box and if the platform happened to developed in F# (which is not) it would allow the C# devs to extend it .

Another interesting use is using C# compiler service within PoshConsole . In Powershell we could use Add-Type for creating types on the fly but with is I wouldn’t have to create a class and method we could get away with just creating lambdas. Here is an example of the usage

[Reflection.Assembly]::LoadFile("D:\tools\Mono.CSharp.dll")
[Mono.CSharp.Evaluator]::Run("using System;")
[Mono.CSharp.Evaluator]::Run("using System.Linq;")
$func = [Mono.CSharp.Evaluator]::Evaluate("new Func<int,bool>( (s) => s == 10);")
$func.Invoke(100)
$func = [Mono.CSharp.Evaluator]::Evaluate("from x in new [] {100,200} select x;")
$func
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: