public override void Generate(ILProcessor processor) { // Now add the IL that creates the delegate. processor.Append(Instruction.Create(OpCodes.Nop)); processor.Append(Instruction.Create(OpCodes.Ldarg_0)); processor.Append(Instruction.Create(OpCodes.Ldftn, this.m_Target)); //processor.Append(Instruction.Create(OpCodes.Ldnull)); processor.Append(Instruction.Create(OpCodes.Newobj, this.m_Constructor)); processor.Append(Instruction.Create(OpCodes.Stloc, this.m_Storage)); }
public override void Generate(ILProcessor processor) { // Load the arguments. foreach (VariableDefinition v in m_Parameters) { processor.Append(Instruction.Create(OpCodes.Ldloc, v)); } // Call the delegate. processor.Append(Instruction.Create(OpCodes.Call, this.m_Target)); // Handle the return type. if (this.m_ReturnType.FullName == this.m_Target.Module.Import(typeof(void)).FullName) { // Return value is void. Discard any result and return. processor.Append(Instruction.Create(OpCodes.Pop)); } else if (this.m_ReturnType.IsValueType || this.m_ReturnType.IsGenericParameter) { // Return value is value type (not reference). Unbox and return it. processor.Append(Instruction.Create(OpCodes.Unbox_Any, this.m_ReturnType)); processor.Append(Instruction.Create(OpCodes.Stloc, this.Result)); } else { // Return value is reference type. Cast it and return it. processor.Append(Instruction.Create(OpCodes.Isinst, this.m_ReturnType)); processor.Append(Instruction.Create(OpCodes.Stloc, this.Result)); } }
private void FillResetWatchdog(ILProcessor ilProc) { Instruction ldarg = Instruction.Create(OpCodes.Ldarg_0); FieldReference targetField = new FieldReference("_computerTarget", GetCommonTingComputer(), _target); Instruction targetToStack = Instruction.Create(OpCodes.Ldfld, targetField); MethodReference injectoid = _source.Methods.First(o => o.Name == "ResetWatchdog"); injectoid = _target.Module.Import(injectoid); Instruction callInjectoid = Instruction.Create(OpCodes.Call, injectoid); Instruction ret = Instruction.Create(OpCodes.Ret); ilProc.Append(ldarg); ilProc.Append(targetToStack); ilProc.Append(callInjectoid); ilProc.Append(ret); }
protected override void ImplementProceed(MethodDefinition methodInfo, MethodBody methodBody, ILProcessor il, FieldReference methodInfoField, MethodReference proceed, Action<ILProcessor> emitProceedTarget, MethodReference proceedTargetMethod, OpCode proceedOpCode) { // If T is an interface, then we want to check if target is null; if so, we want to just return the default value var targetNotNull = il.Create(OpCodes.Nop); EmitProxyFromProceed(il); il.Emit(OpCodes.Ldfld, ClassWeaver.Target); // Load "target" from "this" il.Emit(OpCodes.Brtrue, targetNotNull); // If target is not null, jump below CecilExtensions.CreateDefaultMethodImplementation(methodBody.Method, il); il.Append(targetNotNull); // Mark where the previous branch instruction should jump to base.ImplementProceed(methodInfo, methodBody, il, methodInfoField, proceed, emitProceedTarget, proceedTargetMethod, proceedOpCode); }
/// <summary> /// Emits the instructions that call <see cref="IInitialize.Initialize"/> on a given service instance. /// </summary> /// <param name="il"></param> /// <param name="module">The host module.</param> /// <param name="serviceInstance">The local variable that points to the current service instance.</param> public void Initialize(ILProcessor il, ModuleDefinition module, VariableDefinition serviceInstance) { var body = il.Body; var method = body.Method; var declaringType = method.DeclaringType; var targetField = GetTargetField(declaringType); if (targetField == null) return; var initializeType = module.ImportType<IInitialize>(); il.Emit(OpCodes.Ldloc, serviceInstance); il.Emit(OpCodes.Isinst, initializeType); var initializeMethod = module.ImportMethod<IInitialize>("Initialize"); var skipInitializationCall = il.Create(OpCodes.Nop); il.Emit(OpCodes.Brfalse, skipInitializationCall); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); GetServiceHash(il, module, serviceInstance); var containsMethod = module.ImportMethod<Dictionary<int, int>>("ContainsKey"); il.Emit(OpCodes.Callvirt, containsMethod); il.Emit(OpCodes.Brtrue, skipInitializationCall); // if (!__initializedServices.ContainsKey(currentService.GetHashCode()) { il.Emit(OpCodes.Ldloc, serviceInstance); il.Emit(OpCodes.Isinst, initializeType); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, initializeMethod); // __initializedServices.Add(hashCode, 0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); GetServiceHash(il, module, serviceInstance); il.Emit(OpCodes.Ldc_I4_1); var addMethod = module.ImportMethod<Dictionary<int, int>>("Add"); il.Emit(OpCodes.Callvirt, addMethod); il.Append(skipInitializationCall); }
protected override void ImplementProceed(MethodDefinition methodInfo, MethodBody methodBody, ILProcessor il, FieldReference methodInfoField, MethodReference proceed, Action<ILProcessor> emitProceedTarget, MethodReference proceedTargetMethod, OpCode proceedOpCode) { if (methodInfo.IsAbstract) { CecilExtensions.CreateDefaultMethodImplementation(methodInfo, il); } else { var targetNotNull = il.Create(OpCodes.Nop); EmitProxyFromProceed(il); il.Emit(OpCodes.Ldfld, target); // Load "target" from "this" il.Emit(OpCodes.Brtrue, targetNotNull); // If target is not null, jump below base.ImplementProceed(methodInfo, methodBody, il, methodInfoField, proceed, _ => EmitProxyFromProceed(il), callBaseMethod, OpCodes.Call); il.Append(targetNotNull); // Mark where the previous branch instruction should jump to base.ImplementProceed(methodInfo, methodBody, il, methodInfoField, proceed, emitProceedTarget, proceedTargetMethod, proceedOpCode); } }
/// <summary> /// Emits the cpblk method, supporting x86 and x64 platform. /// </summary> /// <param name="method">The method.</param> /// <param name="gen">The gen.</param> private void EmitCpblk(MethodDefinition method, ILProcessor gen) { var cpblk = gen.Create(OpCodes.Cpblk); //gen.Emit(OpCodes.Sizeof, voidPointerType); //gen.Emit(OpCodes.Ldc_I4_8); //gen.Emit(OpCodes.Bne_Un_S, cpblk); gen.Emit(OpCodes.Unaligned, (byte)1); // unaligned to 1 gen.Append(cpblk); }
static int EmitParameters(MethodDefinition method, MethodBody body, ILProcessor il) { int i; for (i = 0; i < method.Parameters.Count; i++) { var p = method.Module.Import(method.Parameters[i].ParameterType); il.Emit(OpCodes.Ldarg, i); if (p.Name == "StringBuilder") { // void GetShaderInfoLog(..., StringBuilder foo) // IntPtr foo_sb_ptr; // try { // foo_sb_ptr = Marshal.AllocHGlobal(sb.Capacity + 1); // glGetShaderInfoLog(..., foo_sb_ptr); // MarshalPtrToStringBuilder(foo_sb_ptr, sb); // } // finally { // Marshal.FreeHGlobal(sb_ptr); // } // Make sure we have imported StringBuilder::Capacity and Marshal::AllocHGlobal var sb_get_capacity = method.Module.Import(TypeStringBuilder.Methods.First(m => m.Name == "get_Capacity")); var alloc_hglobal = method.Module.Import(TypeMarshal.Methods.First(m => m.Name == "AllocHGlobal")); // IntPtr ptr; var variable_name = p.Name + " _sb_ptr"; body.Variables.Add(new VariableDefinition(variable_name, TypeIntPtr)); int index = body.Variables.Count - 1; // ptr = Marshal.AllocHGlobal(sb.Capacity + 1); il.Emit(OpCodes.Callvirt, sb_get_capacity); il.Emit(OpCodes.Call, alloc_hglobal); il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldloc, index); // We'll emit the try-finally block in the epilogue implementation, // because we haven't yet emitted all necessary instructions here. } else if (p.Name == "String" && !p.IsArray) { EmitStringParameter(method, p, body, il); } else if (p.IsByReference) { body.Variables.Add(new VariableDefinition(new PinnedType(p))); var index = body.Variables.Count - 1; il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldloc, index); il.Emit(OpCodes.Conv_I); } else if (p.IsArray) { if (p.Name != method.Module.Import(typeof(string[])).Name) { // .Net treats 1d arrays differently than higher rank arrays. // 1d arrays are directly supported by instructions such as ldlen and ldelema. // Higher rank arrays must be accessed through System.Array methods such as get_Length. // 1d array: // check array is not null // check ldlen array > 0 // ldc.i4.0 // ldelema // 2d array: // check array is not null // check array.get_Length() > 0 // ldc.i4.0 // ldc.i4.0 // call instance T& T[0..., 0...]::Address(int32, int32) // Mono treats everything as a 1d array. // Interestingly, the .Net approach works on both Mono and .Net. // The Mono approach fails when using high-rank arrays on .Net. // We should report a bug to http://bugzilla.xamarin.com // Pin the array and pass the address // of its first element. var array = (ArrayType)p; var element_type = p.GetElementType(); body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type)))); int pinned_index = body.Variables.Count - 1; var empty = il.Create(OpCodes.Ldc_I4, 0); var pin = il.Create(OpCodes.Ldarg, i); var end = il.Create(OpCodes.Stloc, pinned_index); // if (array == null) goto empty il.Emit(OpCodes.Brfalse, empty); // else if (array.Length != 0) goto pin il.Emit(OpCodes.Ldarg, i); if (array.Rank == 1) { il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); } else { var get_length = method.Module.Import( mscorlib.MainModule.GetType("System.Array").Methods.First(m => m.Name == "get_Length")); il.Emit(OpCodes.Callvirt, get_length); } il.Emit(OpCodes.Brtrue, pin); // empty: IntPtr ptr = IntPtr.Zero il.Append(empty); il.Emit(OpCodes.Conv_U); il.Emit(OpCodes.Br, end); // pin: &array[0] il.Append(pin); if (array.Rank == 1) { // 1d array (vector), address is taken by ldelema il.Emit(OpCodes.Ldc_I4, 0); il.Emit(OpCodes.Ldelema, element_type); } else { // 2d-3d array, address must be taken as follows: // call instance T& T[0..., 0..., 0...]::Address(int, int, int) ByReferenceType t_ref = array.ElementType.MakeByReferenceType(); MethodReference get_address = new MethodReference("Address", t_ref, array); for (int r = 0; r < array.Rank; r++) { get_address.Parameters.Add(new ParameterDefinition(TypeInt32)); } get_address.HasThis = true; // emit the get_address call for (int r = 0; r < array.Rank; r++) { il.Emit(OpCodes.Ldc_I4, 0); } il.Emit(OpCodes.Call, get_address); } // end: fixed (IntPtr ptr = &array[0]) il.Append(end); il.Emit(OpCodes.Ldloc, pinned_index); il.Emit(OpCodes.Conv_I); } else { EmitStringArrayParameter(method, p, body, il); } } } return i; }
/// <summary> /// Defines the instructions that create each service type in the <paramref name="serviceMap"/>. /// </summary> /// <param name="serviceMap">The service map that contains the list of application dependencies.</param> /// <param name="getInstanceMethod">The method that will be used to instantiate the service types.</param> /// <param name="jumpTargetField">The field that holds the dictionary with the switch table target instructions.</param> /// <param name="getServiceHash">The method that calculates the service hash code.</param> /// <param name="il">The <see cref="ILProcessor"/> that points to the body of the factory method.</param> private void DefineServices(IDictionary<IDependency, IImplementation> serviceMap, MethodDefinition getInstanceMethod, FieldDefinition jumpTargetField, MethodDefinition getServiceHash, ILProcessor il) { var endLabel = Instruction.Create(OpCodes.Nop); il.Append(endLabel); var body = il.Body; body.InitLocals = true; var method = body.Method; var returnValue = method.AddLocal<object>(); var declaringType = method.DeclaringType; var module = declaringType.Module; var jumpTargets = new Dictionary<IDependency, Instruction>(); foreach (var dependency in serviceMap.Keys) { jumpTargets[dependency] = il.Create(OpCodes.Nop); } var getItemMethod = module.ImportMethod<Dictionary<int, int>>("get_Item"); var serviceHash = method.AddLocal<int>(); var skipCreate = il.Create(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, jumpTargetField); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, getServiceHash); il.Emit(OpCodes.Stloc, serviceHash); var contains = module.ImportMethod<Dictionary<int, int>>("ContainsKey"); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, jumpTargetField); il.Emit(OpCodes.Ldloc, serviceHash); il.Emit(OpCodes.Callvirt, contains); il.Emit(OpCodes.Brfalse, skipCreate); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, jumpTargetField); il.Emit(OpCodes.Ldloc, serviceHash); il.Emit(OpCodes.Callvirt, getItemMethod); var switchLabels = new List<Instruction>(jumpTargets.Values); var labels = switchLabels.ToArray(); il.Emit(OpCodes.Switch, labels); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc, returnValue); il.Emit(OpCodes.Br, skipCreate); foreach (var dependency in serviceMap.Keys) { // Set the jump target var currentLabel = jumpTargets[dependency]; il.Append(currentLabel); var serviceType = module.ImportType(dependency.ServiceType); // Emit the implementation var implementation = serviceMap[dependency]; EmitService(getInstanceMethod, dependency, implementation, serviceMap); il.Emit(OpCodes.Stloc, returnValue); var serviceInstance = returnValue; // Call IInitialize.Initialize(this) on the current type if (_initializer != null) _initializer.Initialize(il, module, serviceInstance); //il.Emit(OpCodes.Ldloc, returnValue); //il.Emit(OpCodes.Unbox_Any, serviceType); il.Emit(OpCodes.Br, endLabel); } il.Append(skipCreate); var getNextContainer = module.ImportMethod<IMicroContainer>("get_NextContainer"); var otherContainer = method.AddLocal<IMicroContainer>(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, getNextContainer); il.Emit(OpCodes.Stloc, otherContainer); // if (otherContainer != null ) { var skipOtherContainerCall = il.Create(OpCodes.Nop); il.Emit(OpCodes.Ldloc, otherContainer); il.Emit(OpCodes.Brfalse, skipOtherContainerCall); // Prevent the container from calling itself il.Emit(OpCodes.Ldloc, otherContainer); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brtrue, skipOtherContainerCall); var otherGetInstanceMethod = module.ImportMethod<IMicroContainer>("GetInstance"); // return otherContainer.GetInstance(type, key); il.Emit(OpCodes.Ldloc, otherContainer); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, otherGetInstanceMethod); il.Emit(OpCodes.Stloc, returnValue); il.Emit(OpCodes.Br, endLabel); // } il.Append(skipOtherContainerCall); il.Append(endLabel); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldloc, returnValue); }
private static void WriteMessageId(ILProcessor worker, int msgId) { worker.Append(worker.Create(OpCodes.Ldloc_0)); worker.Append(worker.Create(OpCodes.Ldc_I4, msgId)); worker.Append(worker.Create(OpCodes.Conv_U2)); worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteInt16)); }
private static void WriteDirtyCheck(ILProcessor serWorker, bool reset) { Instruction target = serWorker.Create(OpCodes.Nop); serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); serWorker.Append(serWorker.Create(OpCodes.Brtrue, target)); serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference)); serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); if (reset) { serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1)); serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); } serWorker.Append(target); }
private void GenerateSyncListInitializer(ILProcessor awakeWorker, FieldReference fd, int index) { awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldfld, fd)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldsfld, this.m_SyncListStaticFields[index])); GenericInstanceType baseType = (GenericInstanceType) fd.FieldType.Resolve().BaseType; baseType = (GenericInstanceType) Weaver.scriptDef.MainModule.ImportReference(baseType); TypeReference reference = baseType.GenericArguments[0]; TypeReference[] arguments = new TypeReference[] { reference }; MethodReference method = Helpers.MakeHostInstanceGeneric(Weaver.SyncListInitBehaviourReference, arguments); awakeWorker.Append(awakeWorker.Create(OpCodes.Callvirt, method)); Weaver.scriptDef.MainModule.ImportReference(method); }
static DebugVariables EmitDebugPrologue(MethodDefinition wrapper, ILProcessor il) { DebugVariables vars = null; if (il.Body.Method.Name != "GetError") { // Pull out the namespace name, method fullname will look // something like "type namespace.class::method(type arg)" var module = il.Body.Method.FullName; module = module.Substring(module.IndexOf(' ') + 1); module = module.Substring(0, module.IndexOf("::")); module = module.Substring(0, module.LastIndexOf('.')); // Only works for Graphics modules due to hardcoded use of // OpenTK.Graphics.GraphicsContext if (module == "OpenTK.Graphics.OpenGL4" || module == "OpenTK.Graphics.OpenGL" || module == "OpenTK.Graphics.ES10" || module == "OpenTK.Graphics.ES11" || module == "OpenTK.Graphics.ES20" || module == "OpenTK.Graphics.ES30") { var errorHelperType = wrapper.Module.GetType(module, "ErrorHelper"); if (errorHelperType != null) { vars = new DebugVariables(); vars.ErrorHelperType = errorHelperType; // GraphicsContext type var graphicsContext = wrapper.Module.Types.First( type => type.FullName == "OpenTK.Graphics.GraphicsContext"); // IGraphicsContext type var iGraphicsContext = wrapper.Module.Types.First( type => type.FullName == "OpenTK.Graphics.IGraphicsContext"); // Get the constructor that takes a GraphicsContext parameter var ctor = vars.ErrorHelperType.GetConstructors().FirstOrDefault( c => c.Parameters.Count == 1 && c.Parameters[0].ParameterType.FullName == iGraphicsContext.FullName); if (ctor == null) { throw new InvalidOperationException( String.Format( "{0} does needs a constructor taking {1}", errorHelperType, graphicsContext)); } // GraphicsContext.CurrentContext property getter vars.Get_CurrentContext = graphicsContext.Methods.First( method => method.Name == "get_CurrentContext"); vars.Set_ErrorChecking = graphicsContext.Methods.First( method => method.Name == "set_ErrorChecking"); vars.ErrorHelperLocal = new VariableDefinition(vars.ErrorHelperType); // using (new ErrorHelper(GraphicsContext.CurrentContext)) { ... il.Body.Variables.Add(vars.ErrorHelperLocal); il.Emit(OpCodes.Ldloca, vars.ErrorHelperLocal); il.Emit(OpCodes.Call, vars.Get_CurrentContext); il.Emit(OpCodes.Call, ctor); vars.BeginTry = Instruction.Create(OpCodes.Nop); il.Append(vars.BeginTry); // Special case Begin to turn off error checking. if (il.Body.Method.Name == "Begin") { il.Emit(OpCodes.Call, vars.Get_CurrentContext); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Conv_I1); il.Emit(OpCodes.Call, vars.Set_ErrorChecking); } } } } return vars; }
private static void WriteMessageSize(ILProcessor worker) { worker.Append(worker.Create(OpCodes.Ldc_I4_0)); worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteInt16)); }
private void DefaultValueMappingCode(ILProcessor ilProcessor) { ilProcessor.Append(Instruction.Create(OpCodes.Ldsfld, _imports.ObjectFieldRef)); ilProcessor.Append(Instruction.Create(OpCodes.Callvirt, _imports.PropertyMapIsUriRef)); }
private void InjectUriStringTerm(ILProcessor il, string uriString, MethodReference method) { il.Append(Instruction.Create(OpCodes.Ldstr, uriString)); il.Append(Instruction.Create(OpCodes.Newobj, _imports.UriStringConstructorRef)); il.Append(Instruction.Create(OpCodes.Callvirt, method)); }
private void InjectQNameTerm(ILProcessor il, string prefix, string termName, MethodReference method) { il.Append(Instruction.Create(OpCodes.Ldstr, prefix)); il.Append(Instruction.Create(OpCodes.Ldstr, termName)); il.Append(Instruction.Create(OpCodes.Callvirt, method)); }
private static void EmitIsDivisibleBy(ILProcessor processor, int divisor, VariableDefinition storageVariable) { var skipSetFlag = processor.Create(OpCodes.Nop); processor.Emit(OpCodes.Ldarg_1); processor.Emit(OpCodes.Ldc_I4, divisor); processor.Emit(OpCodes.Rem); // var isDivisible = remainder == 0; processor.Emit(OpCodes.Brfalse, skipSetFlag); processor.Emit(OpCodes.Ldc_I4_1); processor.Emit(OpCodes.Stloc, storageVariable); processor.Append(skipSetFlag); }
private void GenerateCommandDelegate(ILProcessor awakeWorker, MethodReference registerMethod, MethodDefinition func, FieldReference field) { awakeWorker.Append(awakeWorker.Create(OpCodes.Ldtoken, this.m_td)); awakeWorker.Append(awakeWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldsfld, field)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldnull)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldftn, func)); awakeWorker.Append(awakeWorker.Create(OpCodes.Newobj, Weaver.CmdDelegateConstructor)); awakeWorker.Append(awakeWorker.Create(OpCodes.Call, registerMethod)); }
static int EmitParameters(MethodDefinition method, MethodBody body, ILProcessor il) { int i; for (i = 0; i < method.Parameters.Count; i++) { var p = method.Module.Import(method.Parameters[i].ParameterType); il.Emit(OpCodes.Ldarg, i); if (p.Name == "StringBuilder") { // void GetShaderInfoLog(..., StringBuilder foo) // IntPtr foo_sb_ptr; // try { // foo_sb_ptr = Marshal.AllocHGlobal(sb.Capacity + 1); // glGetShaderInfoLog(..., foo_sb_ptr); // MarshalPtrToStringBuilder(foo_sb_ptr, sb); // } // finally { // Marshal.FreeHGlobal(sb_ptr); // } // Make sure we have imported StringBuilder::Capacity and Marshal::AllocHGlobal var sb_get_capacity = method.Module.Import(TypeStringBuilder.Methods.First(m => m.Name == "get_Capacity")); var alloc_hglobal = method.Module.Import(TypeMarshal.Methods.First(m => m.Name == "AllocHGlobal")); // IntPtr ptr; var variable_name = p.Name + " _sb_ptr"; body.Variables.Add(new VariableDefinition(variable_name, TypeIntPtr)); int index = body.Variables.Count - 1; // ptr = Marshal.AllocHGlobal(sb.Capacity + 1); il.Emit(OpCodes.Callvirt, sb_get_capacity); il.Emit(OpCodes.Call, alloc_hglobal); il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldloc, index); // We'll emit the try-finally block in the epilogue implementation, // because we haven't yet emitted all necessary instructions here. } else if (p.Name == "String" && !p.IsArray) { EmitStringParameter(method, p, body, il); } else if (p.IsByReference) { body.Variables.Add(new VariableDefinition(new PinnedType(p))); var index = body.Variables.Count - 1; il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldloc, index); il.Emit(OpCodes.Conv_I); } else if (p.IsArray) { if (p.Name != method.Module.Import(typeof(string[])).Name) { // Pin the array and pass the address // of its first element. var element_type = p.GetElementType(); body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type)))); int pinned_index = body.Variables.Count - 1; var empty = il.Create(OpCodes.Ldc_I4, 0); var pin = il.Create(OpCodes.Ldarg, i); var end = il.Create(OpCodes.Stloc, pinned_index); // if (array == null) goto empty il.Emit(OpCodes.Brfalse, empty); // else if (array.Length != 0) goto pin il.Emit(OpCodes.Ldarg, i); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Brtrue, pin); // empty: IntPtr ptr = IntPtr.Zero il.Append(empty); il.Emit(OpCodes.Conv_U); il.Emit(OpCodes.Br, end); // pin: &array[0] il.Append(pin); il.Emit(OpCodes.Ldc_I4, 0); il.Emit(OpCodes.Ldelema, element_type); // end: fixed (IntPtr ptr = &array[0]) il.Append(end); il.Emit(OpCodes.Ldloc, pinned_index); il.Emit(OpCodes.Conv_I); } else { EmitStringArrayParameter(method, p, body, il); } } } return i; }
private void InstrumentInstructions(ILProcessor il, IList<Instruction> instructions, int numberOfReplacedInstructions, Action<ILProcessor> loadInvocation) { var seekDepth = numberOfReplacedInstructions - 1; // Now add all the instructions back, but transforming this.Invocation() if present for (var i = 0; i < instructions.Count; i++) { var instruction = instructions[i]; var nextInstruction = i < instructions.Count - seekDepth ? instructions[i + seekDepth] : null; if (nextInstruction != null && nextInstruction.OpCode == OpCodes.Call) { var methodReference = (MethodReference)nextInstruction.Operand; if (methodReference.FullName == "SexyProxy.Invocation SexyProxy.ProxyExtensions::Invocation(SexyProxy.IReverseProxy)") { // Insert reference to invocation loadInvocation(il); i += seekDepth; continue; } } il.Append(instruction); } }
static int EmitParameters(MethodDefinition method, MethodDefinition native, MethodBody body, ILProcessor il) { int i; for (i = 0; i < method.Parameters.Count; i++) { var parameter = method.Parameters[i]; var p = method.Module.Import(method.Parameters[i].ParameterType); il.Emit(OpCodes.Ldarg, i); if (p.Name.Contains("Int32") && native.Parameters[i].ParameterType.Name.Contains("IntPtr")) { // This is a convenience Int32 overload for an IntPtr (size_t) parameter. // We need to convert the loaded argument to IntPtr. il.Emit(OpCodes.Conv_I); } else if (p.Name == "StringBuilder") { EmitStringBuilderParameter(method, parameter, body, il); } else if (p.Name == "String" && !p.IsArray) { EmitStringParameter(method, parameter, body, il); } else if (p.IsByReference) { body.Variables.Add(new VariableDefinition(new PinnedType(p))); var index = body.Variables.Count - 1; il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldloc, index); il.Emit(OpCodes.Conv_I); } else if (p.IsArray) { if (p.Name != method.Module.Import(typeof(string[])).Name) { // .Net treats 1d arrays differently than higher rank arrays. // 1d arrays are directly supported by instructions such as ldlen and ldelema. // Higher rank arrays must be accessed through System.Array methods such as get_Length. // 1d array: // check array is not null // check ldlen array > 0 // ldc.i4.0 // ldelema // 2d array: // check array is not null // check array.get_Length() > 0 // ldc.i4.0 // ldc.i4.0 // call instance T& T[0..., 0...]::Address(int32, int32) // Mono treats everything as a 1d array. // Interestingly, the .Net approach works on both Mono and .Net. // The Mono approach fails when using high-rank arrays on .Net. // We should report a bug to http://bugzilla.xamarin.com // Pin the array and pass the address // of its first element. var array = (ArrayType)p; var element_type = p.GetElementType(); body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type)))); int pinned_index = body.Variables.Count - 1; var empty = il.Create(OpCodes.Ldc_I4, 0); var pin = il.Create(OpCodes.Ldarg, i); var end = il.Create(OpCodes.Stloc, pinned_index); // if (array == null) goto empty il.Emit(OpCodes.Brfalse, empty); // else if (array.Length != 0) goto pin il.Emit(OpCodes.Ldarg, i); if (array.Rank == 1) { il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); } else { var get_length = method.Module.Import( mscorlib.MainModule.GetType("System.Array").Methods.First(m => m.Name == "get_Length")); il.Emit(OpCodes.Callvirt, get_length); } il.Emit(OpCodes.Brtrue, pin); // empty: IntPtr ptr = IntPtr.Zero il.Append(empty); il.Emit(OpCodes.Conv_U); il.Emit(OpCodes.Br, end); // pin: &array[0] il.Append(pin); if (array.Rank == 1) { // 1d array (vector), address is taken by ldelema il.Emit(OpCodes.Ldc_I4, 0); il.Emit(OpCodes.Ldelema, element_type); } else { // 2d-3d array, address must be taken as follows: // call instance T& T[0..., 0..., 0...]::Address(int, int, int) ByReferenceType t_ref = array.ElementType.MakeByReferenceType(); MethodReference get_address = new MethodReference("Address", t_ref, array); for (int r = 0; r < array.Rank; r++) { get_address.Parameters.Add(new ParameterDefinition(TypeInt32)); } get_address.HasThis = true; // emit the get_address call for (int r = 0; r < array.Rank; r++) { il.Emit(OpCodes.Ldc_I4, 0); } il.Emit(OpCodes.Call, get_address); } // end: fixed (IntPtr ptr = &array[0]) il.Append(end); il.Emit(OpCodes.Ldloc, pinned_index); il.Emit(OpCodes.Conv_I); } else { EmitStringArrayParameter(method, parameter, body, il); } } } return i; }
/// <summary> /// Emits the instructions that will instantiate each property value and assign it to the target property. /// </summary> /// <param name="serviceMap">The service map that contains the application dependencies.</param> /// <param name="targetMethod">The target method.</param> /// <param name="module">The module that hosts the container type.</param> /// <param name="il">The <see cref="ILProcessor"/> that points to the target method body.</param> /// <param name="property">The target property.</param> /// <param name="curentDependency">The <see cref="IDependency"/> that describes the service instance that will be assigned to the target property.</param> private static void EmitPropertySetter(IDictionary<IDependency, IImplementation> serviceMap, MethodDefinition targetMethod, ModuleDefinition module, ILProcessor il, PropertyInfo property, IDependency curentDependency) { // Push the target onto the stack il.Emit(OpCodes.Dup); // Get the code that will instantiate the property value var propertyValueImplementation = serviceMap[curentDependency]; propertyValueImplementation.Emit(curentDependency, serviceMap, targetMethod); // Call the setter var setterMethod = property.GetSetMethod(); var setter = module.Import(setterMethod); var callInstruction = setterMethod.IsVirtual ? il.Create(OpCodes.Callvirt, setter) : il.Create(OpCodes.Call, setter); il.Append(callInstruction); }
private static void WriteServerActiveCheck(ILProcessor worker, string mdName, Instruction label, string errString) { worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkServerGetActive)); worker.Append(worker.Create(OpCodes.Brtrue, label)); worker.Append(worker.Create(OpCodes.Ldstr, errString + " " + mdName + " called on client.")); worker.Append(worker.Create(OpCodes.Call, Weaver.logErrorReference)); worker.Append(worker.Create(OpCodes.Ret)); worker.Append(label); }
static void EmitDebugEpilogue(MethodDefinition wrapper, ILProcessor il, DebugVariables vars) { if (vars != null) { var disposeMethod = vars.ErrorHelperType.Methods.First( method => method.Name == "Dispose"); // Store then reload the result from the call var resultLocal = new VariableDefinition(wrapper.ReturnType); if (resultLocal.VariableType.FullName != Program.TypeVoid.FullName) { il.Body.Variables.Add(resultLocal); il.Emit(OpCodes.Stloc, resultLocal); } // Special case End to turn on error checking. if (il.Body.Method.Name == "End") { il.Emit(OpCodes.Call, vars.Get_CurrentContext); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Conv_I1); il.Emit(OpCodes.Call, vars.Set_ErrorChecking); } // We need a NOP to set up the finally handler range correctly. var nopInstruction = Instruction.Create(OpCodes.Nop); var loadInstruction = Instruction.Create(OpCodes.Ldloca, vars.ErrorHelperLocal); var disposeInstruction = Instruction.Create(OpCodes.Call, disposeMethod); var endFinallyInstruction = Instruction.Create(OpCodes.Endfinally); var endTryInstruction = Instruction.Create(OpCodes.Leave, nopInstruction); il.Append(endTryInstruction); il.Append(loadInstruction); il.Append(disposeInstruction); il.Append(endFinallyInstruction); il.Append(nopInstruction); var finallyHandler = new ExceptionHandler(ExceptionHandlerType.Finally); finallyHandler.TryStart = vars.BeginTry; finallyHandler.TryEnd = loadInstruction; finallyHandler.HandlerStart = loadInstruction; finallyHandler.HandlerEnd = nopInstruction; il.Body.ExceptionHandlers.Add(finallyHandler); if (resultLocal.VariableType.FullName != Program.TypeVoid.FullName) { il.Emit(OpCodes.Ldloc, resultLocal); } } }
/// <summary> /// Injects the anti reflector code. /// </summary> /// <param name="il">The il builder.</param> /// <param name="first">The first instruction to use.</param> private static void InjectAntiReflectorCode(ILProcessor il, Instruction first) { il.Append(il.Create(OpCodes.Br_S, first)); il.Append(ConfuseDecompilationTask.CreateInvalidOpCode()); il.Append(ConfuseDecompilationTask.CreateInvalidOpCode()); il.Append(first); }
private static void Emit(ILProcessor ip, ModuleDefinition mod, VariableDefinition arrayVar, VariableDefinition indexVar, Dictionary<int, Instruction> braces, OpValue[] ops, int i) { OpValue op = ops[i]; switch (op.OpCode) { case BFOpCode.Increment: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Add); ip.Emit(OpCodes.Stelem_I4); break; case BFOpCode.Decrement: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Sub); ip.Emit(OpCodes.Stelem_I4); break; case BFOpCode.ShiftRight: ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Add); ip.Emit(OpCodes.Stloc, indexVar); break; case BFOpCode.ShiftLeft: ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Sub); ip.Emit(OpCodes.Stloc, indexVar); break; case BFOpCode.Output: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Conv_I1); ip.Emit(OpCodes.Call, mod.Import(typeof(Console).GetMethod("Write", new[] { typeof(char) }))); break; case BFOpCode.Input: ip.Emit(OpCodes.Call, mod.Import(typeof(Console).GetMethod("Read", new Type[0]))); ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Conv_I1); break; case BFOpCode.CondLeft: var leftB = ip.Create(OpCodes.Ldloc, arrayVar); var rightB = ip.Create(OpCodes.Nop); ip.Append(leftB); braces[i] = leftB; braces[op.Data] = rightB; ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldelem_I4); ip.Emit(OpCodes.Brfalse, rightB); ip.Emit(OpCodes.Nop); break; case BFOpCode.CondRight: ip.Emit(OpCodes.Br, braces[op.Data]); ip.Append(braces[i]); break; case BFOpCode.Assign: ip.Emit(OpCodes.Ldloc, arrayVar); ip.Emit(OpCodes.Ldloc, indexVar); ip.Emit(OpCodes.Ldc_I4, op.Data); ip.Emit(OpCodes.Stelem_I4); break; } }
protected virtual void ImplementBody(ILProcessor il, FieldReference methodInfoField, FieldReference propertyInfoField, MethodReference proceed, MethodReference proceedTargetMethod) { // Allow the InvocationHandler to opt out of handling (for perf) var notOptedOut = il.Create(OpCodes.Nop); EmitInvocationHandler(il); // Load handler il.Emit(OpCodes.Ldarg_0); // Load this il.Emit(OpCodes.Ldsfld, methodInfoField); // Load the MethodInfo onto the stack if (propertyInfoField == null) il.Emit(OpCodes.Ldnull); // Not a property so load null onto the stack else il.Emit(OpCodes.Ldsfld, propertyInfoField); // Load the PropertyInfo onto the stack il.Emit(OpCodes.Call, ClassWeaver.Context.InvocationHandlerIsHandlerActive); // Call InvocationHandler.IsHandlerActive and leave the bool result on the stack il.Emit(OpCodes.Brtrue, notOptedOut); // If they didn't opt out (returned true), jump to the normal interception logic below ImplementOptOut(il, proceedTargetMethod); // They opted out, so do an implicit (and efficient) equivalent of proceed il.Append(notOptedOut); EmitCallToInvocationHandler(il, methodInfoField, propertyInfoField, proceed); // Return il.Emit(OpCodes.Ret); }
public void EmitToString(Application app, Page page, ILProcessor processor, TypeReference resolved) { if (resolved.FullName == "System.String") return; if (resolved.FullName == "System.Void") { processor.Emit (OpCodes.Ldsfld, application.CommonMethods.StringEmptyField); return; } if (resolved.IsValueType) { processor.Emit (OpCodes.Box, app.Assembly.MainModule.Import (resolved)); processor.Emit (OpCodes.Call, app.Assembly.MainModule.Import (page.ValueToStringMethod)); return; } TypeDefinition rtype = resolved.Resolve (); MethodReference method = rtype.Methods.Where (m => m.Name == "ToString").First (); // Import it so we get a method reference method = application.Assembly.MainModule.Import (method); Instruction inst = processor.Create (OpCodes.Callvirt, (MethodReference) method); processor.Append (inst); }
private static void WriteCreateWriter(ILProcessor worker) { worker.Append(worker.Create(OpCodes.Newobj, Weaver.NetworkWriterCtor)); worker.Append(worker.Create(OpCodes.Stloc_0)); worker.Append(worker.Create(OpCodes.Ldloc_0)); }