Conditional attribute and arguments evaluation

What is the conditional attribute?

The conditional attribute enables including/omitting methods calls during compilation depending on compilation symbols. For example, we can condition that a specific log method calls will be included only when we compile in debug. The compiler in this case will omit the calls to the method. Looking at the next code:

public class Logger
{
[
Conditional("DEBUG")]
public void LogDebugMessage(string str)
{

}
}

And the code calling it:

class MyClass
{
private readonly Logger logger = new Logger();

public void Foo()
{
logger
.LogDebugMessage("Foo");
}
}

We expect the compiler to omit the body of Foo(). As we can see with a disassembler this is exactly what happens:

.method public hidebysig instance void  Foo() cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method MyClass::Foo

How method arguments are treated?

Temp variable assignment optimization

Regardless the conditional attribute, in release mode the compiler performs many optimization which one of them is skipping local variable assignment. You’re most likely to notice it when you assign a value into a local variable and pass it to a method as an argument (while this is the only variable usage). For example:

public void Foo()
{
var foo = "Foo";
logger
.LogDebugMessage(foo);
}

Translates into:

0527C028  mov         edx,dword ptr ds:[2EE78B0h]  	// Load the string address
0527C02E mov ecx,dword ptr [ecx+4] // Load the logger instance
0527C031 cmp dword ptr [ecx],ecx // Null check
0527C033 call dword ptr ds:[50C5BD8h] // Call LogDebugMessage
0527C039 ret

While:

public void Foo()
{
logger
.LogDebugMessage("Foo");
}

Translates into:

0552C028  mov         ecx,dword ptr [ecx+4]  		// Load the logger instance
0552C02B mov edx,dword ptr ds:[31478B0h] // Load the string address
0552C031 cmp dword ptr [ecx],ecx // Null check
0552C033 call dword ptr ds:[5375C30h] // Call LogDebugMessage
0552C039 ret

Which are basically the same. So in case we’re not using the conditional attribute we shouldn’t care about local assignment. We can expect to have no difference in runtime.

Temp variable sent to omitted call optimization?

So an interesting question is what happens to an argument we’re about to send to a conditional method? If call to LogDebugMessage are omitted, what should we expect in this case:

public void Foo()
{
var method = MethodBase.GetCurrentMethod().Name;
logger
.LogDebugMessage(method);
}

And in this case:

public void Foo()
{
logger
.LogDebugMessage(MethodBase.GetCurrentMethod().Name);
}

The answer can be easily found by looking at the methods IL. The first version with temp assignment to a variable compiles into:

.method public hidebysig instance void  Foo() cil managed
{
// Code size 12 (0xc)
.maxstack 8
IL_0000: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
IL_0005: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
IL_000a: pop
IL_000b: ret
} // end of method MyClass::Foo

While the second version compiles into:

.method public hidebysig instance void  Foo() cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method MyClass::Foo

As we can see, in this case the argument was not even evaluated and the whole statement was omitted from the IL. Meaning that in this case, inlining the variable would have influence on the performance. It didn’t happen by chance, this is the defined behavior of the compiler as stated in the Conditional attribute documentation:

“If the symbol is defined, the call is included; otherwise, the call (including evaluation of the parameters of the call) is omitted.”

Conclusion

The most common scenario in which the conditional attribute is involved is logging. Since the main advantage of omitting the logs is usually to avoid performance hit in production it is important to take into consideration the price of evaluating the arguments values. The simplest solution is to inline the variable. This can be done easily when the argument is string.Format() or similar. In case it is more complicated or unreadable it can always be solved by preprocessor directive such as #if.

AOP without weaving

In this post I’ll present a usage of runtime method replacer in AOP context. The idea behind it is to change the behavior of an application without changing the IL of its methods. In this post I’ll show how to log an exception from a method.

This post is based on the work of Ziad Elmalki who posted the original method replacer. It is also based on the updated code for the method replacer by Chung Sung which is compatible with the new .NET framework versions. Lastly thanks to Roy Osherove who mentioned those recently.

Replacing methods

The method replacer uses the following concept – after a method is jitted it receives a pointer of the jitted code. You can see how to extract that address in the original post. After extracting the addresses, we can simply replace one method with another:

