public MetadataToken GetStandAloneSignature(Mono.Cecil.CallSite call_site) { MetadataToken standAloneSignatureToken = this.GetStandAloneSignatureToken(this.metadata.GetCallSiteBlobIndex(call_site)); call_site.MetadataToken = standAloneSignatureToken; return(standAloneSignatureToken); }
/// <summary> /// Patches the method. /// </summary> /// <param name="method">The method.</param> void PatchMethod(MethodDefinition method) { if (method.HasBody) { var ilProcessor = method.Body.GetILProcessor(); var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference) { var methodDescription = (MethodReference)instruction.Operand; if (methodDescription.Name.StartsWith("Calli") && methodDescription.DeclaringType.Name == "LocalInterop") { var callSite = new CallSite(methodDescription.ReturnType) { CallingConvention = MethodCallingConvention.StdCall }; if (methodDescription.Name.StartsWith("CalliCdecl")) { callSite.CallingConvention = MethodCallingConvention.C; } else if (methodDescription.Name.StartsWith("CalliThisCall")) { callSite.CallingConvention = MethodCallingConvention.ThisCall; } else if (methodDescription.Name.StartsWith("CalliStdCall")) { callSite.CallingConvention = MethodCallingConvention.StdCall; } else if (methodDescription.Name.StartsWith("CalliFastCall")) { callSite.CallingConvention = MethodCallingConvention.FastCall; } // Last parameter is the function ptr, so we don't add it as a parameter for calli // as it is already an implicit parameter for calli for (int j = 0; j < methodDescription.Parameters.Count - 1; j++) { var parameterDefinition = methodDescription.Parameters[j]; callSite.Parameters.Add(parameterDefinition); } // Create calli Instruction var callIInstruction = ilProcessor.Create(OpCodes.Calli, callSite); // Replace instruction ilProcessor.Replace(instruction, callIInstruction); } } } } }
private FunctionSignature CreateFunctionSignature(MethodReference context, CallSite callSite) { var numParams = callSite.Parameters.Count; if (callSite.HasThis) numParams++; var parameterTypes = new Type[numParams]; var parameterTypesLLVM = new TypeRef[numParams]; for (int index = 0; index < numParams; index++) { TypeReference parameterTypeReference; var parameter = callSite.Parameters[index]; parameterTypeReference = ResolveGenericsVisitor.Process(context, parameter.ParameterType); var parameterType = CreateType(parameterTypeReference); if (parameterType.DefaultType.Value == IntPtr.Zero) throw new InvalidOperationException(); parameterTypes[index] = parameterType; parameterTypesLLVM[index] = parameterType.DefaultType; } var returnType = CreateType(ResolveGenericsVisitor.Process(context, context.ReturnType)); return new FunctionSignature(returnType, parameterTypes); }
private MethodReference CreateDispatcher(AssemblyDefinition assembly, MethodReference method) { var updateEngineType = GetOrCreateUpdateType(assembly, true); var dispatcherMethod = new MethodDefinition($"Dispatcher_{method.Name}", MethodAttributes.HideBySig | MethodAttributes.Assembly | MethodAttributes.Static, assembly.MainModule.ImportReference(method.ReturnType)); updateEngineType.Methods.Add(dispatcherMethod); dispatcherMethod.Parameters.Add(new ParameterDefinition("this", Mono.Cecil.ParameterAttributes.None, method.DeclaringType)); foreach (var param in method.Parameters) { dispatcherMethod.Parameters.Add(new ParameterDefinition(param.Name, param.Attributes, param.ParameterType)); } var il = dispatcherMethod.Body.GetILProcessor(); il.Emit(OpCodes.Ldarg_0); foreach (var param in dispatcherMethod.Parameters.Skip(1)) // first parameter is "this" { il.Emit(OpCodes.Ldarg, param); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldvirtftn, method); var callsite = new Mono.Cecil.CallSite(method.ReturnType) { HasThis = true }; foreach (var param in method.Parameters) { callsite.Parameters.Add(param); } il.Emit(OpCodes.Calli, callsite); il.Emit(OpCodes.Ret); return(dispatcherMethod); }
public Unit VisitInlineSig(Instruction instruction, CallSite operand) { MarkLabel(instruction); throw new NotImplementedException(); }
/// <summary> /// Patches the method. /// </summary> /// <param name="method">The method.</param> void PatchMethod(MethodDefinition method) { var attributes = GetSharpGenAttributes(method); if (attributes.Contains(GlobalNamespace + ".ModuleInit")) { CreateModuleInit(method); } if (method.DeclaringType.Name == "Interop") { if (method.Name == "memcpy") { CreateMemcpy(method); } else if (method.Name == "memset") { CreateMemset(method); } else if ((method.Name == "Cast") || (method.Name == "CastOut")) { CreateCastMethod(method); } else if (method.Name == "CastArray") { CreateCastArrayMethod(method); } else if (method.Name == "Read" || (method.Name == "ReadOut") || (method.Name == "Read2D")) { if (method.Parameters.Count == 2) { CreateReadMethod(method); } else { CreateReadRangeMethod(method); } } else if (method.Name == "Write" || (method.Name == "Write2D")) { if (method.Parameters.Count == 2) { CreateWriteMethod(method); } else { CreateWriteRangeMethod(method); } } } else if (method.HasBody) { var ilProcessor = method.Body.GetILProcessor(); var instructions = method.Body.Instructions; Instruction instruction = null; Instruction previousInstruction; for (int i = 0; i < instructions.Count; i++) { previousInstruction = instruction; instruction = instructions[i]; if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference) { var methodDescription = (MethodReference)instruction.Operand; if (methodDescription.Name.StartsWith("Calli") && methodDescription.DeclaringType.Name == "LocalInterop") { var callSite = new CallSite(methodDescription.ReturnType) { CallingConvention = MethodCallingConvention.StdCall }; if (methodDescription.Name.StartsWith("CalliCdecl")) { callSite.CallingConvention = MethodCallingConvention.C; } else if (methodDescription.Name.StartsWith("CalliThisCall")) { callSite.CallingConvention = MethodCallingConvention.ThisCall; } else if (methodDescription.Name.StartsWith("CalliStdCall")) { callSite.CallingConvention = MethodCallingConvention.StdCall; } else if (methodDescription.Name.StartsWith("CalliFastCall")) { callSite.CallingConvention = MethodCallingConvention.FastCall; } // Last parameter is the function ptr, so we don't add it as a parameter for calli // as it is already an implicit parameter for calli for (int j = 0; j < methodDescription.Parameters.Count - 1; j++) { var parameterDefinition = methodDescription.Parameters[j]; callSite.Parameters.Add(parameterDefinition); } // Create calli Instruction var callIInstruction = ilProcessor.Create(OpCodes.Calli, callSite); // Replace instruction ilProcessor.Replace(instruction, callIInstruction); } else if (methodDescription.DeclaringType.Name == "Interop") { if (methodDescription.FullName.Contains("Fixed")) { if (methodDescription.Parameters[0].ParameterType.IsArray) { ReplaceFixedArrayStatement(method, ilProcessor, instruction); } else { ReplaceFixedStatement(method, ilProcessor, instruction); } } else if (methodDescription.Name.StartsWith("ReadInline")) { ReplaceReadInline(method, ilProcessor, instruction); } else if (methodDescription.Name.StartsWith("CopyInline") || methodDescription.Name.StartsWith("WriteInline")) { ReplaceCopyInline(method, ilProcessor, instruction); } else if (methodDescription.Name.StartsWith("SizeOf")) { ReplaceSizeOfStructGeneric(method, ilProcessor, instruction); } } } } } }
private static MethodDefinition InflateMethod(TypeDefinition inflatedType, MethodDefinition method, ResolveGenericsVisitor resolveGenericsVisitor) { var clonedMethod = new MethodDefinition(method.Name, method.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(method.ReturnType))); clonedMethod.Parameters.AddRange( method.Parameters.Select(x => new ParameterDefinition(x.Name, x.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x.ParameterType))))); if (method.Body != null) { clonedMethod.Body.Variables.AddRange( method.Body.Variables.Select(x => new VariableDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x.VariableType))))); clonedMethod.Body.InitLocals = method.Body.InitLocals; var mappedInstructions = new Dictionary <Instruction, Instruction>(); foreach (var instruction in method.Body.Instructions) { // Create nop instructions to start with (if we use actual opcode, it would do an operand check) var mappedInstruction = Instruction.Create(OpCodes.Nop); mappedInstruction.OpCode = instruction.OpCode; mappedInstruction.Operand = instruction.Operand; mappedInstructions[instruction] = mappedInstruction; } foreach (var instruction in method.Body.Instructions) { // Fix operand var mappedInstruction = mappedInstructions[instruction]; if (mappedInstruction.Operand is Instruction) { mappedInstruction.Operand = mappedInstructions[(Instruction)instruction.Operand]; } else if (mappedInstruction.Operand is ParameterDefinition) { var parameterIndex = method.Parameters.IndexOf((ParameterDefinition)instruction.Operand); mappedInstruction.Operand = clonedMethod.Parameters[parameterIndex]; } else if (mappedInstruction.Operand is VariableDefinition) { var variableIndex = method.Body.Variables.IndexOf((VariableDefinition)instruction.Operand); mappedInstruction.Operand = clonedMethod.Body.Variables[variableIndex]; } else if (mappedInstruction.Operand is TypeReference) { var newTypeReference = resolveGenericsVisitor.VisitDynamic((TypeReference)mappedInstruction.Operand); newTypeReference = inflatedType.Module.ImportReference(newTypeReference); mappedInstruction.Operand = newTypeReference; } else if (mappedInstruction.Operand is FieldReference) { var fieldReference = (FieldReference)mappedInstruction.Operand; var newFieldReference = new FieldReference(fieldReference.Name, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(fieldReference.FieldType)), inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(fieldReference.DeclaringType))); mappedInstruction.Operand = newFieldReference; } else if (mappedInstruction.Operand is MethodReference) { var methodReference = (MethodReference)mappedInstruction.Operand; var genericInstanceMethod = methodReference as GenericInstanceMethod; if (genericInstanceMethod != null) { methodReference = genericInstanceMethod.ElementMethod; } methodReference = methodReference.GetElementMethod(); var newMethodReference = new MethodReference(methodReference.Name, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(methodReference.ReturnType)), inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(methodReference.DeclaringType))) { HasThis = methodReference.HasThis, ExplicitThis = methodReference.ExplicitThis, CallingConvention = methodReference.CallingConvention, }; foreach (var parameter in methodReference.Parameters) { newMethodReference.Parameters.Add(new ParameterDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(parameter.ParameterType)))); } if (methodReference.HasGenericParameters) { CopyGenericParameters(methodReference, newMethodReference); } if (genericInstanceMethod != null) { newMethodReference = newMethodReference.MakeGenericMethod(genericInstanceMethod.GenericArguments.Select(x => inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x))).ToArray()); } mappedInstruction.Operand = newMethodReference; } else if (mappedInstruction.Operand is Mono.Cecil.CallSite) { var callSite = (Mono.Cecil.CallSite)mappedInstruction.Operand; var newCallSite = new Mono.Cecil.CallSite(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(callSite.ReturnType))) { HasThis = callSite.HasThis, ExplicitThis = callSite.ExplicitThis, CallingConvention = callSite.CallingConvention, }; foreach (var parameter in callSite.Parameters) { newCallSite.Parameters.Add(new ParameterDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(parameter.ParameterType)))); } mappedInstruction.Operand = newCallSite; } else if (mappedInstruction.Operand is Instruction[]) { // Not used in UpdatableProperty<T> throw new NotImplementedException(); } } clonedMethod.Body.Instructions.AddRange(method.Body.Instructions.Select(x => mappedInstructions[x])); } return(clonedMethod); }
private void ProcessMethod(MethodDefinition method) { if (method.HasBody) { ILProcessor ilProcessor = method.Body.GetILProcessor(); //process every instruction of the methods body for (int n = 0; n < ilProcessor.Body.Instructions.Count; n++) //foreach won't work because iterator length is bigger than count?? { var instruction = ilProcessor.Body.Instructions[n]; //check whether the instruction is a call to a method if (instruction.OpCode.Code == Code.Call && instruction.Operand is MethodReference) { //get the called method MethodReference methodDescription = (MethodReference)instruction.Operand; //get the attributes of the called method var attributes = GetAttributes(methodDescription.Resolve()); //check whether the called method is marked with the given calli attribute if (attributes.Contains(_calliAttributeName)) { //MessageIntegration.Info("Patching [{0}] @ [{1}].", method.ToString(), instruction.ToString()); if (!method.Name.EndsWith("Native")) MessageIntegration.Info(String.Format("CallI-Comimport Methodnames should end with a \"Native\". Method: \"{0}\".", method.FullName)); //create a callsite for the calli instruction using stdcall calling convention var callSite = new CallSite(methodDescription.ReturnType) { CallingConvention = MethodCallingConvention.StdCall }; //iterate through every parameter of the original method-call for (int j = 0; j < methodDescription.Parameters.Count - 1; j++) //foreach won't work because iterator length is bigger than count?? { var p = methodDescription.Parameters[j]; if (p.ParameterType.FullName == "System.Boolean") { MessageIntegration.WriteWarning("Native bool has a size of 4 bytes. Make sure to use a 16bit Integer for \"VARIANT_BOOL\" and a 32bit Integer for \"BOOL\".", "CI0001"); } //append every parameter of the method-call to the callsite of the calli instruction callSite.Parameters.Add(p); } //create a calli-instruction including the just built callSite var calliInstruction = ilProcessor.Create(OpCodes.Calli, callSite); //replace the method-call by the calli-instruction ilProcessor.Replace(instruction, calliInstruction); _replacedCallsCount++; } } } } }
/// <summary> /// Patches the Method. /// </summary> /// <param name="Method">The Method.</param> Boolean PatchMethod(MethodDefinition Method) { Boolean IsSharpJit = false; List<String> Attributes = this.GetSharpDXAttributes(Method); if (Attributes.Contains("SharpDX.ModuleInit")) { CreateModuleInit(Method); } if (Method.DeclaringType.Name == "Interop") { if (Method.Name == "memcpy") { CreateMemcpy(Method); } else if (Method.Name == "memset") { CreateMemset(Method); } else if ((Method.Name == "Cast") || (Method.Name == "CastOut")) { CreateCastMethod(Method); } else if (Method.Name == "CastArray") { CreateCastArrayMethod(Method); } else if (Method.Name == "Read" || (Method.Name == "ReadOut") || (Method.Name == "Read2D")) { if (Method.Parameters.Count == 2) CreateReadMethod(Method); else CreateReadRangeMethod(Method); } else if (Method.Name == "Write" || (Method.Name == "Write2D")) { if (Method.Parameters.Count == 2) CreateWriteMethod(Method); else CreateWriteRangeMethod(Method); } } else if (Method.HasBody) { ILProcessor IlProcessor = Method.Body.GetILProcessor(); Collection<Instruction> instructions = Method.Body.Instructions; Instruction Instruction = null; Instruction previousInstruction; for (Int32 Index = 0; Index < instructions.Count; Index++) { previousInstruction = Instruction; Instruction = instructions[Index]; if (Instruction.OpCode != OpCodes.Call || !(Instruction.Operand is MethodReference)) continue; MethodReference MethodDescription = (MethodReference)Instruction.Operand; if (MethodDescription is MethodDefinition) { foreach (CustomAttribute CustomAttribute in ((MethodDefinition)MethodDescription).CustomAttributes) { if (CustomAttribute.AttributeType.FullName == typeof(ObfuscationAttribute).FullName) { foreach (Mono.Cecil.CustomAttributeNamedArgument Arg in CustomAttribute.Properties) { if (Arg.Name == "Feature" && Arg.Argument.Value != null) { var customValue = Arg.Argument.Value.ToString(); if (customValue.StartsWith("SharpJit.")) { IsSharpJit = true; break; } } } } if (IsSharpJit) break; } } if (!IsSharpJit) { if (MethodDescription.Name.StartsWith("Calli") && MethodDescription.DeclaringType.Name == "LocalInterop") { CallSite CallSite = new CallSite(MethodDescription.ReturnType) { CallingConvention = MethodCallingConvention.StdCall }; // Last parameter is the function ptr, so we don't add it as a parameter for calli // as it is already an implicit parameter for calli for (Int32 ParameterIndex = 0; ParameterIndex < MethodDescription.Parameters.Count - 1; ParameterIndex++) { ParameterDefinition ParameterDefinition = MethodDescription.Parameters[ParameterIndex]; CallSite.Parameters.Add(ParameterDefinition); } // Create calli Instruction Instruction CallIInstruction = IlProcessor.Create(OpCodes.Calli, CallSite); // Replace instruction IlProcessor.Replace(Instruction, CallIInstruction); } else if (MethodDescription.DeclaringType.Name == "Interop") { if (MethodDescription.FullName.Contains("Fixed")) { if (MethodDescription.Parameters[0].ParameterType.IsArray) { ReplaceFixedArrayStatement(Method, IlProcessor, Instruction); } else { ReplaceFixedStatement(Method, IlProcessor, Instruction); } } else if (MethodDescription.Name.StartsWith("ReadInline")) { this.ReplaceReadInline(Method, IlProcessor, Instruction); } else if (MethodDescription.Name.StartsWith("CopyInline") || MethodDescription.Name.StartsWith("WriteInline")) { this.ReplaceCopyInline(Method, IlProcessor, Instruction); } else if (MethodDescription.Name.StartsWith("SizeOf")) { this.ReplaceSizeOfStructGeneric(Method, IlProcessor, Instruction); } } } } } return IsSharpJit; }
static void PatchMethod(MethodDefinition method) { if( !method.HasBody ) return; var ilProcessor = method.Body.GetILProcessor(); var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference) { var desc = (MethodReference)instruction.Operand; if( desc.DeclaringType.Name != "Interop" ) continue; if( desc.Name.StartsWith( "Calli" ) ) { var callSite = new CallSite(desc.ReturnType) { CallingConvention = MethodCallingConvention.StdCall }; // Last parameter is the function ptr, so we don't add it as a parameter for calli // as it is already an implicit parameter for calli for (int j = 0; j < desc.Parameters.Count - 1; j++) { callSite.Parameters.Add(desc.Parameters[j]); } var callIInstruction = ilProcessor.Create(OpCodes.Calli, callSite); ilProcessor.Replace(instruction, callIInstruction); } else if( desc.Name.StartsWith( "Fixed" ) ) { ReplaceFixedStatement(method, ilProcessor, instruction); } } } }
public CallSite readCallSite() { var returnType = readTypeReference(); var paramTypes = readTypeReferences(); var callingConvention = (CallingConvention)reader.ReadInt32(); var cs = new CallSite(returnType); foreach (var paramType in paramTypes) cs.Parameters.Add(new ParameterDefinition(paramType)); cs.CallingConvention = convertCallingConvention(callingConvention); return cs; }
private MethodBody GenerateDelegateMethod(MethodDefinition method, Class declaringClass) { // Delegate type var delegateType = corlib.MainModule.GetType(typeof(Delegate).FullName); // Delegate fields var targetField = delegateType.Fields.First(x => x.Name == "_target"); var methodPtrField = delegateType.Fields.First(x => x.Name == "_methodPtr"); var methodPtrAuxField = delegateType.Fields.First(x => x.Name == "_methodPtrAux"); var body = new MethodBody(method); var il = body.GetILProcessor(); if (method.Name == ".ctor") { // Mark //GenerateMulticastInvokeThunk(declaringClass); // Two main cases: // - Instance method: // this._methodPtr = fnptr; // this._target = target; // Result: this._methodPtr(this._target, arg1, ..) will directly work // - Static method: // this._target = this; // this._methodPtrAux = fnptr; // this._methodPtr = (delegate, arg1, ...) => { delegate->_methodPtrAux(arg1, ...); } // Result: this._methodPtr(this._target, arg1, ...) will call thunk, // which will call fnptr (from this._target._methodPtr) without the first argument var target = Instruction.Create(OpCodes.Ldarg_0); // if (target == null) // { il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[0])); il.Append(Instruction.Create(OpCodes.Brtrue, target)); // Generate thunk (for now, done using direct LLVM, not sure weither LLVM or IL is better) // this._methodPtr = (delegate, arg1, ...) => { delegate->_methodPtrAux(arg1, ...); } var invokeMethodHelper = GenerateStaticInvokeThunk(declaringClass); // Fake Nop to push this thunk on stack (TODO: Better way to do this? i.e. store it in some static field?) il.Append(Instruction.Create(OpCodes.Ldarg_0)); var loadFunctionPointerInstruction = Instruction.Create(OpCodes.Nop); InstructionActions.Add(loadFunctionPointerInstruction, (stack) => { // Push the generated method pointer on the stack stack.Add(new StackValue(StackValueType.NativeInt, intPtr, LLVM.BuildPointerCast(builder, invokeMethodHelper, intPtrLLVM, string.Empty))); }); il.Append(loadFunctionPointerInstruction); il.Append(Instruction.Create(OpCodes.Stfld, methodPtrField)); // this._methodPtrAux = method; il.Append(Instruction.Create(OpCodes.Ldarg_0)); il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[1])); il.Append(Instruction.Create(OpCodes.Stfld, methodPtrAuxField)); // this._target = this; il.Append(Instruction.Create(OpCodes.Ldarg_0)); il.Append(Instruction.Create(OpCodes.Ldarg_0)); il.Append(Instruction.Create(OpCodes.Stfld, targetField)); // return; // } il.Append(Instruction.Create(OpCodes.Ret)); // this._target = target; il.Append(target); il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[0])); il.Append(Instruction.Create(OpCodes.Stfld, targetField)); // this._methodPtr = method; il.Append(Instruction.Create(OpCodes.Ldarg_0)); il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[1])); il.Append(Instruction.Create(OpCodes.Stfld, methodPtrField)); // return; il.Append(Instruction.Create(OpCodes.Ret)); } else if (method.Name == "GetMulticastDispatchMethod") { var invokeMethodHelper = GenerateMulticastInvokeThunk(declaringClass); var loadFunctionPointerInstruction = Instruction.Create(OpCodes.Nop); InstructionActions.Add(loadFunctionPointerInstruction, (stack) => { // Push the generated method pointer on the stack stack.Add(new StackValue(StackValueType.NativeInt, intPtr, LLVM.BuildPointerCast(builder, invokeMethodHelper, intPtrLLVM, string.Empty))); }); il.Append(loadFunctionPointerInstruction); il.Append(Instruction.Create(OpCodes.Ret)); } else if (method.Name == "Invoke") { // For now, generate IL // Note that we could probably optimize at callsite too, // but probably not necessary if LLVM and sealed class are optimized/inlined well enough // ldarg_0 // ldfld _target il.Append(Instruction.Create(OpCodes.Ldarg_0)); il.Append(Instruction.Create(OpCodes.Ldfld, targetField)); var callsite = new CallSite(method.ReturnType); callsite.Parameters.Add(new ParameterDefinition(targetField.FieldType)); foreach (var parameter in method.Parameters) { callsite.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, parameter.ParameterType)); // ldarg il.Append(Instruction.Create(OpCodes.Ldarg, parameter)); } // ldarg_0 // ldfld _methodPtr il.Append(Instruction.Create(OpCodes.Ldarg_0)); il.Append(Instruction.Create(OpCodes.Ldfld, methodPtrField)); // calli il.Append(Instruction.Create(OpCodes.Calli, callsite)); // ret il.Append(Instruction.Create(OpCodes.Ret)); } else { LLVM.BuildUnreachable(builder); return null; } return body; }
MetadataToken GetCallSiteToken(CallSite cs) { uint sig; int sentinel = cs.GetSentinel (); if (sentinel > 0) sig = m_reflectWriter.SignatureWriter.AddMethodDefSig ( m_reflectWriter.GetMethodDefSig (cs)); else sig = m_reflectWriter.SignatureWriter.AddMethodRefSig ( m_reflectWriter.GetMethodRefSig (cs)); if (m_standaloneSigCache.Contains (sig)) return (MetadataToken) m_standaloneSigCache [sig]; StandAloneSigTable sasTable = m_reflectWriter.MetadataTableWriter.GetStandAloneSigTable (); StandAloneSigRow sasRow = m_reflectWriter.MetadataRowWriter.CreateStandAloneSigRow (sig); sasTable.Rows.Add(sasRow); MetadataToken token = new MetadataToken (TokenType.Signature, (uint) sasTable.Rows.Count); m_standaloneSigCache [sig] = token; return token; }
public void Accept_InlineSigOperand_InvokesVisitor() { var callsite = new CallSite(CecilUtility.Import(typeof(object))); var instruction = Instruction.Create(OpCodes.Calli, callsite); _visitorMock .Setup(visitor => visitor.VisitInlineSig(instruction, callsite)) .Returns(Unit.Value) .Verifiable(); instruction.Accept(_visitorMock.Object); _visitorMock.Verify(); }
private SignatureHelper MapSignature(CallSite signature) { Type returnType = MapReturnType(signature.ReturnType); // TODO... SignatureHelper helper; switch (signature.MetadataToken.TokenType) { /* case TokenType.Method: helper = SignatureHelper.GetMethodSigHelper(module, (System.Reflection.CallingConventions) signature.CallingConvention, returnType); break; case TokenType.Field: helper = SignatureHelper.GetFieldSigHelper(module); break; case TokenType.Param: helper = SignatureHelper.GetLocalVarSigHelper(module); break; case TokenType.Property: helper = SignatureHelper.GetPropertySigHelper(module, returnType, parameterTypes); break; */ default: throw new NotSupportedException(string.Format("Unexpected metadata token type: {0}.", signature.MetadataToken.TokenType)); } return helper; }
private static void GenerateFunctionCall(ModuleDefinition module, MethodDefinition method) { Console.WriteLine("Modifing {0}", method.Name); method.Body.Instructions.Clear(); var gen = method.Body.GetILProcessor(); int paramaters = method.Parameters.Count; for (int arg = 0; arg < paramaters; ++arg) { if (arg == 0) { gen.Emit(OpCodes.Ldarg_0); } else if (arg == 1) { gen.Emit(OpCodes.Ldarg_1); } else if (arg == 2) { gen.Emit(OpCodes.Ldarg_2); } else if (arg == 3) { gen.Emit(OpCodes.Ldarg_3); } else if (arg <= byte.MaxValue) { gen.Emit(OpCodes.Ldarg_S, (byte)arg); } else { gen.Emit(OpCodes.Ldarg, (ushort)arg); } } var intptr = module.Import(typeof(IntPtr)); gen.Emit(OpCodes.Ldsfld, new FieldReference("context", method.DeclaringType, method.DeclaringType)); gen.Emit(OpCodes.Ldfld, new FieldReference("gl" + method.Name, intptr, method.DeclaringType)); var topointer = module.Import(typeof(IntPtr).GetMethod("ToPointer")); var callsite = new CallSite(method.ReturnType); callsite.CallingConvention = MethodCallingConvention.StdCall; foreach (var param in method.Parameters) { var newParam = new ParameterDefinition(param.ParameterType); callsite.Parameters.Add(newParam); } gen.Emit(OpCodes.Calli, callsite); gen.Emit(OpCodes.Ret); }
/// <summary> /// Patches the method. /// </summary> /// <param name="method">The method.</param> bool PatchMethod(MethodDefinition method) { bool isSharpJit = false; var attributes = this.GetSharpDXAttributes(method); if (attributes.Contains("SharpDX.ModuleInit")) { CreateModuleInit(method); } if (method.DeclaringType.Name == "Interop") { if (method.Name == "memcpy") { CreateMemcpy(method); } else if (method.Name == "memset") { CreateMemset(method); } else if ((method.Name == "Cast") || (method.Name == "CastOut")) { CreateCastMethod(method); } else if (method.Name == "CastArray") { CreateCastArrayMethod(method); } else if (method.Name == "Read" || (method.Name == "ReadOut") || (method.Name == "Read2D")) { if (method.Parameters.Count == 2) CreateReadMethod(method); else CreateReadRangeMethod(method); } else if (method.Name == "Write" || (method.Name == "Write2D")) { if (method.Parameters.Count == 2) CreateWriteMethod(method); else CreateWriteRangeMethod(method); } } else if (method.HasBody) { var ilProcessor = method.Body.GetILProcessor(); var instructions = method.Body.Instructions; Instruction instruction = null; Instruction previousInstruction; for (int i = 0; i < instructions.Count; i++) { previousInstruction = instruction; instruction = instructions[i]; if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference) { var methodDescription = (MethodReference)instruction.Operand; if (methodDescription is MethodDefinition) { foreach (var customAttribute in ((MethodDefinition)methodDescription).CustomAttributes) { if (customAttribute.AttributeType.FullName == typeof(ObfuscationAttribute).FullName) { foreach (var arg in customAttribute.Properties) { if (arg.Name == "Feature" && arg.Argument.Value != null) { var customValue = arg.Argument.Value.ToString(); if (customValue.StartsWith("SharpJit.")) { isSharpJit = true; break; } } } } if (isSharpJit) break; } } if (!isSharpJit) { if (methodDescription.Name.StartsWith("Calli") && methodDescription.DeclaringType.Name == "LocalInterop") { var callSite = new CallSite(methodDescription.ReturnType) { CallingConvention = MethodCallingConvention.StdCall }; // Last parameter is the function ptr, so we don't add it as a parameter for calli // as it is already an implicit parameter for calli for (int j = 0; j < methodDescription.Parameters.Count - 1; j++) { var parameterDefinition = methodDescription.Parameters[j]; callSite.Parameters.Add(parameterDefinition); } // Create calli Instruction var callIInstruction = ilProcessor.Create(OpCodes.Calli, callSite); // Replace instruction ilProcessor.Replace(instruction, callIInstruction); } else if (methodDescription.DeclaringType.Name == "Interop") { if (methodDescription.FullName.Contains("Fixed")) { if (methodDescription.Parameters[0].ParameterType.IsArray) { ReplaceFixedArrayStatement(method, ilProcessor, instruction); } else { ReplaceFixedStatement(method, ilProcessor, instruction); } } else if (methodDescription.Name.StartsWith("ReadInline")) { this.ReplaceReadInline(method, ilProcessor, instruction); } else if (methodDescription.Name.StartsWith("CopyInline") || methodDescription.Name.StartsWith("WriteInline")) { this.ReplaceCopyInline(method, ilProcessor, instruction); } else if (methodDescription.Name.StartsWith("SizeOf")) { this.ReplaceSizeOfStructGeneric(method, ilProcessor, instruction); } } } } } } return isSharpJit; }
static void EmitCalli(ILProcessor il, MethodReference reference) { var signature = new CallSite(reference.ReturnType) { CallingConvention = MethodCallingConvention.StdCall, }; foreach (var p in reference.Parameters) { signature.Parameters.Add(p); } // Since the last parameter is always the entry point address, // we do not need any special preparation before emiting calli. il.Emit(OpCodes.Calli, signature); }
public static void Add(this Collection<Instruction> coll, OpCode opcode, CallSite site) { coll.Add (Instruction.Create (opcode, site)); }
/// <summary> /// Patches the method. /// </summary> /// <param name="method">The method.</param> bool PatchMethod(MethodDefinition method) { bool isSharpJit = false; var attributes = this.GetSharpDXAttributes(method); if (attributes.Contains("SharpDX.ModuleInit")) { CreateModuleInit(method); } if (method.DeclaringType.Name == "Interop") { if (method.Name == "memcpy") { CreateMemcpy(method); } else if (method.Name == "memset") { CreateMemset(method); } else if ((method.Name == "Cast") || (method.Name == "CastOut")) { CreateCastMethod(method); } else if (method.Name == "CastArray") { CreateCastArrayMethod(method); } else if (method.Name == "Read" || (method.Name == "ReadOut") || (method.Name == "Read2D")) { if (method.Parameters.Count == 2) { CreateReadMethod(method); } else { CreateReadRangeMethod(method); } } else if (method.Name == "Write" || (method.Name == "Write2D")) { if (method.Parameters.Count == 2) { CreateWriteMethod(method); } else { CreateWriteRangeMethod(method); } } } else if (method.HasBody) { var ilProcessor = method.Body.GetILProcessor(); var instructions = method.Body.Instructions; Instruction instruction = null; Instruction previousInstruction; for (int i = 0; i < instructions.Count; i++) { previousInstruction = instruction; instruction = instructions[i]; if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference) { var methodDescription = (MethodReference)instruction.Operand; if (methodDescription is MethodDefinition) { foreach (var customAttribute in ((MethodDefinition)methodDescription).CustomAttributes) { if (customAttribute.AttributeType.FullName == typeof(ObfuscationAttribute).FullName) { foreach (var arg in customAttribute.Properties) { if (arg.Name == "Feature" && arg.Argument.Value != null) { var customValue = arg.Argument.Value.ToString(); if (customValue.StartsWith("SharpJit.")) { isSharpJit = true; break; } } } } if (isSharpJit) { break; } } } if (!isSharpJit) { if (methodDescription.Name.StartsWith("Calli") && methodDescription.DeclaringType.Name == "LocalInterop") { var callSite = new CallSite { ReturnType = methodDescription.ReturnType, CallingConvention = MethodCallingConvention.StdCall }; // Last parameter is the function ptr, so we don't add it as a parameter for calli // as it is already an implicit parameter for calli for (int j = 0; j < methodDescription.Parameters.Count - 1; j++) { var parameterDefinition = methodDescription.Parameters[j]; callSite.Parameters.Add(parameterDefinition); } // Create calli Instruction var callIInstruction = ilProcessor.Create(OpCodes.Calli, callSite); // Replace instruction ilProcessor.Replace(instruction, callIInstruction); } else if (methodDescription.DeclaringType.Name == "Interop") { if (methodDescription.FullName.Contains("Fixed")) { if (methodDescription.Parameters[0].ParameterType.IsArray) { ReplaceFixedArrayStatement(method, ilProcessor, instruction); } else { ReplaceFixedStatement(method, ilProcessor, instruction); } } else if (methodDescription.Name.StartsWith("ReadInline")) { this.ReplaceReadInline(method, ilProcessor, instruction); } else if (methodDescription.Name.StartsWith("CopyInline") || methodDescription.Name.StartsWith("WriteInline")) { this.ReplaceCopyInline(method, ilProcessor, instruction); } else if (methodDescription.Name.StartsWith("SizeOf")) { this.ReplaceSizeOfStructGeneric(method, ilProcessor, instruction); } } } } } } return(isSharpJit); }
void addCallSite(CallSite cs) { if (cs == null) return; pushMember(cs.signature); }
private void PatchRawCode(ByteBuffer buffer, int code_size, CodeWriter writer) { OpCode twoBytesOpCode; MetadataToken standAloneSignature; MetadataBuilder metadataBuilder = writer.metadata; buffer.WriteBytes(base.ReadBytes(code_size)); int num = buffer.position; buffer.position -= code_size; while (buffer.position < num) { byte num1 = buffer.ReadByte(); if (num1 == 254) { byte num2 = buffer.ReadByte(); twoBytesOpCode = OpCodes.TwoBytesOpCode[num2]; } else { twoBytesOpCode = OpCodes.OneByteOpCode[num1]; } switch (twoBytesOpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.InlineI: case OperandType.ShortInlineR: { buffer.position += 4; continue; } case OperandType.InlineField: case OperandType.InlineMethod: case OperandType.InlineTok: case OperandType.InlineType: { IMetadataTokenProvider metadataTokenProvider = this.reader.LookupToken(new MetadataToken(buffer.ReadUInt32())); buffer.position -= 4; standAloneSignature = metadataBuilder.LookupToken(metadataTokenProvider); buffer.WriteUInt32(standAloneSignature.ToUInt32()); continue; } case OperandType.InlineI8: case OperandType.InlineR: { buffer.position += 8; continue; } case OperandType.InlineSig: { Mono.Cecil.CallSite callSite = this.GetCallSite(new MetadataToken(buffer.ReadUInt32())); buffer.position -= 4; standAloneSignature = writer.GetStandAloneSignature(callSite); buffer.WriteUInt32(standAloneSignature.ToUInt32()); continue; } case OperandType.InlineString: { string str = this.GetString(new MetadataToken(buffer.ReadUInt32())); buffer.position -= 4; standAloneSignature = new MetadataToken(Mono.Cecil.TokenType.String, metadataBuilder.user_string_heap.GetStringIndex(str)); buffer.WriteUInt32(standAloneSignature.ToUInt32()); continue; } case OperandType.InlineSwitch: { int num3 = buffer.ReadInt32(); ByteBuffer byteBuffer = buffer; byteBuffer.position = byteBuffer.position + num3 * 4; continue; } case OperandType.InlineVar: case OperandType.InlineArg: { buffer.position += 2; continue; } case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineVar: case OperandType.ShortInlineArg: { buffer.position++; continue; } default: { continue; } } } }
void addCallSite(CallSite cs) { pushMember(cs.signature); }
public Type CommitToAssembly <T>(string methodName) where T : IAsmDelegate { if (!typeof(T).IsInterface) { throw new ArgumentException(nameof(T) + " must be an interface type"); } var methodToImplement = typeof(T).GetMethods().Single(); var assembly = AssemblyDefinition.CreateAssembly( new AssemblyNameDefinition(AssemblyName, new Version(1, 0, 0, 0)), AssemblyName, ModuleKind.Console); var module = assembly.MainModule; // create the program type and add it to the module var type = new TypeDefinition(AssemblyName, methodName, Mono.Cecil.TypeAttributes.Class | Mono.Cecil.TypeAttributes.Public, module.ImportReference(typeof(ValueType))); module.Types.Add(type); type.Fields.Add(new FieldDefinition(BUFFER_FIELD, Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private, module.ImportReference(typeof(SafeExecutableBuffer)))); var im = new InterfaceImplementation(module.ImportReference(typeof(T))); type.Interfaces.Add(im); // add an empty constructor var ctor = new MethodDefinition(".ctor", Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.SpecialName | Mono.Cecil.MethodAttributes.RTSpecialName, module.TypeSystem.Void); // create the constructor's method body var il = ctor.Body.GetILProcessor(); il.Append(il.Create(Mono.Cecil.Cil.OpCodes.Nop)); il.Append(il.Create(Mono.Cecil.Cil.OpCodes.Ret)); type.Methods.Add(ctor); var generatedMethod = new MethodDefinition(methodToImplement.Name, Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.Virtual, module.ImportReference(methodToImplement.ReturnType)); type.Methods.Add(generatedMethod); foreach (var parameterInfo in methodToImplement.GetParameters()) { generatedMethod.Parameters.Add(new ParameterDefinition(module.ImportReference(parameterInfo.ParameterType))); } // create the method body il = generatedMethod.Body.GetILProcessor(); ulong funcAddr = NextFunctionPointer; _currentStartPosition = (uint)_stream.Position; il.Append(il.Create(Mono.Cecil.Cil.OpCodes.Ldc_I8, (long)funcAddr)); il.Append(il.Create(Mono.Cecil.Cil.OpCodes.Conv_I)); // If we're honest about what we're calling it adds a bunch of overhead, *nanoseconds* of it (FIVE!!! in my test cases) // If we claim it's a managed function, it can JIT to a simple mov+jmp var cs = new Mono.Cecil.CallSite(module.ImportReference(methodToImplement.ReturnType)); il.Append(il.Create(Mono.Cecil.Cil.OpCodes.Calli, cs)); il.Append(il.Create(Mono.Cecil.Cil.OpCodes.Ret)); generatedMethod.Overrides.Add(module.ImportReference(methodToImplement)); var memstream = new MemoryStream(); assembly.Write(memstream); var realAssembly = Assembly.Load(memstream.ToArray()); var realType = realAssembly.GetType(AssemblyName + "." + methodName); realType.GetField(BUFFER_FIELD, BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, _buffer); return(realType); }
CallSite GetCallSiteAt (int token, GenericContext context) { StandAloneSigTable sasTable = m_reflectReader.TableReader.GetStandAloneSigTable (); MethodSig ms = m_reflectReader.SigReader.GetStandAloneMethodSig ( sasTable [(int) GetRid (token) - 1].Signature); CallSite cs = new CallSite (ms.HasThis, ms.ExplicitThis, ms.MethCallConv, m_reflectReader.GetMethodReturnType (ms, context)); cs.MetadataToken = new MetadataToken (token); for (int i = 0; i < ms.ParamCount; i++) { Param p = ms.Parameters [i]; cs.Parameters.Add (m_reflectReader.BuildParameterDefinition (i, p, context)); } ReflectionReader.CreateSentinelIfNeeded (cs, ms); return cs; }
CallSite GetCallSiteAt(int token, GenericContext context) { StandAloneSigTable sasTable = m_reflectReader.TableReader.GetStandAloneSigTable (); MethodSig ms = m_reflectReader.SigReader.GetStandAloneMethodSig ( sasTable [(int) GetRid (token) - 1].Signature); CallSite cs = new CallSite (ms.HasThis, ms.ExplicitThis, ms.MethCallConv, m_reflectReader.GetMethodReturnType (ms, context)); cs.MetadataToken = new MetadataToken (TokenType.Signature, GetRid (token)); for (int i = 0; i < ms.ParamCount; i++) { Param p = ms.Parameters [i]; cs.Parameters.Add (m_reflectReader.BuildParameterDefinition ( string.Concat ("A_", i), i, (ParamAttributes) 0, p, context)); } return cs; }