public void ComputeMaxStackTestCall() { var methodBody = CreateDummyMethodBody(); var importer = new ReferenceImporter(methodBody.Method.Image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); var instructions = methodBody.Instructions; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, "Lorem Ipsum"), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ret) }); Assert.Equal(1, methodBody.ComputeMaxStack()); }
public void CreateAttributeWithEnumArgument() { // set up temp assembly. var assembly = Utilities.CreateTempNetAssembly(); var tableStream = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>(); var assemblyTable = tableStream.GetTable <AssemblyDefinition>(); var attributeTable = tableStream.GetTable <CustomAttribute>(); var importer = new ReferenceImporter(tableStream); var assemblyDef = assemblyTable[0]; // create custom attribute. var signature = new CustomAttributeSignature(); signature.FixedArguments.Add( new CustomAttributeArgument(importer.ImportTypeSignature(typeof(DebuggableAttribute.DebuggingModes)), new ElementSignature((int)DebuggableAttribute.DebuggingModes.Default))); var attribute = new CustomAttribute(importer.ImportMethod(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(DebuggableAttribute.DebuggingModes) })), signature); assemblyDef.CustomAttributes.Add(attribute); attributeTable.Add(attribute); // build and validate. assembly = Utilities.RebuildNetAssembly(assembly); tableStream = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>(); assemblyTable = tableStream.GetTable <AssemblyDefinition>(); assemblyDef = assemblyTable[0]; attributeTable = tableStream.GetTable <CustomAttribute>(); var newAttribute = attributeTable[0]; Assert.IsTrue(assemblyDef.CustomAttributes.Contains(newAttribute)); Assert.AreEqual(attribute.Constructor.FullName, newAttribute.Constructor.FullName); Assert.AreEqual(attribute.Signature.FixedArguments.Count, newAttribute.Signature.FixedArguments.Count); for (int i = 0; i < attribute.Signature.FixedArguments.Count; i++) { Utilities.ValidateArgument(attribute.Signature.FixedArguments[i], newAttribute.Signature.FixedArguments[i]); } }
public void ImportInternalMethodDefinition() { var assembly = NetAssemblyFactory.CreateAssembly(DummyAssemblyName, true); var image = assembly.NetDirectory.MetadataHeader.LockMetadata(); var importer = new ReferenceImporter(image); var type = new TypeDefinition("SomeNamespace", "SomeType"); image.Assembly.Modules[0].TopLevelTypes.Add(type); var method = new MethodDefinition("SomeMethod", MethodAttributes.Public | MethodAttributes.Static, new MethodSignature(new[] { image.TypeSystem.String }, image.TypeSystem.Void)); type.Methods.Add(method); var newReference = importer.ImportMethod(method); Assert.Same(method, newReference); }
public void StackInsufficientValues() { var methodBody = CreateDummyMethodBody(); var importer = new ReferenceImporter(methodBody.Method.Image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(int) })); var instructions = methodBody.Instructions; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldc_I4, -1), CilInstruction.Create(CilOpCodes.And), CilInstruction.Create(CilOpCodes.Ldc_I4, -1), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ret), }); Assert.Throws <StackInbalanceException>(() => methodBody.ComputeMaxStack()); }
public void ComputeMaxStackBranch() { var methodBody = CreateDummyMethodBody(); var importer = new ReferenceImporter(methodBody.Method.Image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(int) })); var instructions = methodBody.Instructions; var target = CilInstruction.Create(CilOpCodes.Call, writeLine); instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldc_I4_1), CilInstruction.Create(CilOpCodes.Br, target), CilInstruction.Create(CilOpCodes.Ldc_I4_2), target, CilInstruction.Create(CilOpCodes.Ret), }); Assert.Equal(1, methodBody.ComputeMaxStack()); }
public void PreserveTypeRefsWithExtraImportShouldAtLeastHaveOriginalTypeRefs() { var module = ModuleDefinition.FromBytes(Properties.Resources.HelloWorld_NetCore); var originalTypeRefs = GetMembers <TypeReference>(module, TableIndex.TypeRef); var importer = new ReferenceImporter(module); var readKey = importer.ImportMethod(typeof(Console).GetMethod("ReadKey", Type.EmptyTypes)); var instructions = module.ManagedEntrypointMethod.CilMethodBody.Instructions; instructions.RemoveAt(instructions.Count - 1); instructions.Add(CilOpCodes.Call, readKey); instructions.Add(CilOpCodes.Pop); instructions.Add(CilOpCodes.Ret); var newModule = RebuildAndReloadModule(module, MetadataBuilderFlags.PreserveTypeReferenceIndices); var newTypeRefs = GetMembers <TypeReference>(newModule, TableIndex.TypeRef); Assert.Equal(originalTypeRefs, newTypeRefs.Take(originalTypeRefs.Count), Comparer); }
public void PreserveAssemblyRefsWithExtraImportShouldAtLeastHaveOriginalAssemblyRefs() { var module = ModuleDefinition.FromBytes(Properties.Resources.HelloWorld_NetCore); var originalAssemblyRefs = GetMembers <AssemblyReference>(module, TableIndex.AssemblyRef); var importer = new ReferenceImporter(module); var exists = importer.ImportMethod(typeof(File).GetMethod("Exists", new[] { typeof(string) })); var instructions = module.ManagedEntrypointMethod.CilMethodBody.Instructions; instructions.RemoveAt(instructions.Count - 1); instructions.Add(CilOpCodes.Ldstr, "file.txt"); instructions.Add(CilOpCodes.Call, exists); instructions.Add(CilOpCodes.Pop); instructions.Add(CilOpCodes.Ret); var newModule = RebuildAndReloadModule(module, MetadataBuilderFlags.PreserveAssemblyReferenceIndices); var newAssemblyRefs = GetMembers <AssemblyReference>(newModule, TableIndex.AssemblyRef); Assert.Equal(originalAssemblyRefs, newAssemblyRefs.Take(originalAssemblyRefs.Count), Comparer); }
public void PersistentNullArgument() { var assembly = NetAssemblyFactory.CreateAssembly(DummyAssemblyName, true); var header = assembly.NetDirectory.MetadataHeader; var image = header.LockMetadata(); var importer = new ReferenceImporter(image); var customAttribute = new CustomAttribute( (ICustomAttributeType)importer.ImportMethod( typeof(DisplayNameAttribute).GetConstructor(new[] { typeof(string) })), new CustomAttributeSignature(new[] { new CustomAttributeArgument(image.TypeSystem.String, new ElementSignature(null)) })); image.Assembly.CustomAttributes.Add(customAttribute); header.UnlockMetadata(); image = header.LockMetadata(); Assert.Single(image.Assembly.CustomAttributes); Assert.Null(image.Assembly.CustomAttributes[0].Signature.FixedArguments[0].Elements[0].Value); }
public void PersistentConstructor() { var assembly = NetAssemblyFactory.CreateAssembly(DummyAssemblyName, true); var header = assembly.NetDirectory.MetadataHeader; var image = header.LockMetadata(); var importer = new ReferenceImporter(image); var customAttribute = new CustomAttribute( (ICustomAttributeType)importer.ImportMethod( typeof(AssemblyTitleAttribute).GetConstructor(new[] { typeof(string) })), new CustomAttributeSignature(new[] { new CustomAttributeArgument(image.TypeSystem.String, new ElementSignature("SomeArgument")) })); image.Assembly.CustomAttributes.Add(customAttribute); header.UnlockMetadata(); image = header.LockMetadata(); Assert.Single(image.Assembly.CustomAttributes); Assert.Equal(customAttribute.Constructor, image.Assembly.CustomAttributes[0].Constructor, _comparer); }
public void ComputeMaxStackExceptionHandlers() { var methodBody = CreateDummyMethodBody(); var importer = new ReferenceImporter(methodBody.Method.Image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(int) })); var instructions = methodBody.Instructions; var tryStart = CilInstruction.Create(CilOpCodes.Nop); var handlerStart = CilInstruction.Create(CilOpCodes.Pop); var handlerEnd = CilInstruction.Create(CilOpCodes.Nop); instructions.AddRange(new[] { tryStart, CilInstruction.Create(CilOpCodes.Ldc_I4_0), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Leave, handlerEnd), handlerStart, CilInstruction.Create(CilOpCodes.Ldc_I4_1), CilInstruction.Create(CilOpCodes.Ldc_I4_2), CilInstruction.Create(CilOpCodes.Add), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Leave, handlerEnd), handlerEnd, CilInstruction.Create(CilOpCodes.Ret), }); methodBody.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Exception) { TryStart = tryStart, TryEnd = handlerStart, HandlerStart = handlerStart, HandlerEnd = handlerEnd, CatchType = importer.ImportType(typeof(Exception)) }); Assert.Equal(2, methodBody.ComputeMaxStack()); }
public void ImportGenericInstanceMethod() { var assembly = NetAssemblyFactory.CreateAssembly(DummyAssemblyName, true); var image = assembly.NetDirectory.MetadataHeader.LockMetadata(); var importer = new ReferenceImporter(image); var specification = new MethodSpecification( new MemberReference( CreateTypeReference(typeof(Activator)), "CreateInstance", new MethodSignature(new GenericParameterSignature(GenericParameterType.Method, 0)) { GenericParameterCount = 1 }), new GenericInstanceMethodSignature(CreateTypeDefOrRef(typeof(Stream)))); var newSpecification = importer.ImportMethod(specification); Assert.NotSame(specification, newSpecification); Assert.Equal(specification, newSpecification, _comparer); Assert.Equal(image, newSpecification.Image); }
public void CustomBlobs() { var assembly = NetAssemblyFactory.CreateAssembly("SomeAssembly", false); var header = assembly.NetDirectory.MetadataHeader; var image = header.LockMetadata(); var importer = new ReferenceImporter(image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); var main = new MethodDefinition("Main", MethodAttributes.Public | MethodAttributes.Static, new MethodSignature(image.TypeSystem.Void)); main.CilMethodBody = new CilMethodBody(main); main.CilMethodBody.Instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, "Hello, world!"), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ret) }); image.Assembly.Modules[0].TopLevelTypes[0].Methods.Add(main); image.ManagedEntrypoint = main; var extraBlobs = new BlobSignature[] { new DataBlobSignature(new byte[] { 1, 2, 3 }), new DataBlobSignature(new byte[] { 4, 5, 6 }) }; // Commit changes to assembly var builder = new CustomBuilder(extraBlobs); image.Header.UnlockMetadata(builder); var blobStream = header.GetStream <BlobStream>(); Assert.Equal(new byte[] { 1, 2, 3 }, blobStream.GetBlobByOffset(builder.GetBlobOffset(extraBlobs[0]))); Assert.Equal(new byte[] { 4, 5, 6 }, blobStream.GetBlobByOffset(builder.GetBlobOffset(extraBlobs[1]))); }
public void PersistentManagedSmallMethod() { const string expectedOutput = "Hello, world!"; var assembly = CreateTempAssembly(); var image = assembly.NetDirectory.MetadataHeader.Image; var importer = new ReferenceImporter(image); var mainMethod = image.Assembly.Modules[0].TopLevelTypes.First(x => x.Name == TypeName).Methods.First(x => x.Name == MainMethodName); var instructions = mainMethod.CilMethodBody.Instructions; instructions.AddRange(new[] { CilInstruction.Create(CilOpCodes.Ldstr, expectedOutput), CilInstruction.Create(CilOpCodes.Call, importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }))), CilInstruction.Create(CilOpCodes.Ret) }); assembly.NetDirectory.MetadataHeader.UnlockMetadata(); _context.VerifyOutput(assembly, expectedOutput); }
public void PersistentExtraData() { var assembly = NetAssemblyFactory.CreateAssembly(DummyAssemblyName, true); var header = assembly.NetDirectory.MetadataHeader; var image = header.LockMetadata(); var importer = new ReferenceImporter(image); var extraData = new byte[] { 1, 2, 3, 4 }; var customAttribute = new CustomAttribute( (ICustomAttributeType)importer.ImportMethod( typeof(ObfuscationAttribute).GetConstructor(Type.EmptyTypes)), new CustomAttributeSignature { ExtraData = extraData }); image.Assembly.CustomAttributes.Add(customAttribute); header.UnlockMetadata(); image = header.LockMetadata(); Assert.Equal(extraData, image.Assembly.CustomAttributes[0].Signature.ExtraData); }
public void ImportInternalMethodDefinition() { var assembly = Utilities.CreateTempNetAssembly(); var metadataHeader = assembly.NetDirectory.MetadataHeader; var tableStream = metadataHeader.GetStream <TableStream>(); var importer = new ReferenceImporter(tableStream); var type = new TypeDefinition("SomeNamespace", "SomeType"); tableStream.GetTable <TypeDefinition>().Add(type); var method = new MethodDefinition("SomeMethod", MethodAttributes.Public | MethodAttributes.Static, new MethodSignature(new[] { metadataHeader.TypeSystem.String }, metadataHeader.TypeSystem.Void)); type.Methods.Add(method); tableStream.GetTable <MethodDefinition>().Add(method); var newReference = importer.ImportMethod(method); Assert.AreSame(method, newReference, "Imported method definition is not the same object as the original."); }
public void CloneNestedClasses() { var sourceAssembly = WindowsAssembly.FromFile(typeof(SimpleClass).Assembly.Location); var sourceImage = sourceAssembly.NetDirectory.MetadataHeader.LockMetadata(); var assembly = NetAssemblyFactory.CreateAssembly("SomeAssembly", false); var header = assembly.NetDirectory.MetadataHeader; var image = header.LockMetadata(); var importer = new ReferenceImporter(image); var cloner = new MemberCloner(image); var simpleClass = cloner.CloneType(sourceImage.Assembly.Modules[0].TopLevelTypes.First(x => x.Name == "ClassWithNestedClasses")); image.Assembly.Modules[0].TopLevelTypes.Add(simpleClass); var main = new MethodDefinition("Main", MethodAttributes.Public | MethodAttributes.Static, new MethodSignature(image.TypeSystem.Void)); main.CilMethodBody = new CilMethodBody(main); main.CilMethodBody.Instructions.Add(CilInstruction.Create(CilOpCodes.Newobj, simpleClass.Methods.First(x => x.Name == ".ctor"))); main.CilMethodBody.Instructions.Add(CilInstruction.Create(CilOpCodes.Ldc_I4, 12)); main.CilMethodBody.Instructions.Add(CilInstruction.Create(CilOpCodes.Call, simpleClass.Methods.First(x => x.Name == "SomeMethod"))); main.CilMethodBody.Instructions.Add(CilInstruction.Create(CilOpCodes.Call, importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })))); main.CilMethodBody.Instructions.Add(CilInstruction.Create(CilOpCodes.Ret)); image.Assembly.Modules[0].TopLevelTypes[0].Methods.Add(main); image.ManagedEntrypoint = main; header.UnlockMetadata(); _context.VerifyOutput(assembly, "abc" + 12); }
public void ComputeMaxStackLoop() { var methodBody = CreateDummyMethodBody(); var importer = new ReferenceImporter(methodBody.Method.Image); var writeLine = importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new[] { typeof(int) })); var instructions = methodBody.Instructions; var loopHead = CilInstruction.Create(CilOpCodes.Nop); instructions.AddRange(new[] { loopHead, CilInstruction.Create(CilOpCodes.Ldc_I4_1), CilInstruction.Create(CilOpCodes.Ldc_I4_2), CilInstruction.Create(CilOpCodes.Add), CilInstruction.Create(CilOpCodes.Call, writeLine), CilInstruction.Create(CilOpCodes.Ldc_I4_0), CilInstruction.Create(CilOpCodes.Brtrue, loopHead), CilInstruction.Create(CilOpCodes.Ret), }); Assert.Equal(2, methodBody.ComputeMaxStack()); }
public void CreateAttributeWithNamedArgument() { const string fieldName = "MyField"; const string argumentValue = "MyXmlAttribute"; const string propertyName = "IsNullable"; const bool propertyValue = true; // set up temp assembly. var assembly = Utilities.CreateTempNetAssembly(); var typeSystem = assembly.NetDirectory.MetadataHeader.TypeSystem; var tableStream = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>(); var fieldTable = tableStream.GetTable <FieldDefinition>(); var attributeTable = tableStream.GetTable <CustomAttribute>(); var importer = new ReferenceImporter(tableStream); // create temp field. var field = new FieldDefinition(fieldName, FieldAttributes.Static, new FieldSignature(typeSystem.String)); fieldTable.Add(field); // create custom attribute. var signature = new CustomAttributeSignature(); signature.FixedArguments.Add( new CustomAttributeArgument(typeSystem.String, new ElementSignature(argumentValue))); signature.NamedArguments.Add( new CustomAttributeNamedArgument() { ArgumentMemberType = CustomAttributeArgumentMemberType.Property, ArgumentType = typeSystem.Boolean, MemberName = propertyName, Argument = new CustomAttributeArgument(typeSystem.Boolean, new ElementSignature(propertyValue)) }); var attribute = new CustomAttribute(importer.ImportMethod(typeof(XmlAttributeAttribute).GetConstructor(new Type[] { typeof(string) })), signature); field.CustomAttributes.Add(attribute); attributeTable.Add(attribute); // build and validate. assembly = Utilities.RebuildNetAssembly(assembly); fieldTable = tableStream.GetTable <FieldDefinition>(); field = fieldTable.First(x => x.Name == fieldName); attributeTable = tableStream.GetTable <CustomAttribute>(); var newAttribute = attributeTable[0]; Assert.IsTrue(field.CustomAttributes.Contains(newAttribute)); Assert.AreEqual(attribute.Constructor.FullName, newAttribute.Constructor.FullName); Assert.AreEqual(attribute.Signature.FixedArguments.Count, newAttribute.Signature.FixedArguments.Count); for (int i = 0; i < attribute.Signature.FixedArguments.Count; i++) { Utilities.ValidateArgument(attribute.Signature.FixedArguments[i], newAttribute.Signature.FixedArguments[i]); } Assert.AreEqual(attribute.Signature.NamedArguments.Count, newAttribute.Signature.NamedArguments.Count); for (int i = 0; i < attribute.Signature.NamedArguments.Count; i++) { Utilities.ValidateNamedArgument(attribute.Signature.NamedArguments[i], newAttribute.Signature.NamedArguments[i]); } }
/// <inheritdoc /> public override object ResolveMember(MetadataToken token) { switch (token.Table) { case TableIndex.TypeDef: var type = _tokens[(int)token.Rid]; if (type is RuntimeTypeHandle runtimeTypeHandle) { return(_importer.ImportType(Type.GetTypeFromHandle(runtimeTypeHandle))); } break; case TableIndex.Field: var field = _tokens[(int)token.Rid]; if (field is null) { return(null); } if (field is RuntimeFieldHandle runtimeFieldHandle) { return(_importer.ImportField(FieldInfo.GetFieldFromHandle(runtimeFieldHandle))); } if (field.GetType().FullName == "System.Reflection.Emit.GenericFieldInfo") { bool result = FieldReader.TryReadField <RuntimeFieldHandle>(field, "m_field", out var mField); var ctx = FieldReader.ReadField <RuntimeTypeHandle>(field, "m_context"); return(_importer.ImportField(FieldInfo.GetFieldFromHandle(result ? mField : FieldReader.ReadField <RuntimeFieldHandle>(field, "m_fieldHandle"), ctx))); } break; case TableIndex.Method: case TableIndex.MemberRef: var obj = _tokens[(int)token.Rid]; if (obj is RuntimeMethodHandle methodHandle) { return(_importer.ImportMethod(MethodBase.GetMethodFromHandle(methodHandle))); } if (obj.GetType().FullName == "System.Reflection.Emit.GenericMethodInfo") { var context = FieldReader.ReadField <RuntimeTypeHandle>(obj, "m_context"); bool hasHandle = FieldReader.TryReadField <RuntimeMethodHandle>(obj, "m_method", out var mMethod); var mHandle = FieldReader.ReadField <RuntimeMethodHandle>(obj, "m_methodHandle"); var method = MethodBase.GetMethodFromHandle( hasHandle ? mMethod : mHandle, context); return(_importer.ImportMethod(method)); } if (obj.GetType().FullName == "System.Reflection.Emit.VarArgMethod") { return(_importer.ImportMethod(FieldReader.ReadField <MethodInfo>(obj, "m_method"))); } break; case TableIndex.StandAloneSig: var reader = ByteArrayDataSource.CreateReader((byte[])_tokens[(int)token.Rid]); return(CallingConventionSignature.FromReader(new BlobReadContext(_readerContext), ref reader)); } return(token); }
public void NonExistentStreams() { var assembly = NetAssemblyFactory.CreateAssembly("SomeAssembly", true); var header = assembly.NetDirectory.MetadataHeader; // Remove #US Stream. var usHeader = header.StreamHeaders.FirstOrDefault(x => x.Name == "#US"); if (usHeader != null) { header.StreamHeaders.Remove(usHeader); } // Lock metadata. var image = header.LockMetadata(); var importer = new ReferenceImporter(image); // Create new method with a string. var method = new MethodDefinition("Test", MethodAttributes.Public | MethodAttributes.Static, new MethodSignature(image.TypeSystem.Void)); method.CilMethodBody = new CilMethodBody(method) { Instructions = { CilInstruction.Create(CilOpCodes.Ldstr, "Hello, world!"), CilInstruction.Create(CilOpCodes.Call, importer.ImportMethod( typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }))), CilInstruction.Create(CilOpCodes.Ret) } }; image.Assembly.Modules[0].TopLevelTypes[0].Methods.Add(method); // Commit changes. header.UnlockMetadata(); // Check if #US stream is added again. var usStream = header.GetStream <UserStringStream>(); Assert.NotNull(usStream); }