public static void ReplaceMethod(IntPtr srcAdr, IntPtr destAdr)
{
unsafe
{
if (IntPtr.Size == 8)
{
ulong* d = (ulong*)destAdr.ToPointer();
*d = (
ulong)srcAdr.ToInt64();
}
else
{
uint* d = (uint*)destAdr.ToPointer();
*d = (
uint)srcAdr.ToInt32();
}
}
}

As a simple example, if we have these two methods:

public class MyClass
{
public static void Foo()
{
Console.WriteLine("In Foo");
throw new Exception("I am done here!");
}

public static void Bar()
{
Console.WriteLine("In Bar");
}
}

Then executing Foo in the following context:

MethodInfo barMethod = typeof (MyClass).GetMethod("Bar");
MethodInfo fooMethod = typeof (MyClass).GetMethod("Foo");
MethodUtil.ReplaceMethod(barMethod, fooMethod);
MyClass.Foo();

Will actually lead to the next result:

image

Which is… Cool!

Catching exceptions in Foo

What I’d like to present is a simplified example of how to catch an exception in business code without modifying it. A similar functionality to PostSharp exception handling. What we’re about to do is to hijack the original calls to Foo and redirect those to our new wrapper method. Our new wrapper method will call the original one inside a try/catch block.

Storing the original Foo

Since we’re about to intercept calls to Foo based on its address, we’d like to store a “way” to call the original method later. The “way” to do it is simple, we’ll extract the method address before starting the interception and create a delegate to it using marshaling. The delegate will be stored on a field:

MethodInfo fooMethod = typeof (MyClass).GetMethod("Foo");
IntPtr fooAdress = MethodUtil.GetMethodAddress(fooMethod);
OriginalFoo =
Marshal.GetDelegateForFunctionPointer(fooAdress, typeof (Action));

Creating the wrapper

For the purpose of this example we could prepare a stub in the project istelf. But, in order to prove that it is likely possible to create a more general solution, we will generate the wrapper at runtime.

Since the wrapper is going to receive the calls instead of Foo it must have the same signature. Besides, our wrapper will retrieve the original Foo delegate from a static field named OriginalFoo. The delegate will be called from the method inside a try/catch block.

We will generate a dynamic method that replaces the original method:

// The field holding the delegate to the original Foo
FieldInfo originalFooDelegateField = typeof (FooProtector).GetField("OriginalFoo");

MethodInfo invokeDelegateMethod = OriginalFoo.GetType().GetMethod("DynamicInvoke");
MethodInfo innerExceptionGetter = typeof(Exception).GetProperty("InnerException").GetGetMethod();
MethodInfo exceptionMessageGetter = typeof(Exception).GetProperty("Message").GetGetMethod();

var dynamicMethod = new DynamicMethod("FooProtector", typeof(void), new Type[0]);
ILGenerator ilGenerator = dynamicMethod.GetILGenerator();

Label beginExceptionBlock = ilGenerator.BeginExceptionBlock();

// Preparing the call to the original Foo -
// Load the original Foo
ilGenerator.Emit(OpCodes.Ldsfld, originalFooDelegateField);
// Load "no arguments" to invoke the delegate
ilGenerator.Emit(OpCodes.Ldnull);
// Invoke the delegate and call original Foo
ilGenerator.Emit(OpCodes.Callvirt, invokeDelegateMethod);
ilGenerator.Emit(
OpCodes.Pop);

ilGenerator.Emit(
OpCodes.Leave, beginExceptionBlock);
ilGenerator.BeginCatchBlock(
typeof (Exception));

// Extract the exception message
ilGenerator.Emit(OpCodes.Callvirt, innerExceptionGetter);
ilGenerator.Emit(
OpCodes.Callvirt, exceptionMessageGetter);

// Print the exception message
MethodInfo info = typeof (Console).GetMethod("WriteLine", new[] {typeof (string)});
ilGenerator.Emit(
OpCodes.Call, info);

ilGenerator.Emit(
OpCodes.Leave, beginExceptionBlock);
ilGenerator.EndExceptionBlock();
ilGenerator.Emit(
OpCodes.Ret);

// Trigger method compilation
dynamicMethod.CreateDelegate(typeof (Action));

This wrapper calls the original method through a delegate. In case an exception is thrown, it extracts the original exception and prints to the console the message.

Is it working?

Let’s revisit the original code and update it to the protecting code:

FooProtector.ProtectFoo();
MyClass.Foo();

The expected result is two messages printed, where the second one is the exception message “I am done here!”. As we can happily see, this is the exact result:

image

Conclusion

