static void FillJumpInfo(MethodDefinition target, bool bConfirmPopReturnValue) { MethodBody targetBody = target.Body; ILProcessor il = targetBody.GetILProcessor(); if (!bConfirmPopReturnValue) { Instruction retIns = il.Create(OpCodes.Ret); if (!injectType.HasFlag(InjectType.Before)) { if (cursor.Previous.OpCode == OpCodes.Nop) { cursor.Previous.OpCode = retIns.OpCode; cursor.Previous.Operand = retIns.Operand; retIns = cursor.Previous; } else { il.InsertBefore(cursor, retIns); } } else { Instruction start = il.Create(OpCodes.Ldloc, flagDef); if (cursor.Previous.OpCode == OpCodes.Nop) { cursor.Previous.OpCode = start.OpCode; cursor.Previous.Operand = start.Operand; il.InsertAfter(cursor.Previous, retIns); } else { il.InsertBefore(cursor, retIns); il.InsertBefore(retIns, start); } Instruction popIns = il.Create(OpCodes.Pop); bool bGotReturnValue = !target.ReturnVoid(); if (bGotReturnValue) { il.InsertBefore(cursor, popIns); } il.InsertBefore(retIns, il.Create(ldcI4s[(int)InjectType.Before / 2])); il.InsertBefore(retIns, il.Create(OpCodes.Ble_Un, bGotReturnValue ? popIns : cursor)); } } else if (cursor.Previous.OpCode == OpCodes.Nop) { targetBody.Instructions.Remove(cursor.Previous); } }
static void FillInjectMethod(MethodDefinition target, Action <MethodDefinition, InjectType> fillInjectInfo, InjectType runtimeInjectType) { if (runtimeInjectType == InjectType.None) { return; } MethodBody targetBody = target.Body; ILProcessor il = targetBody.GetILProcessor(); cursor = GetMethodNextInsertPosition(target, null, runtimeInjectType.HasFlag(InjectType.After)); while (cursor != null) { bool bAfterInject = runtimeInjectType == InjectType.After; Instruction startPos = il.Create(OpCodes.Ldloc, flagDef); if (bAfterInject) { /// Replace instruction with references reserved Instruction endPos = il.Create(OpCodes.Ret); int replaceIndex = targetBody.Instructions.IndexOf(cursor); cursor.OpCode = startPos.OpCode; cursor.Operand = startPos.Operand; il.InsertAfter(targetBody.Instructions[replaceIndex], endPos); cursor = targetBody.Instructions[replaceIndex + 1]; } else { il.InsertBefore(cursor, startPos); } il.InsertBefore(cursor, il.Create(ldcI4s[(int)InjectType.After / 2])); il.InsertBefore(cursor, il.Create(bAfterInject ? OpCodes.Bne_Un : OpCodes.Ble_Un, cursor)); fillInjectInfo(target, runtimeInjectType); cursor = GetMethodNextInsertPosition(target, cursor, runtimeInjectType.HasFlag(InjectType.After)); } }
static void FillBaseCall(MethodDefinition target, InjectType runtimeInjectType, bool preCall) { MethodBody targetBody = target.Body; ILProcessor il = targetBody.GetILProcessor(); InjectType curBaseInjectType = preCall ? InjectType.ReplaceWithPreInvokeBase : InjectType.ReplaceWithPostInvokeBase; if (runtimeInjectType.HasFlag(curBaseInjectType)) { Instruction end = il.Create(OpCodes.Nop); il.InsertBefore(cursor, end); il.InsertBefore(end, il.Create(OpCodes.Ldloc, flagDef)); il.InsertBefore(end, il.Create(OpCodes.Ldc_I4, (int)curBaseInjectType)); il.InsertBefore(end, il.Create(OpCodes.Bne_Un, end)); FillArgs(target, end, PostProcessBaseMethodArg); il.InsertBefore(end, il.Create(OpCodes.Call, target.GetBaseMethodInstance())); if (!target.ReturnVoid()) { il.InsertBefore(end, il.Create(OpCodes.Pop)); } } }