diff --git a/.gitignore b/.gitignore index 5bf1c1e2b..8b3b163cc 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ x64/ build/ [Bb]in/ [Oo]bj/ +artifacts/ # MSTest test Results [Tt]est[Rr]esult*/ diff --git a/AsmResolver.sln b/AsmResolver.sln index 0cf5601e0..492017f8f 100644 --- a/AsmResolver.sln +++ b/AsmResolver.sln @@ -4,8 +4,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 17.0.31919.166 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{34A95168-A162-4F6A-803B-B6F221FE9EA6}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{786C1732-8C96-45DD-97BB-639C9AA7F45B}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsmResolver", "src\AsmResolver\AsmResolver.csproj", "{4EA3F800-1A1B-4465-931F-4E9949C3373B}" EndProject diff --git a/Directory.Build.props b/Directory.Build.props index fd7226b04..a183e92e4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,14 +1,15 @@ - Copyright © Washi 2016-2023 + Copyright © Washi 2016-2024 https://github.com/Washi1337/AsmResolver https://github.com/Washi1337/AsmResolver/LICENSE.md https://github.com/Washi1337/AsmResolver git 10 - 5.5.0 + 5.5.1 true + true diff --git a/appveyor.yml b/appveyor.yml index 270821ada..2006831eb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ - master image: Visual Studio 2022 - version: 5.5.0-master-build.{build} + version: 5.5.1-master-build.{build} configuration: Release skip_commits: @@ -18,7 +18,7 @@ verbosity: minimal artifacts: - - path: '**\*.nupkg' + - path: 'artifacts\package\release\*.nupkg' deploy: provider: NuGet @@ -33,7 +33,7 @@ - development image: Visual Studio 2022 - version: 5.5.0-dev-build.{build} + version: 5.5.1-dev-build.{build} configuration: Release skip_commits: @@ -47,4 +47,4 @@ verbosity: minimal artifacts: - - path: '**\*.nupkg' + - path: 'artifacts\package\release\*.nupkg' diff --git a/docs/guides/dotnet/importing.md b/docs/guides/dotnet/importing.md index b446d9869..b5a937e3a 100644 --- a/docs/guides/dotnet/importing.md +++ b/docs/guides/dotnet/importing.md @@ -106,6 +106,16 @@ imported through reflection include: is created). - Generic parameters. - Generic type instantiations. +- Function pointer types (.NET 8.0+ only. TFM doesn't matter for this, the runtime used at runtime is all that matters.) (!!WARNING!! ) + +> [!WARNING] +> Function pointer `Type` instances lose their calling conventions unless attained with +> `GetModified(Field/Property/Parameter)Type`. This includes `typeof`! +> `typeof(delegate*unmanaged[Cdecl])` is the same as `typeof(delegate*managed)`. +> `Import(Field/Method)` will also strip the calling conventions from function pointers +> that are the types of fields or in method signatures. +> If you need to handle this, manually set the types in the resulting +> `IMethodDefOrRef` or `MemberReference` to the appropriate type from `ImportType`. Instantiations of generic methods are also supported. diff --git a/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj b/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj index f6c65a741..6db621977 100644 --- a/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj +++ b/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj @@ -4,10 +4,7 @@ AsmResolver.DotNet.Dynamic Dynamic method support for the AsmResolver executable file inspection toolsuite. exe pe directories imports exports resources dotnet cil inspection manipulation assembly disassembly dynamic - true 1701;1702;NU5105 - net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 - enable @@ -23,9 +20,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs b/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs index 8f4b202f4..4368460f8 100644 --- a/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs +++ b/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs @@ -37,7 +37,7 @@ public DynamicCilOperandResolver(SerializedModuleDefinition contextModule, CilMe case TableIndex.TypeDef: object? type = _tokens[(int)token.Rid]; if (type is RuntimeTypeHandle runtimeTypeHandle) - return _importer.ImportType(Type.GetTypeFromHandle(runtimeTypeHandle)); + return _importer.ImportType(Type.GetTypeFromHandle(runtimeTypeHandle)!); break; case TableIndex.Field: diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs b/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs index 4fdc14587..0b6465aa8 100644 --- a/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs +++ b/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs @@ -84,7 +84,10 @@ private static CilMethodBody CreateDynamicMethodBody(MethodDefinition method, ob // if the DynamicMethod code is not flushed yet into the resolver (e.g., it hasn't been invoked yet). object? dynamicILInfo = null; if (FieldReader.TryReadField(resolver, "m_method", out var m) && m is not null) - FieldReader.TryReadField(m, "m_DynamicILInfo", out dynamicILInfo); + { + if (!FieldReader.TryReadField(m, "m_DynamicILInfo", out dynamicILInfo)) + FieldReader.TryReadField(m, "_dynamicILInfo", out dynamicILInfo); + } // Extract all required information to construct the body. byte[]? code; diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs b/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs index 27e3d27c3..909b015d6 100644 --- a/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs +++ b/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs @@ -101,7 +101,9 @@ public static object ResolveDynamicResolver(object dynamicMethodObj) if (dynamicMethodObj.GetType().FullName == "System.Reflection.Emit.DynamicMethod") { - object? resolver = FieldReader.ReadField(dynamicMethodObj, "m_resolver"); + object? resolver = + FieldReader.ReadField(dynamicMethodObj, "m_resolver") + ?? FieldReader.ReadField(dynamicMethodObj, "_resolver"); if (resolver != null) dynamicMethodObj = resolver; } @@ -115,7 +117,7 @@ public static object ResolveDynamicResolver(object dynamicMethodObj) object? ilGenerator = dynamicMethodObj .GetType() .GetRuntimeMethods() - .First(q => q.Name == "GetILGenerator") + .First(q => q.Name == "GetILGenerator" && q.GetParameters().Length == 0) .Invoke(dynamicMethodObj, null); //Create instance of dynamicResolver diff --git a/src/AsmResolver.DotNet/AsmResolver.DotNet.csproj b/src/AsmResolver.DotNet/AsmResolver.DotNet.csproj index aaa73fef2..613b423da 100644 --- a/src/AsmResolver.DotNet/AsmResolver.DotNet.csproj +++ b/src/AsmResolver.DotNet/AsmResolver.DotNet.csproj @@ -4,10 +4,7 @@ AsmResolver.DotNet High level .NET image models for the AsmResolver executable file inspection toolsuite. exe pe directories imports exports resources dotnet cil inspection manipulation assembly disassembly - true 1701;1702;NU5105 - enable - net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 true @@ -24,9 +21,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs b/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs index 970bc7b26..60616bc07 100644 --- a/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs +++ b/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs @@ -459,7 +459,7 @@ private bool TryOptimizeVariable(CilInstruction instruction) { var variable = instruction.GetLocalVariable(Owner.LocalVariables); - CilOpCode code = instruction.OpCode; + var code = instruction.OpCode; object? operand = instruction.Operand; if (instruction.IsLdloc()) @@ -470,7 +470,7 @@ private bool TryOptimizeVariable(CilInstruction instruction) 1 => (CilOpCodes.Ldloc_1, null), 2 => (CilOpCodes.Ldloc_2, null), 3 => (CilOpCodes.Ldloc_3, null), - {} x when x >= byte.MinValue && x <= byte.MaxValue => (CilOpCodes.Ldloc_S, variable), + <= byte.MaxValue and >= byte.MinValue => (CilOpCodes.Ldloc_S, variable), _ => (CilOpCodes.Ldloc, variable), }; } @@ -482,10 +482,15 @@ private bool TryOptimizeVariable(CilInstruction instruction) 1 => (CilOpCodes.Stloc_1, null), 2 => (CilOpCodes.Stloc_2, null), 3 => (CilOpCodes.Stloc_3, null), - {} x when x >= byte.MinValue && x <= byte.MaxValue => (CilOpCodes.Stloc_S, variable), + <= byte.MaxValue and >= byte.MinValue => (CilOpCodes.Stloc_S, variable), _ => (CilOpCodes.Stloc, variable), }; } + else if (instruction.OpCode.Code == CilCode.Ldloca) + { + if (variable.Index is >= byte.MinValue and <= byte.MaxValue) + code = CilOpCodes.Ldloca_S; + } if (code != instruction.OpCode) { @@ -501,7 +506,7 @@ private bool TryOptimizeArgument(CilInstruction instruction) { var parameter = instruction.GetParameter(Owner.Owner.Parameters); - CilOpCode code = instruction.OpCode; + var code = instruction.OpCode; object? operand = instruction.Operand; if (instruction.IsLdarg()) @@ -512,15 +517,19 @@ private bool TryOptimizeArgument(CilInstruction instruction) 1 => (CilOpCodes.Ldarg_1, null), 2 => (CilOpCodes.Ldarg_2, null), 3 => (CilOpCodes.Ldarg_3, null), - {} x when x >= byte.MinValue && x <= byte.MaxValue => (CilOpCodes.Ldarg_S, parameter), + >= byte.MinValue and <= byte.MaxValue => (CilOpCodes.Ldarg_S, parameter), _ => (CilOpCodes.Ldarg, parameter), }; } else if (instruction.IsStarg()) { - code = parameter.MethodSignatureIndex <= byte.MaxValue - ? CilOpCodes.Starg_S - : CilOpCodes.Starg; + if (parameter.MethodSignatureIndex <= byte.MaxValue) + code = CilOpCodes.Starg_S; + } + else if (instruction.OpCode.Code == CilCode.Ldarga) + { + if (parameter.Index is >= byte.MinValue and <= byte.MaxValue) + code = CilOpCodes.Ldarga_S; } if (code != instruction.OpCode) diff --git a/src/AsmResolver.DotNet/Collections/MemberCollection.cs b/src/AsmResolver.DotNet/Collections/MemberCollection.cs new file mode 100644 index 000000000..1803c3141 --- /dev/null +++ b/src/AsmResolver.DotNet/Collections/MemberCollection.cs @@ -0,0 +1,31 @@ +using AsmResolver.Collections; + +namespace AsmResolver.DotNet.Collections +{ + /// + /// Represents an indexed member collection where each member is owned by some object, and prevents the member from + /// being added to any other instance of the collection. + /// + /// The type of the owner object. + /// The type of elements to store. + public class MemberCollection : OwnedCollection + where TOwner : class + where TMember : class, IOwnedCollectionElement + { + internal MemberCollection(TOwner owner) + : base(owner) + { + } + + internal MemberCollection(TOwner owner, int capacity) + : base(owner, capacity) + { + } + + internal void AddNoOwnerCheck(TMember member) + { + member.Owner = Owner; + Items.Add(member); + } + } +} diff --git a/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs b/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs index 35cfefda3..12f403669 100644 --- a/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs +++ b/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs @@ -1,15 +1,13 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; -using AsmResolver.Collections; namespace AsmResolver.DotNet.Collections { /// /// Provides an implementation of a list of method semantics that are associated to a property or event. /// - public class MethodSemanticsCollection : OwnedCollection< IHasSemantics, MethodSemantics> + public class MethodSemanticsCollection : MemberCollection { /// /// Creates a new instance of the class. @@ -36,7 +34,7 @@ internal bool ValidateMembership set; } = true; - private void AssertSemanticsValidity([NotNull] MethodSemantics item) + private void AssertSemanticsValidity(MethodSemantics item) { if (!ValidateMembership) return; diff --git a/src/AsmResolver.DotNet/ModuleDefinition.cs b/src/AsmResolver.DotNet/ModuleDefinition.cs index e539a0197..2ecd38a2e 100644 --- a/src/AsmResolver.DotNet/ModuleDefinition.cs +++ b/src/AsmResolver.DotNet/ModuleDefinition.cs @@ -34,8 +34,6 @@ public class ModuleDefinition : IHasCustomAttribute, IOwnedCollectionElement { - private static MethodInfo? GetHINSTANCEMethod; - private readonly LazyVariable _name; private readonly LazyVariable _mvid; private readonly LazyVariable _encId; @@ -166,14 +164,9 @@ public static ModuleDefinition FromModuleBaseAddress(IntPtr hInstance, PEMapping /// The module. public static ModuleDefinition FromModule(Module module, ModuleReaderParameters readerParameters) { - // We get the base address using GetHINSTANCE, but this method is unfortunately not shipped with - // .NET Standard 2.0, so we need to resort to reflection for this. - GetHINSTANCEMethod ??= typeof(Marshal).GetMethod("GetHINSTANCE", new[] { typeof(Module) }); - - var handle = (IntPtr) GetHINSTANCEMethod?.Invoke(null, new object[] { module })!; - if (handle == IntPtr.Zero) + if (!ReflectionHacks.TryGetHINSTANCE(module, out var handle)) throw new NotSupportedException("The current platform does not support getting the base address of an instance of System.Reflection.Module."); - if (handle == (IntPtr) (-1)) + if (handle == -1) throw new NotSupportedException("Provided module does not have a module base address."); // Dynamically loaded modules are in their unmapped form, as opposed to modules loaded normally by the @@ -302,7 +295,6 @@ public ModuleDefinition(Utf8String? name) Name = name; CorLibTypeFactory = CorLibTypeFactory.CreateMscorlib40TypeFactory(this); - AssemblyReferences.Add((AssemblyReference)CorLibTypeFactory.CorLibScope); MetadataResolver = new DefaultMetadataResolver(new DotNetFrameworkAssemblyResolver()); TopLevelTypes.Add(new TypeDefinition(null, TypeDefinition.ModuleTypeName, 0)); diff --git a/src/AsmResolver.DotNet/ReferenceImporter.cs b/src/AsmResolver.DotNet/ReferenceImporter.cs index c9c2b26c7..f2748e2ef 100644 --- a/src/AsmResolver.DotNet/ReferenceImporter.cs +++ b/src/AsmResolver.DotNet/ReferenceImporter.cs @@ -311,6 +311,8 @@ public virtual TypeSignature ImportTypeSignature(Type type) return new GenericParameterSignature( type.DeclaringMethod != null ? GenericParameterType.Method : GenericParameterType.Type, type.GenericParameterPosition); + if (ReflectionHacks.GetIsFunctionPointer(type)) + return ImportFunctionPointerType(type); var corlibType = TargetModule.CorLibTypeFactory.FromName(type.Namespace, type.Name); if (corlibType != null) @@ -355,6 +357,41 @@ private TypeSignature ImportGenericType(Type type) return result; } + private TypeSignature ImportFunctionPointerType(Type type) + { + var returnType = ImportTypeSignature(ReflectionHacks.GetFunctionPointerReturnType(type)); + var callConvs = ReflectionHacks.GetFunctionPointerCallingConventions(type); + var callConv = CallingConventionAttributes.Default; + if (callConvs.Length == 1) + { + var cc = callConvs[0]; + callConv = cc.FullName switch + { + "System.Runtime.CompilerServices.CallConvCdecl" => CallingConventionAttributes.C, + "System.Runtime.CompilerServices.CallConvFastcall" => CallingConventionAttributes.FastCall, + "System.Runtime.CompilerServices.CallConvStdcall" => CallingConventionAttributes.StdCall, + "System.Runtime.CompilerServices.CallConvThiscall" => CallingConventionAttributes.ThisCall, + _ => CallingConventionAttributes.Default + }; + if (callConv == CallingConventionAttributes.Default) + returnType = returnType.MakeModifierType(ImportType(cc), false); + } + else + { + foreach (var cc in callConvs) + returnType = returnType.MakeModifierType(ImportType(cc), false); + } + + if (callConv == default && ReflectionHacks.GetIsUnmanagedFunctionPointer(type)) + callConv = CallingConventionAttributes.Unmanaged; + + return new MethodSignature( + callConv, + returnType, + ReflectionHacks.GetFunctionPointerParameterTypes(type).Select(ImportTypeSignature) + ).MakeFunctionPointerType(); + } + /// /// Imports a reference to- or an instantiation of a method into the module. /// diff --git a/src/AsmResolver.DotNet/ReflectionHacks.cs b/src/AsmResolver.DotNet/ReflectionHacks.cs new file mode 100644 index 000000000..739398c2c --- /dev/null +++ b/src/AsmResolver.DotNet/ReflectionHacks.cs @@ -0,0 +1,89 @@ +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace AsmResolver.DotNet +{ + internal static class ReflectionHacks + { +#if !NET8_0_OR_GREATER + private static readonly PropertyInfo? IsFunctionPointerProp = typeof(Type).GetProperty("IsFunctionPointer"); + private static readonly PropertyInfo? IsUnmanagedFunctionPointerProp = typeof(Type).GetProperty("IsUnmanagedFunctionPointer"); + private static readonly MethodInfo? GetFunctionPointerReturnTypeMethod = typeof(Type).GetMethod("GetFunctionPointerReturnType", Array.Empty()); + private static readonly MethodInfo? GetFunctionPointerCallingConventionsMethod = typeof(Type).GetMethod("GetFunctionPointerCallingConventions", Array.Empty()); + private static readonly MethodInfo? GetFunctionPointerParameterTypesMethod = typeof(Type).GetMethod("GetFunctionPointerParameterTypes", Array.Empty()); +#endif +#if NETSTANDARD2_0 + private static readonly MethodInfo? GetHINSTANCEMethod = typeof(Marshal).GetMethod("GetHINSTANCE", new[] { typeof(Module) }); +#endif + + internal static bool GetIsFunctionPointer(Type t) + { +#if NET8_0_OR_GREATER + return t.IsFunctionPointer; +#else + return IsFunctionPointerProp != null && (bool)IsFunctionPointerProp.GetValue(t)!; +#endif + } + + internal static bool GetIsUnmanagedFunctionPointer(Type t) + { +#if NET8_0_OR_GREATER + return t.IsUnmanagedFunctionPointer; +#else + // can only be called if the type was already verified to be a function pointer + // therefore the PropertyInfo is not null + return (bool)IsUnmanagedFunctionPointerProp!.GetValue(t)!; +#endif + } + + internal static Type GetFunctionPointerReturnType(Type t) + { +#if NET8_0_OR_GREATER + return t.GetFunctionPointerReturnType(); +#else + // can only be called if the type was already verified to be a function pointer + // therefore the MethodInfo is not null + return (Type)GetFunctionPointerReturnTypeMethod!.Invoke(t, null)!; +#endif + } + + internal static Type[] GetFunctionPointerCallingConventions(Type t) + { +#if NET8_0_OR_GREATER + return t.GetFunctionPointerCallingConventions(); +#else + // can only be called if the type was already verified to be a function pointer + // therefore the MethodInfo is not null + return (Type[])GetFunctionPointerCallingConventionsMethod!.Invoke(t, null)!; +#endif + } + + internal static Type[] GetFunctionPointerParameterTypes(Type t) + { +#if NET8_0_OR_GREATER + return t.GetFunctionPointerParameterTypes(); +#else + // can only be called if the type was already verified to be a function pointer + // therefore the MethodInfo is not null + return (Type[])GetFunctionPointerParameterTypesMethod!.Invoke(t, null)!; +#endif + } + + internal static bool TryGetHINSTANCE(Module m, out nint hinstance) + { +#if !NETSTANDARD2_0 + hinstance = Marshal.GetHINSTANCE(m); + return true; +#else + if (GetHINSTANCEMethod == null) + { + hinstance = default; + return false; + } + hinstance = (nint)GetHINSTANCEMethod.Invoke(null, new object[] { m }); + return true; +#endif + } + } +} diff --git a/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs index 3af420240..d6e254453 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs @@ -2,8 +2,7 @@ using System.Collections.Generic; using System.Runtime.Versioning; using AsmResolver.Collections; -using AsmResolver.PE.DotNet.Metadata.Blob; -using AsmResolver.PE.DotNet.Metadata.Strings; +using AsmResolver.DotNet.Collections; using AsmResolver.PE.DotNet.Metadata.Tables; using AsmResolver.PE.DotNet.Metadata.Tables.Rows; using FileAttributes = AsmResolver.PE.DotNet.Metadata.Tables.Rows.FileAttributes; @@ -58,11 +57,8 @@ public SerializedAssemblyDefinition( /// protected override IList GetModules() { - _manifestModule.Assembly = null; - var result = new OwnedCollection(this) - { - _manifestModule - }; + var result = new MemberCollection(this); + result.AddNoOwnerCheck(_manifestModule); var moduleResolver = _context.Parameters.ModuleResolver; if (moduleResolver is not null) diff --git a/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs index 086de5b61..bcbb9aff5 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs @@ -69,7 +69,7 @@ protected override IList GetSemantics() foreach (uint rid in module.GetMethodSemantics(MetadataToken)) { var semanticsToken = new MetadataToken(TableIndex.MethodSemantics, rid); - result.Add((MethodSemantics) module.LookupMember(semanticsToken)); + result.AddNoOwnerCheck((MethodSemantics) module.LookupMember(semanticsToken)); } result.ValidateMembership = true; diff --git a/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs b/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs index 592a6ef1a..db448b1db 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs @@ -54,12 +54,12 @@ protected override IList GetConstraints() { var module = _context.ParentModule; var rids = module.GetGenericParameterConstraints(MetadataToken); - var result = new OwnedCollection(this, rids.Count); + var result = new MemberCollection(this, rids.Count); foreach (uint rid in rids) { var constraintToken = new MetadataToken(TableIndex.GenericParamConstraint, rid); - result.Add((GenericParameterConstraint) module.LookupMember(constraintToken)); + result.AddNoOwnerCheck((GenericParameterConstraint) module.LookupMember(constraintToken)); } return result; diff --git a/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs index 42675f8ab..046b10039 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs @@ -78,12 +78,12 @@ protected override IList GetSecurityDeclarations() => protected override IList GetParameterDefinitions() { var parameterRange = _context.ParentModule.GetParameterRange(MetadataToken.Rid); - var result = new OwnedCollection(this, parameterRange.Count); + var result = new MemberCollection(this, parameterRange.Count); foreach (var token in parameterRange) { if (_context.ParentModule.TryLookupMember(token, out var member) && member is ParameterDefinition parameter) - result.Add(parameter); + result.AddNoOwnerCheck(parameter); } return result; @@ -106,14 +106,14 @@ protected override IList GetParameterDefinitions() protected override IList GetGenericParameters() { var rids = _context.ParentModule.GetGenericParameters(MetadataToken); - var result = new OwnedCollection(this, rids.Count); + var result = new MemberCollection(this, rids.Count); foreach (uint rid in rids) { if (_context.ParentModule.TryLookupMember(new MetadataToken(TableIndex.GenericParam, rid), out var member) && member is GenericParameter genericParameter) { - result.Add(genericParameter); + result.AddNoOwnerCheck(genericParameter); } } diff --git a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs index 243f31ca5..16a1e0133 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs @@ -229,12 +229,12 @@ internal IList GetCustomAttributeCollection(IHasCustomAttribute { EnsureCustomAttributesInitialized(); var rids = _customAttributes.GetValues(owner.MetadataToken); - var result = new OwnedCollection(owner, rids.Count); + var result = new MemberCollection(owner, rids.Count); foreach (uint rid in rids) { var attribute = (CustomAttribute) LookupMember(new MetadataToken(TableIndex.CustomAttribute, rid)); - result.Add(attribute); + result.AddNoOwnerCheck(attribute); } return result; @@ -274,12 +274,12 @@ internal IList GetSecurityDeclarationCollection(IHasSecurit { EnsureSecurityDeclarationsInitialized(); var rids = _securityDeclarations.GetValues(owner.MetadataToken); - var result = new OwnedCollection(owner, rids.Count); + var result = new MemberCollection(owner, rids.Count); foreach (uint rid in rids) { var attribute = (SecurityDeclaration) LookupMember(new MetadataToken(TableIndex.DeclSecurity, rid)); - result.Add(attribute); + result.AddNoOwnerCheck(attribute); } return result; diff --git a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs index 464553d67..c5063f1b4 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs @@ -1,17 +1,13 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using AsmResolver.Collections; using AsmResolver.DotNet.Collections; using AsmResolver.DotNet.Signatures.Types; using AsmResolver.PE; using AsmResolver.PE.Debug; using AsmResolver.PE.DotNet; -using AsmResolver.PE.DotNet.Metadata.Guid; -using AsmResolver.PE.DotNet.Metadata.Strings; using AsmResolver.PE.DotNet.Metadata.Tables; using AsmResolver.PE.DotNet.Metadata.Tables.Rows; -using AsmResolver.PE.DotNet.Metadata.UserStrings; using AsmResolver.PE.Win32Resources; namespace AsmResolver.DotNet.Serialized @@ -191,7 +187,7 @@ protected override IList GetTopLevelTypes() var typeDefTable = ReaderContext.TablesStream.GetTable(TableIndex.TypeDef); int nestedTypeCount = ReaderContext.TablesStream.GetTable(TableIndex.NestedClass).Count; - var types = new OwnedCollection(this, + var types = new MemberCollection(this, typeDefTable.Count - nestedTypeCount); for (int i = 0; i < typeDefTable.Count; i++) @@ -200,7 +196,7 @@ protected override IList GetTopLevelTypes() if (_typeDefTree.GetKey(rid) == 0) { var token = new MetadataToken(TableIndex.TypeDef, rid); - types.Add(_memberFactory.LookupTypeDefinition(token)!); + types.AddNoOwnerCheck(_memberFactory.LookupTypeDefinition(token)!); } } @@ -212,13 +208,13 @@ protected override IList GetAssemblyReferences() { var table = ReaderContext.TablesStream.GetTable(TableIndex.AssemblyRef); - var result = new OwnedCollection(this, table.Count); + var result = new MemberCollection(this, table.Count); // Don't use the member factory here, this method may be called before the member factory is initialized. for (int i = 0; i < table.Count; i++) { var token = new MetadataToken(TableIndex.AssemblyRef, (uint) i + 1); - result.Add(new SerializedAssemblyReference(ReaderContext, token, table[i])); + result.AddNoOwnerCheck(new SerializedAssemblyReference(ReaderContext, token, table[i])); } return result; @@ -229,13 +225,13 @@ protected override IList GetModuleReferences() { var table = ReaderContext.TablesStream.GetTable(TableIndex.ModuleRef); - var result = new OwnedCollection(this, table.Count); + var result = new MemberCollection(this, table.Count); for (int i = 0; i < table.Count; i++) { var token = new MetadataToken(TableIndex.ModuleRef, (uint) i + 1); if (_memberFactory.TryLookupMember(token, out var member) && member is ModuleReference module) - result.Add(module); + result.AddNoOwnerCheck(module); } return result; @@ -246,13 +242,13 @@ protected override IList GetFileReferences() { var table = ReaderContext.TablesStream.GetTable(TableIndex.File); - var result = new OwnedCollection(this, table.Count); + var result = new MemberCollection(this, table.Count); for (int i = 0; i < table.Count; i++) { var token = new MetadataToken(TableIndex.File, (uint) i + 1); if (_memberFactory.TryLookupMember(token, out var member) && member is FileReference file) - result.Add(file); + result.AddNoOwnerCheck(file); } return result; @@ -263,13 +259,13 @@ protected override IList GetResources() { var table = ReaderContext.TablesStream.GetTable(TableIndex.ManifestResource); - var result = new OwnedCollection(this, table.Count); + var result = new MemberCollection(this, table.Count); for (int i = 0; i < table.Count; i++) { var token = new MetadataToken(TableIndex.ManifestResource, (uint) i + 1); if (_memberFactory.TryLookupMember(token, out var member) && member is ManifestResource resource) - result.Add(resource); + result.AddNoOwnerCheck(resource); } return result; @@ -280,13 +276,13 @@ protected override IList GetExportedTypes() { var table = ReaderContext.TablesStream.GetTable(TableIndex.ExportedType); - var result = new OwnedCollection(this, table.Count); + var result = new MemberCollection(this, table.Count); for (int i = 0; i < table.Count; i++) { var token = new MetadataToken(TableIndex.ExportedType, (uint) i + 1); if (_memberFactory.TryLookupMember(token, out var member) && member is ExportedType exportedType) - result.Add(exportedType); + result.AddNoOwnerCheck(exportedType); } return result; diff --git a/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs index 1d235e66a..ac71f8512 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs @@ -76,7 +76,7 @@ protected override IList GetSemantics() foreach (uint rid in rids) { var semanticsToken = new MetadataToken(TableIndex.MethodSemantics, rid); - result.Add((MethodSemantics) module.LookupMember(semanticsToken)); + result.AddNoOwnerCheck((MethodSemantics) module.LookupMember(semanticsToken)); } result.ValidateMembership = true; diff --git a/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs index ba495ba5c..60f1096f5 100644 --- a/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs +++ b/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using AsmResolver.Collections; using AsmResolver.DotNet.Collections; -using AsmResolver.PE.DotNet.Metadata; -using AsmResolver.PE.DotNet.Metadata.Strings; using AsmResolver.PE.DotNet.Metadata.Tables; using AsmResolver.PE.DotNet.Metadata.Tables.Rows; @@ -58,12 +55,12 @@ public SerializedTypeDefinition(ModuleReaderContext context, MetadataToken token protected override IList GetNestedTypes() { var rids = _context.ParentModule.GetNestedTypeRids(MetadataToken.Rid); - var result = new OwnedCollection(this, rids.Count); + var result = new MemberCollection(this, rids.Count); foreach (uint rid in rids) { var nestedType = (TypeDefinition) _context.ParentModule.LookupMember(new MetadataToken(TableIndex.TypeDef, rid)); - result.Add(nestedType); + result.AddNoOwnerCheck(nestedType); } return result; @@ -97,10 +94,10 @@ protected override IList GetEvents() => private IList CreateMemberCollection(MetadataRange range) where TMember : class, IMetadataMember, IOwnedCollectionElement { - var result = new OwnedCollection(this, range.Count); + var result = new MemberCollection(this, range.Count); foreach (var token in range) - result.Add((TMember) _context.ParentModule.LookupMember(token)); + result.AddNoOwnerCheck((TMember) _context.ParentModule.LookupMember(token)); return result; } @@ -117,14 +114,14 @@ protected override IList GetSecurityDeclarations() => protected override IList GetGenericParameters() { var rids = _context.ParentModule.GetGenericParameters(MetadataToken); - var result = new OwnedCollection(this, rids.Count); + var result = new MemberCollection(this, rids.Count); foreach (uint rid in rids) { if (_context.ParentModule.TryLookupMember(new MetadataToken(TableIndex.GenericParam, rid), out var member) && member is GenericParameter genericParameter) { - result.Add(genericParameter); + result.AddNoOwnerCheck(genericParameter); } } @@ -135,14 +132,14 @@ protected override IList GetGenericParameters() protected override IList GetInterfaces() { var rids = _context.ParentModule.GetInterfaceImplementationRids(MetadataToken); - var result = new OwnedCollection(this, rids.Count); + var result = new MemberCollection(this, rids.Count); foreach (uint rid in rids) { if (_context.ParentModule.TryLookupMember(new MetadataToken(TableIndex.InterfaceImpl, rid), out var member) && member is InterfaceImplementation type) { - result.Add(type); + result.AddNoOwnerCheck(type); } } diff --git a/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs b/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs index fa11e5a67..edbacbc2b 100644 --- a/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs +++ b/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs @@ -208,8 +208,8 @@ public int GetHashCode(CustomModifierTypeSignature obj) unchecked { int hashCode = (int) obj.ElementType << ElementTypeOffset; - hashCode = (hashCode * 397) ^ obj.ModifierType.GetHashCode(); - hashCode = (hashCode * 397) ^ obj.BaseType.GetHashCode(); + hashCode = (hashCode * 397) ^ GetHashCode(obj.ModifierType); + hashCode = (hashCode * 397) ^ GetHashCode(obj.BaseType); return hashCode; } } @@ -233,7 +233,7 @@ public int GetHashCode(GenericInstanceTypeSignature obj) unchecked { int hashCode = (int) obj.ElementType << ElementTypeOffset; - hashCode = (hashCode * 397) ^ obj.GenericType.GetHashCode(); + hashCode = (hashCode * 397) ^ GetHashCode(obj.GenericType); hashCode = (hashCode * 397) ^ GetHashCode(obj.TypeArguments); return hashCode; } diff --git a/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs b/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs index 516342867..2d8075a2f 100644 --- a/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs +++ b/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs @@ -136,15 +136,14 @@ public IResolutionScope CorLibScope /// Gets the element type signature for . /// public CorLibTypeSignature Object => GetOrCreateCorLibTypeSignature(ref _object, ElementType.Object, nameof(Object)); - + /// /// Creates a new type factory that references mscorlib 4.0.0.0. /// /// The factory. public static CorLibTypeFactory CreateMscorlib40TypeFactory(ModuleDefinition module) { - var importer = new ReferenceImporter(module); - return new CorLibTypeFactory(importer.ImportScope(KnownCorLibs.MsCorLib_v4_0_0_0)); + return new CorLibTypeFactory(KnownCorLibs.MsCorLib_v4_0_0_0.ImportWith(module.DefaultImporter)); } /// diff --git a/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj b/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj index aa5d496e7..fb00775e4 100644 --- a/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj +++ b/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj @@ -4,11 +4,8 @@ AsmResolver.PE.File Raw PE file models for the AsmResolver executable file inspection toolsuite. exe pe headers sections inspection manipulation assembly disassembly - true 1701;1702;NU5105 true - enable - net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 true @@ -25,9 +22,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj b/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj index b2fc17031..98bce0723 100644 --- a/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj +++ b/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj @@ -3,10 +3,7 @@ AsmResolver.PE.Win32Resources exe pe directories imports exports resources dotnet cil inspection manipulation assembly disassembly - true 1701;1702;NU5105 - enable - net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 true @@ -18,11 +15,11 @@ bin\Release\AsmResolver.PE.Win32Resources.xml - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/AsmResolver.PE/AsmResolver.PE.csproj b/src/AsmResolver.PE/AsmResolver.PE.csproj index 1ec5862cf..699fbbd7a 100644 --- a/src/AsmResolver.PE/AsmResolver.PE.csproj +++ b/src/AsmResolver.PE/AsmResolver.PE.csproj @@ -4,10 +4,7 @@ AsmResolver.PE PE image models for the AsmResolver executable file inspection toolsuite. exe pe directories imports exports resources dotnet cil inspection manipulation assembly disassembly - true 1701;1702;NU5105 - enable - net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 true @@ -24,7 +21,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs b/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs index 0066a4ce3..659da6912 100644 --- a/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs +++ b/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs @@ -188,9 +188,11 @@ protected virtual void WriteStreamHeaders(IBinaryStreamWriter writer, MetadataSt var header = headers[i]; writer.WriteUInt32(header.Offset); writer.WriteUInt32(header.Size); + + ulong nameOffset = writer.Offset; writer.WriteAsciiString(header.Name); writer.WriteByte(0); - writer.Align(4); + writer.AlignRelative(4, nameOffset); } } diff --git a/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs b/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs index da69e89cf..8f76eb69a 100644 --- a/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs +++ b/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs @@ -60,7 +60,7 @@ public static MetadataStreamHeader FromReader(ref BinaryStreamReader reader) uint offset = reader.ReadUInt32(); uint size = reader.ReadUInt32(); string name = reader.ReadAsciiString(); - reader.Align(4); + reader.AlignRelative(4); return new MetadataStreamHeader(offset, size, name); } diff --git a/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj b/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj index 1b0c09029..61bad1f34 100644 --- a/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj +++ b/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj @@ -3,9 +3,6 @@ AsmResolver Windows PDB models for the AsmResolver executable file inspection toolsuite. - windows pdb symbols - enable - net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 true true @@ -26,9 +23,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/AsmResolver/AsmResolver.csproj b/src/AsmResolver/AsmResolver.csproj index d3591d07c..18ba58436 100644 --- a/src/AsmResolver/AsmResolver.csproj +++ b/src/AsmResolver/AsmResolver.csproj @@ -4,10 +4,7 @@ AsmResolver The base library for the AsmResolver executable file inspection toolsuite. exe pe dotnet cil inspection manipulation assembly disassembly - true 1701;1702;NU5105 - enable - net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 true @@ -22,9 +19,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/AsmResolver/Collections/OwnedCollection.cs b/src/AsmResolver/Collections/OwnedCollection.cs index 6facee7e8..b5617dc90 100644 --- a/src/AsmResolver/Collections/OwnedCollection.cs +++ b/src/AsmResolver/Collections/OwnedCollection.cs @@ -55,7 +55,7 @@ protected void AssertNotNullAndHasNoOwner(TItem? item) { if (item is null) throw new ArgumentNullException(nameof(item)); - if (item.Owner != null && item.Owner != Owner) + if (item.Owner is not null) throw new ArgumentException("Item is already added to another collection."); } diff --git a/src/AsmResolver/IO/IBinaryStreamWriter.cs b/src/AsmResolver/IO/IBinaryStreamWriter.cs index fe772a3f8..c5ac930c1 100644 --- a/src/AsmResolver/IO/IBinaryStreamWriter.cs +++ b/src/AsmResolver/IO/IBinaryStreamWriter.cs @@ -201,10 +201,18 @@ public static void WriteAsciiString(this IBinaryStreamWriter writer, string valu /// /// The writer to align. /// The boundary to use. - public static void Align(this IBinaryStreamWriter writer, uint align) + public static void Align(this IBinaryStreamWriter writer, uint align) => writer.AlignRelative(align, 0); + + /// + /// Aligns the writer to a specified boundary, relative to the provided start offset.. + /// + /// The writer to align. + /// The boundary to use. + /// The starting offset to consider the alignment boundaries from. + public static void AlignRelative(this IBinaryStreamWriter writer, uint align, ulong startOffset) { - ulong currentPosition = writer.Offset; - writer.WriteZeroes((int) (currentPosition.Align(align) - writer.Offset)); + ulong currentPosition = writer.Offset - startOffset; + writer.WriteZeroes((int) (currentPosition.Align(align) - currentPosition)); } /// diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 000000000..93a6227cc --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + net8.0;net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1 + true + enable + $(MSBuildThisFileDirectory)..\artifacts + + diff --git a/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj b/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj index 864745258..0f275278b 100644 --- a/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj +++ b/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 enable diff --git a/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj b/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj index aa91f3a42..8b3a79e64 100644 --- a/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj +++ b/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 disable false @@ -9,9 +9,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs b/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs index c649f621d..94a8a4174 100644 --- a/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs +++ b/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs @@ -54,7 +54,7 @@ public void RtDynamicMethod() object rtDynamicMethod = generatedDynamicMethod .GetType() .GetField("m_dynMethod", (BindingFlags) (-1))? - .GetValue(generatedDynamicMethod); + .GetValue(generatedDynamicMethod) ?? generatedDynamicMethod; var dynamicMethod = new DynamicMethodDefinition(module, rtDynamicMethod!); Assert.NotNull(dynamicMethod); diff --git a/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj b/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj index c9a4eb306..bd8c4745e 100644 --- a/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj +++ b/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj @@ -1,20 +1,22 @@ - net6.0 + net8.0 false disable 11 + + true - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs b/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs index 78eab1163..c3ad3549b 100644 --- a/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs +++ b/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs @@ -62,7 +62,7 @@ public void OptimizeFirst4ArgumentsToMacros(int index, CilCode expectedMacro) public void OptimizeHiddenThisToLdarg0() { var instructions = CreateDummyMethod(true, 0, 0); - instructions.Add(CilOpCodes.Ldarg, instructions.Owner.Owner.Parameters.ThisParameter); + instructions.Add(CilOpCodes.Ldarg, instructions.Owner.Owner.Parameters.ThisParameter!); instructions.Add(CilOpCodes.Ret); instructions.OptimizeMacros(); @@ -183,6 +183,23 @@ public void OptimizeLoadLocalInstructions(int index, CilCode expected) Assert.Equal(expected, instructions[0].OpCode.Code); } + [Theory] + [InlineData(0, CilCode.Ldloca_S)] + [InlineData(1, CilCode.Ldloca_S)] + [InlineData(255, CilCode.Ldloca_S)] + [InlineData(256, CilCode.Ldloca)] + public void OptimizeLoadLocalAddressInstructions(int index, CilCode expected) + { + var instructions = CreateDummyMethod(false, 0, index + 1); + + instructions.Add(CilOpCodes.Ldloca, instructions.Owner.LocalVariables[index]); + instructions.Add(CilOpCodes.Ret); + + instructions.OptimizeMacros(); + + Assert.Equal(expected, instructions[0].OpCode.Code); + } + [Theory] [InlineData(0, CilCode.Stloc_0)] [InlineData(1, CilCode.Stloc_1)] @@ -225,6 +242,24 @@ public void OptimizeLoadArgInstructions(int index, CilCode expected) Assert.Equal(expected, instructions[0].OpCode.Code); } + [Theory] + [InlineData(0, CilCode.Ldarga_S)] + [InlineData(1, CilCode.Ldarga_S)] + [InlineData(255, CilCode.Ldarga_S)] + [InlineData(256, CilCode.Ldarga)] + public void OptimizeLoadArgAddressInstructions(int index, CilCode expected) + { + var instructions = CreateDummyMethod(false, index + 1, 0); + var method = instructions.Owner.Owner; + + instructions.Add(CilOpCodes.Ldarga, method.Parameters[index]); + instructions.Add(CilOpCodes.Ret); + + instructions.OptimizeMacros(); + + Assert.Equal(expected, instructions[0].OpCode.Code); + } + [Theory] [InlineData(0, CilCode.Starg_S)] [InlineData(255, CilCode.Starg_S)] @@ -374,7 +409,7 @@ public void OptimizeShouldUpdateOffsets() instructions.OptimizeMacros(); int[] offsets = instructions.Select(i => i.Offset).ToArray(); - Assert.NotEqual(offsets, instructions.Select(i => 0)); + Assert.All(offsets.Skip(1), offset => Assert.NotEqual(0, offset)); instructions.CalculateOffsets(); Assert.Equal(offsets, instructions.Select(i => i.Offset)); } @@ -393,7 +428,7 @@ public void ExpandShouldUpdateOffsets() instructions.ExpandMacros(); int[] offsets = instructions.Select(i => i.Offset).ToArray(); - Assert.NotEqual(offsets, instructions.Select(i => 0)); + Assert.All(offsets.Skip(1), offset => Assert.NotEqual(0, offset)); instructions.CalculateOffsets(); Assert.Equal(offsets, instructions.Select(i => i.Offset)); } diff --git a/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs b/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs index 3e0c4b177..ba53b1598 100644 --- a/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs +++ b/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs @@ -6,6 +6,7 @@ using AsmResolver.DotNet.TestCases.Fields; using AsmResolver.DotNet.TestCases.Types.Structs; using AsmResolver.PE.DotNet.Cil; +using AsmResolver.PE.DotNet.Metadata.Tables.Rows; using Xunit; namespace AsmResolver.DotNet.Tests @@ -198,6 +199,25 @@ public void PersistentFieldOffset(string name, int offset) Assert.Equal(offset, newField.FieldOffset); } + [Fact] + public void AddSameFieldTwiceToTypeShouldThrow() + { + var module = new ModuleDefinition("SomeModule"); + var field = new FieldDefinition("SomeField", FieldAttributes.Public, module.CorLibTypeFactory.Int32); + var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public); + type.Fields.Add(field); + Assert.Throws(() => type.Fields.Add(field)); + } + [Fact] + public void AddSameFieldToDifferentTypesShouldThrow() + { + var module = new ModuleDefinition("SomeModule"); + var field = new FieldDefinition("SomeField", FieldAttributes.Public, module.CorLibTypeFactory.Int32); + var type1 = new TypeDefinition("SomeNamespace", "SomeType1", TypeAttributes.Public); + var type2 = new TypeDefinition("SomeNamespace", "SomeType2", TypeAttributes.Public); + type1.Fields.Add(field); + Assert.Throws(() => type2.Fields.Add(field)); + } } } diff --git a/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs b/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs index 8d992d293..2f917dfb9 100644 --- a/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs +++ b/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs @@ -167,7 +167,7 @@ public void ReadTypesNoNested() public void ReadTypesNested() { var module = ModuleDefinition.FromFile(typeof(TopLevelClass1).Assembly.Location); - Assert.Equal(new HashSet + Assert.Equal(new Utf8String[] { "", nameof(TopLevelClass1), diff --git a/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs b/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs index 4f745efc9..884420334 100644 --- a/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs +++ b/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs @@ -546,5 +546,60 @@ public void ImportGenericMethodInstantiationWithReturnTypeViaReflection() var signature = Assert.IsAssignableFrom(imported.Signature.ReturnType); Assert.Equal(2, signature.Index); } + +#if NET8_0_OR_GREATER + private static unsafe class DelegatePointerHolder + { + public static delegate*unmanaged[Cdecl, SuppressGCTransition] Complex = null; + public static delegate*unmanaged[Stdcall] StdcallOnly = null; + public static delegate*unmanaged[SuppressGCTransition] GcOnly = null; + } + + [Fact] + public void ImportComplexFunctionPointerFromReflectedFieldType() + { + var fieldType = typeof(DelegatePointerHolder).GetField("Complex")!.GetModifiedFieldType(); + var imported = Assert.IsAssignableFrom(_importer.ImportType(fieldType).ToTypeSignature()); + Assert.Equal(CallingConventionAttributes.Unmanaged, imported.Signature.CallingConvention); + var firstModifier = Assert.IsAssignableFrom(imported.Signature.ReturnType); + Assert.True(firstModifier.ModifierType is + { + Namespace.Value: "System.Runtime.CompilerServices", + Name.Value: "CallConvCdecl" or "CallConvSuppressGCTransition" + }); + var secondModifier = Assert.IsAssignableFrom(firstModifier.BaseType); + Assert.True(secondModifier.ModifierType is + { + Namespace.Value: "System.Runtime.CompilerServices", + Name.Value: "CallConvCdecl" or "CallConvSuppressGCTransition" + }); + } + + [Fact] + public void ImportSimpleFunctionPointerFromReflectedFieldType() + { + var fieldType = typeof(DelegatePointerHolder).GetField("StdcallOnly")!.GetModifiedFieldType(); + var imported = Assert.IsAssignableFrom(_importer.ImportType(fieldType).ToTypeSignature()); + Assert.Equal(CallingConventionAttributes.StdCall, imported.Signature.CallingConvention); + } + + [Fact] + public void ImportModoptOnlyFunctionPointerFromReflectedFieldType() + { + var fieldType = typeof(DelegatePointerHolder).GetField("GcOnly")!.GetModifiedFieldType(); + var imported = Assert.IsAssignableFrom(_importer.ImportType(fieldType).ToTypeSignature()); + Assert.Equal(CallingConventionAttributes.Unmanaged, imported.Signature.CallingConvention); + var firstModifier = Assert.IsAssignableFrom(imported.Signature.ReturnType); + Assert.Equal("System.Runtime.CompilerServices.CallConvSuppressGCTransition", firstModifier.ModifierType.FullName); + } + + [Fact] + public void ImportFunctionPointerFromTypeof() + { + var imported = Assert.IsAssignableFrom(_importer.ImportType(typeof(delegate*)).ToTypeSignature()); + Assert.Collection(imported.Signature.ParameterTypes, t => Assert.Same(_module.CorLibTypeFactory.Int32, t)); + Assert.Same(imported.Signature.ReturnType, _module.CorLibTypeFactory.UInt32); + } +#endif } } diff --git a/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs b/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs index 4e2ebfa28..fe59cc058 100644 --- a/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs +++ b/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using AsmResolver.DotNet.Builder; +using AsmResolver.DotNet.Code.Cil; using AsmResolver.DotNet.Signatures; using AsmResolver.DotNet.Signatures.Types; using AsmResolver.DotNet.TestCases.CustomAttributes; @@ -13,6 +15,7 @@ using AsmResolver.DotNet.TestCases.Properties; using AsmResolver.DotNet.TestCases.Types; using AsmResolver.DotNet.TestCases.Types.Structs; +using AsmResolver.PE.DotNet.Cil; using AsmResolver.PE.DotNet.Metadata.Tables; using AsmResolver.PE.DotNet.Metadata.Tables.Rows; using Xunit; @@ -135,42 +138,42 @@ public void ReadNestedTypes() var module = ModuleDefinition.FromFile(typeof(TopLevelClass1).Assembly.Location); var class1 = module.TopLevelTypes.First(t => t.Name == nameof(TopLevelClass1)); - Assert.Equal(new HashSet + Assert.Equal(new Utf8String[] { nameof(TopLevelClass1.Nested1), nameof(TopLevelClass1.Nested2) }, class1.NestedTypes.Select(t => t.Name)); var nested1 = class1.NestedTypes.First(t => t.Name == nameof(TopLevelClass1.Nested1)); - Assert.Equal(new HashSet + Assert.Equal(new Utf8String[] { nameof(TopLevelClass1.Nested1.Nested1Nested1), nameof(TopLevelClass1.Nested1.Nested1Nested2) }, nested1.NestedTypes.Select(t => t.Name)); var nested2 = class1.NestedTypes.First(t => t.Name == nameof(TopLevelClass1.Nested2)); - Assert.Equal(new HashSet + Assert.Equal(new Utf8String[] { nameof(TopLevelClass1.Nested2.Nested2Nested1), nameof(TopLevelClass1.Nested2.Nested2Nested2) }, nested2.NestedTypes.Select(t => t.Name)); var class2 = module.TopLevelTypes.First(t => t.Name == nameof(TopLevelClass2)); - Assert.Equal(new HashSet + Assert.Equal(new Utf8String[] { nameof(TopLevelClass2.Nested3), nameof(TopLevelClass2.Nested4) }, class2.NestedTypes.Select(t => t.Name)); var nested3 = class2.NestedTypes.First(t => t.Name == nameof(TopLevelClass2.Nested3)); - Assert.Equal(new HashSet + Assert.Equal(new Utf8String[] { nameof(TopLevelClass2.Nested3.Nested3Nested1), nameof(TopLevelClass2.Nested3.Nested3Nested2) }, nested3.NestedTypes.Select(t => t.Name)); var nested4 = class2.NestedTypes.First(t => t.Name == nameof(TopLevelClass2.Nested4)); - Assert.Equal(new HashSet + Assert.Equal(new Utf8String[] { nameof(TopLevelClass2.Nested4.Nested4Nested1), nameof(TopLevelClass2.Nested4.Nested4Nested2) @@ -198,8 +201,10 @@ public void ReadNestedFullName() public void ReadNestedNestedFullName() { var module = ModuleDefinition.FromFile(typeof(TopLevelClass1).Assembly.Location); - var type = (TypeDefinition) module.LookupMember(typeof(TopLevelClass1.Nested1.Nested1Nested2).MetadataToken); - Assert.Equal("AsmResolver.DotNet.TestCases.NestedClasses.TopLevelClass1+Nested1+Nested1Nested2", type.FullName); + var type = (TypeDefinition) module.LookupMember(typeof(TopLevelClass1.Nested1.Nested1Nested2) + .MetadataToken); + Assert.Equal("AsmResolver.DotNet.TestCases.NestedClasses.TopLevelClass1+Nested1+Nested1Nested2", + type.FullName); } [Fact] @@ -723,5 +728,55 @@ public void GetNonExistingConstructorShouldReturnNull() Assert.Null(type.GetConstructor(factory.String)); Assert.Null(type.GetConstructor(factory.String, factory.String)); } + + [Fact] + public void AddTypeToModuleShouldSetOwner() + { + var module = new ModuleDefinition("Dummy"); + var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public); + module.TopLevelTypes.Add(type); + Assert.Same(module, type.Module); + } + + [Fact] + public void AddNestedTypeToModuleShouldSetOwner() + { + var module = new ModuleDefinition("Dummy"); + var type1 = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public); + var type2 = new TypeDefinition(null, "NestedType", TypeAttributes.NestedPublic); + module.TopLevelTypes.Add(type1); + type1.NestedTypes.Add(type2); + Assert.Same(type1, type2.DeclaringType); + Assert.Same(module, type2.Module); + } + + [Fact] + public void AddSameTypeTwiceToModuleShouldThrow() + { + var module = new ModuleDefinition("Dummy"); + var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public); + module.TopLevelTypes.Add(type); + Assert.Throws(() => module.TopLevelTypes.Add(type)); + } + + [Fact] + public void AddSameTypeTwiceToNestedTypeShouldThrow() + { + var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public); + var nestedType = new TypeDefinition(null, "SomeType", TypeAttributes.NestedPublic); + type.NestedTypes.Add(nestedType); + Assert.Throws(() => type.NestedTypes.Add(nestedType)); + } + + [Fact] + public void AddSameNestedTypeToDifferentTypesShouldThrow() + { + var type1 = new TypeDefinition("SomeNamespace", "SomeType1", TypeAttributes.Public); + var type2 = new TypeDefinition("SomeNamespace", "SomeType2", TypeAttributes.Public); + var nestedType = new TypeDefinition(null, "SomeType", TypeAttributes.NestedPublic); + type1.NestedTypes.Add(nestedType); + Assert.Throws(() => type2.NestedTypes.Add(nestedType)); + } + } } diff --git a/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj b/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj index 99e8aa174..057949751 100644 --- a/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj +++ b/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false @@ -10,9 +10,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj b/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj index 01de3b1e4..452bac3e3 100644 --- a/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj +++ b/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false true enable @@ -17,9 +17,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs b/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs index 68573748b..80bd69776 100644 --- a/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs +++ b/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs @@ -18,7 +18,7 @@ public class CilInstructionTest [InlineData(CilCode.Ldc_I4_7, null, 7)] [InlineData(CilCode.Ldc_I4_8, null, 8)] [InlineData(CilCode.Ldc_I4_S, (sbyte) -10, -10)] - public void GetLdcI4ConstantTest(CilCode code, object operand, int expectedValue) + public void GetLdcI4ConstantTest(CilCode code, object? operand, int expectedValue) { var instruction = new CilInstruction(code.ToOpCode(), operand); Assert.Equal(expectedValue, instruction.GetLdcI4Constant()); diff --git a/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs b/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs index dc4a0740d..0203c7e3d 100644 --- a/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs +++ b/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs @@ -34,7 +34,17 @@ public void CorrectStreamHeaders() var peImage = PEImage.FromBytes(Properties.Resources.HelloWorld); var metadata = peImage.DotNetDirectory!.Metadata!; - var expectedNames = new[] {"#~", "#Strings", "#US", "#GUID", "#Blob"}; + string[] expectedNames = new[] {"#~", "#Strings", "#US", "#GUID", "#Blob"}; + Assert.Equal(expectedNames, metadata.Streams.Select(s => s.Name)); + } + + [Fact] + public void CorrectStreamHeadersUnalignedMetadataDirectory() + { + var peImage = PEImage.FromBytes(Properties.Resources.HelloWorld_UnalignedMetadata); + var metadata = peImage.DotNetDirectory!.Metadata!; + + string[] expectedNames = new[] {"#~", "#Strings", "#US", "#GUID", "#Blob"}; Assert.Equal(expectedNames, metadata.Streams.Select(s => s.Name)); } @@ -188,6 +198,5 @@ public void SelectFirstUserStringsStreamInEnCMetadata() { AssertCorrectStreamIsSelected(Properties.Resources.HelloWorld_DoubleUserStringsStream_EnC, true); } - } } diff --git a/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs b/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs index b006b2bea..a01ff3be2 100644 --- a/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs +++ b/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs @@ -171,6 +171,13 @@ public static byte[] HelloWorld_ReadyToRun { } } + public static byte[] HelloWorld_UnalignedMetadata { + get { + object obj = ResourceManager.GetObject("HelloWorld_UnalignedMetadata", resourceCulture); + return ((byte[])(obj)); + } + } + public static byte[] HelloWorldPortablePdb { get { object obj = ResourceManager.GetObject("HelloWorldPortablePdb", resourceCulture); diff --git a/test/AsmResolver.PE.Tests/Properties/Resources.resx b/test/AsmResolver.PE.Tests/Properties/Resources.resx index 00511e896..e588237b0 100644 --- a/test/AsmResolver.PE.Tests/Properties/Resources.resx +++ b/test/AsmResolver.PE.Tests/Properties/Resources.resx @@ -72,6 +72,9 @@ ..\Resources\HelloWorld.ReadyToRun.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\HelloWorld.UnalignedMetadata.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\HelloWorld.pdb;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/test/AsmResolver.PE.Tests/Resources/HelloWorld.UnalignedMetadata.exe b/test/AsmResolver.PE.Tests/Resources/HelloWorld.UnalignedMetadata.exe new file mode 100644 index 000000000..85a079542 Binary files /dev/null and b/test/AsmResolver.PE.Tests/Resources/HelloWorld.UnalignedMetadata.exe differ diff --git a/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj b/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj index 1c80a65b2..9cd8c9b8c 100644 --- a/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj +++ b/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false AsmResolver.PE.Win32Resources.Tests warnings @@ -9,9 +9,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj b/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj index 364078a8a..ed3cc2a91 100644 --- a/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj +++ b/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable false @@ -9,13 +9,9 @@ - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/AsmResolver.Tests/AsmResolver.Tests.csproj b/test/AsmResolver.Tests/AsmResolver.Tests.csproj index 5a5259bc5..2af29423d 100644 --- a/test/AsmResolver.Tests/AsmResolver.Tests.csproj +++ b/test/AsmResolver.Tests/AsmResolver.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false true enable @@ -9,9 +9,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 000000000..171c6ac9d --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + $(MSBuildThisFileDirectory)..\artifacts\test + false + + + diff --git a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj index b4ceea1e3..7a448bff4 100644 --- a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj +++ b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj @@ -24,7 +24,7 @@ - + diff --git a/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj b/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj index b2a147cef..90588ca1e 100644 --- a/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj +++ b/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj @@ -2,7 +2,7 @@ Exe - net47;netcoreapp3.1;net6.0 + net47;netcoreapp3.1;net6.0;net8.0 Resources\Icon.ico true diff --git a/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj b/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj index 399605bab..fb4aa7b71 100644 --- a/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj +++ b/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj @@ -4,6 +4,7 @@ Exe net472 enable + false