The concept of replacing methods using their jitted versions can be useful. It can be used to for AOP where it can be used for logging, exception handling and basically applying any custom aspect. It can also be used to modify some 3rd party code behavior for which we have no source code. Additionally, as Roy says is can be used as an engine for mocking frameworks.

But there are some disadvantages too. Firstly, it is very dependent on the compilation outcome which makes it quite fragile. Secondly, it is sensitive to optimizations, for example inlined methods cannot be handled. Thirdly, when it is used extensively it requires generation and JIT of many dynamic methods which might lead to a performance hit.

How to use switch statement with class

The switch statement controls the execution flow using comparison of constant values. This implies that in each case, the possible values are of primitive or Enum types. What can we do if we want to use a custom class as the switch expression? Clearly this is impossible by default, since custom classes are not primitives or Enums. The solution is to use the implicit cast.

Implicit cast

Implicit cast can is implemented using the implicit cast operator. Implicit cast enables, for example, assignment of instance from one type into a variable of other type.

Example of implicitly castable class:

public class Person
{
public string ID { get; set; }

static public implicit operator int (Person person)
{
return int.Parse(person.ID.Substring(0, 1));
}
}

This casting allows this simple assignment:

var person = new Person() {ID = "0-12345678-9"};
int quality = person;

Switch on class

In order to use a class instance as the switch expression we must choose a governing type for the cases (primitive or Enum) and make the original class castable to that type. For example, if we choose a class of type Person and governing type int then we must have an implicit cast from Person to int.

For example, using the class Person:

var person = new Person() {ID = "0-12345678-9"};

switch (person)
{
case 0:
Console.WriteLine("This is a top level person");
break;
case 9:
Console.WriteLine("This is a bottom level person (probably a developer)");
break;
default:
Console.WriteLine("Just a regular person");
break;
}

Behind the scenes of events

Events are a classic implementation of the observer pattern. Support for events syntax exists in many languages, such as C#. In this post I’ll explain the internals of events.

Delegates’ background

The most abstract way to describe a delegate is a “pointer to a method”. A very relevant feature of delegates is that they can “point” at multiple methods. In order to do so we use the =+ operator and combine to other delegates, for example:

[Test]
public void Invoke_TwoDelegatesCombined_BothCalled()
{
bool wasACalled = false;
bool wasBCalled = false;

Action delA = () => wasACalled = true;
Action delB = () => wasBCalled = true;

Action combine = null;
combine += delA;
combine += delB;

combine.Invoke();

Assert.That(wasACalled);
Assert.That(wasBCalled);
}

But, what actually happens here? Let’s take a look at this code:

combine += delA;

This code compiles to the following IL:

IL_0031: ldloc.2
IL_0032: ldloc.0
IL_0033: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
IL_0038: castclass [mscorlib]System.Action
IL_003d: stloc.2

Which is equivalent to:

combine = Delegate.Combine(combine, delA);

The result of the compiled code is direct call to Delegate.Combine, which makes any future call to the combined result be forwarded to both delegates.

Default event

If we use default event implementation, the compiler generates two methods and a backing field. The backing field is a delegate storing the subscribers; the methods are add and remove the subscribers from the delegate. This implementation allows us to add and remove subscribers for whom the event is visible and raise the event from the type itself. For example:

public class Publisher
{
public event EventHandler MyEvent;

public void Publish()
{
MyEvent(
this, EventArgs.Empty);
}
}

The event compiles into a field, which is a delegate of the event type:

.field private class [mscorlib]System.EventHandler MyEvent

And into two methods for adding and removing subscribers:

.event [mscorlib]System.EventHandler MyEvent
{
.addon instance void Events.Publisher::add_MyEvent(class [mscorlib]System.EventHandler)
.removeon instance void Events.Publisher::remove_MyEvent(class [mscorlib]System.EventHandler)
}

With the signatures:

.method public hidebysig specialname 
instance void add_MyEvent (
class [mscorlib]System.EventHandler 'value'
) cil managed

.method public hidebysig specialname
instance void remove_MyEvent (
class [mscorlib]System.EventHandler 'value'
) cil managed

The bodies of the events, not surprisingly, manipulate the backing field; we can ignore the bodies for now.
So up to here we see what the declaration of event compiles into – an event declaration, a backing field which is a delegate of the event type and two methods for adding and removing subscribers. All this magic from a single C# line of code.
The other side of the event is what happens as we raise it. The event can be raised only from within the type that declares it. For example:

