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: 0Problem 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
- P1: unhandledexception.exe – is the Exe File Name
- P2:1.0.0.0 – is the Exe File assembly version number
- P3:4ce1e0f1- is the Exe File Stamp
- P4:LibraryCode- is the Faulting full assembly name
- P5:1.0.0.0- is the Faulting assembly version
- P6:4ce1e0f1- is the Faulting assembly timestamp
- P7:7- is the Faulting assembly method def
- P8:1f- is Faulting method IL Offset within the faulting method
- 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.

hi naveen, can help me analyze the following log (im getting clr20r3 error in event viewer log upon executing a scheduler for a application. below is the log
Fault bucket , type 0
Event Name: CLR20r3
Response: Not available
Cab Id: 0
Problem signature:
P1: possenderconsoleappmms.exe
P2: 1.1.0.356
P3: 4db922c8
P4: System
P5: 2.0.0.0
P6: 4a275e12
P7: 38b3
P8: 20
P9: System.InvalidOperationException
P10:
Attached files:
These files may be available here:
C:\ProgramData\Microsoft\Windows\WER\ReportQueue\AppCrash_possenderconsole_81ebcb711f38cd3341ada80489642b28885c_0b45952e
Analysis symbol:
Rechecking for solution: 0
Report Id: e5d63f94-8dd1-11e0-a6d5-705ab6941699
Report Status: 4
FYI, the machine spec: WIN 7 Home Basic (32 bit)
sk
June 8, 2011 at 6:07 am
sk, Have you tried what is mentioned in the blog post?
Naveen
June 8, 2011 at 9:00 am
Best way to debug Type Reference Exceptions for a .net 3.5 project running under mono?
rbonini
April 3, 2012 at 11:18 am
Best way to debug a type reference exception for a .net 3.5 project running under mono?
Roberto
rbonini
April 3, 2012 at 11:20 am