MyEvent(this, EventArgs.Empty);

Compiles into:

IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler Events.Publisher::MyEvent
IL_0007: ldarg.0
IL_0008: ldsfld class [mscorlib]System.EventArgs [mscorlib]System.EventArgs::Empty
IL_000d: callvirt instance void [mscorlib]System.EventHandler::Invoke(object, class [mscorlib]System.EventArgs)

All this code does is accessing the delegate backing field and invoking it.

Custom event

In fact, the event is not custom but the add/remove methods are. Custom add/remove for events is a feature in C# which I think is not very commonly used (in contrast to properties). It allows the developer to provide an alternative implementation to the event subscription.

public event EventHandler MyCustomEvent
{
add {}
remove { }
}

The compiled class in this case does not contain a backing field. It contains the declaration of the event and the two methods with the custom provided body.
A difference which derives from the compiled code difference is that there’s no way to raise the event directly. This makes sense since the custom code can do many things (or nothing) with the subscribers and not store them in a common place for later invocation. If we try to raise MyCystomEvent in the same way we tried to raise MyEvent we’ll get a compilation error.

Retrieving property value by name using dynamic method

In the previous post we compared some alternatives of the dynamic keyword. One important and very interesting alternative is based on reflection emit. Reflection emit enables us to generate code using IL at runtime, compile it and execute it straightaway.
In this post we’ll see how to extract a string property named ‘Name’ from an unknown type using a dynamic method.

The code

public static string GetNameByDynamicMethod(object arg)
{
Type type = arg.GetType();

Func<object, string> getterDelegate;
if (!typeToEmitDelegateMap.TryGetValue(type, out getterDelegate))
{
string typeName = type.Name;

PropertyInfo nameProperty = type.GetProperty("Name");
Type returnType = typeof (string);

// Define a new dynamic method
// The method returns a string type
// The method expects single parameter
var method = new DynamicMethod("GetNameFrom" + typeName,
returnType,
new[] {typeof(object)});

ILGenerator ilGenerator = method.GetILGenerator();

// Load to the stack the first method argument.
//In our case, this is an object whose type we already know
ilGenerator.Emit(OpCodes.Ldarg_0);

// Cast the object to the type we already know
ilGenerator.Emit(OpCodes.Castclass, type);

// Call the getter method on the casted instance
ilGenerator.EmitCall(OpCodes.Call, nameProperty.GetGetMethod(), null);

// Return the value from Name property
ilGenerator.Emit(OpCodes.Ret);

// Compile the method and create a delegate to the new method
getterDelegate = (Func<object, string>)method.CreateDelegate(typeof(Func<object, string>));

typeToEmitDelegateMap.Add(type, getterDelegate);
}

return getterDelegate(arg);
}

What we did here was to define a new method, generate its code with IL, compile it and execute it. This new method is equivalent in many ways to a method we had generated in the original program. This new method will be hosted in a dynamic module in the memory.

The advantage of this kind of method over reflection is that it compiles the code once and doesn’t need to explore the type again whenever we need to get the property value.

Performance

A quick comparison for calling these alternatives 10,000,000 times each:

Seconds Ratio to directly
Directly 0.0131 1
Dynamic 0.4609 35
Expression 0.9154 70
Reflection emit 0.9832 75

As can be seen, using the dynamic keyword works much faster than compiling an expression or a dynamic method at runtime.

Another interesting data set shows the time that each alternative takes to set up (The time to perform the first call):

Seconds
Directly 0.00003
Dynamic 0.08047
Expression 0.00114
Reflection emit 0.02169

Performance of the dynamic keyword

In .NET 4.0 a new keyword was introduced: the dynamic keyword. One of the things it allows is calling methods on an instance and bypassing the compile time type checks. It can be useful in many scenarios, for example duck typing.
In this post, we’ll see that in some cases the keyword might have an unnecessary performance hit. Another thing we’ll see is how to save some of that time.

Simple performance measure

Let’s compare the performance of 3 ways of getting a property value – directly, using dynamic and using reflection:

public static string GetName(Student arg)
{
return arg.Name;
}
public static string GetNameByDynamic(dynamic arg)
{
return arg.Name;
}
public static string GetNameByReflection(object arg)
{
Type type = arg.GetType();

MethodInfo getter;
if (!typeToMethodMap.TryGetValue(type, out getter))
{
PropertyInfo property = type.GetProperty("Name");
getter = property.GetGetMethod();
typeToMethodMap.Add(type, getter);
}

return (string) getter.Invoke(arg, null);
}

Calling each method 10,000,000 times sums to: GetName=0.02 seconds, GetNameByDynamic=0.47 seconds, GetNameByReflection=15.41. Meaning, dynamic compared to strong type call is ~20 times slower.

Improving performance using interface

One way to deal with this performance hit is to extract an interface from all possible objects, through using it we can get back to work with strong type:

public interface INameProvider{
string Name { get; set; }
}

And change our method to:

public static string GetNameByInterface(INameProvider arg)
{
return arg.Name;
}

Luckily this code runs at 0.07 seconds, which is ~7 times faster than the dynamic version. The conclusion from this is that if our code is in a critical performance area, we better extract an interface (as long as it makes sense – don’t abuse the interface if the types have no logical commonality!).

Improving reflection version using expressions

What should we do if our code is written in pre-.NET 4.0 version and our solution is based on reflection? In this case, our code runs ~750 times slower than the strong type version. Since we can’t use dynamic, which was introduced first at .NET 4.0, we should find some other solution. A simple one is generating a method using expressions. The main advantage of expressions here is that they can be compiled into a new method which we can reuse.

public static string GetNameByExpression(object arg)
{
Type type = arg.GetType();

Func<object, string> getterDelegate;
if (!typeToDelegateMap.TryGetValue(type, out getterDelegate))
{
var parameterExpression = Expression.Parameter(typeof (object), "arg");
var castExpression = Expression.TypeAs(parameterExpression, type);
MemberExpression memberExpression = Expression.Property(castExpression, "Name");
var lambda = Expression.Lambda<Func<object, string>>(memberExpression, parameterExpression);

getterDelegate = lambda.Compile();
typeToDelegateMap.Add(type, getterDelegate);
}

return getterDelegate(arg);
}

This code here is basically equivalent to generating a lambda which looks like:

(object arg) => ((Student)arg).Name;

After we compile the code once we can skip the reflection invocation each time and end with much faster code. Running this method times 10,000,000 takes 0.86 seconds, which is ~18 times faster than the reflection solution.

Conclusion

If you are writing code which must run as fast as possible, this is the performance summary:

Seconds Ratio to directly
Directly 0.02 1
Through interface 0.07 3.5
Using dynamic 0.47 23.5
Using expression 0.86 43
Reflection 15.41 770

Monitoring execution using Mono Cecil

This post will demonstrate how to monitor the execution of .Net code using Mono Cecil. This can be useful for logging, for performance analysis and just for fun. The concept is obviously IL weaving. We’ll look for entry points and existing IL instructions to weave around the new IL. In this post we’ll show only four types of monitoring, in reality we have some more. The four types are: Enter method, Exit method, Jump from method and Jump back to method. Jump in this context means call another method and return from the other method.
In our example we’ll assume we have some simple ‘notifier’ which the weaved code will call:

public class Notifier
{
public static Action<string> Enter;
public static Action<string> Exit;
public static Action<string> JumpOut;
public static Action<string> JumpBack;

public static void NotifyEnter(string methodName)
{
if (Enter != null)
{
Enter(methodName);
}
}

public static void NotifyExit(string methodName)
{
if (Exit != null)
{
Exit(methodName);
}
}

public static void NotifyJumpOut(string methodName)
{
if (JumpOut != null)
{
JumpOut(methodName);
}
}

public static void NotifyJumpBack(string methodName)
{
if (JumpBack != null)
{
JumpBack(methodName);
}
}
}

Monitoring enter

This is the most trivial weave, which inserts a call to Enter callback before the first instruction in the method body. In order to do so, we first need to load the assembly and find all the methods into which we can weave:

public void Weave()
{
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath);

IEnumerable<MethodDefinition> methodDefinitions = assembly.MainModule.GetTypes()
.SelectMany(type => type.Methods).Where(method => method.HasBody);
foreach (var method in methodDefinitions)
{
WeaveMethod(assembly, method);
}

assembly.Write(assemblyPath);
}

Now we add reference to the the callbacks into the weaved assembly. This is not yet the weaving, this is required definition for the assembly to use in the weaved assembly. We’ll get the called methods using reflection:

Type notifierType = typeof (Notifier);
enterMethod = notifierType.GetMethod(
"NotifyEnter", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (string)}, null);
exitMethod = notifierType.GetMethod(
"NotifyExit", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (string)}, null);
jumpFromMethod = notifierType.GetMethod(
"NotifyJumpOut", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (string)}, null);
jumpBackMethod = notifierType.GetMethod(
"NotifyJumpBack", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (string)}, null);

Afterwards, we’ll add the references to the weaved assembly:

MethodReference enterReference = assembly.MainModule.Import(enterMethod);
MethodReference exitReference = assembly.MainModule.Import(exitMethod);
MethodReference jumpFromReference = assembly.MainModule.Import(jumpFromMethod);
MethodReference jumpBackReference = assembly.MainModule.Import(jumpBackMethod);

So our weave method looks like:

private static void WeaveMethod(AssemblyDefinition assembly, MethodDefinition method)
{
MethodReference enterReference = assembly.MainModule.Import(enterMethod);
MethodReference exitReference = assembly.MainModule.Import(exitMethod);
MethodReference jumpFromReference = assembly.MainModule.Import(jumpFromMethod);
MethodReference jumpBackReference = assembly.MainModule.Import(jumpBackMethod);

string name = method.DeclaringType.FullName + "." + method.Name;

WeaveEnter(method, enterReference, name);
WeaveJump(method, jumpFromReference, jumpBackReference, name);
WeaveExit(method, exitReference, name);
}

Now, we have everything ready to weave the enter monitoring code:

private static void WeaveEnter(MethodDefinition method, MethodReference methodReference, string name)
{
var ilProcessor = method.Body.GetILProcessor();

Instruction loadNameInstruction = ilProcessor.Create(OpCodes.Ldstr, name);
Instruction callEnterInstruction = ilProcessor.Create(OpCodes.Call, methodReference);

ilProcessor.InsertBefore(method.Body.Instructions.First(), loadNameInstruction);
ilProcessor.InsertAfter(loadNameInstruction, callEnterInstruction);
}

The ILProcessor is a helper utility which Cecil provides to make the weaving simpler. The first instruction we weave is loading of a string which is the name of the method being entered. The second instruction we weave is a call instruction which uses as argument the loaded string. We insert the instructions in the beginning of the method and from now on every time the method is entered the callback will be invoked.

Monitoring exit

Monitoring exit is a little more interesting. In contrast to enter where we have a single weaving point, exit may have multiple exit points – multiple return statements, thrown exceptions, etc…
Here we’ll monitor for simplicity return statements only:

private static void WeaveExit(MethodDefinition method, MethodReference exitReference, string name)
{
ILProcessor ilProcessor = method.Body.GetILProcessor();

List<Instruction> returnInstructions = method.Body.Instructions.Where(instruction => instruction.OpCode == OpCodes.Ret).ToList();
foreach (var returnInstruction in returnInstructions)
{
Instruction loadNameInstruction = ilProcessor.Create(OpCodes.Ldstr, name);
Instruction callExitReference = ilProcessor.Create(OpCodes.Call, exitReference);

ilProcessor.InsertBefore(returnInstruction, loadNameInstruction);
ilProcessor.InsertAfter(loadNameInstruction, callExitReference);
}
}

As can be seen, we first find all the return instructions. Afterwards, we insert before them call to our callback before them in a similar way to the enter callback.

Monitoring method jumps

This monitoring type will let us know when we jump to another method. If we are doing performance measuring, in an “ideal” world (where we have a single thread and no context switches) this would be the place where we stop and resume measuring the time for the executed method. Here for simplicity we’ll weave around simple call instructions, ignoring other types of call (like callvirt).

private static void WeaveJump(MethodDefinition method, MethodReference jumpFromReference, MethodReference jumpBackReference, string name)
{
ILProcessor ilProcessor = method.Body.GetILProcessor();

List<Instruction> callInstructions = method.Body.Instructions.Where(instruction => instruction.OpCode == OpCodes.Call).ToList();
foreach (var callInstruction in callInstructions)
{
Instruction loadNameForFromInstruction = ilProcessor.Create(OpCodes.Ldstr, name);
Instruction callJumpFromInstruction = ilProcessor.Create(OpCodes.Call, jumpFromReference);

ilProcessor.InsertBefore(callInstruction, loadNameForFromInstruction);
ilProcessor.InsertAfter(loadNameForFromInstruction, callJumpFromInstruction);

Instruction loadNameForBackInstruction = ilProcessor.Create(OpCodes.Ldstr, name);
Instruction callJumpBackInstruction = ilProcessor.Create(OpCodes.Call, jumpBackReference);

ilProcessor.InsertAfter(callInstruction, loadNameForBackInstruction);
ilProcessor.InsertAfter(loadNameForBackInstruction, callJumpBackInstruction);
}
}

Here, we find all the call instructions and insert a call to JumpFrom before them and a call to JumpBack after them. This way we get a call before leaving and returning to the method.

Example

public void MethodA()
{
MethodB();
}

private void MethodB()
{
}

If we execute MethodA we’re about to receive these calls:

  1. Enter MethodA
  2. JumpFrom MethodA
  3. Enter MethodB
  4. Exit MethodB
  5. JumpBack MethodA
  6. ExitMethod A

Summary

Mono Cecil can be used for low level AOP where the aspects’ targets are IL instructions. There are already some great tools out there for AOP like PostSharp, but it is cool to know how simply a solution can be implemented using Cecil.

The synchronized keyword

What is does

A little known feature of .NET is the synchronized keyword. The keyword can be used on methods and it ensures:

  • Instance method – can be executed in a single thread on the instance (different instances are not synchronized). Equivalent to lock(this).
  • Static method – can be executed in a single thread. Equivalent to lock(typeof(TypeName)).

Usage in C#

If you’ll look at the C# specification you’ll see that there’s no mention of this keyword. The reason is that the keyword is an IL keyword and not a C# one. In order to instruct the compiler to mark the method as synchronized, we can use the MethodImplAttibute with Synchronized MethodImplOptions. For example:

[MethodImpl(MethodImplOptions.Synchronized)]
public void MethodWithSyncAttribute()
{
}

The IL result

Using synchronized keyword

The MethodWithSyncAttribute() looks in IL:

.method public hidebysig instance void  MethodWithSyncAttribute() cil managed synchronized
{
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ret
}

It is very clear that this method has no explicit lock instructions like Monitor.Enter for example. Yet, it’ll still behave the same as if we had used a lock block around the method body.

Using lock block

The previous method is equivalent to the next:

public void MethodWithExplicitLock()
{
lock(this)
{
}
}

This method translates into:

.method public hidebysig instance void  MethodWithExplicitLock() cil managed
{
  // Code size       36 (0x24)
  .maxstack  2
  .locals init ([0] bool ‘s__LockTaken0’,
           [1] class Sync.Logger CS$2$0000,
           [2] bool CS$4$0001)
  IL_0000:  nop
  IL_0001:  ldc.i4.0
  IL_0002:  stloc.0
  .try
  {
    IL_0003:  ldarg.0
    IL_0004:  dup
    IL_0005:  stloc.1
    IL_0006:  ldloca.s   ‘s__LockTaken0’
    IL_0008:  call       void [mscorlib]System.Threading.Monitor::Enter(object,
                                                                        bool&)
    IL_000d:  nop
    IL_000e:  nop
    IL_000f:  nop
    IL_0010:  leave.s    IL_0022
  }  // end .try
  finally
  {
    IL_0012:  ldloc.0
    IL_0013:  ldc.i4.0
    IL_0014:  ceq
    IL_0016:  stloc.2
    IL_0017:  ldloc.2
    IL_0018:  brtrue.s   IL_0021
    IL_001a:  ldloc.1
    IL_001b:  call       void [mscorlib]System.Threading.Monitor::Exit(object)
    IL_0020:  nop
    IL_0021:  endfinally
  }  // end handler
  IL_0022:  nop
  IL_0023:  ret
}

As can be seen, the lock block translates naturally into a try/finally block with calls to Montior.Enter and Monitor.Leave.

Summary

The synchronized keyword is an IL keyword that synchronizes the marked method calls. It causes the method to behave in an equivalent way to the one where the whole body is surrounded with lock block. It is interesting to note that locking instructions are generated only during JIT when using the keyword.
The bottom line is that for C# developers it mostly provides another syntactic sugar for defining trivial lock.

Intercepting unmanaged call in managed code

This post will demonstrate how to intercept unmanaged calls in the executing process. There are many reasons for intercepting unmanaged calls, among them monitoring, debugging and some other hacks.
This post will demonstrate how to intercept calls to CreateFile from Kernel32 library. The CreateFile method is called for opening an existing file and creating new one. For example, calls to File.OpenText will initiate a call to CreateFile.

Hooking CreateFile in unmanaged code

We’ll define a function pointer type for CreateFile:

typedef HANDLE (WINAPI *FileCreateFunction)(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);

Afterwards, we’ll store the original CreateFile method and create a hook which will redirect calls:

FileCreateFunction OriginalCreateFile = (FileCreateFunction)GetProcAddress(GetModuleHandle(L"kernel32"), "CreateFileW");
HANDLE WINAPI CreateFileHook(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
bool hasListener = createFileCallback != NULL;
if(hasListener)
{
createFileCallback(lpFileName);
}

return OriginalCreateFile(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}

For now, ignore the code about the callback; we’ll use this code later for notifying the managed when a file is created.

As we can see, the hook function has the same signature as the original one. This is obvious since the function caller will not be changed, just the target method. The hook observes the function arguments and forwards the call to the original call.

Now, we’ll forward the calls from CreateFile to the new hook using mhook library:

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Mhook_SetHook((PVOID*)&OriginalCreateFile, CreateFileHook);
break;
case DLL_PROCESS_DETACH:
createFileCallback = NULL;
Mhook_Unhook((PVOID*)&OriginalCreateFile);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}

return TRUE;
}

This code will hook the CreateFile method (OriginalCreateFile) to our new defined hook when the library is loaded into the process.

Using the library in managed code

In order to load the unmanaged library we’ll use P/invoke calls:

[DllImport("kernel32", SetLastError = true)]
static extern IntPtr LoadLibrary(string lpFileName);

[
DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule);

Loading the library:

static void Main(string[] args)
{
IntPtr library = LoadLibrary(@"..\..\..\Debug\InterceptionLibrary.dll");
FreeLibrary(library);
}

Right now, all the calls will behave the same, but all will be routed through our new hook (a user of the software will experience no difference).

Preparing a callback in unmanaged code

We would like to know what file is being created, so we’ll define a callback function pointer that matches it:

typedef void (*NotifyCallbackFunction)(const TCHAR* fileName);

The managed code will register a callback using the method:

extern "C" __declspec(dllexport) void RegisterFileCreateListener(
NotifyCallbackFunction callback )
{
createFileCallback = callback;
}

This method is exposed so it can be used by the managed code using:

extern "C" __declspec(dllexport)

Registering the callback through managed code

First, in order to call the register method, we’ll need to define a delegate into the register method will be loaded (ignore the callback delegate for now):

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void RegisterFileListenerDel(OnFileCreatedDel callback);

In order to load the register method into the managed assembly, we’ll need to use:

[DllImport("kernel32", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

Loading the method is done by:

IntPtr pAddressOfFunctionToCall = GetProcAddress(library, "RegisterFileCreateListener");
var registerListener = (RegisterFileListenerDel)
Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall,
typeof (RegisterFileListenerDel));

Now, we’ll have to define a callback delegate and method:

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private delegate void OnFileCreatedDel(string fileName);
private static void OnFileCreated(string fileName)
{
Console.WriteLine("File opened: {0}", fileName);
}

Now, all that’s needed is to register the callback using the method loaded in the previous step:

registerListener(OnFileCreated);

That’s all, as long as the library is loaded our callback we’ll be notified on every CreateFile call.

Example

This is our final version of the main method in the managed code:

static void Main(string[] args)
{
IntPtr library = LoadLibrary(@"..\..\..\Debug\InterceptionLibrary.dll");

IntPtr pAddressOfFunctionToCall = GetProcAddress(library, "RegisterFileCreateListener");
var registerListener = (RegisterFileListenerDel)
Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall,
typeof (RegisterFileListenerDel));
registerListener(OnFileCreated);

File.OpenText(@"C:\Development\wow.txt").Dispose();
File.CreateText(@"C:\Development\wow2.txt").Dispose();

FreeLibrary(library);
}

Running this code will notify these files created:
image

Summary

In order to be notified about a native call in managed code:

  1. Create an unmanaged library
  2. Hook the requested method using mhook
  3. Create and expose a callback registration method
  4. In managed code load the library
  5. Register a callback

You can download the source code example here.

Alternatives

There several alternatives. For example, another possible way to intercept calls in unmanaged calls is Detours, a library developed by Microsoft. Another possible solution is EasyHook, a library that allows intercepting unmanaged calls directly from managed code.